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