reactos/posix/tools/mksystab.c
2002-10-29 04:45:58 +00:00

379 lines
10 KiB
C

/* $Id: mksystab.c,v 1.4 2002/10/29 04:45:58 rex Exp $
*
* PROJECT : ReactOS / POSIX+ Subsystem
* DESCRIPTION: Build the system calls table for
* DESCRIPTION: the POSIX+ LPC server process.
* NOTE : this code is supposed to be portable.
* AUTHOR : Emanuele Aliberti
* DATE : 2001-05-26
* REVISIONS
* 2002-03-19 EA added stub file generation
* 2002-04-06 EA added to the CVS repository
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define PARSER_CONTEXT_LINE_SIZE 1024
#define PARSER_CONTEXT_INTERFACE_SIZE 64
const char * myname = "mksystab";
const char * syscall_name_prefix = "syscall_";
const char * proxy_name_prefix = "psxss_";
typedef enum {
METHOD_SUCCESS,
METHOD_EOF,
METHOD_FAILURE
} METHOD_TYPE;
typedef struct _PARSER_CONTEXT
{
int line_number;
int id;
char line [PARSER_CONTEXT_LINE_SIZE];
char status;
char interface [PARSER_CONTEXT_INTERFACE_SIZE];
int argc;
} PARSER_CONTEXT, * PPARSER_CONTEXT;
typedef struct _MFILE
{
char * name;
FILE * fp;
char * fopen_mode;
METHOD_TYPE (*prologue)(int,PPARSER_CONTEXT);
METHOD_TYPE (*iter)(int,PPARSER_CONTEXT);
METHOD_TYPE (*epilog)(int,PPARSER_CONTEXT);
} MFILE, * PMFILE;
/* MFILE file table */
METHOD_TYPE db_prologue (int self, PPARSER_CONTEXT context);
METHOD_TYPE db_iter (int self, PPARSER_CONTEXT context);
METHOD_TYPE db_epilog (int self, PPARSER_CONTEXT context);
METHOD_TYPE systab_prologue (int self, PPARSER_CONTEXT context);
METHOD_TYPE systab_iter (int self, PPARSER_CONTEXT context);
METHOD_TYPE systab_epilog (int self, PPARSER_CONTEXT context);
METHOD_TYPE psx_include_prologue (int self, PPARSER_CONTEXT context);
METHOD_TYPE psx_include_iter (int self, PPARSER_CONTEXT context);
METHOD_TYPE psx_include_epilog (int self, PPARSER_CONTEXT context);
METHOD_TYPE server_include_prologue (int self, PPARSER_CONTEXT context);
METHOD_TYPE server_include_iter (int self, PPARSER_CONTEXT context);
METHOD_TYPE server_include_epilog (int self, PPARSER_CONTEXT context);
METHOD_TYPE stubs_prologue (int self, PPARSER_CONTEXT context);
METHOD_TYPE stubs_iter (int self, PPARSER_CONTEXT context);
METHOD_TYPE stubs_epilog (int self, PPARSER_CONTEXT context);
MFILE mf [] =
{
{ NULL, NULL, "r", db_prologue, db_iter, db_epilog }, /* it must be 1st */
{ NULL, NULL, "w", systab_prologue, systab_iter, systab_epilog },
{ NULL, NULL, "w", server_include_prologue, server_include_iter, server_include_epilog },
{ NULL, NULL, "w", psx_include_prologue, psx_include_iter, psx_include_epilog },
{ NULL, NULL, "w", stubs_prologue, stubs_iter, stubs_epilog }
};
/* mf objects methods */
int mf_open (int index)
{
mf [index].fp = fopen (mf [index].name, mf [index].fopen_mode);
if (NULL == mf [index].fp)
{
fprintf (stderr, "%s: error %d while opening \"%s\".", myname, errno, mf [index].name);
return METHOD_FAILURE;
}
return METHOD_SUCCESS;
}
void mf_close (int index)
{
fclose (mf[index].fp);
}
/* db file methods */
METHOD_TYPE db_prologue (int self, PPARSER_CONTEXT context)
{
if (METHOD_FAILURE == mf_open (self))
{
return METHOD_FAILURE;
}
fprintf (stderr, "Processing \"%s\"...\n", mf [self].name);
return METHOD_SUCCESS;
}
METHOD_TYPE db_iter (int self, PPARSER_CONTEXT context)
{
char * eol;
do
{
if (feof(mf [self].fp))
{
return METHOD_EOF;
}
if (NULL == fgets (context->line, PARSER_CONTEXT_LINE_SIZE, mf [self].fp))
{
return METHOD_EOF;
}
++ context->line_number;
eol = strchr(context->line, '\n');
if (eol)
{
*eol = '\0';
}
/* Is line empty or a comment? */
} while (0 == strlen (context->line) || context->line[0] == '#');
/* Line is not a comment nor an empty line */
if (3 != sscanf (context->line, "%c%s%d", & context->status, context->interface, & context->argc))
{
fprintf (stderr, "Syntax error at line %d.\n", context->line_number);
return METHOD_FAILURE;
}
return METHOD_SUCCESS;
}
METHOD_TYPE db_epilog (int self, PPARSER_CONTEXT context)
{
mf_close (self);
return METHOD_SUCCESS;
}
/* systab file methods */
METHOD_TYPE systab_prologue (int self, PPARSER_CONTEXT context)
{
if (METHOD_FAILURE == mf_open (self))
{
return METHOD_FAILURE;
}
fprintf (mf[self].fp, "/* POSIX+ system calls (machine generated: do not edit!) */\n");
fprintf (mf[self].fp, "#include <psxss.h>\n");
fprintf (mf[self].fp, "#include <syscall.h>\n");
fprintf (mf[self].fp, "PSX_SYSTEM_CALL SystemCall [] =\n");
fprintf (mf[self].fp, "{\n");
return METHOD_SUCCESS;
}
METHOD_TYPE systab_iter (int self, PPARSER_CONTEXT context)
{
switch (context->status)
{
case '+':
case '-': /* unimplemented interface */
fprintf (mf[self].fp, "(void*)%s%s,\n", syscall_name_prefix, context->interface);
break;
default:
fprintf (stderr, "%s: unknown interface status \"%c\" at line %d.\n",
myname, context->status, context->line_number);
return METHOD_FAILURE;
}
return METHOD_SUCCESS;
}
METHOD_TYPE systab_epilog (int self, PPARSER_CONTEXT context)
{
fprintf (mf[self].fp, "0\n};\n");
fputs ("/* EOF */", mf[self].fp);
return METHOD_SUCCESS;
}
/* server/include file methods */
METHOD_TYPE server_include_prologue (int self, PPARSER_CONTEXT context)
{
if (METHOD_FAILURE == mf_open (self))
{
return METHOD_FAILURE;
}
fprintf (mf[self].fp, "/* POSIX+ system calls (machine generated: do not edit!) */\n");
fprintf (mf[self].fp, "#ifndef _SERVER_SYSCALL_H\n");
fprintf (mf[self].fp, "#define _SERVER_SYSCALL_H\n");
return METHOD_SUCCESS;
}
METHOD_TYPE server_include_iter (int self, PPARSER_CONTEXT context)
{
char interface [PARSER_CONTEXT_INTERFACE_SIZE*2];
sprintf (interface, "%s%s", syscall_name_prefix, context->interface);
fprintf (mf[self].fp, "NTSTATUS STDCALL %s (PPSX_MAX_MESSAGE);\n", interface);
return METHOD_SUCCESS;
}
METHOD_TYPE server_include_epilog (int self, PPARSER_CONTEXT context)
{
fprintf (mf[self].fp, "#endif /* ndef _SERVER_SYSCALL_H */\n");
fputs ("/* EOF */", mf[self].fp);
return METHOD_SUCCESS;
}
/* psx/include file methods */
METHOD_TYPE psx_include_prologue (int self, PPARSER_CONTEXT context)
{
if (METHOD_FAILURE == mf_open (self))
{
return METHOD_FAILURE;
}
fprintf (mf[self].fp, "/* POSIX+ system calls (machine generated: do not edit!) */\n");
fprintf (mf[self].fp, "#ifndef _PSX_SYSCALL_H\n");
fprintf (mf[self].fp, "#define _PSX_SYSCALL_H\n");
return METHOD_SUCCESS;
}
METHOD_TYPE psx_include_iter (int self, PPARSER_CONTEXT context)
{
char interface [PARSER_CONTEXT_INTERFACE_SIZE*2];
sprintf (interface, "%s%s", proxy_name_prefix, context->interface);
fprintf (mf[self].fp, "#define %s %d\n", strupr(interface), context->id ++);
return METHOD_SUCCESS;
}
METHOD_TYPE psx_include_epilog (int self, PPARSER_CONTEXT context)
{
fprintf (mf[self].fp, "#define PSX_SYSCALL_APIPORT_COUNT %d\n", context->id ++);
fprintf (mf[self].fp, "#endif /* ndef _PSX_SYSCALL_H */\n");
fputs ("/* EOF */", mf[self].fp);
return METHOD_SUCCESS;
}
/* stubs file methods */
METHOD_TYPE stubs_prologue (int self, PPARSER_CONTEXT context)
{
if (METHOD_FAILURE == mf_open (self))
{
return METHOD_FAILURE;
}
fprintf( mf[self].fp,
"/* POSIX+ system calls not yet implemented */\n"
"/* (machine generated: do not edit!) */\n"
"#include <psxss.h>\n");
return METHOD_SUCCESS;
}
METHOD_TYPE stubs_iter (int self, PPARSER_CONTEXT context)
{
if ('-' == context->status)
{
fprintf (
mf[self].fp,
"NTSTATUS STDCALL %s%s(PPSX_MAX_MESSAGE Msg){Msg->PsxHeader.Status=STATUS_NOT_IMPLEMENTED;return(STATUS_SUCCESS);}\n",
syscall_name_prefix,
context->interface
);
}
return METHOD_SUCCESS;
}
METHOD_TYPE stubs_epilog (int self, PPARSER_CONTEXT context)
{
fputs ("/* EOF */", mf[self].fp);
return METHOD_SUCCESS;
}
/* main loop */
METHOD_TYPE mksystab ()
{
int index;
int index_top = (sizeof mf / sizeof mf[0]);
int iterate = 1;
PARSER_CONTEXT context;
METHOD_TYPE mt;
/* initialize the parser's context */
context.line_number = 0;
context.id = 0;
/* prologue */
for (index = 0; index < index_top; index ++)
{
if (METHOD_FAILURE == mf[index].prologue (index, & context))
{
return METHOD_FAILURE;
}
}
/* iter */
while (iterate)
{
for (index = 0; index < index_top; index ++)
{
mt = mf[index].iter (index, & context);
if (METHOD_EOF == mt)
{
if (0 == index) /* input MUST be 1st MFILE */
{
iterate = 0;
break; /* input reached EOF */
}
return METHOD_FAILURE;
}
else if (METHOD_FAILURE == mt)
{
return METHOD_FAILURE;
}
}
}
/* epilog */
for (index = 0; index < index_top; index ++)
{
if (METHOD_FAILURE == mf[index].epilog (index, & context))
{
return METHOD_FAILURE;
}
}
/* done */
return METHOD_SUCCESS;
}
/* entry point */
int main (int argc, char **argv)
{
int status = 0;
int index;
/* Check user parameters */
if ((1 + (sizeof mf / sizeof (MFILE))) != argc)
{
printf ("ReactOS Operating System - POSIX+ Environment Subsystem\n");
printf ("Build the system calls table of the POSIX+ server.\n\n");
printf ("usage: %s syscall.db syscall.c syscall.h syscall.h stubs.c\n", argv[0]);
exit (METHOD_FAILURE);
}
/* initialize descriptors */
for (index = 0; index < (sizeof mf / sizeof mf[0]); index ++)
{
mf [index].name = argv [index + 1];
}
/* do process them */
status = mksystab ();
return (status);
}
/* EOF */