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