enumgen.pl 6.02 KB
Newer Older
1 2
#!/usr/bin/perl -w

3
# GIMP - The GNU Image Manipulation Program
4
# Copyright (C) 1999-2003 Manish Singh <yosh@gimp.org>
5

6
# This program is free software: you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 3 of the License, or
9 10 11 12 13 14 15 16
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUTFILE 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
17
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 19

BEGIN {
20 21 22
    $srcdir   = $ENV{srcdir}   || '.';
    $destdir  = $ENV{destdir}   || '.';
    $builddir = $ENV{builddir} || '.';
23 24
}

Manish Singh's avatar
Manish Singh committed
25 26
use lib $srcdir;

27
use Text::Wrap qw(wrap $columns);
Manish Singh's avatar
Manish Singh committed
28
$columns = 77;
29

Elliot Lee's avatar
Elliot Lee committed
30 31
#BEGIN { require 'util.pl' }
require 'util.pl';
Manish Singh's avatar
Manish Singh committed
32 33 34 35

*write_file = \&Gimp::CodeGen::util::write_file;
*FILE_EXT   = \$Gimp::CodeGen::util::FILE_EXT;

36
my $header = <<'HEADER';
37
:# GIMP - The GNU Image Manipulation Program
38
:# Copyright (C) 1999-2003 Manish Singh <yosh@gimp.org>
39
:
40
:# This program is free software: you can redistribute it and/or modify
41
:# it under the terms of the GNU General Public License as published by
42
:# the Free Software Foundation; either version 3 of the License, or
43 44 45 46 47 48 49 50
:# (at your option) any later version.
:
:# This program is distributed in the hope that it will be useful,
:# but WITHOUTFILE 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
51
:# along with this program.  If not, see <http://www.gnu.org/licenses/>.
52 53 54 55 56 57 58 59 60 61 62 63 64
:
:# autogenerated by enumgen.pl
:
:package Gimp::CodeGen::enums;
:
:%enums = (
HEADER

my $footer = <<'FOOTER';
:);
:
:foreach $e (values %enums) {
:    $e->{info} = "";
Manish Singh's avatar
Manish Singh committed
65
:    foreach (@{$e->{symbols}}) {
66
:	$e->{info} .= "$_ ($e->{mapping}->{$_}), "
Manish Singh's avatar
Manish Singh committed
67
:    }
68 69 70 71 72 73
:    $e->{info} =~ s/, $//;
:}
:
:1;
FOOTER

74
my ($enumname, $contig, $symbols, @mapping, $before);
75 76

# Most of this enum parsing stuff was swiped from makeenums.pl in GTK+
Manish Singh's avatar
Manish Singh committed
77 78 79 80 81
sub parse_options {
    my $opts = shift;
    my @opts;

    for $opt (split /\s*,\s*/, $opts) {
82 83 84
	$opt =~ s/^\s*//;
	$opt =~ s/\s*$//;
	my ($key,$val) = $opt =~ /([-\w]+)(?:=(.+))?/;
Manish Singh's avatar
Manish Singh committed
85 86 87 88 89 90
	defined $val or $val = 1;
	push @opts, $key, $val;
    }
    @opts;
}

91 92
sub parse_entries {
    my $file = shift;
93 94
    my $file_name = shift;
    my $looking_for_name = 0;
95 96 97

    while (<$file>) {
	# Read lines until we have no open comments
98
	while (m@/\*([^*]|\*(?!/))*$@) {
99
	    my $new;
100
	    defined ($new = <$file>) || die "Unmatched comment in $ARGV";
101 102
	    $_ .= $new;
	}
103
	# strip comments w/o options
104 105 106 107 108 109 110 111
	s@/\*(?!<)
	    ([^*]+|\*(?!/))*
	   \*/@@gx;
        
	s@\n@ @;
        
	next if m@^\s*$@;

112 113 114 115 116 117 118
	if ($looking_for_name) {
	    if (/^\s*(\w+)/) {
		$enumname = $1;
		return 1;
	    }
	}

119 120 121 122 123
	# Handle include files
	if (/^\#include\s*<([^>]*)>/ ) {
	    my $file= "../$1";
	    open NEWFILE, $file or die "Cannot open include file $file: $!\n";

124
	    if (&parse_entries (\*NEWFILE, $NEWFILE)) {
125 126 127 128 129 130 131 132 133 134 135
		return 1;
	    } else {
		next;
	    }
	}

	if (/^\s*\}\s*(\w+)/) {
	    $enumname = $1;
	    return 1;
	}

136 137 138 139 140
	if (/^\s*\}/) {
	    $looking_for_name = 1;
	    next;
	}

141 142 143 144 145 146 147
	if (m@^\s*
	      (\w+)\s*                   # name
	      (?:=(                      # value
		   (?:[^,/]|/(?!\*))*
		  ))?,?\s*
	      (?:/\*<                    # options 
		(([^*]|\*(?!/))*)
148
	       >\s*\*/)?,?
149 150
	      \s*$
             @x) {
Manish Singh's avatar
Manish Singh committed
151 152 153 154
            my ($name, $value, $options) = ($1, $2, $3);

	    if (defined $options) {
		my %options = parse_options($options);
155
		next if defined $options{"pdb-skip"};
156
	    }
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178

	    $symbols .= $name . ' ';

	    # Figure out a default value (not really foolproof)
	    $value = $before + 1 if !defined $value;
	    $value =~ s/\s*$//s;
	    $value =~ s/^\s*//s;

	    push @mapping, $name, $value;

	    my $test = $before + 1;

	    # Warnings in our eval should be fatal so they set $@
	    local $SIG{__WARN__} = sub { die $_[0] };

	    # Try to get a numeric value
	    eval "\$test = $value * 1;";

	    # Assume noncontiguous if it's not a number
	    $contig = 0 if $contig && ($@ || $test - 1 != $before);

	    $before = $test;
179 180
	} elsif (m@^\s*\#@) {
	    # ignore preprocessor directives
181
        } else {
182
            print STDERR "$0: $file_name:$.: Failed to parse `$_'\n";
183 184 185 186 187 188 189 190 191 192 193
        }
    }
    return 0;
}

my $code = "";
while (<>) {
    if (eof) {
        close (ARGV);           # reset line numbering
    }

194 195 196 197 198 199 200 201 202 203 204
    # read lines until we have no open comments
    while (m@/\*([^*]|\*(?!/))*$@) {
	my $new;
	defined ($new = <>) || die "Unmatched comment in $ARGV";
	$_ .= $new;
    }
    # strip comments w/o options
    s@/\*(?!<)
       ([^*]+|\*(?!/))*
       \*/@@gx;

Manish Singh's avatar
Manish Singh committed
205 206 207 208
    if (m@^\s*typedef\s+enum\s*
	   ({)?\s*
	   (?:/\*<
	     (([^*]|\*(?!/))*)
209
	    >\s*\*/)?
Manish Singh's avatar
Manish Singh committed
210 211 212
         @x) {
        if (defined $2) {
            my %options = parse_options($2);
213
	    next if defined $options{"pdb-skip"};
Manish Singh's avatar
Manish Singh committed
214
	}	    
215 216 217 218 219 220 221 222 223
	# Didn't have trailing '{' look on next lines
	if (!defined $1) {
	    while (<>) {
		if (s/^\s*\{//) {
		    last;
		}
	    }
	}

224
	$symbols = ""; $contig = 1; $before = -1; @mapping = ();
225 226

	# Now parse the entries
227
	&parse_entries (\*ARGV, $ARGV);
228 229 230 231 232 233 234 235 236 237 238

	$symbols =~ s/\s*$//s;
	$symbols = wrap("\t\t\t  ", "\t\t\t  " , $symbols);
	$symbols =~ s/^\s*//s;

	my $mapping = ""; $pos = 1;
	foreach (@mapping) {
	    $mapping .= $pos++ % 2 ? "$_ => " : "'$_',\n\t\t       ";
	}
	$mapping =~ s/,\n\s*$//s;

Manish Singh's avatar
Manish Singh committed
239
	$ARGV =~ s@(?:(?:..|app)/)*@@;
Manish Singh's avatar
Manish Singh committed
240

241
	$code .= <<ENTRY;
Manish Singh's avatar
Manish Singh committed
242 243
:    $enumname =>
:	{ contig => $contig,
Manish Singh's avatar
Manish Singh committed
244
:	  header => '$ARGV',
Manish Singh's avatar
Manish Singh committed
245
:	  symbols => [ qw($symbols) ],
246
:	  mapping => { $mapping }
Manish Singh's avatar
Manish Singh committed
247
:	},
248 249 250 251 252 253
ENTRY
    }
}

$code =~ s/,\n$/\n/s;

Manish Singh's avatar
Manish Singh committed
254 255
foreach ($header, $code, $footer) { s/^://mg }

256
$outfile = "$builddir/tools/pdbgen/enums.pl$FILE_EXT";
Manish Singh's avatar
Manish Singh committed
257
open OUTFILE, "> $outfile";
258 259
print OUTFILE $header, $code, $footer;
close OUTFILE;
260
&write_file($outfile, "$destdir/tools/pdbgen");