#include <stdio.h>
#include <sys/wait.h>
#include "../config.h"
#include "../gen.h"
#include "../util.h"
#include "mpdm.h"
extern struct symtabSt symtab[MAX_RES_DEF + 1];
extern int numResources;
extern char *compiler;
extern char **otherBin;
extern char **sourceFiles;
extern char **otherSrc;
/* processes the mpdm command line after the options. The mpd compiler is
* invoked with the -M option and .mpd files listed on the command line to get
* import information. The information obtained is recorded in the symbol
* table.
*/
buildSymtab (argc, argv, optind)
int argc;
char **argv;
int optind;
{
char inputline[MAX_PATH];
char compType[10]; /* component type: "global" or "resource" */
char compName[MAX_PATH]; /* component name */
char bodyOrSpec[5]; /* keyword "body" or "spec" */
char compOrFileName[MAX_PATH]; /* name of component or file name */
char sourceOrImport[8]; /* keyword "source" or "import" */
char processingSpec; /* flag. TRUE if spec is being processed */
char **nargv; /* command line for mpd compiler */
char c, *s, buf[MAX_PATH];
int i, j, n;
int numMPDfiles; /* number of mpd files on mpdm command line */
int numOtherfiles; /* number of non-mpd files on command line */
FILE *f;
importList *import;
int status; /* used to determine exit status of compiler */
struct { /* cache last component seen */
char *compName; /* component name */
int symtabEntry; /* position of component in symbol table */
} cache;
numResources = 0;
cache.compName = "";
/* optind points to the first mpd file name. Count the number of mpd files
* listed on the command line. Form command line for mpd compiler.
*/
for (i = optind, numMPDfiles = 0;
i < argc && strtail (argv[i], ".mpd");
i++, numMPDfiles++)
;
if (numMPDfiles == 0) {
fprintf (stderr, "No mpd files specified\n");
usageMessage ();
/* NOTREACHED */
}
/* form argument list for mpd compiler */
nargv = (char **) alloc ((numMPDfiles + 4) * sizeof (char *));
nargv[0] = compiler;
nargv[1] = "-w";
nargv[2] = "-M";
for (i = 0; i < numMPDfiles; i++)
nargv[3+i] = argv[optind+i];
nargv[3+i] = NULL;
optind = optind + numMPDfiles; /* optind points to rest of command line */
sourceFiles = nargv + 3; /* list of source files (starts at third
* argument to compiler; ends with null)
*/
if (optind < argc) {
/* process remaining command line arguments. All arguments assumed to
* be files or libraries to be linked into mpd executable.
*/
numOtherfiles = argc - optind;
otherBin = (char **) alloc ((numOtherfiles + 1) * sizeof (char *));
otherSrc = (char **) alloc ((numOtherfiles + 1) * sizeof (char *));
for (i = 0; i < numOtherfiles; i++) {
s = argv[optind + i];
otherSrc[i] = s; /* file name as given */
otherBin[i] = salloc (s); /* may get altered or zapped*/
if (strncmp (s, "-l", 2) == 0) {
otherBin[i] = NULL;
} else {
n = strlen (s);
if (n < 3 || s[n-2] != '.') {
/* not of the form xxxxx.x */
fprintf (stderr, "mpdm: invalid filename: %s\n", s);
exit (1);
}
c = s[n-1];
switch (c) {
case 'a':
case 'o':
if (f = fopen (s, "r")) {
/* file is in this directory; create dependency */
fclose (f);
} else if (f = pathopen (s, "", buf)) {
/* file is found on MPD_PATH; don't create */
fclose (f);
otherBin[i] = NULL;
}
/* else */
/* assume it will be built in this directory */
break;
default:
/* .c or .p or .s or something: depend on .o variant */
otherBin[i][n-1] = 'o';
break;
}
}
}
otherSrc[i] = otherBin[i] = NULL;
}
if (filter (0, compiler, nargv) == 0) /* run compiler into stdin */
mexit ("can't fork compiler");
while (fgets (inputline, MAX_PATH, stdin)) {
sscanf (inputline, "%s %s %s %s %s",
compType, compName, bodyOrSpec, sourceOrImport, compOrFileName);
if (strcmp (cache.compName, compName) != 0) {
/* component name not in cache -- must search symtab */
symtab[numResources].compName = compName;
for (i = 0; strcmp (symtab[i].compName, compName) != 0; i++)
;
if (i == numResources) {
/* haven't seen this component name before */
symtab[numResources].compName = salloc (compName);
numResources++;
}
/* set resource type now -- may not have been set on earlier ref */
if (strcmp (compType, "resource") == 0)
symtab[i].global = FALSE;
else
symtab[i].global = TRUE;
cache.compName = symtab[i].compName;
cache.symtabEntry = i;
}
else /* cache has entry for resource */
i = cache.symtabEntry;
if (strcmp (bodyOrSpec, "spec") == 0)
processingSpec = TRUE;
else
processingSpec = FALSE;
if (strcmp (sourceOrImport, "source") == 0)
if (processingSpec)
if (symtab[i].specSource) {
if (strcmp (symtab[i].specSource, compOrFileName) != 0)
fprintf (stderr,
"mpdm: spec for resource %s defined in files %s and %s.\n",
compName, compOrFileName, symtab[i].specSource);
else
fprintf (stderr,
"mpdm: multiple definitions for resource %s in file %s.\n",
compName, compOrFileName);
exit (1);
}
else
symtab[i].specSource = salloc (compOrFileName);
else
if (symtab[i].bodySource) {
fprintf (stderr,
"mpdm: body for resource %s defined in files %s and %s.\n",
compName, compOrFileName, symtab[i].bodySource);
exit (1);
}
else
symtab[i].bodySource = salloc (compOrFileName);
else {
/* processing an import clause. See if symtab has entry
* for component being imported.
*/
symtab[numResources].compName = compOrFileName;
for (j = 0; strcmp (symtab[j].compName, compOrFileName) != 0; j++)
;
if (j == numResources) {
/* add imported component to symtab */
symtab[numResources].compName = salloc (compOrFileName);
numResources++;
}
symtab[j].timesImported++;
/* add the imported component to the list of components
* imported by the component being processed
*/
if (processingSpec) {
/* component imported by spec */
import = symtab[i].specImports;
while (import != NULL && import->resNum != j)
import = import->next;
if (import == NULL) {
import = (importList *) alloc (sizeof (importList));
import->resNum = j;
import->next = symtab[i].specImports;
symtab[i].specImports = import;
}
}
else {
/* component imported by body */
import = symtab[i].bodyImports;
while (import != NULL && import->resNum != j)
import = import->next;
if (import == NULL) {
import = (importList *) alloc (sizeof (importList));
import->resNum = j;
import->next = symtab[i].bodyImports;
symtab[i].bodyImports = import;
}
}
}
}
/* check compiler's exit status */
if (wait (&status) == -1)
pexit ("mpdm");
if (status != 0)
mexit ("exiting due to compilation errors");
return;
}
syntax highlighted by Code2HTML, v. 0.9.1