Commit | Line | Data |
---|---|---|
85ed45e3 | 1 | #! /usr/bin/perl -w |
767e6f6f | 2 | # |
5bc78089 | 3 | # Build the server/trace.c and server/request.h files |
37ec9275 | 4 | # from the contents of include/wine/server.h. |
767e6f6f AJ |
5 | # |
6 | # Copyright (C) 1998 Alexandre Julliard | |
7 | # | |
0799c1a7 AJ |
8 | # This library is free software; you can redistribute it and/or |
9 | # modify it under the terms of the GNU Lesser General Public | |
10 | # License as published by the Free Software Foundation; either | |
11 | # version 2.1 of the License, or (at your option) any later version. | |
12 | # | |
13 | # This library is distributed in the hope that it will be useful, | |
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | # Lesser General Public License for more details. | |
17 | # | |
18 | # You should have received a copy of the GNU Lesser General Public | |
19 | # License along with this library; if not, write to the Free Software | |
20 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 | # | |
bd007ba1 | 22 | use strict; |
767e6f6f | 23 | |
bd007ba1 | 24 | my %formats = |
767e6f6f | 25 | ( |
3e2517ca | 26 | "int" => "%d", |
0b83d4cb | 27 | "short int" => "%d", |
3e2517ca | 28 | "char" => "%c", |
0a7c1f6c | 29 | "unsigned char" => "%02x", |
838d65ae | 30 | "unsigned short"=> "%04x", |
3e2517ca AJ |
31 | "unsigned int" => "%08x", |
32 | "void*" => "%p", | |
33 | "time_t" => "%ld", | |
9caa71ee | 34 | "size_t" => "%d", |
b3332d74 | 35 | "obj_handle_t" => "%p", |
d8a8c113 | 36 | "atom_t" => "%04x", |
b3332d74 | 37 | "user_handle_t" => "%p", |
91befe1d AJ |
38 | "process_id_t" => "%04x", |
39 | "thread_id_t" => "%04x", | |
462172a3 | 40 | "abs_time_t" => "&dump_abs_time", |
0d50965a | 41 | "rectangle_t" => "&dump_rectangle", |
9caa71ee | 42 | "char_info_t" => "&dump_char_info", |
767e6f6f AJ |
43 | ); |
44 | ||
45 | my @requests = (); | |
46 | my %replies = (); | |
47 | ||
37ec9275 | 48 | my @trace_lines = (); |
767e6f6f | 49 | |
9caa71ee | 50 | |
767e6f6f | 51 | |
11a7b29a FG |
52 | ### Generate a dumping function |
53 | ||
54 | sub DO_DUMP_FUNC($$@) | |
55 | { | |
56 | my $name = shift; | |
57 | my $req = shift; | |
58 | push @trace_lines, "static void dump_${name}_$req( const struct ${name}_$req *req )\n{\n"; | |
59 | while ($#_ >= 0) | |
60 | { | |
61 | my $type = shift; | |
62 | my $var = shift; | |
63 | if (defined($formats{$type})) | |
64 | { | |
65 | if ($formats{$type} =~ /^&(.*)/) | |
66 | { | |
67 | my $func = $1; | |
68 | push @trace_lines, " fprintf( stderr, \" $var=\" );\n"; | |
69 | push @trace_lines, " $func( &req->$var );\n"; | |
70 | push @trace_lines, " fprintf( stderr, \",\" );\n" if ($#_ > 0); | |
71 | } | |
72 | else | |
73 | { | |
74 | push @trace_lines, " fprintf( stderr, \" $var=$formats{$type}"; | |
75 | push @trace_lines, "," if ($#_ > 0); | |
76 | push @trace_lines, "\", "; | |
77 | # In the case of time_t we need to cast the parameter to | |
78 | # long to match the associated "%ld" printf modifier. | |
79 | push @trace_lines, "(long)" if( $type eq "time_t" ); | |
80 | push @trace_lines, "req->$var );\n"; | |
81 | } | |
82 | } | |
83 | else # must be some varargs format | |
84 | { | |
85 | my $func = $type; | |
86 | push @trace_lines, " fprintf( stderr, \" $var=\" );\n"; | |
87 | push @trace_lines, " $func;\n"; | |
88 | push @trace_lines, " fputc( ',', stderr );\n" if ($#_ > 0); | |
89 | } | |
90 | } | |
91 | push @trace_lines, "}\n\n"; | |
92 | } | |
93 | ||
37ec9275 | 94 | ### Parse the request definitions |
767e6f6f | 95 | |
bd007ba1 | 96 | sub PARSE_REQUESTS() |
767e6f6f | 97 | { |
37ec9275 AJ |
98 | # states: 0 = header 1 = declarations 2 = inside @REQ 3 = inside @REPLY |
99 | my $state = 0; | |
100 | my $name = ""; | |
ebe29ef3 AJ |
101 | my @in_struct = (); |
102 | my @out_struct = (); | |
37ec9275 AJ |
103 | |
104 | open(PROTOCOL,"server/protocol.def") or die "Can't open server/protocol.def"; | |
105 | ||
106 | while (<PROTOCOL>) | |
767e6f6f | 107 | { |
37ec9275 AJ |
108 | my ($type, $var); |
109 | # strip comments | |
767e6f6f | 110 | s!/\*.*\*/!!g; |
37ec9275 AJ |
111 | # strip white space at end of line |
112 | s/\s+$//; | |
113 | ||
114 | if (/^\@HEADER/) | |
115 | { | |
116 | die "Misplaced \@HEADER" unless $state == 0; | |
117 | $state++; | |
118 | next; | |
119 | } | |
120 | ||
121 | # ignore everything while in state 0 | |
122 | next if $state == 0; | |
123 | ||
124 | if (/^\@REQ\(\s*(\w+)\s*\)/) | |
86113530 | 125 | { |
37ec9275 AJ |
126 | $name = $1; |
127 | die "Misplaced \@REQ" unless $state == 1; | |
128 | # start a new request | |
129 | @in_struct = (); | |
130 | @out_struct = (); | |
131 | print SERVER_PROT "struct ${name}_request\n{\n"; | |
132 | print SERVER_PROT " struct request_header __header;\n"; | |
133 | $state++; | |
86113530 AJ |
134 | next; |
135 | } | |
37ec9275 AJ |
136 | |
137 | if (/^\@REPLY/) | |
86113530 | 138 | { |
37ec9275 | 139 | die "Misplaced \@REPLY" unless $state == 2; |
9caa71ee AJ |
140 | print SERVER_PROT "};\n"; |
141 | print SERVER_PROT "struct ${name}_reply\n{\n"; | |
142 | print SERVER_PROT " struct reply_header __header;\n"; | |
37ec9275 AJ |
143 | $state++; |
144 | next; | |
86113530 | 145 | } |
37ec9275 AJ |
146 | |
147 | if (/^\@END/) | |
86113530 | 148 | { |
37ec9275 AJ |
149 | die "Misplaced \@END" unless ($state == 2 || $state == 3); |
150 | print SERVER_PROT "};\n"; | |
151 | ||
9caa71ee AJ |
152 | if ($state == 2) # build dummy reply struct |
153 | { | |
154 | print SERVER_PROT "struct ${name}_reply\n{\n"; | |
155 | print SERVER_PROT " struct reply_header __header;\n"; | |
156 | print SERVER_PROT "};\n"; | |
157 | } | |
158 | ||
37ec9275 AJ |
159 | # got a complete request |
160 | push @requests, $name; | |
11a7b29a | 161 | DO_DUMP_FUNC( $name, "request", @in_struct); |
37ec9275 AJ |
162 | if ($#out_struct >= 0) |
163 | { | |
164 | $replies{$name} = 1; | |
11a7b29a | 165 | DO_DUMP_FUNC( $name, "reply", @out_struct); |
37ec9275 AJ |
166 | } |
167 | $state = 1; | |
168 | next; | |
86113530 | 169 | } |
37ec9275 AJ |
170 | |
171 | if ($state != 1) | |
86113530 | 172 | { |
37ec9275 AJ |
173 | # skip empty lines (but keep them in output file) |
174 | if (/^$/) | |
175 | { | |
176 | print SERVER_PROT "\n"; | |
177 | next; | |
178 | } | |
179 | ||
9caa71ee AJ |
180 | if (/^\s*VARARG\((\w+),(\w+),(\w+)\)/) |
181 | { | |
182 | $var = $1; | |
183 | $type = "dump_varargs_" . $2 . "( min(cur_size,req->" . $3 . ") )"; | |
184 | s!(VARARG\(.*\)\s*;)!/* $1 */!; | |
185 | } | |
186 | elsif (/^\s*VARARG\((\w+),(\w+)\)/) | |
37ec9275 AJ |
187 | { |
188 | $var = $1; | |
9caa71ee | 189 | $type = "dump_varargs_" . $2 . "( cur_size )"; |
37ec9275 AJ |
190 | s!(VARARG\(.*\)\s*;)!/* $1 */!; |
191 | } | |
9caa71ee | 192 | elsif (/^\s*(\w+\**(\s+\w+\**)*)\s+(\w+);/) |
37ec9275 | 193 | { |
9caa71ee | 194 | $type = $1; |
37ec9275 | 195 | $var = $3; |
9caa71ee | 196 | die "Unrecognized type $type" unless defined($formats{$type}); |
37ec9275 AJ |
197 | } |
198 | else | |
199 | { | |
200 | die "Unrecognized syntax $_"; | |
201 | } | |
202 | if ($state == 2) { push @in_struct, $type, $var; } | |
203 | if ($state == 3) { push @out_struct, $type, $var; } | |
86113530 | 204 | } |
37ec9275 AJ |
205 | |
206 | # Pass it through into the output file | |
207 | print SERVER_PROT $_ . "\n"; | |
767e6f6f | 208 | } |
37ec9275 | 209 | close PROTOCOL; |
767e6f6f AJ |
210 | } |
211 | ||
37ec9275 AJ |
212 | ### Retrieve the server protocol version from the existing server_protocol.h file |
213 | ||
bd007ba1 | 214 | sub GET_PROTOCOL_VERSION() |
37ec9275 AJ |
215 | { |
216 | my $protocol = 0; | |
217 | open SERVER_PROT, "include/wine/server_protocol.h" or return 0; | |
218 | while (<SERVER_PROT>) | |
219 | { | |
220 | if (/^\#define SERVER_PROTOCOL_VERSION (\d+)/) { $protocol = $1; last; } | |
221 | } | |
222 | close SERVER_PROT; | |
223 | return $protocol; | |
224 | } | |
225 | ||
5bc78089 AJ |
226 | ### Replace the contents of a file between ### make_requests ### marks |
227 | ||
bd007ba1 | 228 | sub REPLACE_IN_FILE($@) |
5bc78089 AJ |
229 | { |
230 | my $name = shift; | |
231 | my @data = @_; | |
232 | my @lines = (); | |
233 | open(FILE,$name) or die "Can't open $name"; | |
234 | while (<FILE>) | |
235 | { | |
236 | push @lines, $_; | |
237 | last if /\#\#\# make_requests begin \#\#\#/; | |
238 | } | |
239 | push @lines, "\n", @data; | |
240 | while (<FILE>) | |
241 | { | |
242 | if (/\#\#\# make_requests end \#\#\#/) { push @lines, "\n", $_; last; } | |
243 | } | |
244 | push @lines, <FILE>; | |
245 | open(FILE,">$name") or die "Can't modify $name"; | |
246 | print FILE @lines; | |
247 | close(FILE); | |
767e6f6f | 248 | } |
bd007ba1 FG |
249 | |
250 | ### Main | |
251 | ||
252 | # Get the server protocol version | |
253 | my $protocol = GET_PROTOCOL_VERSION(); | |
254 | ||
255 | ### Create server_protocol.h and print header | |
256 | ||
257 | open SERVER_PROT, ">include/wine/server_protocol.h" or die "Cannot create include/wine/server_protocol.h"; | |
258 | print SERVER_PROT "/*\n * Wine server protocol definitions\n *\n"; | |
259 | print SERVER_PROT " * This file is automatically generated; DO NO EDIT!\n"; | |
260 | print SERVER_PROT " * Edit server/protocol.def instead and re-run tools/make_requests\n"; | |
261 | print SERVER_PROT " */\n\n"; | |
262 | print SERVER_PROT "#ifndef __WINE_WINE_SERVER_PROTOCOL_H\n"; | |
263 | print SERVER_PROT "#define __WINE_WINE_SERVER_PROTOCOL_H\n"; | |
264 | ||
265 | ### Parse requests to find request/reply structure definitions | |
266 | ||
267 | PARSE_REQUESTS(); | |
268 | ||
269 | ### Build the request list and structures | |
270 | ||
271 | print SERVER_PROT "\n\nenum request\n{\n"; | |
272 | foreach my $req (@requests) { print SERVER_PROT " REQ_$req,\n"; } | |
273 | print SERVER_PROT " REQ_NB_REQUESTS\n};\n\n"; | |
274 | ||
275 | print SERVER_PROT "union generic_request\n{\n"; | |
276 | print SERVER_PROT " struct request_max_size max_size;\n"; | |
277 | print SERVER_PROT " struct request_header request_header;\n"; | |
278 | foreach my $req (@requests) { print SERVER_PROT " struct ${req}_request ${req}_request;\n"; } | |
279 | print SERVER_PROT "};\n"; | |
280 | ||
281 | print SERVER_PROT "union generic_reply\n{\n"; | |
282 | print SERVER_PROT " struct request_max_size max_size;\n"; | |
283 | print SERVER_PROT " struct reply_header reply_header;\n"; | |
284 | foreach my $req (@requests) { print SERVER_PROT " struct ${req}_reply ${req}_reply;\n"; } | |
285 | print SERVER_PROT "};\n\n"; | |
286 | ||
287 | printf SERVER_PROT "#define SERVER_PROTOCOL_VERSION %d\n\n", $protocol + 1; | |
288 | print SERVER_PROT "#endif /* __WINE_WINE_SERVER_PROTOCOL_H */\n"; | |
289 | close SERVER_PROT; | |
290 | ||
291 | ### Output the dumping function tables | |
292 | ||
293 | push @trace_lines, "static const dump_func req_dumpers[REQ_NB_REQUESTS] = {\n"; | |
294 | foreach my $req (@requests) | |
295 | { | |
296 | push @trace_lines, " (dump_func)dump_${req}_request,\n"; | |
297 | } | |
298 | push @trace_lines, "};\n\n"; | |
299 | ||
300 | push @trace_lines, "static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {\n"; | |
301 | foreach my $req (@requests) | |
302 | { | |
303 | push @trace_lines, " (dump_func)", $replies{$req} ? "dump_${req}_reply,\n" : "0,\n"; | |
304 | } | |
305 | push @trace_lines, "};\n\n"; | |
306 | ||
307 | push @trace_lines, "static const char * const req_names[REQ_NB_REQUESTS] = {\n"; | |
308 | foreach my $req (@requests) | |
309 | { | |
310 | push @trace_lines, " \"$req\",\n"; | |
311 | } | |
312 | push @trace_lines, "};\n"; | |
313 | ||
314 | REPLACE_IN_FILE( "server/trace.c", @trace_lines ); | |
691884b9 AJ |
315 | |
316 | ### Output the request handlers list | |
317 | ||
318 | my @request_lines = (); | |
319 | ||
320 | foreach my $req (@requests) { push @request_lines, "DECL_HANDLER($req);\n"; } | |
321 | push @request_lines, "\n#ifdef WANT_REQUEST_HANDLERS\n\n"; | |
322 | push @request_lines, "typedef void (*req_handler)( const void *req, void *reply );\n"; | |
323 | push @request_lines, "static const req_handler req_handlers[REQ_NB_REQUESTS] =\n{\n"; | |
324 | foreach my $req (@requests) | |
325 | { | |
326 | push @request_lines, " (req_handler)req_$req,\n"; | |
327 | } | |
328 | push @request_lines, "};\n#endif /* WANT_REQUEST_HANDLERS */\n"; | |
329 | ||
330 | REPLACE_IN_FILE( "server/request.h", @request_lines ); |