mknodes.c revision 3044
1/*-
2 * Copyright (c) 1991, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Kenneth Almquist.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by the University of
19 *	California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 *	$Id$
37 */
38
39#ifndef lint
40static char copyright[] =
41"@(#) Copyright (c) 1991, 1993\n\
42	The Regents of the University of California.  All rights reserved.\n";
43#endif /* not lint */
44
45#ifndef lint
46static char sccsid[] = "@(#)mknodes.c	8.1 (Berkeley) 5/31/93";
47#endif /* not lint */
48
49/*
50 * This program reads the nodetypes file and nodes.c.pat file.  It generates
51 * the files nodes.h and nodes.c.
52 */
53
54#include <stdio.h>
55
56
57#define MAXTYPES 50		/* max number of node types */
58#define MAXFIELDS 20		/* max fields in a structure */
59#define BUFLEN 100		/* size of character buffers */
60
61/* field types */
62#define T_NODE 1		/* union node *field */
63#define T_NODELIST 2		/* struct nodelist *field */
64#define T_STRING 3
65#define T_INT 4			/* int field */
66#define T_OTHER 5		/* other */
67#define T_TEMP 6		/* don't copy this field */
68
69
70struct field {			/* a structure field */
71	char *name;		/* name of field */
72	int type;			/* type of field */
73	char *decl;		/* declaration of field */
74};
75
76
77struct str {			/* struct representing a node structure */
78	char *tag;		/* structure tag */
79	int nfields;		/* number of fields in the structure */
80	struct field field[MAXFIELDS];	/* the fields of the structure */
81	int done;			/* set if fully parsed */
82};
83
84
85int ntypes;			/* number of node types */
86char *nodename[MAXTYPES];	/* names of the nodes */
87struct str *nodestr[MAXTYPES];	/* type of structure used by the node */
88int nstr;			/* number of structures */
89struct str str[MAXTYPES];	/* the structures */
90struct str *curstr;		/* current structure */
91
92
93FILE *infp = stdin;
94char line[1024];
95int linno;
96char *linep;
97
98
99char *savestr();
100#define equal(s1, s2)	(strcmp(s1, s2) == 0)
101
102
103main(argc, argv)
104	char **argv;
105	{
106	if (argc != 3)
107		error("usage: mknodes file\n");
108	if ((infp = fopen(argv[1], "r")) == NULL)
109		error("Can't open %s", argv[1]);
110	while (readline()) {
111		if (line[0] == ' ' || line[0] == '\t')
112			parsefield();
113		else if (line[0] != '\0')
114			parsenode();
115	}
116	output(argv[2]);
117	exit(0);
118}
119
120
121
122parsenode() {
123	char name[BUFLEN];
124	char tag[BUFLEN];
125	struct str *sp;
126
127	if (curstr && curstr->nfields > 0)
128		curstr->done = 1;
129	nextfield(name);
130	if (! nextfield(tag))
131		error("Tag expected");
132	if (*linep != '\0')
133		error("Garbage at end of line");
134	nodename[ntypes] = savestr(name);
135	for (sp = str ; sp < str + nstr ; sp++) {
136		if (equal(sp->tag, tag))
137			break;
138	}
139	if (sp >= str + nstr) {
140		sp->tag = savestr(tag);
141		sp->nfields = 0;
142		curstr = sp;
143		nstr++;
144	}
145	nodestr[ntypes] = sp;
146	ntypes++;
147}
148
149
150parsefield() {
151	char name[BUFLEN];
152	char type[BUFLEN];
153	char decl[2 * BUFLEN];
154	struct field *fp;
155
156	if (curstr == NULL || curstr->done)
157		error("No current structure to add field to");
158	if (! nextfield(name))
159		error("No field name");
160	if (! nextfield(type))
161		error("No field type");
162	fp = &curstr->field[curstr->nfields];
163	fp->name = savestr(name);
164	if (equal(type, "nodeptr")) {
165		fp->type = T_NODE;
166		sprintf(decl, "union node *%s", name);
167	} else if (equal(type, "nodelist")) {
168		fp->type = T_NODELIST;
169		sprintf(decl, "struct nodelist *%s", name);
170	} else if (equal(type, "string")) {
171		fp->type = T_STRING;
172		sprintf(decl, "char *%s", name);
173	} else if (equal(type, "int")) {
174		fp->type = T_INT;
175		sprintf(decl, "int %s", name);
176	} else if (equal(type, "other")) {
177		fp->type = T_OTHER;
178	} else if (equal(type, "temp")) {
179		fp->type = T_TEMP;
180	} else {
181		error("Unknown type %s", type);
182	}
183	if (fp->type == T_OTHER || fp->type == T_TEMP) {
184		skipbl();
185		fp->decl = savestr(linep);
186	} else {
187		if (*linep)
188			error("Garbage at end of line");
189		fp->decl = savestr(decl);
190	}
191	curstr->nfields++;
192}
193
194
195char writer[] = "\
196/*\n\
197 * This file was generated by the mknodes program.\n\
198 */\n\
199\n";
200
201output(file)
202	char *file;
203	{
204	FILE *hfile;
205	FILE *cfile;
206	FILE *patfile;
207	int i;
208	struct str *sp;
209	struct field *fp;
210	char *p;
211
212	if ((patfile = fopen(file, "r")) == NULL)
213		error("Can't open %s", file);
214	if ((hfile = fopen("nodes.h", "w")) == NULL)
215		error("Can't create nodes.h");
216	if ((cfile = fopen("nodes.c", "w")) == NULL)
217		error("Can't create nodes.c");
218	fputs(writer, hfile);
219	for (i = 0 ; i < ntypes ; i++)
220		fprintf(hfile, "#define %s %d\n", nodename[i], i);
221	fputs("\n\n\n", hfile);
222	for (sp = str ; sp < &str[nstr] ; sp++) {
223		fprintf(hfile, "struct %s {\n", sp->tag);
224		for (i = sp->nfields, fp = sp->field ; --i >= 0 ; fp++) {
225			fprintf(hfile, "      %s;\n", fp->decl);
226		}
227		fputs("};\n\n\n", hfile);
228	}
229	fputs("union node {\n", hfile);
230	fprintf(hfile, "      int type;\n");
231	for (sp = str ; sp < &str[nstr] ; sp++) {
232		fprintf(hfile, "      struct %s %s;\n", sp->tag, sp->tag);
233	}
234	fputs("};\n\n\n", hfile);
235	fputs("struct nodelist {\n", hfile);
236	fputs("\tstruct nodelist *next;\n", hfile);
237	fputs("\tunion node *n;\n", hfile);
238	fputs("};\n\n\n", hfile);
239	fputs("#ifdef __STDC__\n", hfile);
240	fputs("union node *copyfunc(union node *);\n", hfile);
241	fputs("void freefunc(union node *);\n", hfile);
242	fputs("#else\n", hfile);
243	fputs("union node *copyfunc();\n", hfile);
244	fputs("void freefunc();\n", hfile);
245	fputs("#endif\n", hfile);
246
247	fputs(writer, cfile);
248	while (fgets(line, sizeof line, patfile) != NULL) {
249		for (p = line ; *p == ' ' || *p == '\t' ; p++);
250		if (equal(p, "%SIZES\n"))
251			outsizes(cfile);
252		else if (equal(p, "%CALCSIZE\n"))
253			outfunc(cfile, 1);
254		else if (equal(p, "%COPY\n"))
255			outfunc(cfile, 0);
256		else
257			fputs(line, cfile);
258	}
259}
260
261
262
263outsizes(cfile)
264	FILE *cfile;
265	{
266	int i;
267
268	fprintf(cfile, "static const short nodesize[%d] = {\n", ntypes);
269	for (i = 0 ; i < ntypes ; i++) {
270		fprintf(cfile, "      ALIGN(sizeof (struct %s)),\n", nodestr[i]->tag);
271	}
272	fprintf(cfile, "};\n");
273}
274
275
276outfunc(cfile, calcsize)
277	FILE *cfile;
278	{
279	struct str *sp;
280	struct field *fp;
281	int i;
282
283	fputs("      if (n == NULL)\n", cfile);
284	if (calcsize)
285		fputs("	    return;\n", cfile);
286	else
287		fputs("	    return NULL;\n", cfile);
288	if (calcsize)
289		fputs("      funcblocksize += nodesize[n->type];\n", cfile);
290	else {
291		fputs("      new = funcblock;\n", cfile);
292		fputs("      funcblock += nodesize[n->type];\n", cfile);
293	}
294	fputs("      switch (n->type) {\n", cfile);
295	for (sp = str ; sp < &str[nstr] ; sp++) {
296		for (i = 0 ; i < ntypes ; i++) {
297			if (nodestr[i] == sp)
298				fprintf(cfile, "      case %s:\n", nodename[i]);
299		}
300		for (i = sp->nfields ; --i >= 1 ; ) {
301			fp = &sp->field[i];
302			switch (fp->type) {
303			case T_NODE:
304				if (calcsize) {
305					indent(12, cfile);
306					fprintf(cfile, "calcsize(n->%s.%s);\n",
307						sp->tag, fp->name);
308				} else {
309					indent(12, cfile);
310					fprintf(cfile, "new->%s.%s = copynode(n->%s.%s);\n",
311						sp->tag, fp->name, sp->tag, fp->name);
312				}
313				break;
314			case T_NODELIST:
315				if (calcsize) {
316					indent(12, cfile);
317					fprintf(cfile, "sizenodelist(n->%s.%s);\n",
318						sp->tag, fp->name);
319				} else {
320					indent(12, cfile);
321					fprintf(cfile, "new->%s.%s = copynodelist(n->%s.%s);\n",
322						sp->tag, fp->name, sp->tag, fp->name);
323				}
324				break;
325			case T_STRING:
326				if (calcsize) {
327					indent(12, cfile);
328					fprintf(cfile, "funcstringsize += strlen(n->%s.%s) + 1;\n",
329						sp->tag, fp->name);
330				} else {
331					indent(12, cfile);
332					fprintf(cfile, "new->%s.%s = nodesavestr(n->%s.%s);\n",
333						sp->tag, fp->name, sp->tag, fp->name);
334				}
335				break;
336			case T_INT:
337			case T_OTHER:
338				if (! calcsize) {
339					indent(12, cfile);
340					fprintf(cfile, "new->%s.%s = n->%s.%s;\n",
341						sp->tag, fp->name, sp->tag, fp->name);
342				}
343				break;
344			}
345		}
346		indent(12, cfile);
347		fputs("break;\n", cfile);
348	}
349	fputs("      };\n", cfile);
350	if (! calcsize)
351		fputs("      new->type = n->type;\n", cfile);
352}
353
354
355indent(amount, fp)
356	FILE *fp;
357	{
358	while (amount >= 8) {
359		putc('\t', fp);
360		amount -= 8;
361	}
362	while (--amount >= 0) {
363		putc(' ', fp);
364	}
365}
366
367
368int
369nextfield(buf)
370	char *buf;
371	{
372	register char *p, *q;
373
374	p = linep;
375	while (*p == ' ' || *p == '\t')
376		p++;
377	q = buf;
378	while (*p != ' ' && *p != '\t' && *p != '\0')
379		*q++ = *p++;
380	*q = '\0';
381	linep = p;
382	return (q > buf);
383}
384
385
386skipbl() {
387	while (*linep == ' ' || *linep == '\t')
388		linep++;
389}
390
391
392int
393readline() {
394	register char *p;
395
396	if (fgets(line, 1024, infp) == NULL)
397		return 0;
398	for (p = line ; *p != '#' && *p != '\n' && *p != '\0' ; p++);
399	while (p > line && (p[-1] == ' ' || p[-1] == '\t'))
400		p--;
401	*p = '\0';
402	linep = line;
403	linno++;
404	if (p - line > BUFLEN)
405		error("Line too long");
406	return 1;
407}
408
409
410
411error(msg, a1, a2, a3, a4, a5, a6)
412	char *msg;
413	{
414	fprintf(stderr, "line %d: ", linno);
415	fprintf(stderr, msg, a1, a2, a3, a4, a5, a6);
416	putc('\n', stderr);
417	exit(2);
418}
419
420
421
422char *
423savestr(s)
424	char *s;
425	{
426	register char *p;
427	char *malloc();
428
429	if ((p = malloc(strlen(s) + 1)) == NULL)
430		error("Out of space");
431	strcpy(p, s);
432	return p;
433}
434