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