line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#!/usr/bin/perl |
2
|
|
|
|
|
|
|
# |
3
|
|
|
|
|
|
|
# generate the SWIG input file by preprocessing the X and Motif header files |
4
|
|
|
|
|
|
|
# |
5
|
|
|
|
|
|
|
# This was developed incrementally, by feeding the output to SWIG, |
6
|
|
|
|
|
|
|
# seeing what it did not like, and developing PERL regular expressions |
7
|
|
|
|
|
|
|
# to do the proper massaging. |
8
|
|
|
|
|
|
|
# |
9
|
|
|
|
|
|
|
# Porting to another platform will require changes to the way that the |
10
|
|
|
|
|
|
|
# preprocessor is invoked (including possibly a different set of |
11
|
|
|
|
|
|
|
# header files) and some new regexp processing. |
12
|
|
|
|
|
|
|
# |
13
|
|
|
|
|
|
|
|
14
|
1
|
|
|
|
|
5
|
$INFILE = $ARGV[0]; |
15
|
1
|
|
|
|
|
2
|
$NUM_XTPROCS = $ARGV[1]; |
16
|
|
|
|
|
|
|
|
17
|
1
|
|
|
|
|
5
|
read_input(); |
18
|
1
|
|
|
|
|
11
|
discard_uninteresting_header_files(); |
19
|
1
|
|
|
|
|
7
|
make_defines(); |
20
|
1
|
|
|
|
|
11
|
make_output(); |
21
|
1
|
|
|
|
|
26
|
add_xtprocs(); |
22
|
1
|
|
|
|
|
6
|
add_standard_member_functions(); |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
# helper function to emit SWIG input lines |
25
|
|
|
|
|
|
|
sub emit |
26
|
|
|
|
|
|
|
{ |
27
|
0
|
|
|
0
|
|
0
|
my($s) = @_; |
28
|
0
|
|
|
|
|
0
|
$s =~ s#^[^\S\n]*\n##; |
29
|
0
|
|
|
|
|
0
|
$s =~ s#^[^\S\n]+\Z##m; |
30
|
0
|
|
|
|
|
0
|
$s =~ m#^([^\S\n]*\|?)#; |
31
|
0
|
|
|
|
|
0
|
my $x = quotemeta $1; |
32
|
0
|
|
|
|
|
0
|
$s =~ s#^$x##gm; |
33
|
0
|
|
|
|
|
0
|
print STDOUT $s; |
34
|
|
|
|
|
|
|
} |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
# generate and read in the input |
37
|
|
|
|
|
|
|
sub read_input |
38
|
|
|
|
|
|
|
{ |
39
|
|
|
|
|
|
|
# run the preprocessor on the header files in which we are interested |
40
|
1
|
|
|
1
|
|
37746
|
open(IN, q{ |
41
|
|
|
|
|
|
|
set -x |
42
|
|
|
|
|
|
|
TEMP=/tmp/temp.wcl-gen.$$.c |
43
|
|
|
|
|
|
|
grep '^#include' } . $INFILE . q{ >$TEMP |
44
|
|
|
|
|
|
|
$CC -E $CCFLAGS $TEMP |
45
|
|
|
|
|
|
|
rm -f $TEMP |
46
|
|
|
|
|
|
|
|}); |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
# read it all into a string |
49
|
1
|
|
|
|
|
37
|
$x = $/; |
50
|
1
|
|
|
|
|
763
|
undef $/; |
51
|
1
|
|
|
|
|
70046
|
$data = ; |
52
|
1
|
|
|
|
|
20
|
$/ = $x; |
53
|
|
|
|
|
|
|
|
54
|
1
|
|
|
|
|
87
|
close(IN); |
55
|
|
|
|
|
|
|
} |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
# chuck header files not apropos to this application |
58
|
|
|
|
|
|
|
sub discard_uninteresting_header_files |
59
|
|
|
|
|
|
|
{ |
60
|
|
|
|
|
|
|
# remove header files we are not interested in |
61
|
|
|
|
|
|
|
# this is undoubtedly somewhat preprocessor dependent |
62
|
1
|
|
|
1
|
|
13
|
$data =~ s@^#line @# @gm; |
63
|
1
|
|
|
|
|
23
|
$data =~ s@^# \d+\n@@gm; |
64
|
1
|
|
|
|
|
31
|
$data =~ s@^# \d+ "/usr/include/(?!X).*\n(([^#\n].*)?\n)*@@gm; |
65
|
1
|
|
|
|
|
6
|
$data =~ s@^# \d+ "/usr/lib/.*\n(([^#\n].*)?\n)*@@gm; |
66
|
1
|
|
|
|
|
3
|
$data =~ s@^# \d+ "/usr/local/lib/.*\n(([^#\n].*)?\n)*@@gm; |
67
|
1
|
|
|
|
|
4
|
$data =~ s@^# \d+ "/usr/X11R6/include/.*P[.]h".*\n(([^#\n].*)?\n)*@@gm; |
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
# pull #defines out of input; they disappear from cpp output |
71
|
|
|
|
|
|
|
sub make_defines |
72
|
|
|
|
|
|
|
{ |
73
|
|
|
|
|
|
|
# extract #define constants from header files mentioned in input |
74
|
1
|
|
|
1
|
|
24
|
while ($data =~ m@^# \d+ "(\S+)"@gm) { |
75
|
4
|
100
|
|
|
|
38
|
next unless !$seen{$1}++; |
76
|
2
|
|
|
|
|
101
|
open(IN, "<$1"); |
77
|
2
|
|
|
|
|
17
|
while () { |
78
|
|
|
|
|
|
|
# define with no arguments |
79
|
0
|
0
|
|
|
|
0
|
next unless /^\s*#\s*define\s+\w+\s+/; |
80
|
|
|
|
|
|
|
# strip trailing comments |
81
|
0
|
|
|
|
|
0
|
s#\s*/\*((?!\*/).)*\*/[^\S\n]$##; |
82
|
|
|
|
|
|
|
# empty |
83
|
0
|
0
|
|
|
|
0
|
next if /^\s*#\s*define\s+\w+\s*$/; |
84
|
|
|
|
|
|
|
# strings |
85
|
0
|
0
|
|
|
|
0
|
next if /^\s*#\s*define\s+\w+\s+"[^"]*"\s*$/; #" |
86
|
|
|
|
|
|
|
# integer expressions |
87
|
0
|
0
|
|
|
|
0
|
next unless (/^ |
88
|
|
|
|
|
|
|
\s*\#\s*define\s+(\w+)\s+ |
89
|
|
|
|
|
|
|
(( |
90
|
|
|
|
|
|
|
-?\d+L? | |
91
|
|
|
|
|
|
|
-?0[xX][0-9a-fA-F]+L? | |
92
|
|
|
|
|
|
|
[()|] | |
93
|
|
|
|
|
|
|
<< | |
94
|
|
|
|
|
|
|
>> |
95
|
|
|
|
|
|
|
)\s*)+ |
96
|
|
|
|
|
|
|
$/x); |
97
|
0
|
|
|
|
|
0
|
print STDOUT "#ifndef $1\n"; |
98
|
0
|
|
|
|
|
0
|
print STDOUT; |
99
|
0
|
|
|
|
|
0
|
print STDOUT "#endif\n"; |
100
|
|
|
|
|
|
|
} |
101
|
2
|
|
|
|
|
11
|
close(IN); |
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
# massage input header files into something that SWIG can digest |
106
|
|
|
|
|
|
|
sub make_output |
107
|
|
|
|
|
|
|
{ |
108
|
|
|
|
|
|
|
# chuck preprocessor lines |
109
|
1
|
|
|
1
|
|
14
|
$data =~ s@^#.*\n@@gm; |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
# chuck blank lines |
112
|
1
|
|
|
|
|
3
|
$data =~ s/^[^\S\n]*\n//gm; |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
# eliminate trailing white space |
115
|
1
|
|
|
|
|
2
|
$data =~ s/[^\S\n]+\n/\n/g; |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
# convert multiple white space to single blank |
118
|
1
|
|
|
|
|
1
|
$data =~ s/[^\S\n]+/ /g; |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
# eliminate keywords not known to SWIG |
121
|
1
|
|
|
|
|
4
|
$data =~ s#\b(register|__signed||unsigned)\b##gm; |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
# rename C++ reserved words |
124
|
1
|
|
|
|
|
2
|
$data =~ s#\b(new|class)\b#PASS_THROUGH_SWIG_$1#gm; |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
# eliminate global arrays |
127
|
1
|
|
|
|
|
1
|
$data =~ s/^\s*(typedef|extern)( \w+)+ \w+\[\];\n//mg; |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
# eliminate vararg declarations |
130
|
1
|
|
|
|
|
3
|
$data =~ s/^(extern|typedef)( \w+)? \(?\*?\w+\)?\s*\([^)]*,\s*\.\.\.\s*\)\s*;\s*\n//mg; |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
# eliminate function pointer declarations |
133
|
1
|
|
|
|
|
3
|
$data =~ s/^extern \S+ \(\*\w+\(((?!\)\s*;)(.|\n))*\)\s*;\n//mg; |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
# eliminate functions that get passed function pointers |
136
|
1
|
|
|
|
|
5
|
$data =~ s/^extern( \S+)? \*?\w+\(((?!\)\s*;)(.|\n))*,\s*\w+\s*\(\s*\*\s*\)\s*\(((?!\)\s*;)(.|\n))*\)\s*;\n//mg; |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
# various other special cases |
139
|
1
|
|
|
|
|
2
|
$data =~ s/^extern( \w+)? WcWidgetResourcesInitialize\s*\(\s*[^;]*;\n//m; |
140
|
1
|
|
|
|
|
2
|
$data =~ s/^typedef struct( \S+)?\s*\{\n(([^}\n].*)?\n)*\}\s*XImage;\n//m; |
141
|
1
|
|
|
|
|
2
|
$data =~ s/^typedef struct( \S+)?\s*\{\n(([^}\n].*)?\n)*\}\s*XExtData;\n//m; |
142
|
1
|
|
|
|
|
1
|
$data =~ s/^typedef struct( \S+)?\s*\{\n(([^}\n].*)?\n)*\}\s*XSizeHints;\n//m; |
143
|
1
|
|
|
|
|
2
|
$data =~ s/^typedef struct( \S+)?\s*\{\n(([^}\n].*)?\n)*\}\s*\*_XPrivDisplay;\n//m; |
144
|
|
|
|
|
|
|
# added for aix 3.2.5 and HPUX 10 |
145
|
1
|
|
|
|
|
2
|
$data =~ s/^typedef struct( \S+)?\s*\{\n(([^}\n].*)?\n)*\}\s*\*GC;\n//m; |
146
|
1
|
|
|
|
|
2
|
$data =~ s/^void XmpChangeNavigationType \( Widget \)\s*;\n//m; |
147
|
1
|
|
|
|
|
2
|
$data =~ s/^extern void ToggleCursorGC\s*\([^()]*\)\s*;\n//m; |
148
|
|
|
|
|
|
|
# seems to be in header file but missing from libraries in RedHat Motif |
149
|
1
|
|
|
|
|
2
|
$data =~ s/^extern \S+ XmCSTextGetTextPath\s*\([^()]*\)\s*;\s*\n//m; |
150
|
1
|
|
|
|
|
2
|
$data =~ s/^extern \S+ XmCSTextSetTextPath\s*\([^()]*\)\s*;\s*\n//m; |
151
|
1
|
|
|
|
|
2
|
$data =~ s/^extern \S+ XmCSTextMarkRedraw\s*\([^()]*\)\s*;\s*\n//m; |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
# done massaging |
154
|
1
|
|
|
|
|
13
|
print STDOUT $data; |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
# create Xt*Proc() interface |
158
|
|
|
|
|
|
|
sub add_xtprocs |
159
|
|
|
|
|
|
|
{ |
160
|
1
|
|
|
1
|
|
7
|
while ($data =~ m#typedef\s+(\S+)\s*\(\s*\*\s*(Xt\w+Proc)\s*\)\s*\(([^()]*)\)#g) { |
161
|
0
|
|
|
|
|
|
my($type, $name, $args) = ($1, $2, $3); |
162
|
0
|
|
|
|
|
|
my @args = split(/\s*,\s*/, $args); |
163
|
0
|
|
|
|
|
|
my $arg; |
164
|
|
|
|
|
|
|
my @x; |
165
|
0
|
|
|
|
|
|
my @argnames; |
166
|
0
|
|
|
|
|
|
my $i = 0; |
167
|
0
|
|
|
|
|
|
for $arg (@args) { |
168
|
0
|
|
|
|
|
|
push(@x, "$arg arg$i"); |
169
|
0
|
|
|
|
|
|
push(@argnames, ", arg$i"); |
170
|
0
|
|
|
|
|
|
++$i; |
171
|
|
|
|
|
|
|
} |
172
|
0
|
|
|
|
|
|
$args = join(",\n", @x); |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
# emit the standard functions |
175
|
0
|
|
|
|
|
|
emit(qq( |
176
|
|
|
|
|
|
|
\%{ |
177
|
|
|
|
|
|
|
)); |
178
|
0
|
|
|
|
|
|
emit(qq( |
179
|
|
|
|
|
|
|
static int xtproc_key_$name; |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
static $type |
182
|
|
|
|
|
|
|
Standard$name(int function_number, $args) |
183
|
|
|
|
|
|
|
{ |
184
|
|
|
|
|
|
|
char *perl_procedure_name = |
185
|
|
|
|
|
|
|
MapAg_Find(_X11_Wcl_agent, &xtproc_key_$name, function_number, 0); |
186
|
|
|
|
|
|
|
if (perl_procedure_name) { |
187
|
|
|
|
|
|
|
char *argv[1]; |
188
|
|
|
|
|
|
|
argv[0] = 0; |
189
|
|
|
|
|
|
|
/* do the callback, discarding any results */ |
190
|
|
|
|
|
|
|
perl_call_argv(perl_procedure_name, G_DISCARD, argv); |
191
|
|
|
|
|
|
|
} |
192
|
|
|
|
|
|
|
} |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
)); |
195
|
0
|
|
|
|
|
|
for ($i=0; $i<$NUM_XTPROCS; ++$i) { |
196
|
0
|
|
|
|
|
|
emit(qq( |
197
|
|
|
|
|
|
|
static $type |
198
|
|
|
|
|
|
|
Standard$name$i($args) |
199
|
|
|
|
|
|
|
{ |
200
|
|
|
|
|
|
|
Standard$name($i @argnames); |
201
|
|
|
|
|
|
|
} |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
)); |
204
|
|
|
|
|
|
|
} |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
# emit the table of standard functions |
207
|
0
|
|
|
|
|
|
emit(qq( |
208
|
|
|
|
|
|
|
static $name table_$name\[] = { |
209
|
|
|
|
|
|
|
)); |
210
|
0
|
|
|
|
|
|
for ($i=0; $i<$NUM_XTPROCS; ++$i) { |
211
|
0
|
|
|
|
|
|
emit(qq( |
212
|
|
|
|
|
|
|
Standard$name$i, |
213
|
|
|
|
|
|
|
)); |
214
|
|
|
|
|
|
|
} |
215
|
0
|
|
|
|
|
|
emit(qq( |
216
|
|
|
|
|
|
|
}; |
217
|
|
|
|
|
|
|
)); |
218
|
0
|
|
|
|
|
|
emit(qq( |
219
|
|
|
|
|
|
|
\%} |
220
|
|
|
|
|
|
|
)); |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
# emit allocator for standard functions |
223
|
0
|
|
|
|
|
|
emit(qq( |
224
|
|
|
|
|
|
|
\%inline \%{ |
225
|
|
|
|
|
|
|
$name |
226
|
|
|
|
|
|
|
Make$name(char *perl_procedure_name) |
227
|
|
|
|
|
|
|
{ |
228
|
|
|
|
|
|
|
static int counter = 0; |
229
|
|
|
|
|
|
|
if ((counter + 1) < $NUM_XTPROCS) { |
230
|
|
|
|
|
|
|
char *x = strdup(perl_procedure_name); |
231
|
|
|
|
|
|
|
MapAg_Define(_X11_Wcl_agent, &xtproc_key_$name, counter, 0, x); |
232
|
|
|
|
|
|
|
return(table_$name\[counter++]); |
233
|
|
|
|
|
|
|
} else { |
234
|
|
|
|
|
|
|
return(($name)0); |
235
|
|
|
|
|
|
|
} |
236
|
|
|
|
|
|
|
} |
237
|
|
|
|
|
|
|
\%} |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
)); |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
# add constructors, destructors and other member functions to structs |
244
|
|
|
|
|
|
|
# found in the input header files of interest |
245
|
|
|
|
|
|
|
sub add_standard_member_functions |
246
|
|
|
|
|
|
|
{ |
247
|
1
|
|
|
1
|
|
|
while ($data =~ m/ |
248
|
|
|
|
|
|
|
typedef \s* |
249
|
|
|
|
|
|
|
(?:struct|union)(?:\s+\S+)? \s* |
250
|
|
|
|
|
|
|
{ (?: |
251
|
|
|
|
|
|
|
[^{}]+ | |
252
|
|
|
|
|
|
|
{ (?: |
253
|
|
|
|
|
|
|
[^{}]+ | |
254
|
|
|
|
|
|
|
{ (?: |
255
|
|
|
|
|
|
|
[^{}]+ |
256
|
|
|
|
|
|
|
)* } |
257
|
|
|
|
|
|
|
)* } |
258
|
|
|
|
|
|
|
)* } \s* |
259
|
|
|
|
|
|
|
(\*?\w+) |
260
|
|
|
|
|
|
|
/mgx) { |
261
|
0
|
|
|
|
|
|
$struct = $1; |
262
|
0
|
0
|
|
|
|
|
next unless $struct =~ /^\w+$/; |
263
|
0
|
|
|
|
|
|
emit(qq( |
264
|
|
|
|
|
|
|
\%addmethods $struct { |
265
|
|
|
|
|
|
|
$struct(int address = 0, int count = 0) { |
266
|
|
|
|
|
|
|
return(($struct *)_X11_Wcl_do_constructor(address, count, sizeof($struct))); |
267
|
|
|
|
|
|
|
} |
268
|
|
|
|
|
|
|
~$struct() { |
269
|
|
|
|
|
|
|
_X11_Wcl_do_destructor((char *)self); |
270
|
|
|
|
|
|
|
} |
271
|
|
|
|
|
|
|
$struct * |
272
|
|
|
|
|
|
|
idx(int i) { |
273
|
|
|
|
|
|
|
return(self + i); |
274
|
|
|
|
|
|
|
} |
275
|
|
|
|
|
|
|
}; |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
)); |
278
|
|
|
|
|
|
|
} |
279
|
|
|
|
|
|
|
} |