147131Sbostic /*-
260698Sbostic * Copyright (c) 1991, 1993
360698Sbostic * The Regents of the University of California. All rights reserved.
447131Sbostic *
547131Sbostic * This code is derived from software contributed to Berkeley by
647131Sbostic * Kenneth Almquist.
747131Sbostic *
847131Sbostic * %sccs.include.redist.c%
947131Sbostic */
1047131Sbostic
1147131Sbostic #ifndef lint
1260698Sbostic static char copyright[] =
1360698Sbostic "@(#) Copyright (c) 1991, 1993\n\
1460698Sbostic The Regents of the University of California. All rights reserved.\n";
1547131Sbostic #endif /* not lint */
1647131Sbostic
1747131Sbostic #ifndef lint
18*69272Schristos static char sccsid[] = "@(#)mknodes.c 8.2 (Berkeley) 05/04/95";
1947131Sbostic #endif /* not lint */
2047131Sbostic
2147131Sbostic /*
2247131Sbostic * This program reads the nodetypes file and nodes.c.pat file. It generates
2347131Sbostic * the files nodes.h and nodes.c.
2447131Sbostic */
2547131Sbostic
2647131Sbostic #include <stdio.h>
27*69272Schristos #include <stdlib.h>
28*69272Schristos #include <string.h>
29*69272Schristos #if __STDC__
30*69272Schristos #include <stdarg.h>
31*69272Schristos #else
32*69272Schristos #include <varargs.h>
33*69272Schristos #endif
3447131Sbostic
3547131Sbostic
3647131Sbostic #define MAXTYPES 50 /* max number of node types */
3747131Sbostic #define MAXFIELDS 20 /* max fields in a structure */
3847131Sbostic #define BUFLEN 100 /* size of character buffers */
3947131Sbostic
4047131Sbostic /* field types */
4147131Sbostic #define T_NODE 1 /* union node *field */
4247131Sbostic #define T_NODELIST 2 /* struct nodelist *field */
4347131Sbostic #define T_STRING 3
4447131Sbostic #define T_INT 4 /* int field */
4547131Sbostic #define T_OTHER 5 /* other */
4647131Sbostic #define T_TEMP 6 /* don't copy this field */
4747131Sbostic
4847131Sbostic
4947131Sbostic struct field { /* a structure field */
5047131Sbostic char *name; /* name of field */
5147131Sbostic int type; /* type of field */
5247131Sbostic char *decl; /* declaration of field */
5347131Sbostic };
5447131Sbostic
5547131Sbostic
5647131Sbostic struct str { /* struct representing a node structure */
5747131Sbostic char *tag; /* structure tag */
5847131Sbostic int nfields; /* number of fields in the structure */
5947131Sbostic struct field field[MAXFIELDS]; /* the fields of the structure */
6047131Sbostic int done; /* set if fully parsed */
6147131Sbostic };
6247131Sbostic
6347131Sbostic
64*69272Schristos static int ntypes; /* number of node types */
65*69272Schristos static char *nodename[MAXTYPES]; /* names of the nodes */
66*69272Schristos static struct str *nodestr[MAXTYPES]; /* type of structure used by the node */
67*69272Schristos static int nstr; /* number of structures */
68*69272Schristos static struct str str[MAXTYPES]; /* the structures */
69*69272Schristos static struct str *curstr; /* current structure */
70*69272Schristos static FILE *infp = stdin;
71*69272Schristos static char line[1024];
72*69272Schristos static int linno;
73*69272Schristos static char *linep;
7447131Sbostic
75*69272Schristos static void parsenode __P((void));
76*69272Schristos static void parsefield __P((void));
77*69272Schristos static void output __P((char *));
78*69272Schristos static void outsizes __P((FILE *));
79*69272Schristos static void outfunc __P((FILE *, int));
80*69272Schristos static void indent __P((int, FILE *));
81*69272Schristos static int nextfield __P((char *));
82*69272Schristos static void skipbl __P((void));
83*69272Schristos static int readline __P((void));
84*69272Schristos static void error __P((const char *, ...));
85*69272Schristos static char *savestr __P((const char *));
8647131Sbostic
8747131Sbostic
88*69272Schristos int
main(argc,argv)8947131Sbostic main(argc, argv)
90*69272Schristos int argc;
9147131Sbostic char **argv;
92*69272Schristos {
9347131Sbostic if (argc != 3)
9447131Sbostic error("usage: mknodes file\n");
9547131Sbostic if ((infp = fopen(argv[1], "r")) == NULL)
9647131Sbostic error("Can't open %s", argv[1]);
9747131Sbostic while (readline()) {
9847131Sbostic if (line[0] == ' ' || line[0] == '\t')
9947131Sbostic parsefield();
10047131Sbostic else if (line[0] != '\0')
10147131Sbostic parsenode();
10247131Sbostic }
10347131Sbostic output(argv[2]);
10450620Storek exit(0);
10547131Sbostic }
10647131Sbostic
10747131Sbostic
10847131Sbostic
109*69272Schristos static void
parsenode()110*69272Schristos parsenode()
111*69272Schristos {
11247131Sbostic char name[BUFLEN];
11347131Sbostic char tag[BUFLEN];
11447131Sbostic struct str *sp;
11547131Sbostic
11647131Sbostic if (curstr && curstr->nfields > 0)
11747131Sbostic curstr->done = 1;
11847131Sbostic nextfield(name);
11947131Sbostic if (! nextfield(tag))
12047131Sbostic error("Tag expected");
12147131Sbostic if (*linep != '\0')
12247131Sbostic error("Garbage at end of line");
12347131Sbostic nodename[ntypes] = savestr(name);
12447131Sbostic for (sp = str ; sp < str + nstr ; sp++) {
125*69272Schristos if (strcmp(sp->tag, tag) == 0)
12647131Sbostic break;
12747131Sbostic }
12847131Sbostic if (sp >= str + nstr) {
12947131Sbostic sp->tag = savestr(tag);
13047131Sbostic sp->nfields = 0;
13147131Sbostic curstr = sp;
13247131Sbostic nstr++;
13347131Sbostic }
13447131Sbostic nodestr[ntypes] = sp;
13547131Sbostic ntypes++;
13647131Sbostic }
13747131Sbostic
13847131Sbostic
139*69272Schristos static void
parsefield()140*69272Schristos parsefield()
141*69272Schristos {
14247131Sbostic char name[BUFLEN];
14347131Sbostic char type[BUFLEN];
14447131Sbostic char decl[2 * BUFLEN];
14547131Sbostic struct field *fp;
14647131Sbostic
14747131Sbostic if (curstr == NULL || curstr->done)
14847131Sbostic error("No current structure to add field to");
14947131Sbostic if (! nextfield(name))
15047131Sbostic error("No field name");
15147131Sbostic if (! nextfield(type))
15247131Sbostic error("No field type");
15347131Sbostic fp = &curstr->field[curstr->nfields];
15447131Sbostic fp->name = savestr(name);
155*69272Schristos if (strcmp(type, "nodeptr") == 0) {
15647131Sbostic fp->type = T_NODE;
15747131Sbostic sprintf(decl, "union node *%s", name);
158*69272Schristos } else if (strcmp(type, "nodelist") == 0) {
15947131Sbostic fp->type = T_NODELIST;
16047131Sbostic sprintf(decl, "struct nodelist *%s", name);
161*69272Schristos } else if (strcmp(type, "string") == 0) {
16247131Sbostic fp->type = T_STRING;
16347131Sbostic sprintf(decl, "char *%s", name);
164*69272Schristos } else if (strcmp(type, "int") == 0) {
16547131Sbostic fp->type = T_INT;
16647131Sbostic sprintf(decl, "int %s", name);
167*69272Schristos } else if (strcmp(type, "other") == 0) {
16847131Sbostic fp->type = T_OTHER;
169*69272Schristos } else if (strcmp(type, "temp") == 0) {
17047131Sbostic fp->type = T_TEMP;
17147131Sbostic } else {
17247131Sbostic error("Unknown type %s", type);
17347131Sbostic }
17447131Sbostic if (fp->type == T_OTHER || fp->type == T_TEMP) {
17547131Sbostic skipbl();
17647131Sbostic fp->decl = savestr(linep);
17747131Sbostic } else {
17847131Sbostic if (*linep)
17947131Sbostic error("Garbage at end of line");
18047131Sbostic fp->decl = savestr(decl);
18147131Sbostic }
18247131Sbostic curstr->nfields++;
18347131Sbostic }
18447131Sbostic
18547131Sbostic
18647131Sbostic char writer[] = "\
18747131Sbostic /*\n\
18847131Sbostic * This file was generated by the mknodes program.\n\
18947131Sbostic */\n\
19047131Sbostic \n";
19147131Sbostic
192*69272Schristos static void
output(file)19347131Sbostic output(file)
19447131Sbostic char *file;
195*69272Schristos {
19647131Sbostic FILE *hfile;
19747131Sbostic FILE *cfile;
19847131Sbostic FILE *patfile;
19947131Sbostic int i;
20047131Sbostic struct str *sp;
20147131Sbostic struct field *fp;
20247131Sbostic char *p;
20347131Sbostic
20447131Sbostic if ((patfile = fopen(file, "r")) == NULL)
20547131Sbostic error("Can't open %s", file);
20647131Sbostic if ((hfile = fopen("nodes.h", "w")) == NULL)
20747131Sbostic error("Can't create nodes.h");
20847131Sbostic if ((cfile = fopen("nodes.c", "w")) == NULL)
20947131Sbostic error("Can't create nodes.c");
21047131Sbostic fputs(writer, hfile);
21147131Sbostic for (i = 0 ; i < ntypes ; i++)
21247131Sbostic fprintf(hfile, "#define %s %d\n", nodename[i], i);
21347131Sbostic fputs("\n\n\n", hfile);
21447131Sbostic for (sp = str ; sp < &str[nstr] ; sp++) {
21547131Sbostic fprintf(hfile, "struct %s {\n", sp->tag);
21647131Sbostic for (i = sp->nfields, fp = sp->field ; --i >= 0 ; fp++) {
21747131Sbostic fprintf(hfile, " %s;\n", fp->decl);
21847131Sbostic }
21947131Sbostic fputs("};\n\n\n", hfile);
22047131Sbostic }
22147131Sbostic fputs("union node {\n", hfile);
22247131Sbostic fprintf(hfile, " int type;\n");
22347131Sbostic for (sp = str ; sp < &str[nstr] ; sp++) {
22447131Sbostic fprintf(hfile, " struct %s %s;\n", sp->tag, sp->tag);
22547131Sbostic }
22647131Sbostic fputs("};\n\n\n", hfile);
22747131Sbostic fputs("struct nodelist {\n", hfile);
22847131Sbostic fputs("\tstruct nodelist *next;\n", hfile);
22947131Sbostic fputs("\tunion node *n;\n", hfile);
23047131Sbostic fputs("};\n\n\n", hfile);
23147131Sbostic fputs("#ifdef __STDC__\n", hfile);
23247131Sbostic fputs("union node *copyfunc(union node *);\n", hfile);
23347131Sbostic fputs("void freefunc(union node *);\n", hfile);
23447131Sbostic fputs("#else\n", hfile);
23547131Sbostic fputs("union node *copyfunc();\n", hfile);
23647131Sbostic fputs("void freefunc();\n", hfile);
23747131Sbostic fputs("#endif\n", hfile);
23847131Sbostic
23947131Sbostic fputs(writer, cfile);
24047131Sbostic while (fgets(line, sizeof line, patfile) != NULL) {
24147131Sbostic for (p = line ; *p == ' ' || *p == '\t' ; p++);
242*69272Schristos if (strcmp(p, "%SIZES\n") == 0)
24347131Sbostic outsizes(cfile);
244*69272Schristos else if (strcmp(p, "%CALCSIZE\n") == 0)
24547131Sbostic outfunc(cfile, 1);
246*69272Schristos else if (strcmp(p, "%COPY\n") == 0)
24747131Sbostic outfunc(cfile, 0);
24847131Sbostic else
24947131Sbostic fputs(line, cfile);
25047131Sbostic }
25147131Sbostic }
25247131Sbostic
25347131Sbostic
25447131Sbostic
255*69272Schristos static void
outsizes(cfile)25647131Sbostic outsizes(cfile)
25747131Sbostic FILE *cfile;
258*69272Schristos {
25947131Sbostic int i;
26047131Sbostic
26147131Sbostic fprintf(cfile, "static const short nodesize[%d] = {\n", ntypes);
26247131Sbostic for (i = 0 ; i < ntypes ; i++) {
26347131Sbostic fprintf(cfile, " ALIGN(sizeof (struct %s)),\n", nodestr[i]->tag);
26447131Sbostic }
26547131Sbostic fprintf(cfile, "};\n");
26647131Sbostic }
26747131Sbostic
26847131Sbostic
269*69272Schristos static void
outfunc(cfile,calcsize)27047131Sbostic outfunc(cfile, calcsize)
27147131Sbostic FILE *cfile;
272*69272Schristos int calcsize;
273*69272Schristos {
27447131Sbostic struct str *sp;
27547131Sbostic struct field *fp;
27647131Sbostic int i;
27747131Sbostic
27847131Sbostic fputs(" if (n == NULL)\n", cfile);
27947131Sbostic if (calcsize)
28047131Sbostic fputs(" return;\n", cfile);
28147131Sbostic else
28247131Sbostic fputs(" return NULL;\n", cfile);
28347131Sbostic if (calcsize)
28447131Sbostic fputs(" funcblocksize += nodesize[n->type];\n", cfile);
28547131Sbostic else {
28647131Sbostic fputs(" new = funcblock;\n", cfile);
28747131Sbostic fputs(" funcblock += nodesize[n->type];\n", cfile);
28847131Sbostic }
28947131Sbostic fputs(" switch (n->type) {\n", cfile);
29047131Sbostic for (sp = str ; sp < &str[nstr] ; sp++) {
29147131Sbostic for (i = 0 ; i < ntypes ; i++) {
29247131Sbostic if (nodestr[i] == sp)
29347131Sbostic fprintf(cfile, " case %s:\n", nodename[i]);
29447131Sbostic }
29547131Sbostic for (i = sp->nfields ; --i >= 1 ; ) {
29647131Sbostic fp = &sp->field[i];
29747131Sbostic switch (fp->type) {
29847131Sbostic case T_NODE:
29947131Sbostic if (calcsize) {
30047131Sbostic indent(12, cfile);
30147131Sbostic fprintf(cfile, "calcsize(n->%s.%s);\n",
30247131Sbostic sp->tag, fp->name);
30347131Sbostic } else {
30447131Sbostic indent(12, cfile);
30547131Sbostic fprintf(cfile, "new->%s.%s = copynode(n->%s.%s);\n",
30647131Sbostic sp->tag, fp->name, sp->tag, fp->name);
30747131Sbostic }
30847131Sbostic break;
30947131Sbostic case T_NODELIST:
31047131Sbostic if (calcsize) {
31147131Sbostic indent(12, cfile);
31247131Sbostic fprintf(cfile, "sizenodelist(n->%s.%s);\n",
31347131Sbostic sp->tag, fp->name);
31447131Sbostic } else {
31547131Sbostic indent(12, cfile);
31647131Sbostic fprintf(cfile, "new->%s.%s = copynodelist(n->%s.%s);\n",
31747131Sbostic sp->tag, fp->name, sp->tag, fp->name);
31847131Sbostic }
31947131Sbostic break;
32047131Sbostic case T_STRING:
32147131Sbostic if (calcsize) {
32247131Sbostic indent(12, cfile);
32347131Sbostic fprintf(cfile, "funcstringsize += strlen(n->%s.%s) + 1;\n",
32447131Sbostic sp->tag, fp->name);
32547131Sbostic } else {
32647131Sbostic indent(12, cfile);
32747131Sbostic fprintf(cfile, "new->%s.%s = nodesavestr(n->%s.%s);\n",
32847131Sbostic sp->tag, fp->name, sp->tag, fp->name);
32947131Sbostic }
33047131Sbostic break;
33147131Sbostic case T_INT:
33247131Sbostic case T_OTHER:
33347131Sbostic if (! calcsize) {
33447131Sbostic indent(12, cfile);
33547131Sbostic fprintf(cfile, "new->%s.%s = n->%s.%s;\n",
33647131Sbostic sp->tag, fp->name, sp->tag, fp->name);
33747131Sbostic }
33847131Sbostic break;
33947131Sbostic }
34047131Sbostic }
34147131Sbostic indent(12, cfile);
34247131Sbostic fputs("break;\n", cfile);
34347131Sbostic }
34447131Sbostic fputs(" };\n", cfile);
34547131Sbostic if (! calcsize)
34647131Sbostic fputs(" new->type = n->type;\n", cfile);
34747131Sbostic }
34847131Sbostic
34947131Sbostic
350*69272Schristos static void
indent(amount,fp)35147131Sbostic indent(amount, fp)
352*69272Schristos int amount;
35347131Sbostic FILE *fp;
354*69272Schristos {
35547131Sbostic while (amount >= 8) {
35647131Sbostic putc('\t', fp);
35747131Sbostic amount -= 8;
35847131Sbostic }
35947131Sbostic while (--amount >= 0) {
36047131Sbostic putc(' ', fp);
36147131Sbostic }
36247131Sbostic }
36347131Sbostic
36447131Sbostic
365*69272Schristos static int
nextfield(buf)36647131Sbostic nextfield(buf)
36747131Sbostic char *buf;
368*69272Schristos {
36947131Sbostic register char *p, *q;
37047131Sbostic
37147131Sbostic p = linep;
37247131Sbostic while (*p == ' ' || *p == '\t')
37347131Sbostic p++;
37447131Sbostic q = buf;
37547131Sbostic while (*p != ' ' && *p != '\t' && *p != '\0')
37647131Sbostic *q++ = *p++;
37747131Sbostic *q = '\0';
37847131Sbostic linep = p;
37947131Sbostic return (q > buf);
38047131Sbostic }
38147131Sbostic
38247131Sbostic
383*69272Schristos static void
skipbl()384*69272Schristos skipbl()
385*69272Schristos {
38647131Sbostic while (*linep == ' ' || *linep == '\t')
38747131Sbostic linep++;
38847131Sbostic }
38947131Sbostic
39047131Sbostic
391*69272Schristos static int
readline()392*69272Schristos readline()
393*69272Schristos {
39447131Sbostic register char *p;
39547131Sbostic
39647131Sbostic if (fgets(line, 1024, infp) == NULL)
39747131Sbostic return 0;
39847131Sbostic for (p = line ; *p != '#' && *p != '\n' && *p != '\0' ; p++);
39947131Sbostic while (p > line && (p[-1] == ' ' || p[-1] == '\t'))
40047131Sbostic p--;
40147131Sbostic *p = '\0';
40247131Sbostic linep = line;
40347131Sbostic linno++;
40447131Sbostic if (p - line > BUFLEN)
40547131Sbostic error("Line too long");
40647131Sbostic return 1;
40747131Sbostic }
40847131Sbostic
40947131Sbostic
41047131Sbostic
411*69272Schristos static void
412*69272Schristos #if __STDC__
error(const char * msg,...)413*69272Schristos error(const char *msg, ...)
414*69272Schristos #else
415*69272Schristos error(va_alist)
416*69272Schristos va_dcl
417*69272Schristos #endif
418*69272Schristos {
419*69272Schristos va_list va;
420*69272Schristos #if __STDC__
421*69272Schristos va_start(va, msg);
422*69272Schristos #else
42347131Sbostic char *msg;
424*69272Schristos va_start(va);
425*69272Schristos msg = va_arg(va, char *);
426*69272Schristos #endif
427*69272Schristos
428*69272Schristos (void) fprintf(stderr, "line %d: ", linno);
429*69272Schristos (void) vfprintf(stderr, msg, va);
430*69272Schristos (void) fputc('\n', stderr);
431*69272Schristos
432*69272Schristos va_end(va);
433*69272Schristos
43447131Sbostic exit(2);
43547131Sbostic }
43647131Sbostic
43747131Sbostic
43847131Sbostic
439*69272Schristos static char *
savestr(s)44047131Sbostic savestr(s)
441*69272Schristos const char *s;
442*69272Schristos {
44347131Sbostic register char *p;
44447131Sbostic
44547131Sbostic if ((p = malloc(strlen(s) + 1)) == NULL)
44647131Sbostic error("Out of space");
447*69272Schristos (void) strcpy(p, s);
44847131Sbostic return p;
44947131Sbostic }
450