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