xref: /original-bsd/bin/sh/mknodes.c (revision b3c06cab)
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  * %sccs.include.redist.c%
9  */
10 
11 #ifndef lint
12 static char copyright[] =
13 "@(#) Copyright (c) 1991, 1993\n\
14 	The Regents of the University of California.  All rights reserved.\n";
15 #endif /* not lint */
16 
17 #ifndef lint
18 static char sccsid[] = "@(#)mknodes.c	8.2 (Berkeley) 05/04/95";
19 #endif /* not lint */
20 
21 /*
22  * This program reads the nodetypes file and nodes.c.pat file.  It generates
23  * the files nodes.h and nodes.c.
24  */
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #if __STDC__
30 #include <stdarg.h>
31 #else
32 #include <varargs.h>
33 #endif
34 
35 
36 #define MAXTYPES 50		/* max number of node types */
37 #define MAXFIELDS 20		/* max fields in a structure */
38 #define BUFLEN 100		/* size of character buffers */
39 
40 /* field types */
41 #define T_NODE 1		/* union node *field */
42 #define T_NODELIST 2		/* struct nodelist *field */
43 #define T_STRING 3
44 #define T_INT 4			/* int field */
45 #define T_OTHER 5		/* other */
46 #define T_TEMP 6		/* don't copy this field */
47 
48 
49 struct field {			/* a structure field */
50 	char *name;		/* name of field */
51 	int type;			/* type of field */
52 	char *decl;		/* declaration of field */
53 };
54 
55 
56 struct str {			/* struct representing a node structure */
57 	char *tag;		/* structure tag */
58 	int nfields;		/* number of fields in the structure */
59 	struct field field[MAXFIELDS];	/* the fields of the structure */
60 	int done;			/* set if fully parsed */
61 };
62 
63 
64 static int ntypes;			/* number of node types */
65 static char *nodename[MAXTYPES];	/* names of the nodes */
66 static struct str *nodestr[MAXTYPES];	/* type of structure used by the node */
67 static int nstr;			/* number of structures */
68 static struct str str[MAXTYPES];	/* the structures */
69 static struct str *curstr;		/* current structure */
70 static FILE *infp = stdin;
71 static char line[1024];
72 static int linno;
73 static char *linep;
74 
75 static void parsenode __P((void));
76 static void parsefield __P((void));
77 static void output __P((char *));
78 static void outsizes __P((FILE *));
79 static void outfunc __P((FILE *, int));
80 static void indent __P((int, FILE *));
81 static int nextfield __P((char *));
82 static void skipbl __P((void));
83 static int readline __P((void));
84 static void error __P((const char *, ...));
85 static char *savestr __P((const char *));
86 
87 
88 int
89 main(argc, argv)
90 	int argc;
91 	char **argv;
92 {
93 	if (argc != 3)
94 		error("usage: mknodes file\n");
95 	if ((infp = fopen(argv[1], "r")) == NULL)
96 		error("Can't open %s", argv[1]);
97 	while (readline()) {
98 		if (line[0] == ' ' || line[0] == '\t')
99 			parsefield();
100 		else if (line[0] != '\0')
101 			parsenode();
102 	}
103 	output(argv[2]);
104 	exit(0);
105 }
106 
107 
108 
109 static void
110 parsenode()
111 {
112 	char name[BUFLEN];
113 	char tag[BUFLEN];
114 	struct str *sp;
115 
116 	if (curstr && curstr->nfields > 0)
117 		curstr->done = 1;
118 	nextfield(name);
119 	if (! nextfield(tag))
120 		error("Tag expected");
121 	if (*linep != '\0')
122 		error("Garbage at end of line");
123 	nodename[ntypes] = savestr(name);
124 	for (sp = str ; sp < str + nstr ; sp++) {
125 		if (strcmp(sp->tag, tag) == 0)
126 			break;
127 	}
128 	if (sp >= str + nstr) {
129 		sp->tag = savestr(tag);
130 		sp->nfields = 0;
131 		curstr = sp;
132 		nstr++;
133 	}
134 	nodestr[ntypes] = sp;
135 	ntypes++;
136 }
137 
138 
139 static void
140 parsefield()
141 {
142 	char name[BUFLEN];
143 	char type[BUFLEN];
144 	char decl[2 * BUFLEN];
145 	struct field *fp;
146 
147 	if (curstr == NULL || curstr->done)
148 		error("No current structure to add field to");
149 	if (! nextfield(name))
150 		error("No field name");
151 	if (! nextfield(type))
152 		error("No field type");
153 	fp = &curstr->field[curstr->nfields];
154 	fp->name = savestr(name);
155 	if (strcmp(type, "nodeptr") == 0) {
156 		fp->type = T_NODE;
157 		sprintf(decl, "union node *%s", name);
158 	} else if (strcmp(type, "nodelist") == 0) {
159 		fp->type = T_NODELIST;
160 		sprintf(decl, "struct nodelist *%s", name);
161 	} else if (strcmp(type, "string") == 0) {
162 		fp->type = T_STRING;
163 		sprintf(decl, "char *%s", name);
164 	} else if (strcmp(type, "int") == 0) {
165 		fp->type = T_INT;
166 		sprintf(decl, "int %s", name);
167 	} else if (strcmp(type, "other") == 0) {
168 		fp->type = T_OTHER;
169 	} else if (strcmp(type, "temp") == 0) {
170 		fp->type = T_TEMP;
171 	} else {
172 		error("Unknown type %s", type);
173 	}
174 	if (fp->type == T_OTHER || fp->type == T_TEMP) {
175 		skipbl();
176 		fp->decl = savestr(linep);
177 	} else {
178 		if (*linep)
179 			error("Garbage at end of line");
180 		fp->decl = savestr(decl);
181 	}
182 	curstr->nfields++;
183 }
184 
185 
186 char writer[] = "\
187 /*\n\
188  * This file was generated by the mknodes program.\n\
189  */\n\
190 \n";
191 
192 static void
193 output(file)
194 	char *file;
195 {
196 	FILE *hfile;
197 	FILE *cfile;
198 	FILE *patfile;
199 	int i;
200 	struct str *sp;
201 	struct field *fp;
202 	char *p;
203 
204 	if ((patfile = fopen(file, "r")) == NULL)
205 		error("Can't open %s", file);
206 	if ((hfile = fopen("nodes.h", "w")) == NULL)
207 		error("Can't create nodes.h");
208 	if ((cfile = fopen("nodes.c", "w")) == NULL)
209 		error("Can't create nodes.c");
210 	fputs(writer, hfile);
211 	for (i = 0 ; i < ntypes ; i++)
212 		fprintf(hfile, "#define %s %d\n", nodename[i], i);
213 	fputs("\n\n\n", hfile);
214 	for (sp = str ; sp < &str[nstr] ; sp++) {
215 		fprintf(hfile, "struct %s {\n", sp->tag);
216 		for (i = sp->nfields, fp = sp->field ; --i >= 0 ; fp++) {
217 			fprintf(hfile, "      %s;\n", fp->decl);
218 		}
219 		fputs("};\n\n\n", hfile);
220 	}
221 	fputs("union node {\n", hfile);
222 	fprintf(hfile, "      int type;\n");
223 	for (sp = str ; sp < &str[nstr] ; sp++) {
224 		fprintf(hfile, "      struct %s %s;\n", sp->tag, sp->tag);
225 	}
226 	fputs("};\n\n\n", hfile);
227 	fputs("struct nodelist {\n", hfile);
228 	fputs("\tstruct nodelist *next;\n", hfile);
229 	fputs("\tunion node *n;\n", hfile);
230 	fputs("};\n\n\n", hfile);
231 	fputs("#ifdef __STDC__\n", hfile);
232 	fputs("union node *copyfunc(union node *);\n", hfile);
233 	fputs("void freefunc(union node *);\n", hfile);
234 	fputs("#else\n", hfile);
235 	fputs("union node *copyfunc();\n", hfile);
236 	fputs("void freefunc();\n", hfile);
237 	fputs("#endif\n", hfile);
238 
239 	fputs(writer, cfile);
240 	while (fgets(line, sizeof line, patfile) != NULL) {
241 		for (p = line ; *p == ' ' || *p == '\t' ; p++);
242 		if (strcmp(p, "%SIZES\n") == 0)
243 			outsizes(cfile);
244 		else if (strcmp(p, "%CALCSIZE\n") == 0)
245 			outfunc(cfile, 1);
246 		else if (strcmp(p, "%COPY\n") == 0)
247 			outfunc(cfile, 0);
248 		else
249 			fputs(line, cfile);
250 	}
251 }
252 
253 
254 
255 static void
256 outsizes(cfile)
257 	FILE *cfile;
258 {
259 	int i;
260 
261 	fprintf(cfile, "static const short nodesize[%d] = {\n", ntypes);
262 	for (i = 0 ; i < ntypes ; i++) {
263 		fprintf(cfile, "      ALIGN(sizeof (struct %s)),\n", nodestr[i]->tag);
264 	}
265 	fprintf(cfile, "};\n");
266 }
267 
268 
269 static void
270 outfunc(cfile, calcsize)
271 	FILE *cfile;
272 	int calcsize;
273 {
274 	struct str *sp;
275 	struct field *fp;
276 	int i;
277 
278 	fputs("      if (n == NULL)\n", cfile);
279 	if (calcsize)
280 		fputs("	    return;\n", cfile);
281 	else
282 		fputs("	    return NULL;\n", cfile);
283 	if (calcsize)
284 		fputs("      funcblocksize += nodesize[n->type];\n", cfile);
285 	else {
286 		fputs("      new = funcblock;\n", cfile);
287 		fputs("      funcblock += nodesize[n->type];\n", cfile);
288 	}
289 	fputs("      switch (n->type) {\n", cfile);
290 	for (sp = str ; sp < &str[nstr] ; sp++) {
291 		for (i = 0 ; i < ntypes ; i++) {
292 			if (nodestr[i] == sp)
293 				fprintf(cfile, "      case %s:\n", nodename[i]);
294 		}
295 		for (i = sp->nfields ; --i >= 1 ; ) {
296 			fp = &sp->field[i];
297 			switch (fp->type) {
298 			case T_NODE:
299 				if (calcsize) {
300 					indent(12, cfile);
301 					fprintf(cfile, "calcsize(n->%s.%s);\n",
302 						sp->tag, fp->name);
303 				} else {
304 					indent(12, cfile);
305 					fprintf(cfile, "new->%s.%s = copynode(n->%s.%s);\n",
306 						sp->tag, fp->name, sp->tag, fp->name);
307 				}
308 				break;
309 			case T_NODELIST:
310 				if (calcsize) {
311 					indent(12, cfile);
312 					fprintf(cfile, "sizenodelist(n->%s.%s);\n",
313 						sp->tag, fp->name);
314 				} else {
315 					indent(12, cfile);
316 					fprintf(cfile, "new->%s.%s = copynodelist(n->%s.%s);\n",
317 						sp->tag, fp->name, sp->tag, fp->name);
318 				}
319 				break;
320 			case T_STRING:
321 				if (calcsize) {
322 					indent(12, cfile);
323 					fprintf(cfile, "funcstringsize += strlen(n->%s.%s) + 1;\n",
324 						sp->tag, fp->name);
325 				} else {
326 					indent(12, cfile);
327 					fprintf(cfile, "new->%s.%s = nodesavestr(n->%s.%s);\n",
328 						sp->tag, fp->name, sp->tag, fp->name);
329 				}
330 				break;
331 			case T_INT:
332 			case T_OTHER:
333 				if (! calcsize) {
334 					indent(12, cfile);
335 					fprintf(cfile, "new->%s.%s = n->%s.%s;\n",
336 						sp->tag, fp->name, sp->tag, fp->name);
337 				}
338 				break;
339 			}
340 		}
341 		indent(12, cfile);
342 		fputs("break;\n", cfile);
343 	}
344 	fputs("      };\n", cfile);
345 	if (! calcsize)
346 		fputs("      new->type = n->type;\n", cfile);
347 }
348 
349 
350 static void
351 indent(amount, fp)
352 	int amount;
353 	FILE *fp;
354 {
355 	while (amount >= 8) {
356 		putc('\t', fp);
357 		amount -= 8;
358 	}
359 	while (--amount >= 0) {
360 		putc(' ', fp);
361 	}
362 }
363 
364 
365 static int
366 nextfield(buf)
367 	char *buf;
368 {
369 	register char *p, *q;
370 
371 	p = linep;
372 	while (*p == ' ' || *p == '\t')
373 		p++;
374 	q = buf;
375 	while (*p != ' ' && *p != '\t' && *p != '\0')
376 		*q++ = *p++;
377 	*q = '\0';
378 	linep = p;
379 	return (q > buf);
380 }
381 
382 
383 static void
384 skipbl()
385 {
386 	while (*linep == ' ' || *linep == '\t')
387 		linep++;
388 }
389 
390 
391 static int
392 readline()
393 {
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 
411 static void
412 #if __STDC__
413 error(const char *msg, ...)
414 #else
415 error(va_alist)
416 	va_dcl
417 #endif
418 {
419 	va_list va;
420 #if __STDC__
421 	va_start(va, msg);
422 #else
423 	char *msg;
424 	va_start(va);
425 	msg = va_arg(va, char *);
426 #endif
427 
428 	(void) fprintf(stderr, "line %d: ", linno);
429 	(void) vfprintf(stderr, msg, va);
430 	(void) fputc('\n', stderr);
431 
432 	va_end(va);
433 
434 	exit(2);
435 }
436 
437 
438 
439 static char *
440 savestr(s)
441 	const char *s;
442 {
443 	register char *p;
444 
445 	if ((p = malloc(strlen(s) + 1)) == NULL)
446 		error("Out of space");
447 	(void) strcpy(p, s);
448 	return p;
449 }
450