5 # Please find extensive documentation of this program at
6 # <http://os.inf.tu-dresden.de/~hohmuth/prj/preprocess/>
9 # Things this script does:
11 # - Expand class declarations as necessary using member-function
12 # definitions found in the file. Function labelled PUBLIC,
13 # PROTECTED and PRIVATE are put into the corresponding section of
16 # - Put "INTERFACE:" regions in public header file.
18 # - Put "inline" functions and all types they need into public header
21 # - Put all remaining, private types and their inline functions into a
22 # separate header file. This file can be used by a debugger
23 # interface to display the data.
25 # - Place include directives to top of public header file and private
38 sub print_funcdecl($);
40 sub print_classdecl($);
42 sub func_prototype($);
48 our $opt_c = ''; # Base name for generated include directives
49 our $opt_o = ''; # Base name of output files (defaults to -c,
51 our $opt_p = ''; # Prepend to base name of output files (-c)
52 our $opt_h = ''; # Name of public header; overrides -c
53 our $opt_i = 0; # Doing inlines?
54 our $opt_v = 0; # Verboseness?
55 our $opt_l = 0; # Avoid generating #line directives?
56 our $opt_L = 0; # Avoid generatung #line dirs in headers only?
57 # Support for new style FIASCO config
58 our $opt_e = ''; # List of part tags
60 our $opt_d = 0; # verbose drop
62 our $opt_w = 0; # warn if no inline code for needs is found
64 # Added 2003.01.12 by RCB
65 # Support for changing the names of headers
66 our $opt_H = "h"; # Default extenstion for header files
67 our $opt_C = "cc"; # Default extention for source files
70 getopts('e:o:c:p:h:H:C:ivlLsdwt');
75 C and C++ preprocessor (c) by Michael Hohmuth
76 Usage: preprocess [-dilLstvw] -c <base_name> [-C <source_ext>]
77 [-e <tag_list>] [-h <head_name>] [-H <head_ext>]
78 [-o <source_base>] [-p <prefix>] <files>
80 -c <base_name> Base name for generated include directives, generated
81 header files, and generated source files.
82 -C <source_ext> File extension for generated source files (default 'cc').
83 -d Verbose drop sections (only in conjunction with -e).
84 -e <tag_list> Use explicit section selection, and set the given tag
85 list. <tag_list> is a qouted and space separated list of
86 tags that should be enabled. (Useful in conjunction
88 -h <head_name> Name of generated public header (overrides -c)
89 -H <head_ext> File extension for generated header files (default 'h').
90 -i Do inlines, make inline functions real inline.
91 -l Avoid generating #line directives.
92 -L Avoid generating #line directives in headers only.
93 -o <src_base> Base name for generated source files (defaults to -c, and
95 -p Prefix for names of output files.
96 -s Generate a single source file per .cpp file (not a file
98 -t Truncate empty implementation files to zero length (so
99 that even the includ directives are ommitted)
100 -v Be verbose (very).
108 die "Need to specify option -c Classfile_basename;";
111 my $incfile_base = $opt_c;
112 my $public_base = (($opt_h eq '') ? $incfile_base : $opt_h);
115 my $doing_inlines = $opt_i;
116 my $verbose = $opt_v;
117 my $doing_linenumbers = (! $opt_l) && (! $opt_L);
118 my $wno_inline = $opt_w;
122 my %parts = ( '{' => '(',
136 foreach my $p (split(' ',$opt_e))
142 # Added 2003.01.12 by RCB
143 # Support for changing the names of headers
144 my $source_ext = $opt_C;
145 my $header_ext = $opt_H;
149 $outfile_base = $opt_p . $incfile_base;
150 $headerfile_base = $opt_p . $public_base;
154 $outfile_base = $opt_o;
155 $headerfile_base = $outfile_base;
159 # Variable initializations
163 our $print_indent = 0;
171 my %public_inline = ();
172 my %private_inline = ();
173 my %unit_inline = ();
174 my @inline_order_public = ();
175 my @inline_order_private = ();
176 my @inline_order_unit = ();
188 # Fixup incfile_base preproc macro if it contains invalid chars.
189 my $incfile_base_macro;
191 $incfile_base_macro = $incfile_base;
192 $incfile_base_macro =~ s/[+-]/_/g;
194 open(OUT, ">${headerfile_base}.$header_ext")
195 || die "Cannot open ${headerfile_base}.$header_ext for writing!";
196 print OUT "// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*-\n\n";
197 print OUT "#ifndef ${incfile_base_macro}_$header_ext\n" .
198 "#define ${incfile_base_macro}_$header_ext\n";
200 foreach my $i (grep {$_->{type} eq 'include'} @{$sections{"INTERFACE"}})
207 "// INTERFACE definition follows \n" .
210 foreach my $i ( (grep {$_->{type} eq 'classdef'
211 && $_->{syntax} eq 'forwarddecl'}
212 @{$sections{"INTERFACE"}}),
213 (grep {$_->{type} ne 'classdef' || $_->{syntax} ne 'forwarddecl'}
214 @{$sections{"INTERFACE"}}) )
216 if ($i->{type} eq 'code')
220 elsif ($i->{type} eq 'classdef')
222 print_classdecl ($i);
226 foreach my $i (grep {$_->{type} eq 'function' && $_->{class} eq ''
228 @{$sections{"IMPLEMENTATION"}})
233 my @public_templates = grep
235 $_->{type} eq 'function' && $_->{template} ne '' # template func
236 && $_->{fully_specialized_template} eq ''
237 && ! defined $public_inline{$_} # not public inline -- handled elsewhere
238 && ($_->{visibility} eq "free" # free func
239 || ($_->{class} ne '' # or member func of public or published class
240 && ($classes{$_->{class}}->{section} eq 'INTERFACE'
241 || defined $public_inline{$classes{$_->{class}}})))
243 @{$sections{"IMPLEMENTATION"}};
245 my $impl_includes_imported = 0;
247 if (scalar keys %public_inline || scalar @public_templates)
249 if (scalar @public_templates)
251 $impl_includes_imported = 1;
258 "// IMPLEMENTATION includes follow " .
259 "(for use by inline functions/templates)\n" .
262 foreach my $i (grep { $_->{type} eq 'include'
263 && ($impl_includes_imported || $_->{inline}) }
264 @{$sections{"IMPLEMENTATION"}})
273 "// IMPLEMENTATION of inline functions (and needed classes)\n" .
276 print_inlines (@inline_order_public);
282 "// IMPLEMENTATION of function templates\n" .
284 foreach my $i (@public_templates)
291 print OUT "\n#endif // ${incfile_base_macro}_$header_ext\n";
295 # Print "internal data structures" header file
298 open(OUT, ">${outfile_base}_i.$header_ext")
299 || die "Cannot open ${outfile_base}_i.$header_ext for writing!";
300 print OUT "// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*-\n\n";
301 print OUT "#ifndef ${incfile_base_macro}_i_$header_ext\n" .
302 "#define ${incfile_base_macro}_i_$header_ext\n";
304 foreach my $i (grep { $_->{type} eq 'include' }
305 @{$sections{"IMPLEMENTATION"}})
311 ( (grep {$_->{type} eq 'classdef' && $_->{syntax} eq 'forwarddecl'}
312 @{$sections{"IMPLEMENTATION"}}), # first all forward declarations,
313 (grep {$_->{type} eq 'classdef' && $_->{syntax} ne 'forwarddecl'}
314 @{$sections{"IMPLEMENTATION"}}) ) # then all other class / type decls
316 print_classdecl ($i);
320 # XXX should we print #defines here?
324 "// IMPLEMENTATION of inline functions follows\n".
326 print_inlines (@inline_order_private);
331 "// IMPLEMENTATION of function templates\n" .
335 $_->{type} eq 'function' && $_->{template} ne ''
336 && $_->{fully_specialized_template} eq ''
337 && ! defined $public_inline{$_}
338 && ! defined $private_inline{$_}
339 && ($_->{visibility} eq 'static'
340 || ($_->{class} ne ''
341 && ($classes{$_->{class}}->{section} ne 'INTERFACE' &&
342 !defined $public_inline{$classes{$_->{class}}})))
343 } @{$sections{"IMPLEMENTATION"}})
350 print OUT "\n#endif // ${incfile_base_macro}_i_$header_ext\n";
353 $doing_linenumbers = (! $opt_l);
356 # Print implementation file(s)
359 foreach my $part (keys %impl_parts)
361 my $filename = $outfile_base.($part eq '' ? '' : ('-' . $part)) . ".$source_ext";
363 #print "==> $filename\n";
364 open(OUT, ">$filename") || die "Could not open $filename for writing!";
365 print OUT "// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*-\n\n";
366 print OUT "#include \"${public_base}.$header_ext\"\n" .
367 "#include \"${incfile_base}_i.$header_ext\"\n\n";
369 foreach my $i (grep {$_->{type} eq 'function' && $_->{class} eq ''
371 grep {$_->{part_ext} eq $part} @{$sections{"IMPLEMENTATION"}})
376 # Print unparsed code first -- make private inline functions see
379 foreach my $i (grep {$_->{part_ext} eq $part
380 && $_->{type} eq 'code'}
381 @{$sections{"IMPLEMENTATION"}})
387 print_inlines (grep {$_->{part_ext} eq $part} @inline_order_unit);
389 foreach my $i (grep {$_->{part_ext} eq $part
390 && $_->{type} eq 'function'}
391 @{$sections{"IMPLEMENTATION"}})
393 next if $i->{template} ne ''
394 && $i->{fully_specialized_template} eq '';
400 truncate OUT,0 if $empty && $opt_t;
407 #############################################################################
413 my $s_once; # Regexp for whitespace; the \001 stuff is for comments
414 my $s; # Zero or more whitespace
415 my $identifier; # Identifier
416 my $operator_name; # Operator name
420 my $template; # Template declaration tag
421 my $template_arg; # Template argument list
423 my $lineno; # current line to be parsed
424 my $blockfile; # file that contains the currently pares block
425 my $blockstart; # first line of the current block
426 my $current_section; # current section
428 my $current_part_ext;
429 my @ifstack; # stack of #if clauses
432 sub parse_init # Initialize parser variables.
434 # Regexp for whitespace; the \001 stuff is for comments
435 $s_once = '(?:[\n\s]|\001[0-9]+\001)';
437 # Zero or more whitespace
441 $identifier = "(?:[A-Za-z_][A-Za-z_0-9]*)";
444 $operator_name = "(?:operator$s(?:"
445 .'(?:[~,]|[+\-*/%^&|!=<>]=?|[<>]{2}=?|[&|+\-]{2}|->\*?'
446 .'|\(\)|(?:new|delete)?'.$s.'\[\])'."|$identifier))";
452 (?> [^()]+ ) # Non-parens without backtracking
454 (??{ $paren_group }) # Group with matching parens
459 $paren_expr = qr{ (?> $paren_group | [^()]+ )* }x;
461 # Template argument list -- similar to paren_group above
462 $tparen_group = qr { < (?: (?> [^<>]+ ) | (??{ $tparen_group }) )* > }x;
464 # Template argument list
465 $template_arg = qr{ (?> $tparen_group) }x;
467 # Template declaration tag
468 $template = qr{template$s$template_arg$s};
477 my $t = '\(\)&|,\{\}!-';
480 while ($tag =~ /^\s*([$t]|(?:[^\s$t]+))\s*(.*?)$/)
483 $cp .= defined $r ? $r : 0;
487 my $match = eval $cp;
488 #print "TAG: $tag -> $cp = $match\n";
491 die "${ARGV}:$lineno: error: syntax error in tag '$tag'\n";
494 if (($verbose || $opt_d) && (!defined $match || !$match))
496 print "Drop SECTION: [$orig_tag] from".
508 $current_section = "IMPLEMENTATION";
510 my $skip_to_next_section = 0;
515 #print "PARSED: $_\n";
517 $blockstart = $lineno + 1;
528 if (/^$s\/\/-[\s\n]*$/s)
530 handle_source_code ();
537 (?:$s \[ $s ([A-Za-z0-9_,\{\}!\s&|\(\)-]+) $s \] $s)? : )
540 check_empty_ifstack();
541 $skip_to_next_section = 0;
542 $current_section = $2;
543 if ($opt_e ne '' || $current_section eq "IMPLEMENTATION")
550 $skip_to_next_section = !match_e_opt($current_part);
551 next NEXTLINE if $skip_to_next_section;
561 if (defined $3 && $opt_h ne $3)
563 die "${ARGV}:${lineno}: all INTERFACE arguments and "
564 . "option -h must be consistent;"
571 $headerfile_base = $opt_p . $public_base
575 handle_source_code ();
578 elsif ($skip_to_next_section)
583 # Preprocessor directive?
588 last NEXTLINE if ! read_more();
595 next NEXTLINE if ignoring();
597 # Read until we can decide what we have: Read till next block end
603 do {} while ($foo =~ s/\{[^\{\}]*\}//sg); # kill blocks
606 #print "MORE: $foo\n";
607 next MORE; # Still unfinished blocks.
610 elsif (! /;/) # no unclosed blocks & semicolon?
616 if (/^$s(?:$template)?(enum|struct|class|typedef)/s)
620 if (/^$s(?:$template)?
621 (?:enum|struct|class)
622 $s ($identifier (?:$s $template_arg)?)
625 # Have a block -> this is a definition.
631 my $class = { name => $name,
635 #print "CLASS " . $class->{name} . ">" .$class->{pretext} . "###" . $class->{posttext};
636 handle_classdef ($class);
641 # No block or no name -- handle as declaration.
642 if (/^$s(?:$template)?(?:enum|struct|class)$s\{/s)
644 # no name but block -- make this a global variable decl.
645 handle_source_code ();
647 elsif (/^$s(?:$template)?(?:enum|struct|class)/s)
649 # no block -- this seems to be a forward
650 # decl. or a variable decl.
652 if (/^$s(?:$template)?(?:enum|struct|class)$s
653 ($identifier) $s ;/sx)
655 my $class = { syntax => 'forwarddecl',
657 handle_classdef ($class);
661 handle_source_code ();
664 elsif (/^${s} typedef \b /sx) # It's a typedef
666 # strip off function args and array spec
669 $l =~ s/\([^\)]*\) (?:${s}const)? $s $//sx;
670 $l =~ s/(?: \[ [^\[]* \] $s | \) $s )+ $//sx;
671 $l =~ m/($identifier) $s $/sx;
673 my $class = { syntax => 'typedef',
675 handle_classdef ($class);
679 die "${ARGV}:$lineno: Parse error";
686 # Type declaration extension?
687 if (/^$s EXTENSION $s (?:struct|class) $s ($identifier)
688 $s (?::(?!:) $s ([^\{]*))?\{ (.*) \} $s ; $s $/sx)
694 if (! exists $classes{$name})
696 die "${ARGV}:$lineno: Class extension for undefined class " .
700 # XXX XXX we should not handle line directives here --
701 # this is the job of the output functions. However, as
702 # we don't generate a new codechunk for this extension,
703 # we just add the extension's line number here.
705 if ($doing_linenumbers)
707 $classes{$name}->{pretext} .=
708 "\n#line " . $blockstart . " \"" . $ARGV . "\"\n";
711 my $txt = \($classes{$name}->{pretext});
715 if ($$txt =~ /^([^\{]*)/sx)
718 if ($pre =~ /^.*:(?!:)(.*)$/sx)
720 $$txt =~ s/^$pre/$pre\n, $super/s;
721 # print "ADD super classes: , $super\n";
725 $$txt =~ s/^$pre/$pre\n: $super/s;
730 $classes{$name}->{pretext} .= "private:\n" . $string;
735 # Member function definition?
736 if (/^([^\{\(]*?) # pretext, maybe w template decl tag
737 \b ($identifier (?: $s :: $s $identifier)*) # class name
738 ($s $template_arg)? # optional class-template args
740 ((?:$operator_name | (?: ~? $identifier )) # member name
741 (?:$s $template_arg)?) # optional member-template args
742 $s ( \( (?: [^\)] | \([^\)]*\) )* \) [^:\{=]* ) # arg list
743 ((?:\{|:.*\{).* | (?:$s = $s 0 $s ;))$/sx) # initializer ':' and body '{' or pure virtual
745 my ($pretext, $class, $templateargs, $name, $args, $posttext)
746 = ($1, $2, (defined $3 ? $3 : ''), $4, $5, $6);
747 #print "P<$pretext> C<$class> T<$templateargs> N<$name> A<$args> P<$posttext>\n";
748 # Canonify operator names
749 $name =~ s/(?<=\w)(?:$s_once)+(?=\W)//gs;
750 $name =~ s/(?<=\W)(?:$s_once)+(?=\w)//gs;
751 $name =~ s/(?:$s_once)+/ /gs;
752 # Canonify class name
754 my $memberfunction = { class => $class,
756 templateargs => $templateargs,
759 posttext => $posttext };
760 handle_function ($memberfunction);
764 # Free function definition?
765 if (/^([^\{]*) # pretext, maybe w template decl tag
766 \b ($operator_name | $identifier) # function name
767 ($s $template_arg)? # optional template args
768 $s( \( $paren_expr \) [^:\{\(\)=]*) # arg list
771 my $function = { class => '',
773 templateargs => (defined $3
778 handle_function ($function);
782 handle_source_code ();
789 $verbose && print "EOF: " . $_ . "\n";
790 die "${blockfile}:$blockstart: Unexpected end of file in block starting here;";
795 sub read_more () # Read one more line of code. Stow away
796 # comments and character constants
798 # Get a line without comments.
801 if (eof(INPUT)) # Reset line numbering.
803 check_empty_ifstack();
808 return 0 unless $file = shift @ARGV;
810 open(INPUT, $ARGV) || die "Cannot open $ARGV for reading!";
813 # print "FILE: $ARGV\n";
815 if ($ARGV =~ /^(?:.*\/)?(.+)$/ && $1 =~ /(?:[^-]*)-(.*)\..*/)
819 $current_part_ext = $part_ext;
820 $impl_parts{$part_ext} = 1;
821 # print "PART: '$part_ext'\n";
823 print "read file: '$ARGV'\n" if $verbose;
839 # Save comments and strings in @comments array. Save strings
840 # first to catch strings with comment-like contents.
841 my $number = @comments;
843 # We don't touch strings in NEEDS[], neither #includes! Save now --
846 if (s/(^$s \# $s include.*$
847 | NEEDS $s \[[^\]]* )
853 while (s,(\'(?:\\.|[^\']|\\[0-7]+)\'),\002$number\002,s)
859 # while (s,(\"(?:[^\"]|(?<=\\)\")*\"),\002$number\002,s)
860 while (s,(\"(?:[^\\\"]|\\.)*\"),\002$number\002,s)
871 while (s|(//(?!-\s*\n).*)$|\001$number\001|m) # Do not match magic "//-"
872 { # The \001 signifies whitespace.
877 while (s|(/\*.*\*/)|\001$number\001|s)
894 my ($codechunk,$type) = @_;
896 $codechunk->{type} = $type;
897 $codechunk->{section} = $current_section;
898 $codechunk->{string} = $_;
899 $codechunk->{part} = $current_part;
900 $codechunk->{part_ext} = $opt_s ? $current_part_ext : $current_part;
902 $impl_parts{$current_part} = 1 unless $opt_s;
904 $codechunk->{line} = $blockstart;
905 $codechunk->{file} = $ARGV;
906 $codechunk->{printed} = 0;
908 push @{$sections{$current_section}}, $codechunk;
913 foreach my $i (@ifstack)
915 if ($i->{value} == 1)
926 # if ($codeblock->{string} =~ /^$s\#\s*(if|endif|else|elif)/)
928 # die "${ARGV}:${lineno}: Conditional compilation not supported;";
931 if (/^$s\#\s*if\s+0${s}$/)
933 push @ifstack, { value => 1, file => ${ARGV}, line => $lineno };
934 $verbose && print "IF 0: " . ignoring() . "\n";
937 elsif (@ifstack && /^$s\#\s*if(def|ndef)?\s/)
939 push @ifstack, { value => 0, file => ${ARGV}, line => $lineno };
940 $verbose && print "IF: " . ignoring() . "\n";
941 return if ignoring();
943 elsif (@ifstack && /^$s\#\s*(else|elif)/)
945 my $ignoring = ignoring();
946 my $i = pop @ifstack;
947 $i->{value} = -$i->{value};
949 $verbose && print "ELSE/ELIF: " . ignoring() . " ($ignoring)\n";
952 elsif (@ifstack && /^$s\#\s*endif/)
954 my $ignoring = pop @ifstack;
955 $verbose && print "ENDIF: " . ignoring() . "\n";
956 return if ignoring() || $ignoring->{value};
958 elsif (/^$s\#\s*include${s}([\"<][^\">]+[\">])/)
961 $codeblock->{name} = $1;
962 $codeblock->{inline} = 0;
964 $includes{$codeblock->{name}} = $codeblock;
966 label_chunk ($codeblock, "include");
968 $verbose && print "INCLUDE: " . $codeblock->{name} . "\n";
972 # XXX: For now, treat preprocessor stuff besides #include, #if 0 as code.
973 handle_source_code ();
979 foreach my $i (@ifstack)
981 print "$indent$i->{value}: $i->{file}:$i->{line}\n";
986 sub check_empty_ifstack
990 my $i = pop @ifstack;
991 print STDERR "${ARGV}:${lineno}: missing endif for $i->{file}:$i->{line}\n";
997 sub handle_source_code
999 return if /^[\s\n]*$/;
1002 label_chunk ($codeblock, "code");
1004 $verbose && print "UNKNOWN: " . $codeblock->{string};
1010 label_chunk ($class, "classdef");
1012 $class->{funcs} = [];
1014 if ($class->{syntax} ne 'forwarddecl')
1016 $classes{$class->{name}} = $class;
1019 $verbose && print "CLASSDEF: " . $class->{name} . " ["
1020 . $class->{syntax} . "]\n";
1027 $func->{purevirtual} = 0;
1029 if ($func->{class} ne '')
1031 # Nested class hacks
1032 if ($func->{class} =~ /::/
1033 && ! defined $classes{$func->{class}})
1035 # Define class along the way -- the dirty way.
1036 my $class = { name => $func->{class},
1038 nested_class => 1 };
1039 my ($topclass, $rest) = split (/::/, $func->{class});
1040 my $save_sec = $current_section;
1041 $current_section = $classes{$topclass}->{section};
1042 handle_classdef ($class);
1043 $current_section = $save_sec;
1046 $func->{visibility} = "private";
1047 if (s/^($s)PRIVATE([\s\n])/$1$2/s)
1049 $func->{visibility} = "private";
1050 $func->{pretext} =~ s|PRIVATE[ \t]*||s;
1052 elsif (s/^($s)PUBLIC([\s\n])/$1$2/s)
1054 $func->{visibility} = "public";
1055 $func->{pretext} =~ s|PUBLIC[ \t]*||s;
1057 elsif (s/^($s)PROTECTED([\s\n])/$1$2/s)
1059 $func->{visibility} = "protected";
1060 $func->{pretext} =~ s|PROTECTED[ \t]*||s;
1062 elsif (s/^($s)IMPLEMENT([\s\n])/$1$2/s)
1064 # Use a visibility attribute that is never used in adding
1065 # declarations to classes in print_classdecl.
1066 $func->{visibility} = "implementation_only";
1067 $func->{pretext} =~ s|IMPLEMENT[ \t]*||s;
1070 if ($func->{posttext} =~ s/$s=${s}0$s;$s$//s)
1072 $func->{purevirtual} = 1;
1075 if ($func->{class} =~ /::/
1076 && $func->{visibility} ne "implementation_only")
1078 die "${ARGV}:${lineno}: Limitation: Only predeclared members " .
1079 "supported for nested classes. Use IMPLEMENT;";
1082 if (! defined $classes{$func->{class}})
1084 die "${ARGV}:${lineno}: Class " . $func->{class}
1085 . " has not been declared;";
1090 $func->{visibility} = "free";
1093 # Interprete more type attributes.
1094 $func->{inline} = 0;
1095 $func->{always_inline} = 0;
1096 $func->{static} = 0;
1098 $func->{virtual} = 0;
1099 $func->{explicit} = 0;
1100 $func->{classtemplate} = '';
1101 $func->{funtemplate} = '';
1102 $func->{template} = '';
1103 $func->{fully_specialized_template} = '';
1106 if (s/^($s)((?:$template)+)([\s\n])/$1$3/s)
1109 my @specs = split(/(?<= \>)(?= $s template)/sx, $match, 3);
1111 if ($func->{class} eq '') # Free function?
1113 $func->{funtemplate} = shift @specs;
1117 my $class = $classes{$func->{class}};
1118 my $istemplateclass = ($class->{pretext} =~ /^[^\{]*template/s);
1120 if ($istemplateclass)
1122 $func->{classtemplate} = shift @specs;
1123 $func->{funtemplate} = shift @specs if scalar @specs;
1125 else # Not a class template
1127 $func->{funtemplate} = shift @specs;
1131 die "${ARGV}:$lineno: Too many template specs"
1134 $func->{template} = 'yes';
1135 $func->{fully_specialized_template} = 'yes'
1136 if ($match =~ /^(?:${s}template$s<${s}>)+${s}$/s);
1138 $func->{pretext} =~ s/\Q$match//s;
1139 # $func->{pretext} =~ s|$template[ \t]*||s;
1143 if (s/^($s)inline([\s\n])/$1$2/si) # "inline" is case-insensitive.
1145 $func->{inline} = 1 if $doing_inlines
1146 || $func->{fully_specialized_template} ne '';
1147 $func->{pretext} =~ s|inline[ \t]*||si;
1148 @{$func->{needs}} = ();
1151 if (s/^($s)NEEDS\s*\[([^\]]+)\]([\s\n])/$1$3/s)
1153 @{$func->{needs}} = split (/\s*,\s*/, $2);
1154 # Delete NEEDS directive, but keep newlines
1155 while ($func->{pretext} =~
1156 s|NEEDS \s* \[ ( (?:[^\n\]]*\n)* )
1159 |NEEDS[$1\n$2\]|sx) {}
1160 $func->{pretext} =~ s|NEEDS\s*\[ (\n*) [^\n\]]*\]|$1|sx;
1163 if (s/^($s)NOEXPORT([\s\n])/$1$2/si)
1166 $func->{pretext} =~ s|NOEXPORT[ \t]*||s;
1169 if (s/^($s)ALWAYS_INLINE([\s\n])/$1$2/si)
1171 $func->{inline} = 1;
1172 $func->{always_inline} = 1;
1173 $func->{pretext} =~ s|ALWAYS_INLINE[ \t]*||s;
1179 # Reset inline data if inline handling was not enabled by -i
1181 if (! $func->{inline})
1183 undef $func->{needs};
1189 if (s/^($s)static([\s\n])/$1$2/s)
1191 $func->{static} = 1;
1192 $func->{pretext} =~ s/static[ \t]*//s;
1194 if ($func->{class} eq '')
1196 $func->{visibility} = "static";
1203 if (s/^($s)IMPLEMENT([\s\n])/$1$2/s)
1205 $func->{pretext} =~ s/IMPLEMENT[ \t]*//s;
1207 if ($func->{class} eq '')
1209 $func->{visibility} = "implementation_only";
1215 if (s/^($s)explicit([\s\n])/$1$2/s)
1217 $func->{explicit} = 1;
1218 $func->{pretext} =~ s|explicit[ \t]*||s;
1222 if (s/^($s)virtual([\s\n])/$1$2/s)
1224 $func->{virtual} = 1;
1225 $func->{pretext} =~ s|virtual[ \t]*||s;
1229 if (/^($s)(PRIVATE|PUBLIC|PROTECTED)([\s\n])/)
1231 die "${blockfile}:$blockstart: only one visibility attribute allowed at start of declaration;";
1237 label_chunk ($func, "function");
1239 if ($current_section eq 'INTERFACE')
1241 die "${ARGV}:${lineno}: Function " . $func->{name}
1242 . " in INTERFACE section;";
1245 push @{$classes{$func->{class}}->{funcs}}, $func;
1247 $verbose && print "FUNC: " . ($func->{class} ne ''
1248 ? ($func->{class} . "::")
1251 . ($func->{classtemplate} ne ''
1252 ? " T: " . $func->{classtemplate} : "")
1253 . ($func->{funtemplate} ne ''
1254 ? " M: " . $func->{funtemplate} : "")
1255 . ($func->{fully_specialized_template} ne ''
1256 ? " FULLY_SPEC" : "")
1260 #############################################################################
1269 sub print_head # Save header. Print it only if a
1270 # print_expand() follows
1272 $saved_head .= $_[0];
1273 $saved_indent = $print_indent;
1281 sub print_expand($) # Expands comments and prints to OUT.
1285 if ($saved_head ne '')
1287 local $print_indent = $saved_indent;
1288 my $str = $saved_head;
1291 print_expand $str; # Recurse.
1294 $str =~ s/\n(?:[ \t]*\n)+/\n\n/sg if ! $doing_linenumbers;
1296 while ( $str =~ s/([\001\002])([0-9]+)\1/$comments[$2]/sg )
1301 my $istr = " " x $print_indent;
1302 $str =~ s/^/$istr/mg;
1310 return if ! $doing_linenumbers;
1314 print_expand ''; # print headers we accumulated
1315 print OUT "#line " . $object->{line} . " \"" . $object->{file} . "\"\n";
1318 sub print_lineno_sans_empty_lines($)
1320 return if ! $doing_linenumbers;
1324 my $start_of_code = $object->{string};
1325 $start_of_code =~ s/^([\s\n]+).*$/$1/s;
1327 my @startcomments = split /\n/, " $start_of_code ";
1329 print OUT "#line " . ($object->{line} + @startcomments - 1)
1330 . " \"" . $object->{file} . "\"\n";
1333 sub weedout_whitespace # Delete whitespace except on lines w/comments
1337 $str =~ s/^[\s\n]+//s;
1339 if (! $doing_linenumbers) # more cosmetic changes if we do not
1340 { # have to be correct line-number-wise
1341 my @lines = split /\n/, $str;
1345 foreach my $line (@lines)
1350 if ($line =~ /\001/ || $line =~ /^\s*$/)
1360 # Found something like code: Remove trailing whitespace
1363 $str .= "\n" if $str ne '';
1378 sub func_prototype($) # Return a function declaration from
1382 my $pretext = $func->{pretext};
1384 if ($func->{inline})
1386 $pretext =~ s/^($s)/${1}inline /s;
1389 if ($func->{explicit})
1391 $pretext =~ s/^($s)/${1}explicit /s;
1394 if ($func->{static})
1396 $pretext =~ s/^($s)/${1}static /s;
1399 if ($func->{virtual})
1401 $pretext =~ s/^($s)/${1}virtual /s;
1404 if ($func->{funtemplate} ne '')
1406 $pretext =~ s/^($s)/${1}$func->{funtemplate} /s;
1409 my $func_header = weedout_whitespace($pretext .
1410 $func->{name} . $func->{args});
1412 # Insert ; at the correct place, that is, before any comments.
1413 my $e = $func->{purevirtual} ? ' = 0' : '';
1414 $func_header =~ s/($s)$/$e;$1/s;
1416 return $func_header;
1419 sub print_funcdecl($)
1421 my $function = $_[0];
1423 if ($function->{visibility} ne "implementation_only")
1426 print_lineno_sans_empty_lines $function;
1427 print_expand func_prototype($function) . "\n";
1431 if ($function->{inline})
1433 handle_inline ($function);
1437 sub print_classdecl($)
1440 return if check_if_printed ($class);
1442 print_lineno $class;
1444 if (defined $class->{nested_class})
1446 # (This will not actually print anything, but do other processing.)
1447 foreach my $function (@{$class->{funcs}})
1450 if $function->{visibility} ne "implementation_only";
1451 print_funcdecl $function;
1454 elsif ($class->{syntax} =~ /^(?:struct|class)$/)
1456 if (! $doing_inlines)
1458 $class->{pretext} =~ s/\binline\b[ \t]*//g;
1461 print_expand $class->{pretext};
1463 print_head "\npublic:";
1465 foreach my $function (grep {$_->{visibility} eq "public"}
1468 print_funcdecl $function;
1472 print_head "\nprotected:";
1474 foreach my $function (grep {$_->{visibility} eq "protected"}
1477 print_funcdecl $function;
1481 print_head "\nprivate:";
1483 foreach my $function (grep {$_->{visibility} eq "private"}
1486 print_funcdecl $function;
1491 # Also, don't forget to "print" already-declared functions.
1492 # (This will not actually print anything, but do other processing.)
1493 foreach my $function (grep {$_->{visibility} eq "implementation_only"}
1496 print_funcdecl $function;
1499 print_expand $class->{posttext};
1503 print_expand $class->{string};
1508 sub print_funcdef($)
1510 my $function = $_[0];
1511 return if $function->{purevirtual};
1512 return if check_if_printed ($function);
1514 my $pretext = $function->{pretext};
1516 if ($function->{inline})
1518 if ($function->{always_inline})
1520 $pretext =~ s/^($s)/${1}ALWAYS_INLINE /s;
1522 $pretext =~ s/^($s)/${1}inline /s;
1525 if ($function->{static} && $function->{class} eq '')
1527 $pretext =~ s/^($s)/${1}static /s;
1530 if ($function->{funtemplate} ne '')
1532 $pretext =~ s/^($s)/${1}$function->{funtemplate} /s;
1535 if ($function->{classtemplate} ne '')
1537 $pretext =~ s/^($s)/${1}$function->{classtemplate} /s;
1540 # Remove default arguments from argument list
1541 my $args = $function->{args};
1542 $parengroup = qr{ # Matches correctly-nested groups of parens
1545 (?> [^()]* ) # Non-parens without backtracking
1547 (??{ $parengroup }) # Backtrack: Group with parens
1551 my $expr = qr{ [^(),]* (?:$parengroup)? [^(),]* }x;
1552 $args =~ s/$s = $expr//gx;
1555 print_lineno $function;
1556 print_expand $pretext
1557 . ($function->{class} ne ''
1558 ? $function->{class} . $function->{templateargs}
1559 . "::" . $function->{name}
1560 : $function->{name} . $function->{templateargs})
1561 . $args . $function->{posttext};
1566 my $codeblock = $_[0];
1567 return if check_if_printed ($codeblock);
1568 print_lineno $codeblock;
1569 print_expand $codeblock->{string};
1572 sub check_if_printed
1574 my $codeblock = $_[0];
1575 return 1 if $codeblock->{printed};
1576 $codeblock->{printed} = 1;
1580 #############################################################################
1583 # Inline-function bookkeeping.
1586 sub lookup_by_name # Return (list of) item(s) matching name.
1588 my ($item, $context) = @_;
1590 # Is it a class name?
1591 if (defined $classes{$item})
1593 return $classes{$item};
1596 # Is it an include file?
1597 if (defined $includes{$item})
1599 $includes{$item}->{inline} = 1;
1600 return $includes{$item};
1603 # Must be a function name!
1604 my ($classname, $funcname);
1608 ($classname, $funcname) = split /::/, $item;
1612 ($classname, $funcname) = ('' , $item);
1615 my @grepresult = grep {$_->{name} eq $funcname && $_->{inline}}
1616 @{$classes{$classname}->{funcs}};
1618 return shift @grepresult
1619 if (scalar @grepresult == 1);
1621 if (scalar @grepresult == 0)
1623 my @xgrepresult = grep {$_->{name} eq $funcname}
1624 @{$classes{$classname}->{funcs}};
1625 die $context->{file} . ":" . $context->{line} . ": Cannot find $item;"
1626 if (scalar @xgrepresult == 0);
1627 $wno_inline && print STDERR $context->{file} . ":" . $context->{line} .
1628 ": warning: Cannot find inline code ".
1632 return @grepresult; # Return list of matching function names.
1635 # Check if Function $function can already see Object $item in its context.
1638 my ($item, $function) = @_;
1640 if ($item->{type} eq "function"
1642 && ! $function->{hide})
1644 die $function->{file} . ":" . $function->{line} .
1645 ": Nonhidden function " . funcname($function) .
1646 " depends on hidden function " . funcname($item) . " (" .
1647 ($item->{visibility} eq 'static' ? "static" : "NOEXPORT") . ")";
1650 return exists $public_inline{$item}
1651 || (($function->{visibility} eq 'private'
1652 || ($function->{class} ne ''
1653 && $classes{$function->{class}}->{section} eq "IMPLEMENTATION"))
1654 && exists $private_inline{$item})
1655 || ($function->{hide}
1656 && exists $unit_inline{$item});
1659 # Put inline function $1 and all its dependencies (given by NEEDS
1660 # directives) into @inline_order_[public/private/unit], depending on
1661 # visibility of $1. Function handle_inline is called when printing
1662 # inline-function declarations, so the sequence of handle_inline calls
1663 # is determined by declaration-printing order.
1666 my $function = $_[0];
1667 my $class = $function->{class};
1671 print "INLINE " . funcname($function) . " NEEDS ";
1673 # Add all needed items, then add my own name as well as my class
1674 # name for good measure.
1675 foreach my $item (@{$function->{needs}})
1677 push @needed, lookup_by_name ($item, $function);
1680 push @needed, $function;
1681 unshift @needed, lookup_by_name ($class, $function)
1687 my $object = $needed[0];
1689 if (inline_known ($object, $function))
1695 # Check for further dependencies.
1696 my @moreneeded = ();
1698 if ($object->{type} eq "function" && $object->{class} ne '')
1700 my $class = lookup_by_name ($object->{class}, $object);
1701 push @moreneeded, $class;
1704 if (defined $object->{needs})
1706 foreach my $item (@{$object->{needs}})
1708 my $o = lookup_by_name ($item, $object);
1709 next if ! ref $o; # Skip referenced but noninline objects
1710 push @moreneeded, $o;
1714 # Check if we have everything that's needed for $item.
1715 foreach my $i (@moreneeded)
1717 if (inline_known ($i, $function))
1722 if ($i == $function) # Function depends on itself!
1724 my $callstack = " " . funcname ($function) . "\n";;
1725 my $prev = $function;
1726 push @needed, $function;
1727 foreach my $j (@needed)
1729 # $j is not part of call stack if it does not need $prev
1730 next if ! grep {lookup_by_name ($_, $object) == $prev}
1732 $callstack .= " " . funcname ($j) . "\n";
1734 last if $j == $function;
1737 die $object->{file} . ":" . $object->{line} . ": Function " .
1738 funcname ($object) . " NEEDS " . funcname ($i) .
1739 ", which circularly depends on this function:\n" .
1743 unshift @needed, $i;
1747 $verbose && print &funcname ($object) . " ";
1749 if ($function->{hide})
1751 $unit_inline{$object} = 1;
1752 push @inline_order_unit, $object;
1754 elsif ($function->{visibility} eq 'private'
1756 && $classes{$class}->{section} eq "IMPLEMENTATION"))
1758 $private_inline{$object} = 1;
1759 push @inline_order_private, $object;
1763 $public_inline{$object} = 1;
1764 push @inline_order_public, $object;
1770 $verbose && print "\n";
1775 foreach my $object (grep {$_->{type} eq "classdef"} @_)
1777 if ($object->{section} ne 'INTERFACE')
1779 print_classdecl $object;
1783 foreach my $object (grep {$_->{type} eq "function"} @_)
1785 print_funcdef $object;
1789 ######################################################################
1795 my $function = $_[0];
1797 return ($function->{class} ? ($function->{class} . "::") : "")
1798 . $function->{name};