nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 ########################
2 # IDL Parse::Yapp parser
3 # Copyright (C) Andrew Tridgell <tridge@samba.org>
4 # released under the GNU GPL version 3 or later
5  
6  
7  
8 # the precedence actually doesn't matter at all for this grammar, but
9 # by providing a precedence we reduce the number of conflicts
10 # enormously
11 %left '-' '+' '&' '|' '*' '>' '.' '/' '(' ')' '[' ',' ';'
12  
13  
14 ################
15 # grammar
16 %%
17 idl:
18 #empty { {} }
19 |
20 idl interface { push(@{$_[1]}, $_[2]); $_[1] }
21 |
22 idl coclass { push(@{$_[1]}, $_[2]); $_[1] }
23 |
24 idl import { push(@{$_[1]}, $_[2]); $_[1] }
25 |
26 idl include { push(@{$_[1]}, $_[2]); $_[1] }
27 |
28 idl importlib { push(@{$_[1]}, $_[2]); $_[1] }
29 |
30 idl cpp_quote { push(@{$_[1]}, $_[2]); $_[1] }
31 ;
32  
33 import:
34 'import' commalist ';'
35 {{
36 "TYPE" => "IMPORT",
37 "PATHS" => $_[2],
38 "FILE" => $_[0]->YYData->{FILE},
39 "LINE" => $_[0]->YYData->{LINE},
40 }}
41 ;
42  
43 include:
44 'include' commalist ';'
45 {{
46 "TYPE" => "INCLUDE",
47 "PATHS" => $_[2],
48 "FILE" => $_[0]->YYData->{FILE},
49 "LINE" => $_[0]->YYData->{LINE},
50 }}
51 ;
52  
53 importlib:
54 'importlib' commalist ';'
55 {{
56 "TYPE" => "IMPORTLIB",
57 "PATHS" => $_[2],
58 "FILE" => $_[0]->YYData->{FILE},
59 "LINE" => $_[0]->YYData->{LINE},
60 }}
61 ;
62  
63 commalist:
64 text { [ $_[1] ] }
65 |
66 commalist ',' text { push(@{$_[1]}, $_[3]); $_[1] }
67 ;
68  
69 coclass:
70 property_list 'coclass' identifier '{' interface_names '}' optional_semicolon
71 {{
72 "TYPE" => "COCLASS",
73 "PROPERTIES" => $_[1],
74 "NAME" => $_[3],
75 "DATA" => $_[5],
76 "FILE" => $_[0]->YYData->{FILE},
77 "LINE" => $_[0]->YYData->{LINE},
78 }}
79 ;
80  
81 interface_names:
82 #empty { {} }
83 |
84 interface_names 'interface' identifier ';' { push(@{$_[1]}, $_[2]); $_[1] }
85 ;
86  
87 interface:
88 property_list 'interface' identifier base_interface '{' definitions '}' optional_semicolon
89 {{
90 "TYPE" => "INTERFACE",
91 "PROPERTIES" => $_[1],
92 "NAME" => $_[3],
93 "BASE" => $_[4],
94 "DATA" => $_[6],
95 "FILE" => $_[0]->YYData->{FILE},
96 "LINE" => $_[0]->YYData->{LINE},
97 }}
98 ;
99  
100 base_interface:
101 #empty
102 |
103 ':' identifier { $_[2] }
104 ;
105  
106  
107 cpp_quote:
108 'cpp_quote' '(' text ')'
109 {{
110 "TYPE" => "CPP_QUOTE",
111 "DATA" => $_[3],
112 "FILE" => $_[0]->YYData->{FILE},
113 "LINE" => $_[0]->YYData->{LINE},
114 }}
115 ;
116  
117 definitions:
118 definition { [ $_[1] ] }
119 |
120 definitions definition { push(@{$_[1]}, $_[2]); $_[1] }
121 ;
122  
123 definition:
124 function
125 |
126 const
127 |
128 typedef
129 |
130 typedecl
131 ;
132  
133 const:
134 'const' identifier pointers identifier '=' anytext ';'
135 {{
136 "TYPE" => "CONST",
137 "DTYPE" => $_[2],
138 "POINTERS" => $_[3],
139 "NAME" => $_[4],
140 "VALUE" => $_[6],
141 "FILE" => $_[0]->YYData->{FILE},
142 "LINE" => $_[0]->YYData->{LINE},
143 }}
144 |
145 'const' identifier pointers identifier array_len '=' anytext ';'
146 {{
147 "TYPE" => "CONST",
148 "DTYPE" => $_[2],
149 "POINTERS" => $_[3],
150 "NAME" => $_[4],
151 "ARRAY_LEN" => $_[5],
152 "VALUE" => $_[7],
153 "FILE" => $_[0]->YYData->{FILE},
154 "LINE" => $_[0]->YYData->{LINE},
155 }}
156 ;
157  
158 function:
159 property_list type identifier '(' element_list2 ')' ';'
160 {{
161 "TYPE" => "FUNCTION",
162 "NAME" => $_[3],
163 "RETURN_TYPE" => $_[2],
164 "PROPERTIES" => $_[1],
165 "ELEMENTS" => $_[5],
166 "FILE" => $_[0]->YYData->{FILE},
167 "LINE" => $_[0]->YYData->{LINE},
168 }}
169 ;
170  
171 typedef:
172 property_list 'typedef' type pointers identifier array_len ';'
173 {{
174 "TYPE" => "TYPEDEF",
175 "PROPERTIES" => $_[1],
176 "NAME" => $_[5],
177 "DATA" => $_[3],
178 "POINTERS" => $_[4],
179 "ARRAY_LEN" => $_[6],
180 "FILE" => $_[0]->YYData->{FILE},
181 "LINE" => $_[0]->YYData->{LINE},
182 }}
183 ;
184  
185 usertype:
186 struct
187 |
188 union
189 |
190 enum
191 |
192 bitmap
193 |
194 pipe
195 ;
196  
197 typedecl:
198 usertype ';' { $_[1] }
199 ;
200  
201 sign:
202 'signed'
203 |
204 'unsigned'
205 ;
206  
207 existingtype:
208 sign identifier { ($_[1]?$_[1]:"signed") ." $_[2]" }
209 |
210 identifier
211 ;
212  
213 type:
214 usertype
215 |
216 existingtype
217 |
218 void { "void" }
219 ;
220  
221 enum_body:
222 '{' enum_elements '}' { $_[2] }
223 ;
224  
225 opt_enum_body:
226 #empty
227 |
228 enum_body
229 ;
230  
231 enum:
232 property_list 'enum' optional_identifier opt_enum_body
233 {{
234 "TYPE" => "ENUM",
235 "PROPERTIES" => $_[1],
236 "NAME" => $_[3],
237 "ELEMENTS" => $_[4],
238 "FILE" => $_[0]->YYData->{FILE},
239 "LINE" => $_[0]->YYData->{LINE},
240 }}
241 ;
242  
243 enum_elements:
244 enum_element { [ $_[1] ] }
245 |
246 enum_elements ',' enum_element { push(@{$_[1]}, $_[3]); $_[1] }
247 ;
248  
249 enum_element:
250 identifier
251 |
252 identifier '=' anytext { "$_[1]$_[2]$_[3]" }
253 ;
254  
255 bitmap_body:
256 '{' opt_bitmap_elements '}' { $_[2] }
257 ;
258  
259 opt_bitmap_body:
260 #empty
261 |
262 bitmap_body
263 ;
264  
265 bitmap:
266 property_list 'bitmap' optional_identifier opt_bitmap_body
267 {{
268 "TYPE" => "BITMAP",
269 "PROPERTIES" => $_[1],
270 "NAME" => $_[3],
271 "ELEMENTS" => $_[4],
272 "FILE" => $_[0]->YYData->{FILE},
273 "LINE" => $_[0]->YYData->{LINE},
274 }}
275 ;
276  
277 bitmap_elements:
278 bitmap_element { [ $_[1] ] }
279 |
280 bitmap_elements ',' bitmap_element { push(@{$_[1]}, $_[3]); $_[1] }
281 ;
282  
283 opt_bitmap_elements:
284 #empty
285 |
286 bitmap_elements
287 ;
288  
289 bitmap_element:
290 identifier '=' anytext { "$_[1] ( $_[3] )" }
291 ;
292  
293 struct_body:
294 '{' element_list1 '}' { $_[2] }
295 ;
296  
297 opt_struct_body:
298 #empty
299 |
300 struct_body
301 ;
302  
303 struct:
304 property_list 'struct' optional_identifier opt_struct_body
305 {{
306 "TYPE" => "STRUCT",
307 "PROPERTIES" => $_[1],
308 "NAME" => $_[3],
309 "ELEMENTS" => $_[4],
310 "FILE" => $_[0]->YYData->{FILE},
311 "LINE" => $_[0]->YYData->{LINE},
312 }}
313 ;
314  
315 empty_element:
316 property_list ';'
317 {{
318 "NAME" => "",
319 "TYPE" => "EMPTY",
320 "PROPERTIES" => $_[1],
321 "POINTERS" => 0,
322 "ARRAY_LEN" => [],
323 "FILE" => $_[0]->YYData->{FILE},
324 "LINE" => $_[0]->YYData->{LINE},
325 }}
326 ;
327  
328 base_or_empty:
329 base_element ';'
330 |
331 empty_element;
332  
333 optional_base_element:
334 property_list base_or_empty { $_[2]->{PROPERTIES} = FlattenHash([$_[1],$_[2]->{PROPERTIES}]); $_[2] }
335 ;
336  
337 union_elements:
338 #empty
339 |
340 union_elements optional_base_element { push(@{$_[1]}, $_[2]); $_[1] }
341 ;
342  
343 union_body:
344 '{' union_elements '}' { $_[2] }
345 ;
346  
347 opt_union_body:
348 #empty
349 |
350 union_body
351 ;
352  
353 union:
354 property_list 'union' optional_identifier opt_union_body
355 {{
356 "TYPE" => "UNION",
357 "PROPERTIES" => $_[1],
358 "NAME" => $_[3],
359 "ELEMENTS" => $_[4],
360 "FILE" => $_[0]->YYData->{FILE},
361 "LINE" => $_[0]->YYData->{LINE},
362 }}
363 ;
364  
365 base_element:
366 property_list type pointers identifier array_len
367 {{
368 "NAME" => $_[4],
369 "TYPE" => $_[2],
370 "PROPERTIES" => $_[1],
371 "POINTERS" => $_[3],
372 "ARRAY_LEN" => $_[5],
373 "FILE" => $_[0]->YYData->{FILE},
374 "LINE" => $_[0]->YYData->{LINE},
375 }}
376 ;
377  
378 pointers:
379 #empty
380 { 0 }
381 |
382 pointers '*' { $_[1]+1 }
383 ;
384  
385 pipe:
386 property_list 'pipe' type
387 {{
388 "TYPE" => "PIPE",
389 "PROPERTIES" => $_[1],
390 "NAME" => undef,
391 "DATA" => {
392 "TYPE" => "STRUCT",
393 "PROPERTIES" => $_[1],
394 "NAME" => undef,
395 "ELEMENTS" => [{
396 "NAME" => "count",
397 "PROPERTIES" => $_[1],
398 "POINTERS" => 0,
399 "ARRAY_LEN" => [],
400 "TYPE" => "uint3264",
401 "FILE" => $_[0]->YYData->{FILE},
402 "LINE" => $_[0]->YYData->{LINE},
403 },{
404 "NAME" => "array",
405 "PROPERTIES" => $_[1],
406 "POINTERS" => 0,
407 "ARRAY_LEN" => [ "count" ],
408 "TYPE" => $_[3],
409 "FILE" => $_[0]->YYData->{FILE},
410 "LINE" => $_[0]->YYData->{LINE},
411 }],
412 "FILE" => $_[0]->YYData->{FILE},
413 "LINE" => $_[0]->YYData->{LINE},
414 },
415 "FILE" => $_[0]->YYData->{FILE},
416 "LINE" => $_[0]->YYData->{LINE},
417 }}
418 ;
419  
420 element_list1:
421 #empty
422 { [] }
423 |
424 element_list1 base_element ';' { push(@{$_[1]}, $_[2]); $_[1] }
425 ;
426  
427 optional_const:
428 #empty
429 |
430 'const'
431 ;
432  
433 element_list2:
434 #empty
435 |
436 'void'
437 |
438 optional_const base_element { [ $_[2] ] }
439 |
440 element_list2 ',' optional_const base_element { push(@{$_[1]}, $_[4]); $_[1] }
441 ;
442  
443 array_len:
444 #empty { [] }
445 |
446 '[' ']' array_len { push(@{$_[3]}, "*"); $_[3] }
447 |
448 '[' anytext ']' array_len { push(@{$_[4]}, "$_[2]"); $_[4] }
449 ;
450  
451 property_list:
452 #empty
453 |
454 property_list '[' properties ']' { FlattenHash([$_[1],$_[3]]); }
455 ;
456  
457 properties:
458 property { $_[1] }
459 |
460 properties ',' property { FlattenHash([$_[1], $_[3]]); }
461 ;
462  
463 property:
464 identifier {{ "$_[1]" => "1" }}
465 |
466 identifier '(' commalisttext ')' {{ "$_[1]" => "$_[3]" }}
467 ;
468  
469 commalisttext:
470 anytext
471 |
472 commalisttext ',' anytext { "$_[1],$_[3]" }
473 ;
474  
475 anytext:
476 #empty
477 { "" }
478 |
479 identifier
480 |
481 constant
482 |
483 text
484 |
485 anytext '-' anytext { "$_[1]$_[2]$_[3]" }
486 |
487 anytext '.' anytext { "$_[1]$_[2]$_[3]" }
488 |
489 anytext '*' anytext { "$_[1]$_[2]$_[3]" }
490 |
491 anytext '>' anytext { "$_[1]$_[2]$_[3]" }
492 |
493 anytext '<' anytext { "$_[1]$_[2]$_[3]" }
494 |
495 anytext '|' anytext { "$_[1]$_[2]$_[3]" }
496 |
497 anytext '&' anytext { "$_[1]$_[2]$_[3]" }
498 |
499 anytext '/' anytext { "$_[1]$_[2]$_[3]" }
500 |
501 anytext '?' anytext { "$_[1]$_[2]$_[3]" }
502 |
503 anytext ':' anytext { "$_[1]$_[2]$_[3]" }
504 |
505 anytext '=' anytext { "$_[1]$_[2]$_[3]" }
506 |
507 anytext '+' anytext { "$_[1]$_[2]$_[3]" }
508 |
509 anytext '~' anytext { "$_[1]$_[2]$_[3]" }
510 |
511 anytext '(' commalisttext ')' anytext { "$_[1]$_[2]$_[3]$_[4]$_[5]" }
512 |
513 anytext '{' commalisttext '}' anytext { "$_[1]$_[2]$_[3]$_[4]$_[5]" }
514 ;
515  
516 identifier:
517 IDENTIFIER
518 ;
519  
520 optional_identifier:
521 #empty { undef }
522 |
523 IDENTIFIER
524 ;
525  
526 constant:
527 CONSTANT
528 ;
529  
530 text:
531 TEXT { "\"$_[1]\"" }
532 ;
533  
534 optional_semicolon:
535 #empty
536 |
537 ';'
538 ;
539  
540  
541 #####################################
542 # start code
543 %%
544  
545 use Parse::Pidl qw(error);
546  
547 #####################################################################
548 # flatten an array of hashes into a single hash
549 sub FlattenHash($)
550 {
551 my $a = shift;
552 my %b;
553 for my $d (@{$a}) {
554 for my $k (keys %{$d}) {
555 $b{$k} = $d->{$k};
556 }
557 }
558 return \%b;
559 }
560  
561 #####################################################################
562 # traverse a perl data structure removing any empty arrays or
563 # hashes and any hash elements that map to undef
564 sub CleanData($)
565 {
566 sub CleanData($);
567 my($v) = shift;
568  
569 return undef if (not defined($v));
570  
571 if (ref($v) eq "ARRAY") {
572 foreach my $i (0 .. $#{$v}) {
573 CleanData($v->[$i]);
574 }
575 # this removes any undefined elements from the array
576 @{$v} = grep { defined $_ } @{$v};
577 } elsif (ref($v) eq "HASH") {
578 foreach my $x (keys %{$v}) {
579 CleanData($v->{$x});
580 if (!defined $v->{$x}) {
581 delete($v->{$x});
582 next;
583 }
584 }
585 }
586  
587 return $v;
588 }
589  
590 sub _Error {
591 if (exists $_[0]->YYData->{ERRMSG}) {
592 error($_[0]->YYData, $_[0]->YYData->{ERRMSG});
593 delete $_[0]->YYData->{ERRMSG};
594 return;
595 }
596  
597 my $last_token = $_[0]->YYData->{LAST_TOKEN};
598  
599 error($_[0]->YYData, "Syntax error near '$last_token'");
600 }
601  
602 sub _Lexer($)
603 {
604 my($parser)=shift;
605  
606 $parser->YYData->{INPUT} or return('',undef);
607  
608 again:
609 $parser->YYData->{INPUT} =~ s/^[ \t]*//;
610  
611 for ($parser->YYData->{INPUT}) {
612 if (/^\#/) {
613 # Linemarker format is described at
614 # http://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html
615 if (s/^\# (\d+) \"(.*?)\"(( \d+){1,4}|)//) {
616 $parser->YYData->{LINE} = $1-1;
617 $parser->YYData->{FILE} = $2;
618 goto again;
619 }
620 if (s/^\#line (\d+) \"(.*?)\"( \d+|)//) {
621 $parser->YYData->{LINE} = $1-1;
622 $parser->YYData->{FILE} = $2;
623 goto again;
624 }
625 if (s/^(\#.*)$//m) {
626 goto again;
627 }
628 }
629 if (s/^(\n)//) {
630 $parser->YYData->{LINE}++;
631 goto again;
632 }
633 if (s/^\"(.*?)\"//) {
634 $parser->YYData->{LAST_TOKEN} = $1;
635 return('TEXT',$1);
636 }
637 if (s/^(\d+)(\W|$)/$2/) {
638 $parser->YYData->{LAST_TOKEN} = $1;
639 return('CONSTANT',$1);
640 }
641 if (s/^([\w_]+)//) {
642 $parser->YYData->{LAST_TOKEN} = $1;
643 if ($1 =~
644 /^(coclass|interface|import|importlib
645 |include|cpp_quote|typedef
646 |union|struct|enum|bitmap|pipe
647 |void|const|unsigned|signed)$/x) {
648 return $1;
649 }
650 return('IDENTIFIER',$1);
651 }
652 if (s/^(.)//s) {
653 $parser->YYData->{LAST_TOKEN} = $1;
654 return($1,$1);
655 }
656 }
657 }
658  
659 sub parse_string
660 {
661 my ($data,$filename) = @_;
662  
663 my $self = new Parse::Pidl::IDL;
664  
665 $self->YYData->{FILE} = $filename;
666 $self->YYData->{INPUT} = $data;
667 $self->YYData->{LINE} = 0;
668 $self->YYData->{LAST_TOKEN} = "NONE";
669  
670 my $idl = $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error );
671  
672 return CleanData($idl);
673 }
674  
675 sub parse_file($$)
676 {
677 my ($filename,$incdirs) = @_;
678  
679 my $saved_delim = $/;
680 undef $/;
681 my $cpp = $ENV{CPP};
682 my $options = "";
683 if (! defined $cpp) {
684 if (defined $ENV{CC}) {
685 $cpp = "$ENV{CC}";
686 $options = "-E";
687 } else {
688 $cpp = "cpp";
689 }
690 }
691 my $includes = join('',map { " -I$_" } @$incdirs);
692 my $data = `$cpp $options -D__PIDL__$includes -xc "$filename"`;
693 $/ = $saved_delim;
694  
695 return parse_string($data, $filename);
696 }