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