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