mknodes.c revision 90111
1193323Sed/*- 2193323Sed * Copyright (c) 1991, 1993 3193323Sed * The Regents of the University of California. All rights reserved. 4193323Sed * 5193323Sed * This code is derived from software contributed to Berkeley by 6193323Sed * Kenneth Almquist. 7193323Sed * 8193323Sed * Redistribution and use in source and binary forms, with or without 9193323Sed * modification, are permitted provided that the following conditions 10193323Sed * are met: 11193323Sed * 1. Redistributions of source code must retain the above copyright 12193323Sed * notice, this list of conditions and the following disclaimer. 13193323Sed * 2. Redistributions in binary form must reproduce the above copyright 14193323Sed * notice, this list of conditions and the following disclaimer in the 15193323Sed * documentation and/or other materials provided with the distribution. 16193323Sed * 3. All advertising materials mentioning features or use of this software 17193323Sed * must display the following acknowledgement: 18193323Sed * This product includes software developed by the University of 19193323Sed * California, Berkeley and its contributors. 20193323Sed * 4. Neither the name of the University nor the names of its contributors 21193323Sed * may be used to endorse or promote products derived from this software 22193323Sed * without specific prior written permission. 23193323Sed * 24193323Sed * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25193323Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26193323Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27193323Sed * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28193323Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29193323Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30193323Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31193323Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32193323Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33193323Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34193323Sed * SUCH DAMAGE. 35193323Sed */ 36193323Sed 37193323Sed#ifndef lint 38193323Sedstatic char const copyright[] = 39193323Sed"@(#) Copyright (c) 1991, 1993\n\ 40193323Sed The Regents of the University of California. All rights reserved.\n"; 41193323Sed#endif /* not lint */ 42193323Sed 43193323Sed#ifndef lint 44193323Sed#if 0 45193323Sedstatic char sccsid[] = "@(#)mknodes.c 8.2 (Berkeley) 5/4/95"; 46193323Sed#endif 47193323Sedstatic const char rcsid[] = 48193323Sed "$FreeBSD: head/bin/sh/mknodes.c 90111 2002-02-02 06:50:57Z imp $"; 49193323Sed#endif /* not lint */ 50193323Sed 51193323Sed/* 52193323Sed * This program reads the nodetypes file and nodes.c.pat file. It generates 53193323Sed * the files nodes.h and nodes.c. 54193323Sed */ 55193323Sed 56193323Sed#include <stdio.h> 57193323Sed#include <stdlib.h> 58193323Sed#include <string.h> 59193323Sed#include <errno.h> 60193323Sed#include <stdarg.h> 61193323Sed 62193323Sed#define MAXTYPES 50 /* max number of node types */ 63193323Sed#define MAXFIELDS 20 /* max fields in a structure */ 64193323Sed#define BUFLEN 100 /* size of character buffers */ 65193323Sed 66193323Sed/* field types */ 67193323Sed#define T_NODE 1 /* union node *field */ 68193323Sed#define T_NODELIST 2 /* struct nodelist *field */ 69193323Sed#define T_STRING 3 70193323Sed#define T_INT 4 /* int field */ 71193323Sed#define T_OTHER 5 /* other */ 72193323Sed#define T_TEMP 6 /* don't copy this field */ 73193323Sed 74193323Sed 75193323Sedstruct field { /* a structure field */ 76193323Sed char *name; /* name of field */ 77193323Sed int type; /* type of field */ 78193323Sed char *decl; /* declaration of field */ 79193323Sed}; 80193323Sed 81193323Sed 82193323Sedstruct str { /* struct representing a node structure */ 83193323Sed char *tag; /* structure tag */ 84193323Sed int nfields; /* number of fields in the structure */ 85193323Sed struct field field[MAXFIELDS]; /* the fields of the structure */ 86193323Sed int done; /* set if fully parsed */ 87193323Sed}; 88193323Sed 89193323Sed 90193323Sedstatic int ntypes; /* number of node types */ 91193323Sedstatic char *nodename[MAXTYPES]; /* names of the nodes */ 92193323Sedstatic struct str *nodestr[MAXTYPES]; /* type of structure used by the node */ 93193323Sedstatic int nstr; /* number of structures */ 94193323Sedstatic struct str str[MAXTYPES]; /* the structures */ 95193323Sedstatic struct str *curstr; /* current structure */ 96193323Sedstatic FILE *infp; 97193323Sedstatic char line[1024]; 98193323Sedstatic int linno; 99193323Sedstatic char *linep; 100193323Sed 101193323Sedstatic void parsenode(void); 102193323Sedstatic void parsefield(void); 103193323Sedstatic void output(char *); 104193323Sedstatic void outsizes(FILE *); 105193323Sedstatic void outfunc(FILE *, int); 106193323Sedstatic void indent(int, FILE *); 107193323Sedstatic int nextfield(char *); 108193323Sedstatic void skipbl(void); 109193323Sedstatic int readline(void); 110193323Sedstatic void error(const char *, ...) __printf0like(1, 2); 111193323Sedstatic char *savestr(const char *); 112193323Sed 113193323Sed 114193323Sedint 115193323Sedmain(int argc, char *argv[]) 116193323Sed{ 117193323Sed if (argc != 3) 118193323Sed error("usage: mknodes file"); 119193323Sed infp = stdin; 120193323Sed if ((infp = fopen(argv[1], "r")) == NULL) 121193323Sed error("Can't open %s: %s", argv[1], strerror(errno)); 122193323Sed while (readline()) { 123193323Sed if (line[0] == ' ' || line[0] == '\t') 124193323Sed parsefield(); 125193323Sed else if (line[0] != '\0') 126193323Sed parsenode(); 127193323Sed } 128193323Sed output(argv[2]); 129193323Sed exit(0); 130193323Sed} 131193323Sed 132193323Sed 133193323Sed 134193323Sedstatic void 135193323Sedparsenode(void) 136193323Sed{ 137193323Sed char name[BUFLEN]; 138193323Sed char tag[BUFLEN]; 139193323Sed struct str *sp; 140193323Sed 141193323Sed if (curstr && curstr->nfields > 0) 142193323Sed curstr->done = 1; 143193323Sed nextfield(name); 144193323Sed if (! nextfield(tag)) 145193323Sed error("Tag expected"); 146193323Sed if (*linep != '\0') 147193323Sed error("Garbage at end of line"); 148193323Sed nodename[ntypes] = savestr(name); 149193323Sed for (sp = str ; sp < str + nstr ; sp++) { 150193323Sed if (strcmp(sp->tag, tag) == 0) 151193323Sed break; 152193323Sed } 153193323Sed if (sp >= str + nstr) { 154193323Sed sp->tag = savestr(tag); 155193323Sed sp->nfields = 0; 156193323Sed curstr = sp; 157193323Sed nstr++; 158193323Sed } 159193323Sed nodestr[ntypes] = sp; 160193323Sed ntypes++; 161193323Sed} 162193323Sed 163193323Sed 164193323Sedstatic void 165193323Sedparsefield(void) 166193323Sed{ 167193323Sed char name[BUFLEN]; 168193323Sed char type[BUFLEN]; 169193323Sed char decl[2 * BUFLEN]; 170193323Sed struct field *fp; 171193323Sed 172193323Sed if (curstr == NULL || curstr->done) 173193323Sed error("No current structure to add field to"); 174193323Sed if (! nextfield(name)) 175193323Sed error("No field name"); 176193323Sed if (! nextfield(type)) 177193323Sed error("No field type"); 178193323Sed fp = &curstr->field[curstr->nfields]; 179193323Sed fp->name = savestr(name); 180193323Sed if (strcmp(type, "nodeptr") == 0) { 181193323Sed fp->type = T_NODE; 182193323Sed sprintf(decl, "union node *%s", name); 183193323Sed } else if (strcmp(type, "nodelist") == 0) { 184193323Sed fp->type = T_NODELIST; 185193323Sed sprintf(decl, "struct nodelist *%s", name); 186193323Sed } else if (strcmp(type, "string") == 0) { 187193323Sed fp->type = T_STRING; 188193323Sed sprintf(decl, "char *%s", name); 189193323Sed } else if (strcmp(type, "int") == 0) { 190193323Sed fp->type = T_INT; 191193323Sed sprintf(decl, "int %s", name); 192193323Sed } else if (strcmp(type, "other") == 0) { 193193323Sed fp->type = T_OTHER; 194193323Sed } else if (strcmp(type, "temp") == 0) { 195193323Sed fp->type = T_TEMP; 196193323Sed } else { 197193323Sed error("Unknown type %s", type); 198193323Sed } 199193323Sed if (fp->type == T_OTHER || fp->type == T_TEMP) { 200193323Sed skipbl(); 201193323Sed fp->decl = savestr(linep); 202193323Sed } else { 203193323Sed if (*linep) 204193323Sed error("Garbage at end of line"); 205193323Sed fp->decl = savestr(decl); 206193323Sed } 207193323Sed curstr->nfields++; 208193323Sed} 209193323Sed 210193323Sed 211193323Sedchar writer[] = "\ 212193323Sed/*\n\ 213193323Sed * This file was generated by the mknodes program.\n\ 214193323Sed */\n\ 215193323Sed\n"; 216193323Sed 217193323Sedstatic void 218193323Sedoutput(char *file) 219193323Sed{ 220193323Sed FILE *hfile; 221193323Sed FILE *cfile; 222193323Sed FILE *patfile; 223193323Sed int i; 224193323Sed struct str *sp; 225193323Sed struct field *fp; 226193323Sed char *p; 227193323Sed 228193323Sed if ((patfile = fopen(file, "r")) == NULL) 229193323Sed error("Can't open %s: %s", file, strerror(errno)); 230193323Sed if ((hfile = fopen("nodes.h", "w")) == NULL) 231193323Sed error("Can't create nodes.h: %s", strerror(errno)); 232193323Sed if ((cfile = fopen("nodes.c", "w")) == NULL) 233193323Sed error("Can't create nodes.c"); 234193323Sed fputs(writer, hfile); 235193323Sed for (i = 0 ; i < ntypes ; i++) 236193323Sed fprintf(hfile, "#define %s %d\n", nodename[i], i); 237193323Sed fputs("\n\n\n", hfile); 238193323Sed for (sp = str ; sp < &str[nstr] ; sp++) { 239193323Sed fprintf(hfile, "struct %s {\n", sp->tag); 240193323Sed for (i = sp->nfields, fp = sp->field ; --i >= 0 ; fp++) { 241193323Sed fprintf(hfile, " %s;\n", fp->decl); 242193323Sed } 243193323Sed fputs("};\n\n\n", hfile); 244193323Sed } 245193323Sed fputs("union node {\n", hfile); 246193323Sed fprintf(hfile, " int type;\n"); 247193323Sed for (sp = str ; sp < &str[nstr] ; sp++) { 248193323Sed fprintf(hfile, " struct %s %s;\n", sp->tag, sp->tag); 249193323Sed } 250193323Sed fputs("};\n\n\n", hfile); 251193323Sed fputs("struct nodelist {\n", hfile); 252193323Sed fputs("\tstruct nodelist *next;\n", hfile); 253193323Sed fputs("\tunion node *n;\n", hfile); 254193323Sed fputs("};\n\n\n", hfile); 255193323Sed fputs("union node *copyfunc(union node *);\n", hfile); 256193323Sed fputs("void freefunc(union node *);\n", hfile); 257193323Sed 258193323Sed fputs(writer, cfile); 259193323Sed while (fgets(line, sizeof line, patfile) != NULL) { 260193323Sed for (p = line ; *p == ' ' || *p == '\t' ; p++); 261193323Sed if (strcmp(p, "%SIZES\n") == 0) 262193323Sed outsizes(cfile); 263193323Sed else if (strcmp(p, "%CALCSIZE\n") == 0) 264193323Sed outfunc(cfile, 1); 265193323Sed else if (strcmp(p, "%COPY\n") == 0) 266193323Sed outfunc(cfile, 0); 267193323Sed else 268193323Sed fputs(line, cfile); 269193323Sed } 270193323Sed} 271193323Sed 272193323Sed 273193323Sed 274193323Sedstatic void 275193323Sedoutsizes(FILE *cfile) 276193323Sed{ 277193323Sed int i; 278193323Sed 279193323Sed fprintf(cfile, "static const short nodesize[%d] = {\n", ntypes); 280193323Sed for (i = 0 ; i < ntypes ; i++) { 281193323Sed fprintf(cfile, " ALIGN(sizeof (struct %s)),\n", nodestr[i]->tag); 282193323Sed } 283193323Sed fprintf(cfile, "};\n"); 284193323Sed} 285193323Sed 286193323Sed 287193323Sedstatic void 288193323Sedoutfunc(FILE *cfile, int calcsize) 289193323Sed{ 290193323Sed struct str *sp; 291193323Sed struct field *fp; 292193323Sed int i; 293193323Sed 294193323Sed fputs(" if (n == NULL)\n", cfile); 295193323Sed if (calcsize) 296193323Sed fputs(" return;\n", cfile); 297193323Sed else 298193323Sed fputs(" return NULL;\n", cfile); 299193323Sed if (calcsize) 300193323Sed fputs(" funcblocksize += nodesize[n->type];\n", cfile); 301193323Sed else { 302193323Sed fputs(" new = funcblock;\n", cfile); 303193323Sed fputs(" funcblock = (char *)funcblock + nodesize[n->type];\n", cfile); 304193323Sed } 305193323Sed fputs(" switch (n->type) {\n", cfile); 306193323Sed for (sp = str ; sp < &str[nstr] ; sp++) { 307193323Sed for (i = 0 ; i < ntypes ; i++) { 308193323Sed if (nodestr[i] == sp) 309193323Sed fprintf(cfile, " case %s:\n", nodename[i]); 310193323Sed } 311193323Sed for (i = sp->nfields ; --i >= 1 ; ) { 312193323Sed fp = &sp->field[i]; 313193323Sed switch (fp->type) { 314193323Sed case T_NODE: 315193323Sed if (calcsize) { 316193323Sed indent(12, cfile); 317193323Sed fprintf(cfile, "calcsize(n->%s.%s);\n", 318193323Sed sp->tag, fp->name); 319193323Sed } else { 320193323Sed indent(12, cfile); 321193323Sed fprintf(cfile, "new->%s.%s = copynode(n->%s.%s);\n", 322193323Sed sp->tag, fp->name, sp->tag, fp->name); 323193323Sed } 324193323Sed break; 325193323Sed case T_NODELIST: 326193323Sed if (calcsize) { 327193323Sed indent(12, cfile); 328193323Sed fprintf(cfile, "sizenodelist(n->%s.%s);\n", 329193323Sed sp->tag, fp->name); 330193323Sed } else { 331193323Sed indent(12, cfile); 332193323Sed fprintf(cfile, "new->%s.%s = copynodelist(n->%s.%s);\n", 333193323Sed sp->tag, fp->name, sp->tag, fp->name); 334193323Sed } 335193323Sed break; 336193323Sed case T_STRING: 337193323Sed if (calcsize) { 338193323Sed indent(12, cfile); 339193323Sed fprintf(cfile, "funcstringsize += strlen(n->%s.%s) + 1;\n", 340193323Sed sp->tag, fp->name); 341193323Sed } else { 342193323Sed indent(12, cfile); 343193323Sed fprintf(cfile, "new->%s.%s = nodesavestr(n->%s.%s);\n", 344193323Sed sp->tag, fp->name, sp->tag, fp->name); 345193323Sed } 346193323Sed break; 347193323Sed case T_INT: 348193323Sed case T_OTHER: 349193323Sed if (! calcsize) { 350193323Sed indent(12, cfile); 351193323Sed fprintf(cfile, "new->%s.%s = n->%s.%s;\n", 352193323Sed sp->tag, fp->name, sp->tag, fp->name); 353193323Sed } 354193323Sed break; 355193323Sed } 356193323Sed } 357193323Sed indent(12, cfile); 358193323Sed fputs("break;\n", cfile); 359193323Sed } 360193323Sed fputs(" };\n", cfile); 361193323Sed if (! calcsize) 362193323Sed fputs(" new->type = n->type;\n", cfile); 363193323Sed} 364193323Sed 365193323Sed 366193323Sedstatic void 367193323Sedindent(int amount, FILE *fp) 368193323Sed{ 369193323Sed while (amount >= 8) { 370193323Sed putc('\t', fp); 371193323Sed amount -= 8; 372193323Sed } 373193323Sed while (--amount >= 0) { 374193323Sed putc(' ', fp); 375193323Sed } 376193323Sed} 377193323Sed 378193323Sed 379193323Sedstatic int 380193323Sednextfield(char *buf) 381193323Sed{ 382193323Sed char *p, *q; 383193323Sed 384193323Sed p = linep; 385193323Sed while (*p == ' ' || *p == '\t') 386193323Sed p++; 387193323Sed q = buf; 388193323Sed while (*p != ' ' && *p != '\t' && *p != '\0') 389193323Sed *q++ = *p++; 390193323Sed *q = '\0'; 391193323Sed linep = p; 392193323Sed return (q > buf); 393193323Sed} 394193323Sed 395193323Sed 396193323Sedstatic void 397193323Sedskipbl(void) 398193323Sed{ 399193323Sed while (*linep == ' ' || *linep == '\t') 400193323Sed linep++; 401193323Sed} 402193323Sed 403193323Sed 404193323Sedstatic int 405193323Sedreadline(void) 406193323Sed{ 407193323Sed char *p; 408193323Sed 409193323Sed if (fgets(line, 1024, infp) == NULL) 410193323Sed return 0; 411193323Sed for (p = line ; *p != '#' && *p != '\n' && *p != '\0' ; p++); 412193323Sed while (p > line && (p[-1] == ' ' || p[-1] == '\t')) 413193323Sed p--; 414193323Sed *p = '\0'; 415193323Sed linep = line; 416193323Sed linno++; 417193323Sed if (p - line > BUFLEN) 418193323Sed error("Line too long"); 419193323Sed return 1; 420193323Sed} 421193323Sed 422193323Sed 423193323Sed 424193323Sedstatic void 425193323Sederror(const char *msg, ...) 426193323Sed{ 427193323Sed va_list va; 428193323Sed va_start(va, msg); 429193323Sed 430193323Sed (void) fprintf(stderr, "line %d: ", linno); 431193323Sed (void) vfprintf(stderr, msg, va); 432193323Sed (void) fputc('\n', stderr); 433193323Sed 434193323Sed va_end(va); 435193323Sed 436193323Sed exit(2); 437193323Sed} 438193323Sed 439193323Sed 440193323Sed 441193323Sedstatic char * 442193323Sedsavestr(const char *s) 443193323Sed{ 444193323Sed char *p; 445193323Sed 446193323Sed if ((p = malloc(strlen(s) + 1)) == NULL) 447193323Sed error("Out of space"); 448193323Sed (void) strcpy(p, s); 449193323Sed return p; 450193323Sed} 451193323Sed