mknodes.c revision 90111
1193323Sed/*-
2193323Sed * Copyright (c) 1991, 1993
3193323Sed *	The Regents of the University of California.  All rights reserved.
4193323Sed *
5193323Sed * This code is derived from software contributed to Berkeley by
6193323Sed * Kenneth Almquist.
7193323Sed *
8193323Sed * Redistribution and use in source and binary forms, with or without
9193323Sed * modification, are permitted provided that the following conditions
10193323Sed * are met:
11193323Sed * 1. Redistributions of source code must retain the above copyright
12193323Sed *    notice, this list of conditions and the following disclaimer.
13193323Sed * 2. Redistributions in binary form must reproduce the above copyright
14193323Sed *    notice, this list of conditions and the following disclaimer in the
15193323Sed *    documentation and/or other materials provided with the distribution.
16193323Sed * 3. All advertising materials mentioning features or use of this software
17193323Sed *    must display the following acknowledgement:
18193323Sed *	This product includes software developed by the University of
19193323Sed *	California, Berkeley and its contributors.
20193323Sed * 4. Neither the name of the University nor the names of its contributors
21193323Sed *    may be used to endorse or promote products derived from this software
22193323Sed *    without specific prior written permission.
23193323Sed *
24193323Sed * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25193323Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26193323Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27193323Sed * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28193323Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29193323Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30193323Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31193323Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32193323Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33193323Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34193323Sed * SUCH DAMAGE.
35193323Sed */
36193323Sed
37193323Sed#ifndef lint
38193323Sedstatic char const copyright[] =
39193323Sed"@(#) Copyright (c) 1991, 1993\n\
40193323Sed	The Regents of the University of California.  All rights reserved.\n";
41193323Sed#endif /* not lint */
42193323Sed
43193323Sed#ifndef lint
44193323Sed#if 0
45193323Sedstatic char sccsid[] = "@(#)mknodes.c	8.2 (Berkeley) 5/4/95";
46193323Sed#endif
47193323Sedstatic const char rcsid[] =
48193323Sed  "$FreeBSD: head/bin/sh/mknodes.c 90111 2002-02-02 06:50:57Z imp $";
49193323Sed#endif /* not lint */
50193323Sed
51193323Sed/*
52193323Sed * This program reads the nodetypes file and nodes.c.pat file.  It generates
53193323Sed * the files nodes.h and nodes.c.
54193323Sed */
55193323Sed
56193323Sed#include <stdio.h>
57193323Sed#include <stdlib.h>
58193323Sed#include <string.h>
59193323Sed#include <errno.h>
60193323Sed#include <stdarg.h>
61193323Sed
62193323Sed#define MAXTYPES 50		/* max number of node types */
63193323Sed#define MAXFIELDS 20		/* max fields in a structure */
64193323Sed#define BUFLEN 100		/* size of character buffers */
65193323Sed
66193323Sed/* field types */
67193323Sed#define T_NODE 1		/* union node *field */
68193323Sed#define T_NODELIST 2		/* struct nodelist *field */
69193323Sed#define T_STRING 3
70193323Sed#define T_INT 4			/* int field */
71193323Sed#define T_OTHER 5		/* other */
72193323Sed#define T_TEMP 6		/* don't copy this field */
73193323Sed
74193323Sed
75193323Sedstruct field {			/* a structure field */
76193323Sed	char *name;		/* name of field */
77193323Sed	int type;			/* type of field */
78193323Sed	char *decl;		/* declaration of field */
79193323Sed};
80193323Sed
81193323Sed
82193323Sedstruct str {			/* struct representing a node structure */
83193323Sed	char *tag;		/* structure tag */
84193323Sed	int nfields;		/* number of fields in the structure */
85193323Sed	struct field field[MAXFIELDS];	/* the fields of the structure */
86193323Sed	int done;			/* set if fully parsed */
87193323Sed};
88193323Sed
89193323Sed
90193323Sedstatic int ntypes;			/* number of node types */
91193323Sedstatic char *nodename[MAXTYPES];	/* names of the nodes */
92193323Sedstatic struct str *nodestr[MAXTYPES];	/* type of structure used by the node */
93193323Sedstatic int nstr;			/* number of structures */
94193323Sedstatic struct str str[MAXTYPES];	/* the structures */
95193323Sedstatic struct str *curstr;		/* current structure */
96193323Sedstatic FILE *infp;
97193323Sedstatic char line[1024];
98193323Sedstatic int linno;
99193323Sedstatic char *linep;
100193323Sed
101193323Sedstatic void parsenode(void);
102193323Sedstatic void parsefield(void);
103193323Sedstatic void output(char *);
104193323Sedstatic void outsizes(FILE *);
105193323Sedstatic void outfunc(FILE *, int);
106193323Sedstatic void indent(int, FILE *);
107193323Sedstatic int nextfield(char *);
108193323Sedstatic void skipbl(void);
109193323Sedstatic int readline(void);
110193323Sedstatic void error(const char *, ...) __printf0like(1, 2);
111193323Sedstatic char *savestr(const char *);
112193323Sed
113193323Sed
114193323Sedint
115193323Sedmain(int argc, char *argv[])
116193323Sed{
117193323Sed	if (argc != 3)
118193323Sed		error("usage: mknodes file");
119193323Sed	infp = stdin;
120193323Sed	if ((infp = fopen(argv[1], "r")) == NULL)
121193323Sed		error("Can't open %s: %s", argv[1], strerror(errno));
122193323Sed	while (readline()) {
123193323Sed		if (line[0] == ' ' || line[0] == '\t')
124193323Sed			parsefield();
125193323Sed		else if (line[0] != '\0')
126193323Sed			parsenode();
127193323Sed	}
128193323Sed	output(argv[2]);
129193323Sed	exit(0);
130193323Sed}
131193323Sed
132193323Sed
133193323Sed
134193323Sedstatic void
135193323Sedparsenode(void)
136193323Sed{
137193323Sed	char name[BUFLEN];
138193323Sed	char tag[BUFLEN];
139193323Sed	struct str *sp;
140193323Sed
141193323Sed	if (curstr && curstr->nfields > 0)
142193323Sed		curstr->done = 1;
143193323Sed	nextfield(name);
144193323Sed	if (! nextfield(tag))
145193323Sed		error("Tag expected");
146193323Sed	if (*linep != '\0')
147193323Sed		error("Garbage at end of line");
148193323Sed	nodename[ntypes] = savestr(name);
149193323Sed	for (sp = str ; sp < str + nstr ; sp++) {
150193323Sed		if (strcmp(sp->tag, tag) == 0)
151193323Sed			break;
152193323Sed	}
153193323Sed	if (sp >= str + nstr) {
154193323Sed		sp->tag = savestr(tag);
155193323Sed		sp->nfields = 0;
156193323Sed		curstr = sp;
157193323Sed		nstr++;
158193323Sed	}
159193323Sed	nodestr[ntypes] = sp;
160193323Sed	ntypes++;
161193323Sed}
162193323Sed
163193323Sed
164193323Sedstatic void
165193323Sedparsefield(void)
166193323Sed{
167193323Sed	char name[BUFLEN];
168193323Sed	char type[BUFLEN];
169193323Sed	char decl[2 * BUFLEN];
170193323Sed	struct field *fp;
171193323Sed
172193323Sed	if (curstr == NULL || curstr->done)
173193323Sed		error("No current structure to add field to");
174193323Sed	if (! nextfield(name))
175193323Sed		error("No field name");
176193323Sed	if (! nextfield(type))
177193323Sed		error("No field type");
178193323Sed	fp = &curstr->field[curstr->nfields];
179193323Sed	fp->name = savestr(name);
180193323Sed	if (strcmp(type, "nodeptr") == 0) {
181193323Sed		fp->type = T_NODE;
182193323Sed		sprintf(decl, "union node *%s", name);
183193323Sed	} else if (strcmp(type, "nodelist") == 0) {
184193323Sed		fp->type = T_NODELIST;
185193323Sed		sprintf(decl, "struct nodelist *%s", name);
186193323Sed	} else if (strcmp(type, "string") == 0) {
187193323Sed		fp->type = T_STRING;
188193323Sed		sprintf(decl, "char *%s", name);
189193323Sed	} else if (strcmp(type, "int") == 0) {
190193323Sed		fp->type = T_INT;
191193323Sed		sprintf(decl, "int %s", name);
192193323Sed	} else if (strcmp(type, "other") == 0) {
193193323Sed		fp->type = T_OTHER;
194193323Sed	} else if (strcmp(type, "temp") == 0) {
195193323Sed		fp->type = T_TEMP;
196193323Sed	} else {
197193323Sed		error("Unknown type %s", type);
198193323Sed	}
199193323Sed	if (fp->type == T_OTHER || fp->type == T_TEMP) {
200193323Sed		skipbl();
201193323Sed		fp->decl = savestr(linep);
202193323Sed	} else {
203193323Sed		if (*linep)
204193323Sed			error("Garbage at end of line");
205193323Sed		fp->decl = savestr(decl);
206193323Sed	}
207193323Sed	curstr->nfields++;
208193323Sed}
209193323Sed
210193323Sed
211193323Sedchar writer[] = "\
212193323Sed/*\n\
213193323Sed * This file was generated by the mknodes program.\n\
214193323Sed */\n\
215193323Sed\n";
216193323Sed
217193323Sedstatic void
218193323Sedoutput(char *file)
219193323Sed{
220193323Sed	FILE *hfile;
221193323Sed	FILE *cfile;
222193323Sed	FILE *patfile;
223193323Sed	int i;
224193323Sed	struct str *sp;
225193323Sed	struct field *fp;
226193323Sed	char *p;
227193323Sed
228193323Sed	if ((patfile = fopen(file, "r")) == NULL)
229193323Sed		error("Can't open %s: %s", file, strerror(errno));
230193323Sed	if ((hfile = fopen("nodes.h", "w")) == NULL)
231193323Sed		error("Can't create nodes.h: %s", strerror(errno));
232193323Sed	if ((cfile = fopen("nodes.c", "w")) == NULL)
233193323Sed		error("Can't create nodes.c");
234193323Sed	fputs(writer, hfile);
235193323Sed	for (i = 0 ; i < ntypes ; i++)
236193323Sed		fprintf(hfile, "#define %s %d\n", nodename[i], i);
237193323Sed	fputs("\n\n\n", hfile);
238193323Sed	for (sp = str ; sp < &str[nstr] ; sp++) {
239193323Sed		fprintf(hfile, "struct %s {\n", sp->tag);
240193323Sed		for (i = sp->nfields, fp = sp->field ; --i >= 0 ; fp++) {
241193323Sed			fprintf(hfile, "      %s;\n", fp->decl);
242193323Sed		}
243193323Sed		fputs("};\n\n\n", hfile);
244193323Sed	}
245193323Sed	fputs("union node {\n", hfile);
246193323Sed	fprintf(hfile, "      int type;\n");
247193323Sed	for (sp = str ; sp < &str[nstr] ; sp++) {
248193323Sed		fprintf(hfile, "      struct %s %s;\n", sp->tag, sp->tag);
249193323Sed	}
250193323Sed	fputs("};\n\n\n", hfile);
251193323Sed	fputs("struct nodelist {\n", hfile);
252193323Sed	fputs("\tstruct nodelist *next;\n", hfile);
253193323Sed	fputs("\tunion node *n;\n", hfile);
254193323Sed	fputs("};\n\n\n", hfile);
255193323Sed	fputs("union node *copyfunc(union node *);\n", hfile);
256193323Sed	fputs("void freefunc(union node *);\n", hfile);
257193323Sed
258193323Sed	fputs(writer, cfile);
259193323Sed	while (fgets(line, sizeof line, patfile) != NULL) {
260193323Sed		for (p = line ; *p == ' ' || *p == '\t' ; p++);
261193323Sed		if (strcmp(p, "%SIZES\n") == 0)
262193323Sed			outsizes(cfile);
263193323Sed		else if (strcmp(p, "%CALCSIZE\n") == 0)
264193323Sed			outfunc(cfile, 1);
265193323Sed		else if (strcmp(p, "%COPY\n") == 0)
266193323Sed			outfunc(cfile, 0);
267193323Sed		else
268193323Sed			fputs(line, cfile);
269193323Sed	}
270193323Sed}
271193323Sed
272193323Sed
273193323Sed
274193323Sedstatic void
275193323Sedoutsizes(FILE *cfile)
276193323Sed{
277193323Sed	int i;
278193323Sed
279193323Sed	fprintf(cfile, "static const short nodesize[%d] = {\n", ntypes);
280193323Sed	for (i = 0 ; i < ntypes ; i++) {
281193323Sed		fprintf(cfile, "      ALIGN(sizeof (struct %s)),\n", nodestr[i]->tag);
282193323Sed	}
283193323Sed	fprintf(cfile, "};\n");
284193323Sed}
285193323Sed
286193323Sed
287193323Sedstatic void
288193323Sedoutfunc(FILE *cfile, int calcsize)
289193323Sed{
290193323Sed	struct str *sp;
291193323Sed	struct field *fp;
292193323Sed	int i;
293193323Sed
294193323Sed	fputs("      if (n == NULL)\n", cfile);
295193323Sed	if (calcsize)
296193323Sed		fputs("	    return;\n", cfile);
297193323Sed	else
298193323Sed		fputs("	    return NULL;\n", cfile);
299193323Sed	if (calcsize)
300193323Sed		fputs("      funcblocksize += nodesize[n->type];\n", cfile);
301193323Sed	else {
302193323Sed		fputs("      new = funcblock;\n", cfile);
303193323Sed		fputs("      funcblock = (char *)funcblock + nodesize[n->type];\n", cfile);
304193323Sed	}
305193323Sed	fputs("      switch (n->type) {\n", cfile);
306193323Sed	for (sp = str ; sp < &str[nstr] ; sp++) {
307193323Sed		for (i = 0 ; i < ntypes ; i++) {
308193323Sed			if (nodestr[i] == sp)
309193323Sed				fprintf(cfile, "      case %s:\n", nodename[i]);
310193323Sed		}
311193323Sed		for (i = sp->nfields ; --i >= 1 ; ) {
312193323Sed			fp = &sp->field[i];
313193323Sed			switch (fp->type) {
314193323Sed			case T_NODE:
315193323Sed				if (calcsize) {
316193323Sed					indent(12, cfile);
317193323Sed					fprintf(cfile, "calcsize(n->%s.%s);\n",
318193323Sed						sp->tag, fp->name);
319193323Sed				} else {
320193323Sed					indent(12, cfile);
321193323Sed					fprintf(cfile, "new->%s.%s = copynode(n->%s.%s);\n",
322193323Sed						sp->tag, fp->name, sp->tag, fp->name);
323193323Sed				}
324193323Sed				break;
325193323Sed			case T_NODELIST:
326193323Sed				if (calcsize) {
327193323Sed					indent(12, cfile);
328193323Sed					fprintf(cfile, "sizenodelist(n->%s.%s);\n",
329193323Sed						sp->tag, fp->name);
330193323Sed				} else {
331193323Sed					indent(12, cfile);
332193323Sed					fprintf(cfile, "new->%s.%s = copynodelist(n->%s.%s);\n",
333193323Sed						sp->tag, fp->name, sp->tag, fp->name);
334193323Sed				}
335193323Sed				break;
336193323Sed			case T_STRING:
337193323Sed				if (calcsize) {
338193323Sed					indent(12, cfile);
339193323Sed					fprintf(cfile, "funcstringsize += strlen(n->%s.%s) + 1;\n",
340193323Sed						sp->tag, fp->name);
341193323Sed				} else {
342193323Sed					indent(12, cfile);
343193323Sed					fprintf(cfile, "new->%s.%s = nodesavestr(n->%s.%s);\n",
344193323Sed						sp->tag, fp->name, sp->tag, fp->name);
345193323Sed				}
346193323Sed				break;
347193323Sed			case T_INT:
348193323Sed			case T_OTHER:
349193323Sed				if (! calcsize) {
350193323Sed					indent(12, cfile);
351193323Sed					fprintf(cfile, "new->%s.%s = n->%s.%s;\n",
352193323Sed						sp->tag, fp->name, sp->tag, fp->name);
353193323Sed				}
354193323Sed				break;
355193323Sed			}
356193323Sed		}
357193323Sed		indent(12, cfile);
358193323Sed		fputs("break;\n", cfile);
359193323Sed	}
360193323Sed	fputs("      };\n", cfile);
361193323Sed	if (! calcsize)
362193323Sed		fputs("      new->type = n->type;\n", cfile);
363193323Sed}
364193323Sed
365193323Sed
366193323Sedstatic void
367193323Sedindent(int amount, FILE *fp)
368193323Sed{
369193323Sed	while (amount >= 8) {
370193323Sed		putc('\t', fp);
371193323Sed		amount -= 8;
372193323Sed	}
373193323Sed	while (--amount >= 0) {
374193323Sed		putc(' ', fp);
375193323Sed	}
376193323Sed}
377193323Sed
378193323Sed
379193323Sedstatic int
380193323Sednextfield(char *buf)
381193323Sed{
382193323Sed	char *p, *q;
383193323Sed
384193323Sed	p = linep;
385193323Sed	while (*p == ' ' || *p == '\t')
386193323Sed		p++;
387193323Sed	q = buf;
388193323Sed	while (*p != ' ' && *p != '\t' && *p != '\0')
389193323Sed		*q++ = *p++;
390193323Sed	*q = '\0';
391193323Sed	linep = p;
392193323Sed	return (q > buf);
393193323Sed}
394193323Sed
395193323Sed
396193323Sedstatic void
397193323Sedskipbl(void)
398193323Sed{
399193323Sed	while (*linep == ' ' || *linep == '\t')
400193323Sed		linep++;
401193323Sed}
402193323Sed
403193323Sed
404193323Sedstatic int
405193323Sedreadline(void)
406193323Sed{
407193323Sed	char *p;
408193323Sed
409193323Sed	if (fgets(line, 1024, infp) == NULL)
410193323Sed		return 0;
411193323Sed	for (p = line ; *p != '#' && *p != '\n' && *p != '\0' ; p++);
412193323Sed	while (p > line && (p[-1] == ' ' || p[-1] == '\t'))
413193323Sed		p--;
414193323Sed	*p = '\0';
415193323Sed	linep = line;
416193323Sed	linno++;
417193323Sed	if (p - line > BUFLEN)
418193323Sed		error("Line too long");
419193323Sed	return 1;
420193323Sed}
421193323Sed
422193323Sed
423193323Sed
424193323Sedstatic void
425193323Sederror(const char *msg, ...)
426193323Sed{
427193323Sed	va_list va;
428193323Sed	va_start(va, msg);
429193323Sed
430193323Sed	(void) fprintf(stderr, "line %d: ", linno);
431193323Sed	(void) vfprintf(stderr, msg, va);
432193323Sed	(void) fputc('\n', stderr);
433193323Sed
434193323Sed	va_end(va);
435193323Sed
436193323Sed	exit(2);
437193323Sed}
438193323Sed
439193323Sed
440193323Sed
441193323Sedstatic char *
442193323Sedsavestr(const char *s)
443193323Sed{
444193323Sed	char *p;
445193323Sed
446193323Sed	if ((p = malloc(strlen(s) + 1)) == NULL)
447193323Sed		error("Out of space");
448193323Sed	(void) strcpy(p, s);
449193323Sed	return p;
450193323Sed}
451193323Sed