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