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 const 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 #if 0 45 static char sccsid[] = "@(#)mknodes.c 8.2 (Berkeley) 5/4/95"; 46 #endif 47 static const char rcsid[] = 48 "$Id$"; 49 #endif /* not lint */ 50 51 /* 52 * This program reads the nodetypes file and nodes.c.pat file. It generates 53 * the files nodes.h and nodes.c. 54 */ 55 56 #include <stdio.h> 57 #include <stdlib.h> 58 #include <string.h> 59 #ifdef __STDC__ 60 #include <stdarg.h> 61 #else 62 #include <varargs.h> 63 #endif 64 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 FILE *infp = stdin; 101 static char line[1024]; 102 static int linno; 103 static char *linep; 104 105 static void parsenode __P((void)); 106 static void parsefield __P((void)); 107 static void output __P((char *)); 108 static void outsizes __P((FILE *)); 109 static void outfunc __P((FILE *, int)); 110 static void indent __P((int, FILE *)); 111 static int nextfield __P((char *)); 112 static void skipbl __P((void)); 113 static int readline __P((void)); 114 static void error __P((const char *, ...)); 115 static char *savestr __P((const char *)); 116 117 118 int 119 main(argc, argv) 120 int argc; 121 char **argv; 122 { 123 if (argc != 3) 124 error("usage: mknodes file"); 125 if ((infp = fopen(argv[1], "r")) == NULL) 126 error("Can't open %s", argv[1]); 127 while (readline()) { 128 if (line[0] == ' ' || line[0] == '\t') 129 parsefield(); 130 else if (line[0] != '\0') 131 parsenode(); 132 } 133 output(argv[2]); 134 exit(0); 135 } 136 137 138 139 static void 140 parsenode() 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() 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 char writer[] = "\ 217 /*\n\ 218 * This file was generated by the mknodes program.\n\ 219 */\n\ 220 \n"; 221 222 static void 223 output(file) 224 char *file; 225 { 226 FILE *hfile; 227 FILE *cfile; 228 FILE *patfile; 229 int i; 230 struct str *sp; 231 struct field *fp; 232 char *p; 233 234 if ((patfile = fopen(file, "r")) == NULL) 235 error("Can't open %s", file); 236 if ((hfile = fopen("nodes.h", "w")) == NULL) 237 error("Can't create nodes.h"); 238 if ((cfile = fopen("nodes.c", "w")) == NULL) 239 error("Can't create nodes.c"); 240 fputs(writer, hfile); 241 for (i = 0 ; i < ntypes ; i++) 242 fprintf(hfile, "#define %s %d\n", nodename[i], i); 243 fputs("\n\n\n", hfile); 244 for (sp = str ; sp < &str[nstr] ; sp++) { 245 fprintf(hfile, "struct %s {\n", sp->tag); 246 for (i = sp->nfields, fp = sp->field ; --i >= 0 ; fp++) { 247 fprintf(hfile, " %s;\n", fp->decl); 248 } 249 fputs("};\n\n\n", hfile); 250 } 251 fputs("union node {\n", hfile); 252 fprintf(hfile, " int type;\n"); 253 for (sp = str ; sp < &str[nstr] ; sp++) { 254 fprintf(hfile, " struct %s %s;\n", sp->tag, sp->tag); 255 } 256 fputs("};\n\n\n", hfile); 257 fputs("struct nodelist {\n", hfile); 258 fputs("\tstruct nodelist *next;\n", hfile); 259 fputs("\tunion node *n;\n", hfile); 260 fputs("};\n\n\n", hfile); 261 fputs("#ifdef __STDC__\n", hfile); 262 fputs("union node *copyfunc(union node *);\n", hfile); 263 fputs("void freefunc(union node *);\n", hfile); 264 fputs("#else\n", hfile); 265 fputs("union node *copyfunc();\n", hfile); 266 fputs("void freefunc();\n", hfile); 267 fputs("#endif\n", hfile); 268 269 fputs(writer, cfile); 270 while (fgets(line, sizeof line, patfile) != NULL) { 271 for (p = line ; *p == ' ' || *p == '\t' ; p++); 272 if (strcmp(p, "%SIZES\n") == 0) 273 outsizes(cfile); 274 else if (strcmp(p, "%CALCSIZE\n") == 0) 275 outfunc(cfile, 1); 276 else if (strcmp(p, "%COPY\n") == 0) 277 outfunc(cfile, 0); 278 else 279 fputs(line, cfile); 280 } 281 } 282 283 284 285 static void 286 outsizes(cfile) 287 FILE *cfile; 288 { 289 int i; 290 291 fprintf(cfile, "static const short nodesize[%d] = {\n", ntypes); 292 for (i = 0 ; i < ntypes ; i++) { 293 fprintf(cfile, " ALIGN(sizeof (struct %s)),\n", nodestr[i]->tag); 294 } 295 fprintf(cfile, "};\n"); 296 } 297 298 299 static void 300 outfunc(cfile, calcsize) 301 FILE *cfile; 302 int calcsize; 303 { 304 struct str *sp; 305 struct field *fp; 306 int i; 307 308 fputs(" if (n == NULL)\n", cfile); 309 if (calcsize) 310 fputs(" return;\n", cfile); 311 else 312 fputs(" return NULL;\n", cfile); 313 if (calcsize) 314 fputs(" funcblocksize += nodesize[n->type];\n", cfile); 315 else { 316 fputs(" new = funcblock;\n", cfile); 317 fputs(" funcblock = (char *)funcblock + nodesize[n->type];\n", cfile); 318 } 319 fputs(" switch (n->type) {\n", cfile); 320 for (sp = str ; sp < &str[nstr] ; sp++) { 321 for (i = 0 ; i < ntypes ; i++) { 322 if (nodestr[i] == sp) 323 fprintf(cfile, " case %s:\n", nodename[i]); 324 } 325 for (i = sp->nfields ; --i >= 1 ; ) { 326 fp = &sp->field[i]; 327 switch (fp->type) { 328 case T_NODE: 329 if (calcsize) { 330 indent(12, cfile); 331 fprintf(cfile, "calcsize(n->%s.%s);\n", 332 sp->tag, fp->name); 333 } else { 334 indent(12, cfile); 335 fprintf(cfile, "new->%s.%s = copynode(n->%s.%s);\n", 336 sp->tag, fp->name, sp->tag, fp->name); 337 } 338 break; 339 case T_NODELIST: 340 if (calcsize) { 341 indent(12, cfile); 342 fprintf(cfile, "sizenodelist(n->%s.%s);\n", 343 sp->tag, fp->name); 344 } else { 345 indent(12, cfile); 346 fprintf(cfile, "new->%s.%s = copynodelist(n->%s.%s);\n", 347 sp->tag, fp->name, sp->tag, fp->name); 348 } 349 break; 350 case T_STRING: 351 if (calcsize) { 352 indent(12, cfile); 353 fprintf(cfile, "funcstringsize += strlen(n->%s.%s) + 1;\n", 354 sp->tag, fp->name); 355 } else { 356 indent(12, cfile); 357 fprintf(cfile, "new->%s.%s = nodesavestr(n->%s.%s);\n", 358 sp->tag, fp->name, sp->tag, fp->name); 359 } 360 break; 361 case T_INT: 362 case T_OTHER: 363 if (! calcsize) { 364 indent(12, cfile); 365 fprintf(cfile, "new->%s.%s = n->%s.%s;\n", 366 sp->tag, fp->name, sp->tag, fp->name); 367 } 368 break; 369 } 370 } 371 indent(12, cfile); 372 fputs("break;\n", cfile); 373 } 374 fputs(" };\n", cfile); 375 if (! calcsize) 376 fputs(" new->type = n->type;\n", cfile); 377 } 378 379 380 static void 381 indent(amount, fp) 382 int amount; 383 FILE *fp; 384 { 385 while (amount >= 8) { 386 putc('\t', fp); 387 amount -= 8; 388 } 389 while (--amount >= 0) { 390 putc(' ', fp); 391 } 392 } 393 394 395 static int 396 nextfield(buf) 397 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() 415 { 416 while (*linep == ' ' || *linep == '\t') 417 linep++; 418 } 419 420 421 static int 422 readline() 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 #ifdef __STDC__ 443 error(const char *msg, ...) 444 #else 445 error(va_alist) 446 va_dcl 447 #endif 448 { 449 va_list va; 450 #ifdef __STDC__ 451 va_start(va, msg); 452 #else 453 char *msg; 454 va_start(va); 455 msg = va_arg(va, char *); 456 #endif 457 458 (void) fprintf(stderr, "line %d: ", linno); 459 (void) vfprintf(stderr, msg, va); 460 (void) fputc('\n', stderr); 461 462 va_end(va); 463 464 exit(2); 465 } 466 467 468 469 static char * 470 savestr(s) 471 const char *s; 472 { 473 char *p; 474 475 if ((p = malloc(strlen(s) + 1)) == NULL) 476 error("Out of space"); 477 (void) strcpy(p, s); 478 return p; 479 } 480