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