PSX: The tool to build internal system calls tables and auxiliary C files.
[reactos.git] / posix / tools / mksystab.c
1 /* $Id: mksystab.c,v 1.1 2002/04/06 16:07:34 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-02 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, "#endif /* ndef _PSX_SYSCALL_H */\n");
253 fputs ("/* EOF */", mf[self].fp);
254 return METHOD_SUCCESS;
255 }
256
257
258 /* stubs file methods */
259
260 METHOD_TYPE stubs_prologue (int self, PPARSER_CONTEXT context)
261 {
262 if (METHOD_FAILURE == mf_open (self))
263 {
264 return METHOD_FAILURE;
265 }
266 fprintf( mf[self].fp,
267 "/* POSIX+ system calls not yet implemented */\n"
268 "/* (machine generated: do not edit!) */\n"
269 "#include <psxss.h>\n");
270 return METHOD_SUCCESS;
271 }
272
273 METHOD_TYPE stubs_iter (int self, PPARSER_CONTEXT context)
274 {
275 if ('-' == context->status)
276 {
277 fprintf (
278 mf[self].fp,
279 "NTSTATUS STDCALL %s%s(PPSX_MAX_MESSAGE Msg){Msg->PsxHeader.Status=STATUS_NOT_IMPLEMENTED;return(STATUS_SUCCESS);}\n",
280 syscall_name_prefix,
281 context->interface
282 );
283 }
284 return METHOD_SUCCESS;
285 }
286
287 METHOD_TYPE stubs_epilog (int self, PPARSER_CONTEXT context)
288 {
289 fputs ("/* EOF */", mf[self].fp);
290 return METHOD_SUCCESS;
291 }
292
293
294 /* main loop */
295
296 METHOD_TYPE mksystab ()
297 {
298 int index;
299 int index_top = (sizeof mf / sizeof mf[0]);
300 int iterate = 1;
301 PARSER_CONTEXT context;
302 METHOD_TYPE mt;
303
304 /* initialize the parser's context */
305 context.line_number = 0;
306 context.id = 0;
307
308 /* prologue */
309 for (index = 0; index < index_top; index ++)
310 {
311 if (METHOD_FAILURE == mf[index].prologue (index, & context))
312 {
313 return METHOD_FAILURE;
314 }
315 }
316 /* iter */
317 while (iterate)
318 {
319 for (index = 0; index < index_top; index ++)
320 {
321 mt = mf[index].iter (index, & context);
322 if (METHOD_EOF == mt)
323 {
324 if (0 == index) /* input MUST be 1st MFILE */
325 {
326 iterate = 0;
327 break; /* input reached EOF */
328 }
329 return METHOD_FAILURE;
330 }
331 else if (METHOD_FAILURE == mt)
332 {
333 return METHOD_FAILURE;
334 }
335 }
336 }
337 /* epilog */
338 for (index = 0; index < index_top; index ++)
339 {
340 if (METHOD_FAILURE == mf[index].epilog (index, & context))
341 {
342 return METHOD_FAILURE;
343 }
344 }
345
346 /* done */
347 return METHOD_SUCCESS;
348 }
349
350 /* entry point */
351
352 int main (int argc, char **argv)
353 {
354 int status = 0;
355 int index;
356
357 /* Check user parameters */
358 if ((1 + (sizeof mf / sizeof (MFILE))) != argc)
359 {
360 printf ("ReactOS Operating System - POSIX+ Environment Subsystem\n");
361 printf ("Build the system calls table of the POSIX+ server.\n\n");
362 printf ("usage: %s syscall.db syscall.c syscall.h syscall.h stubs.c\n", argv[0]);
363 exit (METHOD_FAILURE);
364 }
365 /* initialize descriptors */
366 for (index = 0; index < (sizeof mf / sizeof mf[0]); index ++)
367 {
368 mf [index].name = argv [index + 1];
369 }
370
371 /* do process them */
372 status = mksystab ();
373
374 return (status);
375 }
376
377
378 /* EOF */