]> Pileus Git - ~andy/gtk/blob - gdk/makeenums.pl
Updated German translation
[~andy/gtk] / gdk / makeenums.pl
1 #!/usr/bin/perl -w
2
3 # Information about the current enumeration
4
5 my $flags;                      # Is enumeration a bitmask
6 my $seenbitshift;                       # Have we seen bitshift operators?
7 my $prefix;                     # Prefix for this enumeration
8 my $enumname;                   # Name for this enumeration
9 my $firstenum = 1;              # Is this the first enumeration in file?
10 my @entries;                    # [ $name, $val ] for each entry
11
12 sub parse_options {
13     my $opts = shift;
14     my @opts;
15
16     for $opt (split /\s*,\s*/, $opts) {
17         my ($key,$val) = $opt =~ /\s*(\w+)(?:=(\S+))?/;
18         defined $val or $val = 1;
19         push @opts, $key, $val;
20     }
21     @opts;
22 }
23 sub parse_entries {
24     my $file = shift;
25
26     while (<$file>) {
27         # Read lines until we have no open comments
28         while (m@/\*
29                ([^*]|\*(?!/))*$
30                @x) {
31             my $new;
32             defined ($new = <$file>) || die "Unmatched comment";
33             $_ .= $new;
34         }
35         # Now strip comments
36         s@/\*(?!<)
37             ([^*]+|\*(?!/))*
38            \*/@@gx;
39         
40         s@\n@ @;
41         
42         next if m@^\s*$@;
43
44         # Handle include files
45         if (/^\#include\s*<([^>]*)>/ ) {
46             my $file= "../$1";
47             open NEWFILE, $file or die "Cannot open include file $file: $!\n";
48             
49             if (parse_entries (\*NEWFILE)) {
50                 return 1;
51             } else {
52                 next;
53             }
54         }
55         
56         if (/^\s*\}\s*(\w+)/) {
57             $enumname = $1;
58             return 1;
59         }
60
61         if (m@^\s*
62               (\w+)\s*                   # name
63               (?:=(                      # value
64                    (?:[^,/]|/(?!\*))*
65                   ))?,?\s*
66               (?:/\*<                    # options 
67                 (([^*]|\*(?!/))*)
68                >\*/)?
69               \s*$
70              @x) {
71             my ($name, $value, $options) = ($1,$2,$3);
72
73             if (!defined $flags && defined $value && $value =~ /<</) {
74                 $seenbitshift = 1;
75             }
76             if (defined $options) {
77                 my %options = parse_options($options);
78                 if (!defined $options{skip}) {
79                     push @entries, [ $name, $options{nick} ];
80                 }
81             } else {
82                 push @entries, [ $name ];
83             }
84         } else {
85             print STDERR "Can't understand: $_\n";
86         }
87     }
88     return 0;
89 }
90
91
92 my $gen_arrays = 0;
93 my $gen_defs = 0;
94 my $gen_includes = 0;
95 my $gen_cfile = 0;
96
97 # Parse arguments
98
99 if (@ARGV) {
100     if ($ARGV[0] eq "arrays") {
101         shift @ARGV;
102         $gen_arrays = 1;
103     } elsif ($ARGV[0] eq "defs") {
104         shift @ARGV;
105         $gen_defs = 1;
106     } elsif ($ARGV[0] eq "include") {
107         shift @ARGV;
108         $gen_includes = 1;
109     } elsif ($ARGV[0] eq "cfile") {
110         shift @ARGV;
111         $gen_cfile = 1;
112     }
113 }
114
115 if ($gen_defs) {
116     print ";; generated by makeenums.pl  ; -*- scheme -*-\n\n";
117 } else {
118     print "/* Generated by makeenums.pl */\n\n";
119 }
120
121 if ($gen_includes) {
122   print "#ifndef __GDK_ENUM_TYPES_H__\n";
123   print "#define __GDK_ENUM_TYPES_H__\n";
124 }
125
126 if ($gen_cfile) {
127   print "#include \"gdk.h\"\n";
128 }
129
130 ENUMERATION:
131 while (<>) {
132     if (eof) {
133         close (ARGV);           # reset line numbering
134         $firstenum = 1;         # Flag to print filename at next enum
135     }
136
137     if (m@^\s*typedef\s+enum\s*
138            ({)?\s*
139            (?:/\*<
140              (([^*]|\*(?!/))*)
141             >\*/)?
142          @x) {
143       print "\n";
144         if (defined $2) {
145             my %options = parse_options($2);
146             $prefix = $options{prefix};
147             $flags = $options{flags};
148         } else {
149             $prefix = undef;
150             $flags = undef;
151         }
152         # Didn't have trailing '{' look on next lines
153         if (!defined $1) {
154             while (<>) {
155                 if (s/^\s*\{//) {
156                     last;
157                 }
158             }
159         }
160
161         $seenbitshift = 0;
162         @entries = ();
163
164         # Now parse the entries
165         parse_entries (\*ARGV);
166
167         # figure out if this was a flags or enums enumeration
168
169         if (!defined $flags) {
170             $flags = $seenbitshift;
171         }
172
173         # Autogenerate a prefix
174
175         if (!defined $prefix) {
176             for (@entries) {
177                 my $name = $_->[0];
178                 if (defined $prefix) {
179                     my $tmp = ~ ($name ^ $prefix);
180                     ($tmp) = $tmp =~ /(^\xff*)/;
181                     $prefix = $prefix & $tmp;
182                 } else {
183                     $prefix = $name;
184                 }
185             }
186             # Trim so that it ends in an underscore
187             $prefix =~ s/_[^_]*$/_/;
188         }
189         
190         for $entry (@entries) {
191             my ($name,$nick) = @{$entry};
192             if (!defined $nick) {
193                 ($nick = $name) =~ s/^$prefix//;
194                 $nick =~ tr/_/-/;
195                 $nick = lc($nick);
196                 @{$entry} = ($name, $nick);
197             }
198         }
199
200         # Spit out the output
201
202         my $valuename = $enumname;
203         $valuename =~ s/([^A-Z])([A-Z])/$1_$2/g;
204         $valuename =~ s/([A-Z][A-Z])([A-Z][0-9a-z])/$1_$2/g;
205         $valuename = lc($valuename);
206
207         my $typemacro = $enumname;
208         $typemacro =~ s/([^A-Z])([A-Z])/$1_$2/g;
209         $typemacro =~ s/([A-Z][A-Z])([A-Z][0-9a-z])/$1_$2/g;
210         $typemacro = uc($valuename);
211         $typemacro =~ s/GDK_/GDK_TYPE_/g;
212
213         if ($gen_defs) {
214             if ($firstenum) {
215                 print qq(\n; enumerations from "$ARGV"\n);
216                 $firstenum = 0;
217             }
218
219             print "\n(define-".($flags ? "flags" : "enum")." $enumname";
220
221             for (@entries) {
222                 my ($name,$nick) = @{$_};
223                 print "\n   ($nick $name)";
224             }
225             print ")\n";
226
227         } elsif ($gen_arrays) {
228
229             print "static const GtkEnumValue _${valuename}_values[] = {\n";
230             for (@entries) {
231                 my ($name,$nick) = @{$_};
232                 print qq(  { $name, "$name", "$nick" },\n);
233             }
234             print "  { 0, NULL, NULL }\n";
235             print "};\n";
236         } elsif ($gen_includes) {
237             print "GType ${valuename}_get_type (void);\n";
238             print "#define ${typemacro} ${valuename}_get_type ()\n";
239           } elsif ($gen_cfile) {
240             print (<<EOF);
241 GType
242 ${valuename}_get_type (void)
243 {
244   static GType etype = 0;
245   if (etype == 0)
246     {
247 EOF
248             if ($flags) {
249               print "      static const GFlagsValue values[] = {\n";
250             } else {
251               print "      static const GEnumValue values[] = {\n";
252             }
253             for (@entries) {
254               my ($name,$nick) = @{$_};
255               print qq(        { $name, "$name", "$nick" },\n);
256             }
257             print "        { 0, NULL, NULL }\n";
258             print "      };\n";
259
260             if ($flags) {
261               print "      etype = g_flags_register_static (\"$enumname\", values);\n";
262             } else {
263               print "      etype = g_enum_register_static (\"$enumname\", values);\n";
264             }
265
266             print (<<EOF);
267     }
268   return etype;
269 }
270 EOF
271           }
272         print "\n";
273       }
274   }
275
276
277 if ($gen_includes) {
278   print "#endif /* __GDK_ENUMS_H__ */\n";
279 }