#!/usr/bin/perl # # gapi_pp.pl : A source preprocessor for the extraction of API info from a # C library source directory. # # Authors: Mike Kestner # Martin Willemoes Hansen # # Copyright (c) 2001 Mike Kestner # Copyright (c) 2003 Martin Willemoes Hansen # Copyright (c) 2003-2004 Novell, Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of version 2 of the GNU General Public # License as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public # License along with this program; if not, write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. $private_regex = '^#if.*(ENABLE_BACKEND|ENABLE_ENGINE)'; $eatit_regex = '^#if(.*(__cplusplus|DEBUG|DISABLE_COMPAT|ENABLE_BROKEN)|\s+0\s*$)'; $ignoreit_regex = '^\s+\*|#ident|#error|#\s*include|#\s*else|#\s*undef|G_(BEGIN|END)_DECLS|GDKVAR|GTKVAR|GTKMAIN_C_VAR|GTKTYPEUTILS_VAR|VARIABLE|GTKTYPEBUILTIN'; foreach $arg (@ARGV) { if (-d $arg && -e $arg) { @hdrs = (@hdrs, `ls $arg/*.h`); @srcs = (@srcs, `ls $arg/*.c`); } elsif (-f $arg && -e $arg) { @hdrs = (@hdrs, $arg) if ($arg =~ /\.h$/); @srcs = (@srcs, $arg) if ($arg =~ /\.c$/); } else { die "unable to process arg: $arg"; } } foreach $fname (@hdrs) { if ($fname =~ /test|private|internals|gtktextlayout|gtkmarshalers/) { @privhdrs = (@privhdrs, $fname); next; } open(INFILE, $fname) || die "Could open $fname\n"; $braces = 0; $deprecated = -1; $ifdeflevel = 0; $prepend = ""; while ($line = ) { $braces++ if ($line =~ /{/ and $line !~ /}/); $braces-- if ($line =~ /}/ and $line !~ /{/); next if ($line =~ /$ignoreit_regex/); $line =~ s/\/\*[^<].*?\*\///g; next if ($line !~ /\S/); $line = $prepend . $line; $prepend = ""; if ($line =~ /#\s*define\s+\w+\s+\"/) { $def = $line; while ($def !~ /\".*\"/) {$def .= ($line = );} print $def; } elsif ($line =~ /#\s*define\s+\w+\s*\D+/) { $def = $line; while ($line =~ /\\\n/) {$def .= ($line = );} if ($def =~ /_CHECK_\w*CAST|INSTANCE_GET_INTERFACE/) { $def =~ s/\\\n//g; print $def; } } elsif ($line =~ /^\s*\/\*[^<]/) { while ($line !~ /\*\//) {$line = ;} } elsif ($line =~ /^extern/) { while ($line !~ /;/) {$line = ;} } elsif ($line =~ /$private_regex/) { $nested = 0; while ($line = ) { last if (!$nested && ($line =~ /#else|#endif/)); if ($line =~ /#if/) { $nested++; } elsif ($line =~ /#endif/) { $nested-- } next if ($line !~ /^struct/); print "private$line"; do { $line = ; print $line; } until ($line =~ /^\}/); } } elsif ($line =~ /$eatit_regex/) { $nested = 0; while ($line = ) { last if (!$nested && ($line =~ /#else|#endif/)); if ($line =~ /#if/) { $nested++; } elsif ($line =~ /#endif/) { $nested-- } } } elsif ($line =~ /^#\s*ifn?\s*\!?def/) { $ifdeflevel++; #print "#ifn?def ($ifdeflevel): $line\n"; if ($line =~ /#ifndef.*DISABLE_DEPRECATED/) { $deprecated = $ifdeflevel; } elsif ($line =~ /#if !defined.*DISABLE_DEPRECATED/) { $deprecated = $ifdeflevel; } } elsif ($line =~ /^#\s*endif/) { #print "#endif ($ifdeflevel): $line\n"; if ($deprecated == $ifdeflevel) { $deprecated = -1; } $ifdeflevel--; } elsif ($line =~ /typedef struct\s*\{/) { my $first_line = $line; my @lines = (); $line = ; while ($line !~ /^}\s*(\w+);/) { push @lines, $line; $line = ; } $line =~ /^}\s*(\w+);/; my $name = $1; print "typedef struct _$name $name;\n"; print "struct _$name {\n"; foreach $line (@lines) { if ($line =~ /(\s*.+\;)/) { $field = $1; $field =~ s/(\w+) const/const $1/; print "$field\n"; } } print "};\n"; } elsif ($line =~ /^enum\s+\{/) { while ($line !~ /^};/) {$line = ;} } elsif ($line =~ /^(typedef\s+)?union/) { next if ($line =~ /^typedef\s+union\s+\w+\s+\w+;/); while ($line !~ /^};/) {$line = ;} } elsif ($line =~ /(\s+)union\s*{/) { # this is a hack for now, but I need it for the fields to work $indent = $1; $do_print = 1; while ($line !~ /^$indent}\s*\w+;/) { $line = ; next if ($line !~ /;/); print $line if $do_print; $do_print = 0; } } else { if ($braces or $line =~ /;|\/\*/) { if ($deprecated == -1) { print $line; } else { print "deprecated$line"; } } else { $prepend = $line; $prepend =~ s/\n/ /g; } } } } foreach $fname (@srcs, @privhdrs) { open(INFILE, $fname) || die "Could open $fname\n"; if ($fname =~ /builtins_ids/) { while ($line = ) { next if ($line !~ /\{/); chomp($line); $builtin = "BUILTIN" . $line; $builtin .= ; print $builtin; } next; } while ($line = ) { next if ($line !~ /^(struct|\w+_class_init|\w+_base_init|\w+_get_type\b|G_DEFINE_TYPE_WITH_CODE)/); if ($line =~ /^struct/) { # need some of these to parse out parent types print "private"; if ($line =~ /;/) { print $line; next; } } elsif ($line =~ /^G_DEFINE_TYPE_WITH_CODE/) { my $macro; while ($line =~ /(.*)\\$/) { $macro .= $1; $line = ; } $macro .= $line; print $macro; next; } $comment = 0; $begin = 0; $end = 0; do { # Following ifs strips out // and /* */ C comments if ($line =~ /\/\*/) { $comment = 1; $begin = 1; } if ($comment != 1) { $line =~ s/\/\/.*//; print $line; } if ($line =~ /\*\//) { $comment = 0; $end = 1; } if ($begin == 1 && $end == 1) { $line =~ s/\/\*.*\*\///; print $line; } $begin = 0; $end = 0; } until (($line = ) =~ /^}/); print $line; } }