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