/* * rtmk - A single address space real-time micro-kernel. * Copyright (c) 1999, 2000 Johan Rydberg. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ /* * $Id: rig.c,v 1.1 2001/12/13 02:09:38 jrydberg Exp $ */ #include #include #include #include #include "getopt.h" #include #include #include #include #include #include "rig.h" #include "be-c.h" #define NMAXARGS 32 #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif /* XXX */ extern FILE *yyin, *yyout; /** the default C pre-processor: */ #define CPP "cpp" char *progname, *source, *target, *output_file = 0; /* flags: */ int flag_nopthread = 0; int flag_kernel = 0; int flag_server = 0; /* other options: */ char *prefix = ""; /* this is one if we use static buffers */ int use_static_buffers = 0; /* if we should use PARAMS in prototypes or not */ int no_use_params = 0; /* size of static buffers (if used) */ int static_buffer_size = TARGET_STATIC_BUFFER_SIZE; /* The number of routines in this subsystem. */ int number_of_routines = 0; /* this is true if the "interface is a subsystem" */ int is_subsystem; /** the main file: */ struct parsedfile *currfile = 0; /** booleans: */ int server = 0, client = 0, header = 0; /* counters: */ int counter_routines = 0; /* XXX */ FILE *output_fp; /** information about the subsystem: */ char *subsystem_name = NULL, *subsystemPortal = NULL; int subsystem_base = 0; int errors = 0; void usage() { printf("usage: %s [--cpp cpp] <--header | --client | --server> [-o file | --output file]\n" " [-Idirectory] [-Ddefine] [-Udefine] file.defs\n", progname); } void version() { printf ("%s %s for rtmk\n", PACKAGE, VERSION); printf ("Copyright (c) 1999, 2000 by Johan Rydberg. All Rights Reserved.\n"); } void error (char *err, ...) { static struct parsedfile *last = 0; struct parsedfile *pf; static char buf [256]; va_list ap; if (last != currfile) { if (currfile->parent == 0) printf ("%s: At top level:\n", currfile->name); else { for(pf = currfile->parent; pf != NULL; pf = pf->parent) { printf("In file included from %s:%d:\n", pf->name, pf->lineno); } last = currfile; } } va_start (ap, err); vsnprintf (buf, sizeof buf, err, ap); va_end (ap); printf("%s:%d: %s\n", currfile->name, currfile->lineno, buf); errors++; } void error_line (char *file, int line, char *err, ...) { static struct parsedfile *last = 0; struct parsedfile *pf; static char buf [256]; va_list ap; va_start (ap, err); vsnprintf (buf, sizeof buf, err, ap); va_end (ap); printf("%s:%d: %s\n", file, line, buf); errors++; } /* XXX */ int indent_level = 0; /* XXX comment here doesn't like this. */ void output (char *fmt, ...) { static char buff [256], dst [256]; char *s, *p; va_list ap; int i; s = fmt; p = buff; if (*s != '\a') { for (i = 0; i < indent_level; i++) *p++ = ' '; } else s++; for (; *s != '\0'; s++) { switch (*s) { #if 0 case '\\i': for (i = 0; i < indent_level; i++) *p++ = ' '; break; #endif case '\r': *p++ = '\n'; break; case '\n': /* If this is in the end of the line XXX */ if (*(s+1) == '\0') { *p++ = *s; break; } *p++ = '\n'; for (i = 0; i < indent_level; i++) *p++ = ' '; break; default: *p++ = *s; } } *p++ = '\0'; va_start (ap, fmt); (void) vsnprintf (dst, sizeof dst, buff, ap); va_end (ap); fprintf (output_fp, dst); } int lineno = 0; int main (argc, argv) int argc; char **argv; { char *new_argv[NMAXARGS] = { 0, }, *cpp = CPP, buff[128], *sptr, *s; int pipes[2], i, n, optindex, cpid, status; static struct option options[] = { { "help", FALSE, 0, '?' }, { "version", FALSE, 0, 'V' }, { "cpp", TRUE, 0, 'C' }, { "header", FALSE, 0, 'h' }, { "client", FALSE, 0, 'c' }, { "server", FALSE, 0, 's' }, { "output", TRUE, 0, 'o' }, { "prefix", TRUE, 0, 'p' }, { "kernel", FALSE, 0, 'k' }, { "include", TRUE, 0, 'i' }, { "no-pthread", FALSE,0, 'P' }, { 0, 0, 0, 0 } }; FILE *fp; progname = argv[0]; target = tmpnam(NULL); cpp = getenv("CPP"); if (cpp == 0) cpp = CPP; /* Parse all the arguments. */ n = 1; while ((i = getopt_long(argc, argv, "PI:U:D:o:p:Sf:i:", options, &optindex)) != -1) { switch(i) { case 'P': flag_nopthread = 1; break; case 'C': cpp = optarg; break; case 'S': flag_server = 1; break; case 'h': header = TRUE; break; case 'c': client = TRUE; break; case 's': server = TRUE; break; case 'k': flag_kernel = 1; break; case 'o': output_file = optarg; break; case 'p': #if 0 sprintf (buff, "%s_", optarg); prefix = strdup (buff); #else prefix = strdup (optarg); #endif break; case 'I': new_argv[n++] = "-I"; new_argv[n++] = optarg; break; case 'U': new_argv[n++] = "-U"; new_argv[n++] = optarg; break; case 'D': new_argv[n++] = "-D"; new_argv[n++] = optarg; break; case 'i': new_argv[n++] = "-include"; new_argv[n++] = optarg; break; /* flags */ case 'f': { int optint = -1; char *s; if ((s = strchr (optarg, '='))) { optint = atoi (s+1); *s = '\0'; } if (strcmp (optarg, "use-static-buffers") == 0) use_static_buffers = true; else if (strcmp (optarg, "static-buffer-size") == 0) { if (optint < 0) { fprintf (stderr, "%s: %s -- must specify size\n", progname, optarg); return 1; } static_buffer_size = optint; } else if (strcmp (optarg, "no-PARAMS") == 0) { no_use_params = true; } else { fprintf (stderr, "%s: %s -- invalid flag\n", progname, optarg); return 1; } } break; case '?': usage(); return 0; case 'V': version(); return 0; } } /* Get the file. */ if (optind < argc) { source = argv[optind]; new_argv[n++] = source; new_argv[n++] = target; } else { printf("%s: must specify file\n", argv[0]); usage(); return 1; } /* Check if the user have specified a command. */ if (!header && !client && !server) { printf("%s: must specify command\n", argv[0]); usage(); return 1; } new_argv[n] = NULL; new_argv[0] = cpp; /* Output file: */ if (output_file == NULL) { strcpy (buff, source); sptr = buff; if ((s = rindex(buff, '/'))) { *s++ = '\0'; sptr = s; } if (rindex(sptr, '.')) *rindex (sptr, '.') = '\0'; if (header == TRUE) strcat (sptr, ".h"); else strcat (sptr, ".c"); output_file = sptr; } /* Create a pipe that we use for geting the result from the preprocessor. */ if (pipe(pipes) != 0) { printf("%s: error: couldn't create a pipe. bailing out.\n", argv[0]); return 1; } /* Fork a process and it should parse the file. */ if ((cpid = fork()) < 0) { printf("%s: error: can't fork. bailing out.\n", argv[0]); return 1; } /* child: */ if (cpid == 0) { #if 1 (void) close(1); if (dup(pipes[1]) == -1) return 1; #endif (void) execvp(cpp, new_argv); /*NOTREACHED*/ return 0; } /* parent: */ else { wait(&status); if (WEXITSTATUS(status) != 0) { printf("%s: error: child exit with error code.\n", progname); unlink(target); return 1; } } types_init (); routines_init (); imports_init (); /* Allocate a new file */ currfile = pf_allocate(); currfile->name = source; currfile->lineno = 0; /* XXX */ if ((yyin = fopen(target, "r+")) == NULL) { printf("%s: can't open temporary file. bailing out.\n", progname); return 1; } if (yyparse() == 0 && errors == 0) { /* Well, the parsing went ok, lets open the target file. */ fp = fopen (output_file, "w"); if (fp == 0) { fprintf (stderr, "%s: can't create %s\n", progname, output_file); exit (1); } output_fp = fp; if (client) be_generate_client (); else if (server) be_generate_server (); else if (header) be_generate_header (); fclose (output_fp); } unlink (target); return 0; } struct parsedfile * pf_allocate( void) { struct parsedfile *pf = (struct parsedfile *) malloc(sizeof(struct parsedfile)); pf->parent = NULL; pf->name = NULL; pf->lineno = 0; return pf; }