blob: 34cd54d0b53285eec73bc4e03bf053223922c1c4 [file] [log] [blame]
Alexandre Julliard85ed45e1998-08-22 19:03:56 +00001#! /usr/bin/perl -w
Alexandre Julliard767e6f61998-08-09 12:47:43 +00002#
Alexandre Julliard5bc78081999-06-22 17:26:53 +00003# Build the server/trace.c and server/request.h files
Alexandre Julliard37ec9272001-07-19 00:35:37 +00004# from the contents of include/wine/server.h.
Alexandre Julliard767e6f61998-08-09 12:47:43 +00005#
6# Copyright (C) 1998 Alexandre Julliard
7#
8
9%formats =
10(
Alexandre Julliard3e2517c2000-01-20 18:59:03 +000011 "int" => "%d",
Eric Pouech0b83d4c2001-11-23 23:04:58 +000012 "short int" => "%d",
Alexandre Julliard3e2517c2000-01-20 18:59:03 +000013 "char" => "%c",
Alexandre Julliard0a7c1f62000-01-27 02:54:17 +000014 "unsigned char" => "%02x",
Alexandre Julliard838d65a2001-06-19 19:16:41 +000015 "unsigned short"=> "%04x",
Alexandre Julliard3e2517c2000-01-20 18:59:03 +000016 "unsigned int" => "%08x",
17 "void*" => "%p",
18 "time_t" => "%ld",
Alexandre Julliard9caa71e2001-11-30 18:46:42 +000019 "size_t" => "%d",
Alexandre Julliard8081e5a2001-01-05 04:08:07 +000020 "handle_t" => "%d",
Alexandre Julliardd8a8c112001-10-12 18:45:29 +000021 "atom_t" => "%04x",
Alexandre Julliard1a66d222001-08-28 18:44:52 +000022 "user_handle_t" => "%08x",
Alexandre Julliard0d509652001-10-16 21:55:37 +000023 "rectangle_t" => "&dump_rectangle",
Alexandre Julliard9caa71e2001-11-30 18:46:42 +000024 "char_info_t" => "&dump_char_info",
Alexandre Julliard767e6f61998-08-09 12:47:43 +000025);
26
27my @requests = ();
28my %replies = ();
29
Alexandre Julliard5bc78081999-06-22 17:26:53 +000030my @trace_lines = ();
31
Alexandre Julliard37ec9272001-07-19 00:35:37 +000032# Get the server protocol version
33my $protocol = &GET_PROTOCOL_VERSION;
34
35### Create server_protocol.h and print header
36
37open SERVER_PROT, ">include/wine/server_protocol.h" or die "Cannot create include/wine/server_protocol.h";
38print SERVER_PROT "/*\n * Wine server protocol definitions\n *\n";
39print SERVER_PROT " * This file is automatically generated; DO NO EDIT!\n";
40print SERVER_PROT " * Edit server/protocol.def instead and re-run tools/make_requests\n";
41print SERVER_PROT " */\n\n";
42print SERVER_PROT "#ifndef __WINE_WINE_SERVER_PROTOCOL_H\n";
43print SERVER_PROT "#define __WINE_WINE_SERVER_PROTOCOL_H\n";
44
45### Parse requests to find request/reply structure definitions
46
47&PARSE_REQUESTS;
48
Alexandre Julliard9caa71e2001-11-30 18:46:42 +000049### Build the request list and structures
Alexandre Julliard37ec9272001-07-19 00:35:37 +000050
51print SERVER_PROT "\n\nenum request\n{\n";
52foreach $req (@requests) { print SERVER_PROT " REQ_$req,\n"; }
53print SERVER_PROT " REQ_NB_REQUESTS\n};\n\n";
Alexandre Julliard9caa71e2001-11-30 18:46:42 +000054
Alexandre Julliard37ec9272001-07-19 00:35:37 +000055print SERVER_PROT "union generic_request\n{\n";
56print SERVER_PROT " struct request_max_size max_size;\n";
Alexandre Julliard9caa71e2001-11-30 18:46:42 +000057print SERVER_PROT " struct request_header request_header;\n";
58foreach $req (@requests) { print SERVER_PROT " struct ${req}_request ${req}_request;\n"; }
59print SERVER_PROT "};\n";
60
61print SERVER_PROT "union generic_reply\n{\n";
62print SERVER_PROT " struct request_max_size max_size;\n";
63print SERVER_PROT " struct reply_header reply_header;\n";
64foreach $req (@requests) { print SERVER_PROT " struct ${req}_reply ${req}_reply;\n"; }
Alexandre Julliard37ec9272001-07-19 00:35:37 +000065print SERVER_PROT "};\n\n";
Alexandre Julliard9caa71e2001-11-30 18:46:42 +000066
Alexandre Julliard37ec9272001-07-19 00:35:37 +000067printf SERVER_PROT "#define SERVER_PROTOCOL_VERSION %d\n\n", $protocol + 1;
68print SERVER_PROT "#endif /* __WINE_WINE_SERVER_PROTOCOL_H */\n";
69close SERVER_PROT;
Alexandre Julliard767e6f61998-08-09 12:47:43 +000070
71### Output the dumping function tables
72
Alexandre Julliard5bc78081999-06-22 17:26:53 +000073push @trace_lines, "static const dump_func req_dumpers[REQ_NB_REQUESTS] = {\n";
Alexandre Julliard767e6f61998-08-09 12:47:43 +000074foreach $req (@requests)
75{
Alexandre Julliard5bc78081999-06-22 17:26:53 +000076 push @trace_lines, " (dump_func)dump_${req}_request,\n";
Alexandre Julliard767e6f61998-08-09 12:47:43 +000077}
Alexandre Julliard5bc78081999-06-22 17:26:53 +000078push @trace_lines, "};\n\n";
Alexandre Julliardd2b7a0b1999-05-24 12:33:10 +000079
Alexandre Julliard5bc78081999-06-22 17:26:53 +000080push @trace_lines, "static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {\n";
Alexandre Julliardd2b7a0b1999-05-24 12:33:10 +000081foreach $req (@requests)
82{
Alexandre Julliard5bc78081999-06-22 17:26:53 +000083 push @trace_lines, " (dump_func)", $replies{$req} ? "dump_${req}_reply,\n" : "0,\n";
Alexandre Julliardd2b7a0b1999-05-24 12:33:10 +000084}
Alexandre Julliard5bc78081999-06-22 17:26:53 +000085push @trace_lines, "};\n\n";
Alexandre Julliard767e6f61998-08-09 12:47:43 +000086
Alexandre Julliard5bc78081999-06-22 17:26:53 +000087push @trace_lines, "static const char * const req_names[REQ_NB_REQUESTS] = {\n";
Alexandre Julliard767e6f61998-08-09 12:47:43 +000088foreach $req (@requests)
89{
Alexandre Julliard5bc78081999-06-22 17:26:53 +000090 push @trace_lines, " \"$req\",\n";
Alexandre Julliard767e6f61998-08-09 12:47:43 +000091}
Alexandre Julliard5bc78081999-06-22 17:26:53 +000092push @trace_lines, "};\n";
Alexandre Julliard767e6f61998-08-09 12:47:43 +000093
Alexandre Julliard5bc78081999-06-22 17:26:53 +000094REPLACE_IN_FILE( "server/trace.c", @trace_lines );
Alexandre Julliard767e6f61998-08-09 12:47:43 +000095
Alexandre Julliard5bc78081999-06-22 17:26:53 +000096### Output the request handlers list
Alexandre Julliardd2b7a0b1999-05-24 12:33:10 +000097
Alexandre Julliard5bc78081999-06-22 17:26:53 +000098my @request_lines = ();
Alexandre Julliard767e6f61998-08-09 12:47:43 +000099
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000100foreach $req (@requests) { push @request_lines, "DECL_HANDLER($req);\n"; }
101push @request_lines, "\n#ifdef WANT_REQUEST_HANDLERS\n\n";
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000102push @request_lines, "typedef void (*req_handler)( const void *req, void *reply );\n";
Alexandre Julliardea0d0282000-03-10 22:16:10 +0000103push @request_lines, "static const req_handler req_handlers[REQ_NB_REQUESTS] =\n{\n";
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000104foreach $req (@requests)
105{
Alexandre Julliardea0d0282000-03-10 22:16:10 +0000106 push @request_lines, " (req_handler)req_$req,\n";
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000107}
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000108push @request_lines, "};\n#endif /* WANT_REQUEST_HANDLERS */\n";
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000109
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000110REPLACE_IN_FILE( "server/request.h", @request_lines );
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000111
Alexandre Julliard37ec9272001-07-19 00:35:37 +0000112### Parse the request definitions
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000113
Alexandre Julliard37ec9272001-07-19 00:35:37 +0000114sub PARSE_REQUESTS
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000115{
Alexandre Julliard37ec9272001-07-19 00:35:37 +0000116 # states: 0 = header 1 = declarations 2 = inside @REQ 3 = inside @REPLY
117 my $state = 0;
118 my $name = "";
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000119 my @in_struct = ();
120 my @out_struct = ();
Alexandre Julliard37ec9272001-07-19 00:35:37 +0000121
122 open(PROTOCOL,"server/protocol.def") or die "Can't open server/protocol.def";
123
124 while (<PROTOCOL>)
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000125 {
Alexandre Julliard37ec9272001-07-19 00:35:37 +0000126 my ($type, $var);
127 # strip comments
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000128 s!/\*.*\*/!!g;
Alexandre Julliard37ec9272001-07-19 00:35:37 +0000129 # strip white space at end of line
130 s/\s+$//;
131
132 if (/^\@HEADER/)
Alexandre Julliard86113532000-08-29 03:54:30 +0000133 {
Alexandre Julliard37ec9272001-07-19 00:35:37 +0000134 die "Misplaced \@HEADER" unless $state == 0;
135 $state++;
Alexandre Julliard86113532000-08-29 03:54:30 +0000136 next;
137 }
Alexandre Julliard37ec9272001-07-19 00:35:37 +0000138
139 # ignore everything while in state 0
140 next if $state == 0;
141
142 if (/^\@REQ\(\s*(\w+)\s*\)/)
Alexandre Julliard86113532000-08-29 03:54:30 +0000143 {
Alexandre Julliard37ec9272001-07-19 00:35:37 +0000144 $name = $1;
145 die "Misplaced \@REQ" unless $state == 1;
146 # start a new request
147 @in_struct = ();
148 @out_struct = ();
149 print SERVER_PROT "struct ${name}_request\n{\n";
150 print SERVER_PROT " struct request_header __header;\n";
151 $state++;
152 next;
Alexandre Julliard86113532000-08-29 03:54:30 +0000153 }
Alexandre Julliard37ec9272001-07-19 00:35:37 +0000154
155 if (/^\@REPLY/)
Alexandre Julliard86113532000-08-29 03:54:30 +0000156 {
Alexandre Julliard37ec9272001-07-19 00:35:37 +0000157 die "Misplaced \@REPLY" unless $state == 2;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000158 print SERVER_PROT "};\n";
159 print SERVER_PROT "struct ${name}_reply\n{\n";
160 print SERVER_PROT " struct reply_header __header;\n";
Alexandre Julliard37ec9272001-07-19 00:35:37 +0000161 $state++;
162 next;
Alexandre Julliard86113532000-08-29 03:54:30 +0000163 }
Alexandre Julliard37ec9272001-07-19 00:35:37 +0000164
165 if (/^\@END/)
Alexandre Julliard86113532000-08-29 03:54:30 +0000166 {
Alexandre Julliard37ec9272001-07-19 00:35:37 +0000167 die "Misplaced \@END" unless ($state == 2 || $state == 3);
168 print SERVER_PROT "};\n";
169
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000170 if ($state == 2) # build dummy reply struct
171 {
172 print SERVER_PROT "struct ${name}_reply\n{\n";
173 print SERVER_PROT " struct reply_header __header;\n";
174 print SERVER_PROT "};\n";
175 }
176
Alexandre Julliard37ec9272001-07-19 00:35:37 +0000177 # got a complete request
178 push @requests, $name;
179 &DO_DUMP_FUNC( $name, "request", @in_struct);
180 if ($#out_struct >= 0)
181 {
182 $replies{$name} = 1;
183 &DO_DUMP_FUNC( $name, "reply", @out_struct);
184 }
185 $state = 1;
186 next;
Alexandre Julliard86113532000-08-29 03:54:30 +0000187 }
Alexandre Julliard37ec9272001-07-19 00:35:37 +0000188
189 if ($state != 1)
190 {
191 # skip empty lines (but keep them in output file)
192 if (/^$/)
193 {
194 print SERVER_PROT "\n";
195 next;
196 }
197
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000198 if (/^\s*VARARG\((\w+),(\w+),(\w+)\)/)
Alexandre Julliard37ec9272001-07-19 00:35:37 +0000199 {
200 $var = $1;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000201 $type = "dump_varargs_" . $2 . "( min(cur_size,req->" . $3 . ") )";
Alexandre Julliard37ec9272001-07-19 00:35:37 +0000202 s!(VARARG\(.*\)\s*;)!/* $1 */!;
203 }
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000204 elsif (/^\s*VARARG\((\w+),(\w+)\)/)
Alexandre Julliard37ec9272001-07-19 00:35:37 +0000205 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000206 $var = $1;
207 $type = "dump_varargs_" . $2 . "( cur_size )";
208 s!(VARARG\(.*\)\s*;)!/* $1 */!;
209 }
210 elsif (/^\s*(\w+\**(\s+\w+\**)*)\s+(\w+);/)
211 {
212 $type = $1;
Alexandre Julliard37ec9272001-07-19 00:35:37 +0000213 $var = $3;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000214 die "Unrecognized type $type" unless defined($formats{$type});
Alexandre Julliard37ec9272001-07-19 00:35:37 +0000215 }
216 else
217 {
218 die "Unrecognized syntax $_";
219 }
220 if ($state == 2) { push @in_struct, $type, $var; }
221 if ($state == 3) { push @out_struct, $type, $var; }
222 }
223
224 # Pass it through into the output file
225 print SERVER_PROT $_ . "\n";
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000226 }
Alexandre Julliard37ec9272001-07-19 00:35:37 +0000227 close PROTOCOL;
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000228}
229
230### Generate a dumping function
231
232sub DO_DUMP_FUNC
233{
234 my $name = shift;
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000235 my $req = shift;
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000236 push @trace_lines, "static void dump_${name}_$req( const struct ${name}_$req *req )\n{\n";
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000237 while ($#_ >= 0)
238 {
239 my $type = shift;
240 my $var = shift;
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000241 if (defined($formats{$type}))
Alexandre Julliard338e7571998-12-27 15:28:54 +0000242 {
Alexandre Julliardfbb9a9f1999-11-23 19:38:18 +0000243 if ($formats{$type} =~ /^&(.*)/)
244 {
245 my $func = $1;
246 push @trace_lines, " fprintf( stderr, \" $var=\" );\n";
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000247 push @trace_lines, " $func( &req->$var );\n";
Alexandre Julliardfbb9a9f1999-11-23 19:38:18 +0000248 push @trace_lines, " fprintf( stderr, \",\" );\n" if ($#_ > 0);
249 }
250 else
251 {
252 push @trace_lines, " fprintf( stderr, \" $var=$formats{$type}";
253 push @trace_lines, "," if ($#_ > 0);
254 push @trace_lines, "\", ";
255 push @trace_lines, "req->$var );\n";
256 }
Alexandre Julliardebe29ef1999-06-26 08:43:26 +0000257 }
258 else # must be some varargs format
259 {
Alexandre Julliard9caa71e2001-11-30 18:46:42 +0000260 my $func = $type;
261 push @trace_lines, " fprintf( stderr, \" $var=\" );\n";
262 push @trace_lines, " $func;\n";
263 push @trace_lines, " fputc( ',', stderr );\n" if ($#_ > 0);
Alexandre Julliard338e7571998-12-27 15:28:54 +0000264 }
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000265 }
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000266 push @trace_lines, "}\n\n";
267}
268
Alexandre Julliard37ec9272001-07-19 00:35:37 +0000269### Retrieve the server protocol version from the existing server_protocol.h file
270
271sub GET_PROTOCOL_VERSION
272{
273 my $protocol = 0;
274 open SERVER_PROT, "include/wine/server_protocol.h" or return 0;
275 while (<SERVER_PROT>)
276 {
277 if (/^\#define SERVER_PROTOCOL_VERSION (\d+)/) { $protocol = $1; last; }
278 }
279 close SERVER_PROT;
280 return $protocol;
281}
282
Alexandre Julliard5bc78081999-06-22 17:26:53 +0000283### Replace the contents of a file between ### make_requests ### marks
284
285sub REPLACE_IN_FILE
286{
287 my $name = shift;
288 my @data = @_;
289 my @lines = ();
290 open(FILE,$name) or die "Can't open $name";
291 while (<FILE>)
292 {
293 push @lines, $_;
294 last if /\#\#\# make_requests begin \#\#\#/;
295 }
296 push @lines, "\n", @data;
297 while (<FILE>)
298 {
299 if (/\#\#\# make_requests end \#\#\#/) { push @lines, "\n", $_; last; }
300 }
301 push @lines, <FILE>;
302 open(FILE,">$name") or die "Can't modify $name";
303 print FILE @lines;
304 close(FILE);
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000305}