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