1 ########################
2 # Parse::Yapp parser for a C header file that contains only structures
5 # Copyright (C) 2005, Tim Potter <tpot@samba.org> released under the
6 # GNU GPL version 2 or later
14 definition { [$_[1]] }
15 | definitions definition { push(@{$_[1]}, $_[2]); $_[1] }
25 struct: STRUCT optional_identifier '{' elements '}' pointers optional_identifiers ';'
29 "STRUCT_NAME" => $_[2],
37 UNION optional_identifier '{' elements '}' pointers optional_identifier ';'
41 "UNION_NAME" => $_[2],
49 TYPEDEF STRUCT '{' elements '}' optional_identifier ';'
53 ENUM IDENTIFIER '{' enum_identifiers '}' ';'
56 enum_identifiers: enum_identifier
57 | enum_identifiers ',' enum_identifier
60 enum_identifier: IDENTIFIER
61 | IDENTIFIER '=' IDENTIFIER
65 | elements element { push(@{$_[1]}, $_[2]); $_[1] }
71 | STRUCT IDENTIFIER pointers IDENTIFIER ';'
75 "TYPE" => "struct $_[2]",
77 | UNION IDENTIFIER pointers IDENTIFIER ';'
81 "TYPE" => "union $_[2]",
83 | CONST type pointers IDENTIFIER array ';'
89 | type pointers IDENTIFIER array ';'
94 "ARRAY_LENGTH" => $_[4]
99 | '[' CONSTANT ']' { int($_[2]) }
109 | pointers '*' { $_[1]+1 }
112 optional_identifiers: optional_identifier { [$_[1]] }
113 | optional_identifiers ',' optional_identifier { push(@{$_[1]}, $_[3]); $_[1] }
116 optional_identifier: IDENTIFIER | #empty { undef }
121 #####################################################################
122 # traverse a perl data structure removing any empty arrays or
123 # hashes and any hash elements that map to undef
128 if (ref($v) eq "ARRAY") {
129 foreach my $i (0 .. $#{$v}) {
131 if (ref($v->[$i]) eq "ARRAY" && $#{$v->[$i]}==-1) {
136 # this removes any undefined elements from the array
137 @{$v} = grep { defined $_ } @{$v};
138 } elsif (ref($v) eq "HASH") {
139 foreach my $x (keys %{$v}) {
141 if (!defined $v->{$x}) { delete($v->{$x}); next; }
142 if (ref($v->{$x}) eq "ARRAY" && $#{$v->{$x}}==-1) { delete($v->{$x}); next; }
149 if (exists $_[0]->YYData->{ERRMSG}) {
150 print $_[0]->YYData->{ERRMSG};
151 delete $_[0]->YYData->{ERRMSG};
154 my $line = $_[0]->YYData->{LINE};
155 my $last_token = $_[0]->YYData->{LAST_TOKEN};
156 my $file = $_[0]->YYData->{INPUT_FILENAME};
158 print "$file:$line: Syntax error near '$last_token'\n";
165 $parser->YYData->{INPUT} or return('',undef);
168 $parser->YYData->{INPUT} =~ s/^[ \t]*//;
170 for ($parser->YYData->{INPUT}) {
172 if (s/^\# (\d+) \"(.*?)\"( \d+|)//) {
173 $parser->YYData->{LINE} = $1-1;
174 $parser->YYData->{INPUT_FILENAME} = $2;
177 if (s/^\#line (\d+) \"(.*?)\"( \d+|)//) {
178 $parser->YYData->{LINE} = $1-1;
179 $parser->YYData->{INPUT_FILENAME} = $2;
187 $parser->YYData->{LINE}++;
190 if (s/^\"(.*?)\"//) {
191 $parser->YYData->{LAST_TOKEN} = $1;
194 if (s/^(\d+)(\W|$)/$2/) {
195 $parser->YYData->{LAST_TOKEN} = $1;
196 return('CONSTANT',$1);
199 $parser->YYData->{LAST_TOKEN} = $1;
201 /^(const|typedef|union|struct|enum)$/x) {
204 return('IDENTIFIER',$1);
207 $parser->YYData->{LAST_TOKEN} = $1;
215 my ($self,$filename) = @_;
217 my $saved_delim = $/;
220 if (! defined $cpp) {
223 my $data = `$cpp -D__PIDL__ -xc $filename`;
226 $self->YYData->{INPUT} = $data;
227 $self->YYData->{LINE} = 0;
228 $self->YYData->{LAST_TOKEN} = "NONE";
230 my $idl = $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error );
232 return CleanData($idl);