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;
172 my %public_inline = ();
173 my %private_inline = ();
174 my %unit_inline = ();
175 my @inline_order_public = ();
176 my @inline_order_private = ();
177 my @inline_order_unit = ();
189 # Fixup incfile_base preproc macro if it contains invalid chars.
190 my $incfile_base_macro;
192 $incfile_base_macro = $incfile_base;
193 $incfile_base_macro =~ s/[+-]/_/g;
195 open(OUT, ">${headerfile_base}.$header_ext")
196 || die "Cannot open ${headerfile_base}.$header_ext for writing!";
197 print OUT "// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*-\n\n";
198 print OUT "#ifndef ${incfile_base_macro}_$header_ext\n" .
199 "#define ${incfile_base_macro}_$header_ext\n";
201 foreach my $i (grep {$_->{type} eq 'include'} @{$sections{"INTERFACE"}})
208 "// INTERFACE definition follows \n" .
211 foreach my $i ( (grep {$_->{type} eq 'classdef'
212 && $_->{syntax} eq 'forwarddecl'}
213 @{$sections{"INTERFACE"}}),
214 (grep {$_->{type} ne 'classdef' || $_->{syntax} ne 'forwarddecl'}
215 @{$sections{"INTERFACE"}}) )
217 if ($i->{type} eq 'code')
221 elsif ($i->{type} eq 'classdef')
223 print_classdecl ($i);
227 foreach my $i (grep {$_->{type} eq 'function' && $_->{class} eq ''
229 @{$sections{"IMPLEMENTATION"}})
234 my @public_templates = grep
236 $_->{type} eq 'function' && $_->{template} ne '' # template func
237 && $_->{fully_specialized_template} eq ''
238 && ! defined $public_inline{$_} # not public inline -- handled elsewhere
239 && ($_->{visibility} eq "free" # free func
240 || ($_->{class} ne '' # or member func of public or published class
241 && ($classes{$_->{class}}->{section} eq 'INTERFACE'
242 || defined $public_inline{$classes{$_->{class}}})))
244 @{$sections{"IMPLEMENTATION"}};
246 my $impl_includes_imported = 0;
248 if (scalar keys %public_inline || scalar @public_templates)
250 if (scalar @public_templates)
252 $impl_includes_imported = 1;
259 "// IMPLEMENTATION includes follow " .
260 "(for use by inline functions/templates)\n" .
263 foreach my $i (grep { $_->{type} eq 'include'
264 && ($impl_includes_imported || $_->{inline}) }
265 @{$sections{"IMPLEMENTATION"}})
274 "// IMPLEMENTATION of inline functions (and needed classes)\n" .
277 print_inlines (@inline_order_public);
283 "// IMPLEMENTATION of function templates\n" .
285 foreach my $i (@public_templates)
292 print OUT "\n#endif // ${incfile_base_macro}_$header_ext\n";
296 # Print "internal data structures" header file
299 open(OUT, ">${outfile_base}_i.$header_ext")
300 || die "Cannot open ${outfile_base}_i.$header_ext for writing!";
301 print OUT "// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*-\n\n";
302 print OUT "#ifndef ${incfile_base_macro}_i_$header_ext\n" .
303 "#define ${incfile_base_macro}_i_$header_ext\n";
305 foreach my $i (grep { $_->{type} eq 'include' }
306 @{$sections{"IMPLEMENTATION"}})
312 ( (grep {$_->{type} eq 'classdef' && $_->{syntax} eq 'forwarddecl'}
313 @{$sections{"IMPLEMENTATION"}}), # first all forward declarations,
314 (grep {$_->{type} eq 'classdef' && $_->{syntax} ne 'forwarddecl'}
315 @{$sections{"IMPLEMENTATION"}}) ) # then all other class / type decls
317 print_classdecl ($i);
321 # XXX should we print #defines here?
325 "// IMPLEMENTATION of inline functions follows\n".
327 print_inlines (@inline_order_private);
332 "// IMPLEMENTATION of function templates\n" .
336 $_->{type} eq 'function' && $_->{template} ne ''
337 && $_->{fully_specialized_template} eq ''
338 && ! defined $public_inline{$_}
339 && ! defined $private_inline{$_}
340 && ($_->{visibility} eq 'static'
341 || ($_->{class} ne ''
342 && ($classes{$_->{class}}->{section} ne 'INTERFACE' &&
343 !defined $public_inline{$classes{$_->{class}}})))
344 } @{$sections{"IMPLEMENTATION"}})
351 print OUT "\n#endif // ${incfile_base_macro}_i_$header_ext\n";
354 $doing_linenumbers = (! $opt_l);
357 # Print implementation file(s)
360 foreach my $part (keys %impl_parts)
362 my $filename = $outfile_base.($part eq '' ? '' : ('-' . $part)) . ".$source_ext";
364 #print "==> $filename\n";
365 open(OUT, ">$filename") || die "Could not open $filename for writing!";
366 print OUT "// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*-\n\n";
367 print OUT "#include \"${public_base}.$header_ext\"\n" .
368 "#include \"${incfile_base}_i.$header_ext\"\n\n";
370 foreach my $i (grep {$_->{type} eq 'function' && $_->{class} eq ''
372 grep {$_->{part_ext} eq $part} @{$sections{"IMPLEMENTATION"}})
377 # Print unparsed code first -- make private inline functions see
380 foreach my $i (grep {$_->{part_ext} eq $part
381 && $_->{type} eq 'code'}
382 @{$sections{"IMPLEMENTATION"}})
388 print_inlines (grep {$_->{part_ext} eq $part} @inline_order_unit);
390 foreach my $i (grep {$_->{part_ext} eq $part
391 && $_->{type} eq 'function'}
392 @{$sections{"IMPLEMENTATION"}})
394 next if $i->{template} ne ''
395 && $i->{fully_specialized_template} eq '';
401 truncate OUT,0 if $empty && $opt_t;
408 #############################################################################
414 my $s_once; # Regexp for whitespace; the \001 stuff is for comments
415 my $s; # Zero or more whitespace
416 my $identifier; # Identifier
417 my $operator_name; # Operator name
421 my $template; # Template declaration tag
422 my $template_arg; # Template argument list
424 my $lineno; # current line to be parsed
425 my $blockfile; # file that contains the currently pares block
426 my $blockstart; # first line of the current block
427 my $current_section; # current section
429 my $current_part_ext;
430 my @ifstack; # stack of #if clauses
433 sub parse_init # Initialize parser variables.
435 # Regexp for whitespace; the \001 stuff is for comments
436 $s_once = '(?:[\n\s]|\001[0-9]+\001)';
438 # Zero or more whitespace
442 $identifier = "(?:[A-Za-z_][A-Za-z_0-9]*)";
445 $operator_name = "(?:operator$s(?:"
446 .'(?:[~,]|[+\-*/%^&|!=<>]=?|[<>]{2}=?|[&|+\-]{2}|->\*?'
447 .'|\(\)|(?:new|delete)?'.$s.'\[\])'."|$identifier))";
453 (?> [^()]+ ) # Non-parens without backtracking
455 (??{ $paren_group }) # Group with matching parens
460 $paren_expr = qr{ (?> $paren_group | [^()]+ )* }x;
462 # Template argument list -- similar to paren_group above
463 $tparen_group = qr { < (?: (?> [^<>]+ ) | (??{ $tparen_group }) )* > }x;
465 # Template argument list
466 $template_arg = qr{ (?> $tparen_group) }x;
468 # Template declaration tag
469 $template = qr{template$s$template_arg$s};
478 my $t = '\(\)&|,\{\}!-';
481 while ($tag =~ /^\s*([$t]|(?:[^\s$t]+))\s*(.*?)$/)
484 $cp .= defined $r ? $r : 0;
488 my $match = eval $cp;
489 #print "TAG: $tag -> $cp = $match\n";
492 die "${ARGV}:$lineno: error: syntax error in tag '$tag'\n";
495 if (($verbose || $opt_d) && (!defined $match || !$match))
497 print "Drop SECTION: [$orig_tag] from".
509 $current_section = "IMPLEMENTATION";
511 my $skip_to_next_section = 0;
516 #print "PARSED: $_\n";
518 $blockstart = $lineno + 1;
529 if (/^$s\/\/-[\s\n]*$/s)
531 handle_source_code ();
538 (?:$s \[ $s ([A-Za-z0-9_,\{\}!\s&|\(\)-]+) $s \] $s)? : )
541 check_empty_ifstack();
542 $skip_to_next_section = 0;
543 $current_section = $2;
544 if ($opt_e ne '' || $current_section eq "IMPLEMENTATION")
551 $skip_to_next_section = !match_e_opt($current_part);
552 next NEXTLINE if $skip_to_next_section;
562 if (defined $3 && $opt_h ne $3)
564 die "${ARGV}:${lineno}: all INTERFACE arguments and "
565 . "option -h must be consistent;"
572 $headerfile_base = $opt_p . $public_base
576 handle_source_code ();
579 elsif ($skip_to_next_section)
584 # Preprocessor directive?
589 last NEXTLINE if ! read_more();
596 next NEXTLINE if ignoring();
598 # Read until we can decide what we have: Read till next block end
604 do {} while ($foo =~ s/\{[^\{\}]*\}//sg); # kill blocks
607 #print "MORE: $foo\n";
608 next MORE; # Still unfinished blocks.
611 elsif (! /;/) # no unclosed blocks & semicolon?
617 if (/^$s(?:$template)?(enum|struct|class|typedef)/s)
621 if (/^$s(?:$template)?
622 (?:enum|struct|class)
623 $s ($identifier (?:$s $template_arg)?)
626 # Have a block -> this is a definition.
632 my $class = { name => $name,
636 #print "CLASS " . $class->{name} . ">" .$class->{pretext} . "###" . $class->{posttext};
637 handle_classdef ($class);
642 # No block or no name -- handle as declaration.
643 if (/^$s(?:$template)?(?:enum|struct|class)$s\{/s)
645 # no name but block -- make this a global variable decl.
646 handle_source_code ();
648 elsif (/^$s(?:$template)?(?:enum|struct|class)/s)
650 # no block -- this seems to be a forward
651 # decl. or a variable decl.
653 if (/^$s(?:$template)?(?:enum|struct|class)$s
654 ($identifier) $s ;/sx)
656 my $class = { syntax => 'forwarddecl',
658 handle_classdef ($class);
662 handle_source_code ();
665 elsif (/^${s} typedef \b /sx) # It's a typedef
667 # strip off function args and array spec
670 $l =~ s/\([^\)]*\) (?:${s}const)? $s $//sx;
671 $l =~ s/(?: \[ [^\[]* \] $s | \) $s )+ $//sx;
672 $l =~ m/($identifier) $s $/sx;
674 my $class = { syntax => 'typedef',
676 handle_classdef ($class);
680 die "${ARGV}:$lineno: Parse error";
687 # Type declaration extension?
688 if (/^$s EXTENSION $s (?:struct|class) $s ($identifier)
689 $s (?::(?!:) $s ([^\{]*))?\{ (.*) \} $s ; $s $/sx)
695 if (! exists $classes{$name})
697 die "${ARGV}:$lineno: Class extension for undefined class " .
701 # XXX XXX we should not handle line directives here --
702 # this is the job of the output functions. However, as
703 # we don't generate a new codechunk for this extension,
704 # we just add the extension's line number here.
706 if ($doing_linenumbers)
708 $classes{$name}->{pretext} .=
709 "\n#line " . $blockstart . " \"" . $ARGV . "\"\n";
712 my $txt = \($classes{$name}->{pretext});
716 if ($$txt =~ /^([^\{]*)/sx)
719 if ($pre =~ /^.*:(?!:)(.*)$/sx)
721 $$txt =~ s/^$pre/$pre\n, $super/s;
722 # print "ADD super classes: , $super\n";
726 $$txt =~ s/^$pre/$pre\n: $super/s;
731 $classes{$name}->{pretext} .= "private:\n" . $string;
736 # Member function definition?
737 # if (/^([^\{\(]*?) # pretext, maybe w template decl tag
738 if (/^((?:[^\{\(]|\(\()*?) # pretext, maybe w template decl tag
739 \b ($identifier (?: $s :: $s $identifier)*) # class name
740 ($s $template_arg)? # optional class-template args
742 ((?:$operator_name | (?: ~? $identifier )) # member name
743 (?:$s $template_arg)?) # optional member-template args
744 $s ( \( (?: [^\)] | \([^\)]*\) )* \) [^:\{=]* ) # arg list
745 ((?:\{|:.*\{).* | (?:$s = $s 0 $s ;))$/sx) # initializer ':' and body '{' or pure virtual
747 my ($pretext, $class, $templateargs, $name, $args, $posttext)
748 = ($1, $2, (defined $3 ? $3 : ''), $4, $5, $6);
749 #print "Member: P<$pretext> C<$class> T<$templateargs> N<$name> A<$args> P<$posttext>\n";
750 # Canonify operator names
751 $name =~ s/(?<=\w)(?:$s_once)+(?=\W)//gs;
752 $name =~ s/(?<=\W)(?:$s_once)+(?=\w)//gs;
753 $name =~ s/(?:$s_once)+/ /gs;
754 # Canonify class name
756 my $memberfunction = { class => $class,
758 templateargs => $templateargs,
761 posttext => $posttext };
762 handle_function ($memberfunction);
766 # Free function definition?
767 if (/^([^\{]*) # pretext, maybe w template decl tag
768 \b ($operator_name | $identifier) # function name
769 ($s $template_arg)? # optional template args
770 $s( \( $paren_expr \) [^:\{\(\)=]*) # arg list
773 #print "Free function: $2 T(" . (defined $3 ? $3 : "") . ") PRE($1) ARGS($4) POST($5)\n";
774 my $function = { class => '',
776 templateargs => (defined $3
781 handle_function ($function);
785 handle_source_code ();
792 $verbose && print "EOF: " . $_ . "\n";
793 die "${blockfile}:$blockstart: Unexpected end of file in block starting here;";
798 sub read_more () # Read one more line of code. Stow away
799 # comments and character constants
801 # Get a line without comments.
804 if (eof(INPUT)) # Reset line numbering.
806 check_empty_ifstack();
811 return 0 unless $file = shift @ARGV;
813 open(INPUT, $ARGV) || die "Cannot open $ARGV for reading!";
816 # print "FILE: $ARGV\n";
818 if ($ARGV =~ /^(?:.*\/)?(.+)$/ && $1 =~ /(?:[^-]*)-(.*)\..*/)
822 $current_part_ext = $part_ext;
823 $impl_parts{$part_ext} = 1;
824 # print "PART: '$part_ext'\n";
826 print "read file: '$ARGV'\n" if $verbose;
842 # Save comments and strings in @comments array. Save strings
843 # first to catch strings with comment-like contents.
844 my $number = @comments;
846 # We don't touch strings in NEEDS[], neither #includes! Save now --
849 if (s/(^$s \# $s include.*$
850 | NEEDS $s \[[^\]]* )
856 while (s,(\'(?:\\.|[^\']|\\[0-7]+)\'),\002$number\002,s)
862 # while (s,(\"(?:[^\"]|(?<=\\)\")*\"),\002$number\002,s)
863 while (s,(\"(?:[^\\\"]|\\.)*\"),\002$number\002,s)
874 while (s|(//(?!-\s*\n).*\n)|\001$number\001|m) # Do not match magic "//-"
875 { # The \001 signifies whitespace.
880 while (s|(/\*.*\*/)|\001$number\001|s)
897 my ($codechunk,$type) = @_;
899 $codechunk->{type} = $type;
900 $codechunk->{section} = $current_section;
901 $codechunk->{string} = $_;
902 $codechunk->{part} = $current_part;
903 $codechunk->{part_ext} = $opt_s ? $current_part_ext : $current_part;
905 $impl_parts{$current_part} = 1 unless $opt_s;
907 $codechunk->{line} = $blockstart;
908 $codechunk->{file} = $ARGV;
909 $codechunk->{printed} = 0;
911 push @{$sections{$current_section}}, $codechunk;
916 foreach my $i (@ifstack)
918 if ($i->{value} == 1)
929 # if ($codeblock->{string} =~ /^$s\#\s*(if|endif|else|elif)/)
931 # die "${ARGV}:${lineno}: Conditional compilation not supported;";
934 if (/^$s\#\s*if\s+0${s}$/)
936 push @ifstack, { value => 1, file => ${ARGV}, line => $lineno };
937 $verbose && print "IF 0: " . ignoring() . "\n";
940 elsif (@ifstack && /^$s\#\s*if(def|ndef)?\s/)
942 push @ifstack, { value => 0, file => ${ARGV}, line => $lineno };
943 $verbose && print "IF: " . ignoring() . "\n";
944 return if ignoring();
946 elsif (@ifstack && /^$s\#\s*(else|elif)/)
948 my $ignoring = ignoring();
949 my $i = pop @ifstack;
950 $i->{value} = -$i->{value};
952 $verbose && print "ELSE/ELIF: " . ignoring() . " ($ignoring)\n";
955 elsif (@ifstack && /^$s\#\s*endif/)
957 my $ignoring = pop @ifstack;
958 $verbose && print "ENDIF: " . ignoring() . "\n";
959 return if ignoring() || $ignoring->{value};
961 elsif (/^$s\#\s*include${s}([\"<][^\">]+[\">])/)
964 $codeblock->{name} = $1;
965 $codeblock->{inline} = 0;
967 $includes{$codeblock->{name}} = $codeblock;
969 label_chunk ($codeblock, "include");
971 $verbose && print "INCLUDE: " . $codeblock->{name} . "\n";
975 # XXX: For now, treat preprocessor stuff besides #include, #if 0 as code.
976 handle_source_code ();
982 foreach my $i (@ifstack)
984 print "$indent$i->{value}: $i->{file}:$i->{line}\n";
989 sub check_empty_ifstack
993 my $i = pop @ifstack;
994 print STDERR "${ARGV}:${lineno}: missing endif for $i->{file}:$i->{line}\n";
1000 sub handle_source_code
1002 return if /^[\s\n]*$/;
1005 label_chunk ($codeblock, "code");
1007 $verbose && print "UNKNOWN: " . $codeblock->{string};
1013 label_chunk ($class, "classdef");
1015 $class->{funcs} = [];
1017 if ($class->{syntax} ne 'forwarddecl')
1019 $classes{$class->{name}} = $class;
1022 $verbose && print "CLASSDEF: " . $class->{name} . " ["
1023 . $class->{syntax} . "]\n";
1030 $func->{purevirtual} = 0;
1032 if ($func->{class} ne '')
1034 # Nested class hacks
1035 if ($func->{class} =~ /::/
1036 && ! defined $classes{$func->{class}})
1038 # Define class along the way -- the dirty way.
1039 my $class = { name => $func->{class},
1041 nested_class => 1 };
1042 my ($topclass, $rest) = split (/::/, $func->{class});
1043 my $save_sec = $current_section;
1044 $current_section = $classes{$topclass}->{section};
1045 handle_classdef ($class);
1046 $current_section = $save_sec;
1049 $func->{visibility} = "private";
1050 if (s/^($s)PRIVATE([\s\n])/$1$2/s)
1052 $func->{visibility} = "private";
1053 $func->{pretext} =~ s|PRIVATE[ \t]*||s;
1055 elsif (s/^($s)PUBLIC([\s\n])/$1$2/s)
1057 $func->{visibility} = "public";
1058 $func->{pretext} =~ s|PUBLIC[ \t]*||s;
1060 elsif (s/^($s)PROTECTED([\s\n])/$1$2/s)
1062 $func->{visibility} = "protected";
1063 $func->{pretext} =~ s|PROTECTED[ \t]*||s;
1065 elsif (s/^($s)IMPLEMENT([\s\n])/$1$2/s)
1067 # Use a visibility attribute that is never used in adding
1068 # declarations to classes in print_classdecl.
1069 $func->{visibility} = "implementation_only";
1070 $func->{pretext} =~ s|IMPLEMENT[ \t]*||s;
1072 elsif (s/^($s)IMPLEMENT_DEFAULT([\s\n])/$1$2/s)
1074 # Use a visibility attribute that is never used in adding
1075 # declarations to classes in print_classdecl.
1076 $func->{visibility} = "implementation_only";
1077 $func->{default_impl} = 1;
1078 $func->{pretext} =~ s|IMPLEMENT_DEFAULT[ \t]*||s;
1081 if ($func->{posttext} =~ s/$s=${s}0$s;$s$//s)
1083 $func->{purevirtual} = 1;
1086 if ($func->{class} =~ /::/
1087 && $func->{visibility} ne "implementation_only")
1089 die "${ARGV}:${lineno}: Limitation: Only predeclared members " .
1090 "supported for nested classes. Use IMPLEMENT;";
1093 if (! defined $classes{$func->{class}})
1095 die "${ARGV}:${lineno}: Class " . $func->{class}
1096 . " has not been declared;";
1101 $func->{visibility} = "free";
1104 # Interprete more type attributes.
1105 $func->{inline} = 0;
1106 $func->{always_inline} = 0;
1107 $func->{static} = 0;
1109 $func->{virtual} = 0;
1110 $func->{explicit} = 0;
1111 $func->{classtemplate} = '';
1112 $func->{funtemplate} = '';
1113 $func->{template} = '';
1114 $func->{fully_specialized_template} = '';
1117 if (s/^($s)((?:$template)+)([\s\n])/$1$3/s)
1120 my @specs = split(/(?<= \>)(?= $s template)/sx, $match, 3);
1122 if ($func->{class} eq '') # Free function?
1124 $func->{funtemplate} = shift @specs;
1128 my $class = $classes{$func->{class}};
1129 my $istemplateclass = ($class->{pretext} =~ /^[^\{]*template/s);
1131 if ($istemplateclass)
1133 $func->{classtemplate} = shift @specs;
1134 $func->{funtemplate} = shift @specs if scalar @specs;
1136 else # Not a class template
1138 $func->{funtemplate} = shift @specs;
1142 die "${ARGV}:$lineno: Too many template specs"
1145 $func->{template} = 'yes';
1146 $func->{fully_specialized_template} = 'yes'
1147 if ($match =~ /^(?:${s}template$s<${s}>)+${s}$/s);
1149 $func->{pretext} =~ s/\Q$match//s;
1153 if (s/^($s)inline([\s\n])/$1$2/si) # "inline" is case-insensitive.
1155 $func->{inline} = 1 if $doing_inlines
1156 || $func->{fully_specialized_template} ne '';
1157 $func->{pretext} =~ s|inline[ \t]*||si;
1158 @{$func->{needs}} = ();
1161 if (s/^($s)NEEDS\s*\[([^\]]+)\]([\s\n])/$1$3/s)
1163 @{$func->{needs}} = split (/\s*,\s*/, $2);
1164 # Delete NEEDS directive, but keep newlines
1165 while ($func->{pretext} =~
1166 s|NEEDS \s* \[ ( (?:[^\n\]]*\n)* )
1169 |NEEDS[$1\n$2\]|sx) {}
1170 $func->{pretext} =~ s|NEEDS\s*\[ (\n*) [^\n\]]*\]|$1|sx;
1173 if (s/^($s)NOEXPORT([\s\n])/$1$2/si)
1176 $func->{pretext} =~ s|NOEXPORT[ \t]*||s;
1179 if (s/^($s)ALWAYS_INLINE([\s\n])/$1$2/si)
1181 $func->{inline} = 1;
1182 $func->{always_inline} = 1;
1183 $func->{pretext} =~ s|ALWAYS_INLINE[ \t]*||s;
1189 # Reset inline data if inline handling was not enabled by -i
1191 if (! $func->{inline})
1193 undef $func->{needs};
1199 if (s/^($s)static([\s\n])/$1$2/s)
1201 $func->{static} = 1;
1202 $func->{pretext} =~ s/static[ \t]*//s;
1204 if ($func->{class} eq '')
1206 $func->{visibility} = "static";
1213 if (s/^($s)IMPLEMENT([\s\n])/$1$2/s)
1215 $func->{pretext} =~ s/IMPLEMENT[ \t]*//s;
1217 if ($func->{class} eq '')
1219 $func->{visibility} = "implementation_only";
1224 if (s/^($s)IMPLEMENT_DEFAULT([\s\n])/$1$2/s)
1226 $func->{pretext} =~ s/IMPLEMENT_DEFAULT[ \t]*//s;
1228 if ($func->{class} eq '')
1230 $func->{visibility} = "implementation_only";
1231 $func->{default_impl} = 1;
1237 if (s/^($s)explicit([\s\n])/$1$2/s)
1239 $func->{explicit} = 1;
1240 $func->{pretext} =~ s|explicit[ \t]*||s;
1244 if (s/^($s)virtual([\s\n])/$1$2/s)
1246 $func->{virtual} = 1;
1247 $func->{pretext} =~ s|virtual[ \t]*||s;
1251 if (/^($s)(PRIVATE|PUBLIC|PROTECTED)([\s\n])/)
1253 die "${blockfile}:$blockstart: only one visibility attribute allowed at start of declaration;";
1259 label_chunk ($func, "function");
1261 if ($current_section eq 'INTERFACE')
1263 die "${ARGV}:${lineno}: Function " . $func->{name}
1264 . " in INTERFACE section;";
1267 if (defined $functions{"$func->{class}::$func->{name}"})
1269 my $f = $functions{"$func->{class}::$func->{name}"};
1270 if (defined $f->{default_impl})
1274 elsif (defined $func->{default_impl})
1276 $func->{printed} = 1;
1281 $functions{"$func->{class}::$func->{name}"} = $func;
1284 push @{$classes{$func->{class}}->{funcs}}, $func;
1286 $verbose && print "FUNC: " . ($func->{class} ne ''
1287 ? ($func->{class} . "::")
1290 . ($func->{classtemplate} ne ''
1291 ? " T: " . $func->{classtemplate} : "")
1292 . ($func->{funtemplate} ne ''
1293 ? " M: " . $func->{funtemplate} : "")
1294 . ($func->{fully_specialized_template} ne ''
1295 ? " FULLY_SPEC" : "")
1299 #############################################################################
1308 sub print_head # Save header. Print it only if a
1309 # print_expand() follows
1311 $saved_head .= $_[0];
1312 $saved_indent = $print_indent;
1320 sub print_expand($) # Expands comments and prints to OUT.
1324 if ($saved_head ne '')
1326 local $print_indent = $saved_indent;
1327 my $str = $saved_head;
1330 print_expand $str; # Recurse.
1333 $str =~ s/\n(?:[ \t]*\n)+/\n\n/sg if ! $doing_linenumbers;
1335 while ( $str =~ s/([\001\002])([0-9]+)\1/$comments[$2]/sg )
1340 my $istr = " " x $print_indent;
1341 $str =~ s/^/$istr/mg;
1349 return if ! $doing_linenumbers;
1353 print_expand ''; # print headers we accumulated
1354 print OUT "#line " . $object->{line} . " \"" . $object->{file} . "\"\n";
1357 sub print_lineno_sans_empty_lines($)
1359 return if ! $doing_linenumbers;
1363 my $start_of_code = $object->{string};
1364 $start_of_code =~ s/^([\s\n]+).*$/$1/s;
1366 my @startcomments = split /\n/, " $start_of_code ";
1368 print OUT "#line " . ($object->{line} + @startcomments - 1)
1369 . " \"" . $object->{file} . "\"\n";
1372 sub weedout_whitespace # Delete whitespace except on lines w/comments
1376 $str =~ s/^[\s\n]+//s;
1378 if (! $doing_linenumbers) # more cosmetic changes if we do not
1379 { # have to be correct line-number-wise
1380 my @lines = split /\n/, $str;
1384 foreach my $line (@lines)
1389 if ($line =~ /\001/ || $line =~ /^\s*$/)
1399 # Found something like code: Remove trailing whitespace
1402 $str .= "\n" if $str ne '';
1417 sub func_prototype($) # Return a function declaration from
1421 my $pretext = $func->{pretext};
1423 if ($func->{inline})
1425 $pretext =~ s/^($s)/${1}inline /s;
1428 if ($func->{explicit})
1430 $pretext =~ s/^($s)/${1}explicit /s;
1433 if ($func->{static})
1435 $pretext =~ s/^($s)/${1}static /s;
1438 if ($func->{virtual})
1440 $pretext =~ s/^($s)/${1}virtual /s;
1443 if ($func->{funtemplate} ne '')
1445 $pretext =~ s/^($s)/${1}$func->{funtemplate} /s;
1448 my $func_header = weedout_whitespace($pretext .
1449 $func->{name} . $func->{args});
1451 # Insert ; at the correct place, that is, before any comments.
1452 my $e = $func->{purevirtual} ? ' = 0' : '';
1453 $func_header =~ s/($s)$/$e;$1/s;
1455 return $func_header;
1458 sub print_funcdecl($)
1460 my $function = $_[0];
1462 if ($function->{visibility} ne "implementation_only")
1465 print_lineno_sans_empty_lines $function;
1466 print_expand func_prototype($function) . "\n";
1470 if ($function->{inline})
1472 handle_inline ($function);
1476 sub print_classdecl($)
1479 return if check_if_printed ($class);
1481 print_lineno $class;
1483 if (defined $class->{nested_class})
1485 # (This will not actually print anything, but do other processing.)
1486 foreach my $function (@{$class->{funcs}})
1489 if $function->{visibility} ne "implementation_only";
1490 print_funcdecl $function;
1493 elsif ($class->{syntax} =~ /^(?:struct|class)$/)
1495 if (! $doing_inlines)
1497 $class->{pretext} =~ s/\binline\b[ \t]*//g;
1500 print_expand $class->{pretext};
1502 print_head "\npublic:";
1504 foreach my $function (grep {$_->{visibility} eq "public"}
1507 print_funcdecl $function;
1511 print_head "\nprotected:";
1513 foreach my $function (grep {$_->{visibility} eq "protected"}
1516 print_funcdecl $function;
1520 print_head "\nprivate:";
1522 foreach my $function (grep {$_->{visibility} eq "private"}
1525 print_funcdecl $function;
1530 # Also, don't forget to "print" already-declared functions.
1531 # (This will not actually print anything, but do other processing.)
1532 foreach my $function (grep {$_->{visibility} eq "implementation_only"}
1535 print_funcdecl $function;
1538 print_expand $class->{posttext};
1542 print_expand $class->{string};
1547 sub print_funcdef($)
1549 my $function = $_[0];
1550 return if $function->{purevirtual};
1551 return if check_if_printed ($function);
1553 my $pretext = $function->{pretext};
1555 if ($function->{inline})
1557 if ($function->{always_inline})
1559 $pretext =~ s/^($s)/${1}ALWAYS_INLINE /s;
1561 $pretext =~ s/^($s)/${1}inline /s;
1564 if ($function->{static} && $function->{class} eq '')
1566 $pretext =~ s/^($s)/${1}static /s;
1569 if ($function->{funtemplate} ne '')
1571 $pretext =~ s/^($s)/${1}$function->{funtemplate} /s;
1574 if ($function->{classtemplate} ne '')
1576 $pretext =~ s/^($s)/${1}$function->{classtemplate} /s;
1579 # Remove default arguments from argument list
1580 my $args = $function->{args};
1581 $parengroup = qr{ # Matches correctly-nested groups of parens
1584 (?> [^()]* ) # Non-parens without backtracking
1586 (??{ $parengroup }) # Backtrack: Group with parens
1590 my $expr = qr{ [^(),]* (?:$parengroup)? [^(),]* }x;
1591 $args =~ s/$s = $expr//gx;
1594 print_lineno $function;
1595 print_expand $pretext
1596 . ($function->{class} ne ''
1597 ? $function->{class} . $function->{templateargs}
1598 . "::" . $function->{name}
1599 : $function->{name} . $function->{templateargs})
1600 . $args . $function->{posttext};
1605 my $codeblock = $_[0];
1606 return if check_if_printed ($codeblock);
1607 print_lineno $codeblock;
1608 print_expand $codeblock->{string};
1611 sub check_if_printed
1613 my $codeblock = $_[0];
1614 return 1 if $codeblock->{printed};
1615 $codeblock->{printed} = 1;
1619 #############################################################################
1622 # Inline-function bookkeeping.
1625 sub lookup_by_name # Return (list of) item(s) matching name.
1627 my ($item, $context) = @_;
1629 # Is it a class name?
1630 if (defined $classes{$item})
1632 return $classes{$item};
1635 # Is it an include file?
1636 if (defined $includes{$item})
1638 $includes{$item}->{inline} = 1;
1639 return $includes{$item};
1642 # Must be a function name!
1643 my ($classname, $funcname);
1647 ($classname, $funcname) = split /::/, $item;
1651 ($classname, $funcname) = ('' , $item);
1654 my @grepresult = grep {$_->{name} eq $funcname && $_->{inline}}
1655 @{$classes{$classname}->{funcs}};
1657 return shift @grepresult
1658 if (scalar @grepresult == 1);
1660 if (scalar @grepresult == 0)
1662 my @xgrepresult = grep {$_->{name} eq $funcname}
1663 @{$classes{$classname}->{funcs}};
1664 die $context->{file} . ":" . $context->{line} . ": Cannot find $item;"
1665 if (scalar @xgrepresult == 0);
1666 $wno_inline && print STDERR $context->{file} . ":" . $context->{line} .
1667 ": warning: Cannot find inline code ".
1671 return @grepresult; # Return list of matching function names.
1674 # Check if Function $function can already see Object $item in its context.
1677 my ($item, $function) = @_;
1679 if ($item->{type} eq "function"
1681 && ! $function->{hide})
1683 die $function->{file} . ":" . $function->{line} .
1684 ": Nonhidden function " . funcname($function) .
1685 " depends on hidden function " . funcname($item) . " (" .
1686 ($item->{visibility} eq 'static' ? "static" : "NOEXPORT") . ")";
1689 return exists $public_inline{$item}
1690 || (($function->{visibility} eq 'private'
1691 || ($function->{class} ne ''
1692 && $classes{$function->{class}}->{section} eq "IMPLEMENTATION"))
1693 && exists $private_inline{$item})
1694 || ($function->{hide}
1695 && exists $unit_inline{$item});
1698 # Put inline function $1 and all its dependencies (given by NEEDS
1699 # directives) into @inline_order_[public/private/unit], depending on
1700 # visibility of $1. Function handle_inline is called when printing
1701 # inline-function declarations, so the sequence of handle_inline calls
1702 # is determined by declaration-printing order.
1705 my $function = $_[0];
1706 my $class = $function->{class};
1710 print "INLINE " . funcname($function) . " NEEDS ";
1712 # Add all needed items, then add my own name as well as my class
1713 # name for good measure.
1714 foreach my $item (@{$function->{needs}})
1716 push @needed, lookup_by_name ($item, $function);
1719 push @needed, $function;
1720 unshift @needed, lookup_by_name ($class, $function)
1726 my $object = $needed[0];
1728 if (inline_known ($object, $function))
1734 # Check for further dependencies.
1735 my @moreneeded = ();
1737 if ($object->{type} eq "function" && $object->{class} ne '')
1739 my $class = lookup_by_name ($object->{class}, $object);
1740 push @moreneeded, $class;
1743 if (defined $object->{needs})
1745 foreach my $item (@{$object->{needs}})
1747 my $o = lookup_by_name ($item, $object);
1748 next if ! ref $o; # Skip referenced but noninline objects
1749 push @moreneeded, $o;
1753 # Check if we have everything that's needed for $item.
1754 foreach my $i (@moreneeded)
1756 if (inline_known ($i, $function))
1761 if ($i == $function) # Function depends on itself!
1763 my $callstack = " " . funcname ($function) . "\n";;
1764 my $prev = $function;
1765 push @needed, $function;
1766 foreach my $j (@needed)
1768 # $j is not part of call stack if it does not need $prev
1769 next if ! grep {lookup_by_name ($_, $object) == $prev}
1771 $callstack .= " " . funcname ($j) . "\n";
1773 last if $j == $function;
1776 die $object->{file} . ":" . $object->{line} . ": Function " .
1777 funcname ($object) . " NEEDS " . funcname ($i) .
1778 ", which circularly depends on this function:\n" .
1782 unshift @needed, $i;
1786 $verbose && print &funcname ($object) . " ";
1788 if ($function->{hide})
1790 $unit_inline{$object} = 1;
1791 push @inline_order_unit, $object;
1793 elsif ($function->{visibility} eq 'private'
1795 && $classes{$class}->{section} eq "IMPLEMENTATION"))
1797 $private_inline{$object} = 1;
1798 push @inline_order_private, $object;
1802 $public_inline{$object} = 1;
1803 push @inline_order_public, $object;
1809 $verbose && print "\n";
1814 foreach my $object (grep {$_->{type} eq "classdef"} @_)
1816 if ($object->{section} ne 'INTERFACE')
1818 print_classdecl $object;
1822 foreach my $object (grep {$_->{type} eq "function"} @_)
1824 print_funcdef $object;
1828 ######################################################################
1834 my $function = $_[0];
1836 return ($function->{class} ? ($function->{class} . "::") : "")
1837 . $function->{name};