Fixed a memory leakage in DeleteFileW.
[reactos.git] / posix / tools / mksystab.c
1 /* $Id: mksystab.c,v 1.2 2002/04/10 21:13:30 ea Exp $
2 *
3 * PROJECT : ReactOS / POSIX+ Subsystem
4 * DESCRIPTION: Build the system calls table for
5 * DESCRIPTION: the POSIX+ LPC server process.
6 * NOTE : this code is supposed to be portable.
7 * AUTHOR : Emanuele Aliberti
8 * DATE : 2001-05-26
9 * REVISIONS
10 * 2002-03-19 EA added stub file generation
11 * 2002-04-06 EA added to the CVS repository
12 */
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <errno.h>
17
18 #define PARSER_CONTEXT_LINE_SIZE 1024
19 #define PARSER_CONTEXT_INTERFACE_SIZE 64
20
21 const char * myname = "mksystab";
22
23 const char * syscall_name_prefix = "syscall_";
24 const char * proxy_name_prefix = "psxss_";
25
26 typedef enum {
27 METHOD_SUCCESS,
28 METHOD_EOF,
29 METHOD_FAILURE
30 } METHOD_TYPE;
31
32 typedef struct _PARSER_CONTEXT
33 {
34 int line_number;
35 int id;
36 char line [PARSER_CONTEXT_LINE_SIZE];
37 char status;
38 char interface [PARSER_CONTEXT_INTERFACE_SIZE];
39 int argc;
40
41 } PARSER_CONTEXT, * PPARSER_CONTEXT;
42
43 typedef struct _MFILE
44 {
45 char * name;
46 FILE * fp;
47 char * fopen_mode;
48 METHOD_TYPE (*prologue)(int,PPARSER_CONTEXT);
49 METHOD_TYPE (*iter)(int,PPARSER_CONTEXT);
50 METHOD_TYPE (*epilog)(int,PPARSER_CONTEXT);
51
52 } MFILE, * PMFILE;
53
54 /* MFILE file table */
55
56 METHOD_TYPE db_prologue (int self, PPARSER_CONTEXT context);
57 METHOD_TYPE db_iter (int self, PPARSER_CONTEXT context);
58 METHOD_TYPE db_epilog (int self, PPARSER_CONTEXT context);
59
60 METHOD_TYPE systab_prologue (int self, PPARSER_CONTEXT context);
61 METHOD_TYPE systab_iter (int self, PPARSER_CONTEXT context);
62 METHOD_TYPE systab_epilog (int self, PPARSER_CONTEXT context);
63
64 METHOD_TYPE psx_include_prologue (int self, PPARSER_CONTEXT context);
65 METHOD_TYPE psx_include_iter (int self, PPARSER_CONTEXT context);
66 METHOD_TYPE psx_include_epilog (int self, PPARSER_CONTEXT context);
67
68 METHOD_TYPE server_include_prologue (int self, PPARSER_CONTEXT context);
69 METHOD_TYPE server_include_iter (int self, PPARSER_CONTEXT context);
70 METHOD_TYPE server_include_epilog (int self, PPARSER_CONTEXT context);
71
72 METHOD_TYPE stubs_prologue (int self, PPARSER_CONTEXT context);
73 METHOD_TYPE stubs_iter (int self, PPARSER_CONTEXT context);
74 METHOD_TYPE stubs_epilog (int self, PPARSER_CONTEXT context);
75
76
77 MFILE mf [] =
78 {
79 { NULL, NULL, "r", db_prologue, db_iter, db_epilog }, /* it must be 1st */
80 { NULL, NULL, "w", systab_prologue, systab_iter, systab_epilog },
81 { NULL, NULL, "w", server_include_prologue, server_include_iter, server_include_epilog },
82 { NULL, NULL, "w", psx_include_prologue, psx_include_iter, psx_include_epilog },
83 { NULL, NULL, "w", stubs_prologue, stubs_iter, stubs_epilog }
84 };
85
86
87 /* mf objects methods */
88
89 int mf_open (int index)
90 {
91 mf [index].fp = fopen (mf [index].name, mf [index].fopen_mode);
92 if (NULL == mf [index].fp)
93 {
94 fprintf (stderr, "%s: error %d while opening \"%s\".", myname, errno, mf [index].name);
95 return METHOD_FAILURE;
96 }
97 return METHOD_SUCCESS;
98 }
99
100 void mf_close (int index)
101 {
102 fclose (mf[index].fp);
103 }
104
105 /* db file methods */
106
107 METHOD_TYPE db_prologue (int self, PPARSER_CONTEXT context)
108 {
109 if (METHOD_FAILURE == mf_open (self))
110 {
111 return METHOD_FAILURE;
112 }
113 fprintf (stderr, "Processing \"%s\"...\n", mf [self].name);
114 return METHOD_SUCCESS;
115 }
116
117 METHOD_TYPE db_iter (int self, PPARSER_CONTEXT context)
118 {
119 char * eol;
120
121 do
122 {
123 if (feof(mf [self].fp))
124 {
125 return METHOD_EOF;
126 }
127 if (NULL == fgets (context->line, PARSER_CONTEXT_LINE_SIZE, mf [self].fp))
128 {
129 return METHOD_EOF;
130 }
131 ++ context->line_number;
132 eol = strchr(context->line, '\n');
133 if (eol)
134 {
135 *eol = '\0';
136 }
137 /* Is line empty or a comment? */
138 } while (0 == strlen (context->line) || context->line[0] == '#');
139 /* Line is not a comment nor an empty line */
140 if (3 != sscanf (context->line, "%c%s%d", & context->status, context->interface, & context->argc))
141 {
142 fprintf (stderr, "Syntax error at line %d.\n", context->line_number);
143 return METHOD_FAILURE;
144 }
145 return METHOD_SUCCESS;
146 }
147
148 METHOD_TYPE db_epilog (int self, PPARSER_CONTEXT context)
149 {
150 mf_close (self);
151 return METHOD_SUCCESS;
152 }
153
154 /* systab file methods */
155
156 METHOD_TYPE systab_prologue (int self, PPARSER_CONTEXT context)
157 {
158 if (METHOD_FAILURE == mf_open (self))
159 {
160 return METHOD_FAILURE;
161 }
162 fprintf (mf[self].fp, "/* POSIX+ system calls (machine generated: do not edit!) */\n");
163 fprintf (mf[self].fp, "#include <psxss.h>\n");
164 fprintf (mf[self].fp, "#include <syscall.h>\n");
165 fprintf (mf[self].fp, "PSX_SYSTEM_CALL SystemCall [] =\n");
166 fprintf (mf[self].fp, "{\n");
167 return METHOD_SUCCESS;
168 }
169
170 METHOD_TYPE systab_iter (int self, PPARSER_CONTEXT context)
171 {
172 switch (context->status)
173 {
174 case '+':
175 case '-': /* unimplemented interface */
176 fprintf (mf[self].fp, "(void*)%s%s,\n", syscall_name_prefix, context->interface);
177 break;
178 default:
179 fprintf (stderr, "%s: unknown interface status \"%c\" at line %d.\n",
180 myname, context->status, context->line_number);
181 return METHOD_FAILURE;
182 }
183 return METHOD_SUCCESS;
184 }
185
186 METHOD_TYPE systab_epilog (int self, PPARSER_CONTEXT context)
187 {
188 fprintf (mf[self].fp, "0\n};\n");
189 fputs ("/* EOF */", mf[self].fp);
190 return METHOD_SUCCESS;
191 }
192
193
194 /* server/include file methods */
195
196 METHOD_TYPE server_include_prologue (int self, PPARSER_CONTEXT context)
197 {
198 if (METHOD_FAILURE == mf_open (self))
199 {
200 return METHOD_FAILURE;
201 }
202 fprintf (mf[self].fp, "/* POSIX+ system calls (machine generated: do not edit!) */\n");
203 fprintf (mf[self].fp, "#ifndef _SERVER_SYSCALL_H\n");
204 fprintf (mf[self].fp, "#define _SERVER_SYSCALL_H\n");
205 return METHOD_SUCCESS;
206 }
207
208 METHOD_TYPE server_include_iter (int self, PPARSER_CONTEXT context)
209 {
210 char interface [PARSER_CONTEXT_INTERFACE_SIZE*2];
211
212 sprintf (interface, "%s%s", syscall_name_prefix, context->interface);
213 fprintf (mf[self].fp, "NTSTATUS STDCALL %s (PPSX_MAX_MESSAGE);\n", interface);
214
215 return METHOD_SUCCESS;
216 }
217
218 METHOD_TYPE server_include_epilog (int self, PPARSER_CONTEXT context)
219 {
220 fprintf (mf[self].fp, "#endif /* ndef _SERVER_SYSCALL_H */\n");
221 fputs ("/* EOF */", mf[self].fp);
222 return METHOD_SUCCESS;
223 }
224
225
226 /* psx/include file methods */
227
228 METHOD_TYPE psx_include_prologue (int self, PPARSER_CONTEXT context)
229 {
230 if (METHOD_FAILURE == mf_open (self))
231 {
232 return METHOD_FAILURE;
233 }
234 fprintf (mf[self].fp, "/* POSIX+ system calls (machine generated: do not edit!) */\n");
235 fprintf (mf[self].fp, "#ifndef _PSX_SYSCALL_H\n");
236 fprintf (mf[self].fp, "#define _PSX_SYSCALL_H\n");
237 return METHOD_SUCCESS;
238 }
239
240 METHOD_TYPE psx_include_iter (int self, PPARSER_CONTEXT context)
241 {
242 char interface [PARSER_CONTEXT_INTERFACE_SIZE*2];
243
244 sprintf (interface, "%s%s", proxy_name_prefix, context->interface);
245 fprintf (mf[self].fp, "#define %s %d\n", strupr(interface), context->id ++);
246
247 return METHOD_SUCCESS;
248 }
249
250 METHOD_TYPE psx_include_epilog (int self, PPARSER_CONTEXT context)
251 {
252 fprintf (mf[self].fp, "#define PSX_SYSCALL_APIPORT_COUNT %d\n", context->id ++);
253 fprintf (mf[self].fp, "#endif /* ndef _PSX_SYSCALL_H */\n");
254 fputs ("/* EOF */", mf[self].fp);
255 return METHOD_SUCCESS;
256 }
257
258
259 /* stubs file methods */
260
261 METHOD_TYPE stubs_prologue (int self, PPARSER_CONTEXT context)
262 {
263 if (METHOD_FAILURE == mf_open (self))
264 {
265 return METHOD_FAILURE;
266 }
267 fprintf( mf[self].fp,
268 "/* POSIX+ system calls not yet implemented */\n"
269 "/* (machine generated: do not edit!) */\n"
270 "#include <psxss.h>\n");
271 return METHOD_SUCCESS;
272 }
273
274 METHOD_TYPE stubs_iter (int self, PPARSER_CONTEXT context)
275 {
276 if ('-' == context->status)
277 {
278 fprintf (
279 mf[self].fp,
280 "NTSTATUS STDCALL %s%s(PPSX_MAX_MESSAGE Msg){Msg->PsxHeader.Status=STATUS_NOT_IMPLEMENTED;return(STATUS_SUCCESS);}\n",
281 syscall_name_prefix,
282 context->interface
283 );
284 }
285 return METHOD_SUCCESS;
286 }
287
288 METHOD_TYPE stubs_epilog (int self, PPARSER_CONTEXT context)
289 {
290 fputs ("/* EOF */", mf[self].fp);
291 return METHOD_SUCCESS;
292 }
293
294
295 /* main loop */
296
297 METHOD_TYPE mksystab ()
298 {
299 int index;
300 int index_top = (sizeof mf / sizeof mf[0]);
301 int iterate = 1;
302 PARSER_CONTEXT context;
303 METHOD_TYPE mt;
304
305 /* initialize the parser's context */
306 context.line_number = 0;
307 context.id = 0;
308
309 /* prologue */
310 for (index = 0; index < index_top; index ++)
311 {
312 if (METHOD_FAILURE == mf[index].prologue (index, & context))
313 {
314 return METHOD_FAILURE;
315 }
316 }
317 /* iter */
318 while (iterate)
319 {
320 for (index = 0; index < index_top; index ++)
321 {
322 mt = mf[index].iter (index, & context);
323 if (METHOD_EOF == mt)
324 {
325 if (0 == index) /* input MUST be 1st MFILE */
326 {
327 iterate = 0;
328 break; /* input reached EOF */
329 }
330 return METHOD_FAILURE;
331 }
332 else if (METHOD_FAILURE == mt)
333 {
334 return METHOD_FAILURE;
335 }
336 }
337 }
338 /* epilog */
339 for (index = 0; index < index_top; index ++)
340 {
341 if (METHOD_FAILURE == mf[index].epilog (index, & context))
342 {
343 return METHOD_FAILURE;
344 }
345 }
346
347 /* done */
348 return METHOD_SUCCESS;
349 }
350
351 /* entry point */
352
353 int main (int argc, char **argv)
354 {
355 int status = 0;
356 int index;
357
358 /* Check user parameters */
359 if ((1 + (sizeof mf / sizeof (MFILE))) != argc)
360 {
361 printf ("ReactOS Operating System - POSIX+ Environment Subsystem\n");
362 printf ("Build the system calls table of the POSIX+ server.\n\n");
363 printf ("usage: %s syscall.db syscall.c syscall.h syscall.h stubs.c\n", argv[0]);
364 exit (METHOD_FAILURE);
365 }
366 /* initialize descriptors */
367 for (index = 0; index < (sizeof mf / sizeof mf[0]); index ++)
368 {
369 mf [index].name = argv [index + 1];
370 }
371
372 /* do process them */
373 status = mksystab ();
374
375 return (status);
376 }
377
378
379 /* EOF */