1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
|
package CParse::Declaration;
use 5.6.0;
use strict;
use warnings;
sub new
{
my $this = shift;
my $class = ref($this) || $this;
my $specifiers = shift;
my $declarators = shift;
my $self = {specifiers => $specifiers,
declarators => $declarators,
};
bless $self, $class;
return $self;
}
sub dump_c
{
my $self = shift;
my $specifiers = join(' ', grep {$_} map {$_->dump_c} @{$self->{specifiers}});
my $declarators = join(', ', map {$_->dump_c} @{$self->{declarators}});
return join(' ', grep {$_} ($specifiers, $declarators)) . ";\n";
}
sub set_location
{
my $self = shift;
$self->{file} = shift;
$self->{line} = shift;
$self->{pos} = shift;
}
sub process
{
my $self = shift;
my $namespace = shift;
my $storage_class;
my $inline;
my @attributes;
my @specifiers;
my @process_specifiers;
$CParse::current_location = $self;
foreach my $specifier (@{$self->{specifiers}})
{
if ($specifier->isa('CParse::StorageClass'))
{
if ($storage_class)
{
print STDERR "$self->{file}:$self->{line}:$self->{pos}: multiple storage class specifiers\n";
print STDERR "$self->{file}:$self->{line}:$self->{pos}: in " . $self->dump_c;
exit 1;
}
$storage_class = $specifier;
}
elsif ($specifier->isa('CParse::FunctionSpecifier'))
{
if ($specifier->name ne 'inline')
{
die "Internal error: unrecognised storage class specifier " . $specifier->name;
}
$inline = 1;
}
elsif ($specifier->isa('CParse::AttributeList'))
{
push @attributes, $specifier->attributes;
}
elsif ($specifier->isa('CParse::Struct') or $specifier->isa('CParse::Union') or $specifier->isa('CParse::Enum'))
{
push @specifiers, $specifier;
push @process_specifiers, $specifier;
}
else
{
push @specifiers, $specifier;
}
}
eval
{
$_->process($namespace) foreach @process_specifiers;
$_->process_decl($namespace, $storage_class, \@specifiers, $inline, \@attributes) foreach @{$self->{declarators}};
};
if ($@)
{
my $err = $@;
$err =~ s/\n*$//;
my @err = split /\n/, $err;
print STDERR "$self->{file}:$self->{line}:$self->{pos}: $_\n" foreach @err;
my $dump = eval {$self->dump_c};
if ($dump)
{
my @dump = split /\n/, $dump;
my $first = 1;
foreach (@dump)
{
print STDERR "$self->{file}:$self->{line}:$self->{pos}: " . ($first ? "in" : " ") . " $_\n";
$first = 0;
}
}
exit 1;
}
$CParse::current_location = undef;
}
1;
|