Annotation of researchv10dc/lbin/kermit/ckwart.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.