mknodes.c revision 75577
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 38static 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 45static char sccsid[] = "@(#)mknodes.c 8.2 (Berkeley) 5/4/95"; 46#endif 47static const char rcsid[] = 48 "$FreeBSD: head/bin/sh/mknodes.c 75577 2001-04-17 07:46:38Z kris $"; 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 80struct 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 87struct 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 95static int ntypes; /* number of node types */ 96static char *nodename[MAXTYPES]; /* names of the nodes */ 97static struct str *nodestr[MAXTYPES]; /* type of structure used by the node */ 98static int nstr; /* number of structures */ 99static struct str str[MAXTYPES]; /* the structures */ 100static struct str *curstr; /* current structure */ 101static FILE *infp = stdin; 102static char line[1024]; 103static int linno; 104static char *linep; 105 106static void parsenode __P((void)); 107static void parsefield __P((void)); 108static void output __P((char *)); 109static void outsizes __P((FILE *)); 110static void outfunc __P((FILE *, int)); 111static void indent __P((int, FILE *)); 112static int nextfield __P((char *)); 113static void skipbl __P((void)); 114static int readline __P((void)); 115static void error __P((const char *, ...)) __printf0like(1, 2); 116static char *savestr __P((const char *)); 117 118 119int 120main(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 140static void 141parsenode() 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 170static void 171parsefield() 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 217char writer[] = "\ 218/*\n\ 219 * This file was generated by the mknodes program.\n\ 220 */\n\ 221\n"; 222 223static void 224output(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 286static void 287outsizes(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 300static void 301outfunc(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 381static void 382indent(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 396static int 397nextfield(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 414static void 415skipbl() 416{ 417 while (*linep == ' ' || *linep == '\t') 418 linep++; 419} 420 421 422static int 423readline() 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 442static void 443#ifdef __STDC__ 444error(const char *msg, ...) 445#else 446error(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 470static char * 471savestr(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