|
|
1.1 ! root 1: char *wartv = "Wart Version 2A(009) 14 Jan 92"; ! 2: ! 3: #ifdef MDEBUG ! 4: /* Use the real ones in this module only */ ! 5: #ifdef malloc ! 6: #undef malloc ! 7: #endif /* malloc */ ! 8: #ifdef calloc ! 9: #undef calloc ! 10: #endif /* calloc */ ! 11: #ifdef realloc ! 12: #undef realloc ! 13: #endif /* realloc */ ! 14: #ifdef free ! 15: #undef free ! 16: #endif /* free */ ! 17: #endif /* MDEBUG */ ! 18: ! 19: #ifdef MAC ! 20: #define VOID void ! 21: #endif /* MAC */ ! 22: ! 23: /* W A R T */ ! 24: ! 25: /* ! 26: A small subset of "lex". ! 27: ! 28: Authors: Jeff Damens, Frank da Cruz ! 29: Columbia University Center for Computing Activites. ! 30: First released November 1984. ! 31: Copyright (C) 1984, 1992, Trustees of Columbia University in the City of New ! 32: York. Permission is granted to any individual or institution to use this ! 33: software as long as it is not sold for profit. This copyright notice must be ! 34: retained. This software may not be included in commercial products without ! 35: written permission of Columbia University. ! 36: */ ! 37: ! 38: /* ! 39: * input format is: ! 40: * lines to be copied | %state <state names...> ! 41: * %% ! 42: * <state> | <state,state,...> CHAR { actions } ! 43: * ... ! 44: * %% ! 45: * more lines to be copied ! 46: */ ! 47: ! 48: #include "ckcdeb.h" /* Includes */ ! 49: ! 50: /* ! 51: The following "char" should be changed to "short", "int", or "long" if your ! 52: wart program will generate more than 127 states. Since wart is used mainly ! 53: with C-Kermit, which has about 50 states, "char" is adequate. This ! 54: keeps the program about 3K-4K smaller. ! 55: */ ! 56: ! 57: #define TBL_TYPE "char" /* C data type of state table */ ! 58: ! 59: #define C_L 014 /* Formfeed */ ! 60: ! 61: #define SEP 1 /* Token types */ ! 62: #define LBRACK 2 ! 63: #define RBRACK 3 ! 64: #define WORD 4 ! 65: #define COMMA 5 ! 66: ! 67: /* Storage sizes */ ! 68: ! 69: #define MAXSTATES 50 /* max number of states */ ! 70: #define MAXWORD 50 /* max # of chars/word */ ! 71: #define SBYTES ((MAXSTATES+6)/8) /* # of bytes for state bitmask */ ! 72: ! 73: /* Name of wart function in generated program */ ! 74: ! 75: #ifndef FNAME ! 76: #define FNAME "wart" ! 77: #endif /* FNAME */ ! 78: ! 79: /* Structure for state information */ ! 80: ! 81: struct transx { ! 82: CHAR states[SBYTES]; /* included states */ ! 83: int anyst; /* true if this good from any state */ ! 84: CHAR inchr; /* input character */ ! 85: int actno; /* associated action */ ! 86: struct transx *nxt; ! 87: }; /* next transition */ ! 88: typedef struct transx *trans; ! 89: ! 90: /* Function prototypes */ ! 91: ! 92: _PROTOTYP( VOID setwstate, (int, trans) ); ! 93: _PROTOTYP( int teststate, (int, trans) ); ! 94: _PROTOTYP( trans rdinput, (FILE *, FILE *) ); ! 95: _PROTOTYP( VOID initial, (FILE *, FILE *) ); ! 96: _PROTOTYP( int isin, (char *, int) ); ! 97: _PROTOTYP( int isword, (int) ); ! 98: _PROTOTYP( VOID rdword, (FILE *, char *) ); ! 99: _PROTOTYP( VOID rdstates, (FILE *, FILE *) ); ! 100: _PROTOTYP( trans newtrans, (void) ); ! 101: _PROTOTYP( trans rdrules, (FILE *, FILE *) ); ! 102: _PROTOTYP( VOID statelist, (FILE *, trans) ); ! 103: _PROTOTYP( VOID copyact, (FILE *, FILE *, int) ); ! 104: _PROTOTYP( int faction, (trans, int, int) ); ! 105: _PROTOTYP( VOID emptytbl, (void) ); ! 106: _PROTOTYP( VOID addaction, (int, int, int) ); ! 107: _PROTOTYP( VOID writetbl, (FILE *) ); ! 108: _PROTOTYP( VOID warray, (FILE *, char *, int [], int, char *) ); ! 109: _PROTOTYP( VOID fatal, (char *) ); ! 110: _PROTOTYP( VOID prolog, (FILE *) ); ! 111: _PROTOTYP( VOID epilogue, (FILE *) ); ! 112: _PROTOTYP( VOID copyrest, (FILE *, FILE *) ); ! 113: _PROTOTYP( int gettoken, (FILE *) ); ! 114: _PROTOTYP( VOID rdcmnt, (FILE *) ); ! 115: _PROTOTYP( VOID clrhash, (void) ); ! 116: _PROTOTYP( int hash, (char *) ); ! 117: _PROTOTYP( VOID enter, (char *, int) ); ! 118: _PROTOTYP( int lkup, (char *) ); ! 119: _PROTOTYP( static char* copy, (char *s) ); ! 120: ! 121: /* Variables and tables */ ! 122: ! 123: /* lt 1992-10-08 Begin ! 124: * provide definition for deblog variable ! 125: * ckcdeb.h declares as extern. DECC AXP is strict about ref/def model ! 126: * Variable is unused herein, to the best of my knowledge. ! 127: */ ! 128: #ifdef VMS ! 129: int deblog; ! 130: #endif /* VMS */ ! 131: /* lt 1992-10-08 End ! 132: */ ! 133: ! 134: static int lines, nstates, nacts; ! 135: ! 136: static char tokval[MAXWORD]; ! 137: ! 138: static int tbl[MAXSTATES*96]; ! 139: ! 140: char *tbl_type = TBL_TYPE; ! 141: ! 142: char *txt1 = "\n#define BEGIN state =\n\nint state = 0;\n\nint\n"; ! 143: ! 144: char *fname = FNAME; /* Generated function name goes here */ ! 145: ! 146: /* rest of program... */ ! 147: ! 148: char *txt2 = "()\n\ ! 149: {\n\ ! 150: int c,actno;\n\ ! 151: extern "; ! 152: ! 153: /* Data type of state table is inserted here (short or int) */ ! 154: ! 155: char *txt2a = " tbl[];\n while (1) {\n c = input() - 32;\n\ ! 156: if (c < 0 || c > 95) c = 0;\n"; ! 157: ! 158: char *txt2b = " if ((actno = tbl[c + state*96]) != -1)\n\ ! 159: switch(actno) {\n"; ! 160: ! 161: /* this program's output goes here, followed by final text... */ ! 162: ! 163: char *txt3 = "\n }\n }\n}\n\n"; ! 164: ! 165: ! 166: /* ! 167: * turn on the bit associated with the given state ! 168: * ! 169: */ ! 170: VOID ! 171: setwstate(state,t) int state; trans t; { ! 172: int idx,msk; ! 173: idx = state/8; /* byte associated with state */ ! 174: msk = 0x80 >> (state % 8); /* bit mask for state */ ! 175: t->states[idx] |= msk; ! 176: } ! 177: ! 178: /* ! 179: * see if the state is involved in the transition ! 180: * ! 181: */ ! 182: int ! 183: teststate(state,t) int state; trans t; { ! 184: int idx,msk; ! 185: idx = state/8; ! 186: msk = 0x80 >> (state % 8); ! 187: return(t->states[idx] & msk); ! 188: } ! 189: ! 190: ! 191: /* ! 192: * read input from here... ! 193: * ! 194: */ ! 195: ! 196: trans ! 197: rdinput(infp,outfp) FILE *infp,*outfp; { ! 198: trans x,rdrules(); ! 199: lines = 1; /* line counter */ ! 200: nstates = 0; /* no states */ ! 201: nacts = 0; /* no actions yet */ ! 202: fprintf(outfp,"\n%c* WARNING -- This C source program generated by ",'/'); ! 203: fprintf(outfp,"Wart preprocessor. */\n"); ! 204: fprintf(outfp,"%c* Do not edit this file; edit the Wart-format ",'/'); ! 205: fprintf(outfp,"source file instead, */\n"); ! 206: fprintf(outfp,"%c* and then run it through Wart to produce a new ",'/'); ! 207: fprintf(outfp,"C source file. */\n\n"); ! 208: fprintf(outfp,"%c* Wart Version Info: */\n",'/'); ! 209: fprintf(outfp,"char *wartv = \"%s\";\n\n",wartv); ! 210: ! 211: initial(infp,outfp); /* read state names, initial defs */ ! 212: prolog(outfp); /* write out our initial code */ ! 213: x = rdrules(infp,outfp); /* read rules */ ! 214: epilogue(outfp); /* write out epilogue code */ ! 215: return(x); ! 216: } ! 217: ! 218: ! 219: /* ! 220: * initial - read initial definitions and state names. Returns ! 221: * on EOF or %%. ! 222: * ! 223: */ ! 224: VOID ! 225: initial(infp,outfp) FILE *infp, *outfp; { ! 226: int c; ! 227: char wordbuf[MAXWORD]; ! 228: while ((c = getc(infp)) != EOF) { ! 229: if (c == '%') { ! 230: rdword(infp,wordbuf); ! 231: if (strcmp(wordbuf,"states") == 0) ! 232: rdstates(infp,outfp); ! 233: else if (strcmp(wordbuf,"%") == 0) return; ! 234: else fprintf(outfp,"%%%s",wordbuf); ! 235: } ! 236: else putc(c,outfp); ! 237: if (c == '\n') lines++; ! 238: } ! 239: } ! 240: ! 241: /* ! 242: * boolean function to tell if the given character can be part of ! 243: * a word. ! 244: * ! 245: */ ! 246: int ! 247: isin(s,c) char *s; int c; { ! 248: for (; *s != '\0'; s++) ! 249: if (*s == (char) c) return(1); ! 250: return(0); ! 251: } ! 252: int ! 253: isword(c) int c; { ! 254: static char special[] = ".%_-$@"; /* these are allowable */ ! 255: return(isalnum(c) || isin(special,c)); ! 256: } ! 257: ! 258: /* ! 259: * read the next word into the given buffer. ! 260: * ! 261: */ ! 262: VOID ! 263: rdword(fp,buf) FILE *fp; char *buf; { ! 264: int len = 0,c; ! 265: while (isword(c = getc(fp)) && ++len < MAXWORD) *buf++ = (char) c; ! 266: *buf++ = '\0'; /* tie off word */ ! 267: ungetc(c,fp); /* put break char back */ ! 268: } ! 269: ! 270: /* ! 271: * read state names, up to a newline. ! 272: * ! 273: */ ! 274: VOID ! 275: rdstates(fp,ofp) FILE *fp,*ofp; { ! 276: int c; ! 277: char wordbuf[MAXWORD]; ! 278: while ((c = getc(fp)) != EOF && c != '\n') { ! 279: if (isspace(c) || c == C_L) continue; /* skip whitespace */ ! 280: ungetc(c,fp); /* put char back */ ! 281: rdword(fp,wordbuf); /* read the whole word */ ! 282: enter(wordbuf,++nstates); /* put into symbol tbl */ ! 283: fprintf(ofp,"#define %s %d\n",wordbuf,nstates); ! 284: } ! 285: lines++; ! 286: } ! 287: ! 288: /* ! 289: * allocate a new, empty transition node ! 290: * ! 291: */ ! 292: trans ! 293: newtrans() { ! 294: trans new; ! 295: int i; ! 296: new = (trans) malloc(sizeof (struct transx)); ! 297: for (i=0; i<SBYTES; i++) new->states[i] = 0; ! 298: new->anyst = 0; ! 299: new->nxt = NULL; ! 300: return(new); ! 301: } ! 302: ! 303: ! 304: /* ! 305: * read all the rules. ! 306: * ! 307: */ ! 308: ! 309: trans ! 310: rdrules(fp,out) FILE *fp,*out; { ! 311: trans head,cur,prev; ! 312: int curtok; ! 313: head = cur = prev = NULL; ! 314: while ((curtok = gettoken(fp)) != SEP) ! 315: ! 316: switch(curtok) { ! 317: case LBRACK: ! 318: if (cur == NULL) ! 319: cur = newtrans(); ! 320: else ! 321: fatal("duplicate state list"); ! 322: statelist(fp,cur); /* set states */ ! 323: continue; /* prepare to read char */ ! 324: ! 325: case WORD: ! 326: if ((int)strlen(tokval) != 1) ! 327: fatal("multiple chars in state"); ! 328: if (cur == NULL) { ! 329: cur = newtrans(); ! 330: cur->anyst = 1; ! 331: } ! 332: cur->actno = ++nacts; ! 333: cur->inchr = (char) (tokval[0] - 32); ! 334: if (head == NULL) ! 335: head = cur; ! 336: else ! 337: prev->nxt = cur; ! 338: prev = cur; ! 339: cur = NULL; ! 340: copyact(fp,out,nacts); ! 341: break; ! 342: default: fatal("bad input format"); ! 343: } ! 344: return(head); ! 345: } ! 346: ! 347: /* ! 348: * read a list of (comma-separated) states, set them in the ! 349: * given transition. ! 350: * ! 351: */ ! 352: VOID ! 353: statelist(fp,t) FILE *fp; trans t; { ! 354: int curtok,sval; ! 355: curtok = COMMA; ! 356: while (curtok != RBRACK) { ! 357: if (curtok != COMMA) fatal("missing comma"); ! 358: if ((curtok = gettoken(fp)) != WORD) fatal("missing state name"); ! 359: if ((sval = lkup(tokval)) == -1) { ! 360: fprintf(stderr,"state %s undefined\n",tokval); ! 361: fatal("undefined state"); ! 362: } ! 363: setwstate(sval,t); ! 364: curtok = gettoken(fp); ! 365: } ! 366: } ! 367: ! 368: /* ! 369: * copy an action from the input to the output file ! 370: * ! 371: */ ! 372: VOID ! 373: copyact(inp,outp,actno) FILE *inp,*outp; int actno; { ! 374: int c,bcnt; ! 375: fprintf(outp,"case %d:\n",actno); ! 376: while (c = getc(inp), (isspace(c) || c == C_L)) ! 377: if (c == '\n') lines++; ! 378: if (c == '{') { ! 379: bcnt = 1; ! 380: fputs(" {",outp); ! 381: while (bcnt > 0 && (c = getc(inp)) != EOF) { ! 382: if (c == '{') bcnt++; ! 383: else if (c == '}') bcnt--; ! 384: else if (c == '\n') lines++; ! 385: putc(c,outp); ! 386: } ! 387: if (bcnt > 0) fatal("action doesn't end"); ! 388: } else { ! 389: while (c != '\n' && c != EOF) { ! 390: putc(c,outp); ! 391: c = getc(inp); ! 392: } ! 393: lines++; ! 394: } ! 395: fprintf(outp,"\n break;\n"); ! 396: } ! 397: ! 398: /* ! 399: * find the action associated with a given character and state. ! 400: * returns -1 if one can't be found. ! 401: * ! 402: */ ! 403: int ! 404: faction(hd,state,chr) trans hd; int state,chr; { ! 405: while (hd != NULL) { ! 406: if (hd->anyst || teststate(state,hd)) ! 407: if (hd->inchr == ('.' - 32) || hd->inchr == (char) chr) ! 408: return(hd->actno); ! 409: hd = hd->nxt; ! 410: } ! 411: return(-1); ! 412: } ! 413: ! 414: /* ! 415: * empty the table... ! 416: * ! 417: */ ! 418: VOID ! 419: emptytbl() { ! 420: int i; ! 421: for (i=0; i<nstates*96; i++) tbl[i] = -1; ! 422: } ! 423: ! 424: /* ! 425: * add the specified action to the output for the given state and chr. ! 426: * ! 427: */ ! 428: VOID ! 429: addaction(act,state,chr) int act,state,chr; { ! 430: tbl[state*96 + chr] = act; ! 431: } ! 432: ! 433: VOID ! 434: writetbl(fp) FILE *fp; { ! 435: warray(fp,"tbl",tbl,96*(nstates+1),TBL_TYPE); ! 436: } ! 437: ! 438: ! 439: /* ! 440: * write an array to the output file, given its name and size. ! 441: * ! 442: */ ! 443: VOID ! 444: warray(fp,nam,cont,siz,typ) FILE *fp; char *nam; int cont[],siz; char *typ; { ! 445: int i; ! 446: fprintf(fp,"%s %s[] = {\n",typ,nam); ! 447: for (i = 0; i < siz - 1; ) { ! 448: fprintf(fp,"%2d, ",cont[i]); ! 449: if ((++i % 16) == 0) putc('\n',fp); ! 450: } ! 451: fprintf(fp,"%2d ",cont[siz-1]); ! 452: fprintf(fp,"};\n"); ! 453: } ! 454: ! 455: VOID ! 456: main(argc,argv) int argc; char *argv[]; { ! 457: trans head; ! 458: int state,c; ! 459: FILE *infile,*outfile; ! 460: ! 461: if (argc > 1) { ! 462: if ((infile = fopen(argv[1],"r")) == NULL) { ! 463: fprintf(stderr,"Can't open %s\n",argv[1]); ! 464: fatal("unreadable input file"); ! 465: } ! 466: } else infile = stdin; ! 467: ! 468: if (argc > 2) { ! 469: if ((outfile = fopen(argv[2],"w")) == NULL) { ! 470: fprintf(stderr,"Can't write to %s\n",argv[2]); ! 471: fatal("bad output file"); ! 472: } ! 473: } else outfile = stdout; ! 474: ! 475: clrhash(); /* empty hash table */ ! 476: head = rdinput(infile,outfile); /* read input file */ ! 477: emptytbl(); /* empty our tables */ ! 478: for (state = 0; state <= nstates; state++) ! 479: for (c = 1; c < 96; c++) /* find actions, */ ! 480: addaction(faction(head,state,c),state,c); /* add to tbl */ ! 481: writetbl(outfile); ! 482: copyrest(infile,outfile); ! 483: printf("%d states, %d actions\n",nstates,nacts); ! 484: exit(GOOD_EXIT); ! 485: } ! 486: ! 487: ! 488: /* ! 489: * fatal error handler ! 490: * ! 491: */ ! 492: ! 493: VOID ! 494: fatal(msg) char *msg; { ! 495: fprintf(stderr,"error in line %d: %s\n",lines,msg); ! 496: exit(BAD_EXIT); ! 497: } ! 498: ! 499: VOID ! 500: prolog(outfp) FILE *outfp; { ! 501: int c; ! 502: while ((c = *txt1++) != '\0') putc(c,outfp); ! 503: while ((c = *fname++) != '\0') putc(c,outfp); ! 504: while ((c = *txt2++) != '\0') putc(c,outfp); ! 505: while ((c = *tbl_type++) != '\0') putc(c,outfp); ! 506: while ((c = *txt2a++) != '\0') putc(c,outfp); ! 507: while ((c = *txt2b++) != '\0') putc(c,outfp); ! 508: } ! 509: ! 510: VOID ! 511: epilogue(outfp) FILE *outfp; { ! 512: int c; ! 513: while ((c = *txt3++) != '\0') putc(c,outfp); ! 514: } ! 515: ! 516: VOID ! 517: copyrest(in,out) FILE *in,*out; { ! 518: int c; ! 519: while ((c = getc(in)) != EOF) putc(c,out); ! 520: } ! 521: ! 522: /* ! 523: * gettoken - returns token type of next token, sets tokval ! 524: * to the string value of the token if appropriate. ! 525: * ! 526: */ ! 527: ! 528: int ! 529: gettoken(fp) FILE *fp; { ! 530: int c; ! 531: while (1) { /* loop if reading comments... */ ! 532: do { ! 533: c = getc(fp); ! 534: if (c == '\n') lines++; ! 535: } while ((isspace(c) || c == C_L)); /* skip whitespace */ ! 536: switch(c) { ! 537: case EOF: ! 538: return(SEP); ! 539: case '%': ! 540: if ((c = getc(fp)) == '%') return(SEP); ! 541: tokval[0] = '%'; ! 542: tokval[1] = (char) c; ! 543: rdword(fp,tokval+2); ! 544: return(WORD); ! 545: case '<': ! 546: return(LBRACK); ! 547: case '>': ! 548: return(RBRACK); ! 549: case ',': ! 550: return(COMMA); ! 551: case '/': ! 552: if ((c = getc(fp)) == '*') { ! 553: rdcmnt(fp); /* skip over the comment */ ! 554: continue; ! 555: } else { /* and keep looping */ ! 556: ungetc(c,fp); /* put this back into input */ ! 557: c = '/'; /* put character back, fall thru */ ! 558: } ! 559: ! 560: default: ! 561: if (isword(c)) { ! 562: ungetc(c,fp); ! 563: rdword(fp,tokval); ! 564: return(WORD); ! 565: } else fatal("Invalid character in input"); ! 566: } ! 567: } ! 568: } ! 569: ! 570: /* ! 571: * skip over a comment ! 572: * ! 573: */ ! 574: ! 575: VOID ! 576: rdcmnt(fp) FILE *fp; { ! 577: int c,star,prcnt; ! 578: prcnt = star = 0; /* no star seen yet */ ! 579: while (!((c = getc(fp)) == '/' && star)) { ! 580: if (c == EOF || (prcnt && c == '%')) fatal("Unterminated comment"); ! 581: prcnt = (c == '%'); ! 582: star = (c == '*'); ! 583: if (c == '\n') lines++; ! 584: } ! 585: } ! 586: ! 587: /* ! 588: * symbol table management for wart ! 589: * ! 590: * entry points: ! 591: * clrhash - empty hash table. ! 592: * enter - enter a name into the symbol table ! 593: * lkup - find a name's value in the symbol table. ! 594: * ! 595: */ ! 596: ! 597: #define HASHSIZE 101 /* # of entries in hash table */ ! 598: ! 599: struct sym { ! 600: char *name; /* symbol name */ ! 601: int val; /* value */ ! 602: struct sym *hnxt; /* next on collision chain */ ! 603: } *htab[HASHSIZE]; /* the hash table */ ! 604: ! 605: /* ! 606: * empty the hash table before using it... ! 607: * ! 608: */ ! 609: VOID ! 610: clrhash() { ! 611: int i; ! 612: for (i=0; i<HASHSIZE; i++) htab[i] = NULL; ! 613: } ! 614: ! 615: /* ! 616: * compute the value of the hash for a symbol ! 617: * ! 618: */ ! 619: int ! 620: hash(name) char *name; { ! 621: int sum; ! 622: for (sum = 0; *name != '\0'; name++) sum += (sum + *name); ! 623: sum %= HASHSIZE; /* take sum mod hashsize */ ! 624: if (sum < 0) sum += HASHSIZE; /* disallow negative hash value */ ! 625: return(sum); ! 626: } ! 627: ! 628: /* ! 629: * make a private copy of a string... ! 630: * ! 631: */ ! 632: static char* ! 633: copy(s) char *s; { ! 634: char *new; ! 635: new = (char *) malloc((int)strlen(s) + 1); ! 636: strcpy(new,s); ! 637: return(new); ! 638: } ! 639: ! 640: /* ! 641: * enter state name into the hash table ! 642: * ! 643: */ ! 644: VOID ! 645: enter(name,svalue) char *name; int svalue; { ! 646: int h; ! 647: struct sym *cur; ! 648: if (lkup(name) != -1) { ! 649: fprintf(stderr,"state \"%s\" appears twice...\n", name); ! 650: exit(BAD_EXIT); ! 651: } ! 652: h = hash(name); ! 653: cur = (struct sym *)malloc(sizeof (struct sym)); ! 654: cur->name = copy(name); ! 655: cur->val = svalue; ! 656: cur->hnxt = htab[h]; ! 657: htab[h] = cur; ! 658: } ! 659: ! 660: /* ! 661: * find name in the symbol table, return its value. Returns -1 ! 662: * if not found. ! 663: * ! 664: */ ! 665: int ! 666: lkup(name) char *name; { ! 667: struct sym *cur; ! 668: for (cur = htab[hash(name)]; cur != NULL; cur = cur->hnxt) ! 669: if (strcmp(cur->name,name) == 0) return(cur->val); ! 670: return(-1); ! 671: } ! 672: ! 673:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.