Annotation of 43BSDReno/contrib/rcs/src/rcslex.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *                     RCS file input
                      3:  */
                      4: #ifndef lint
                      5: static char rcsid[]= "$Id: rcslex.c,v 4.6 89/05/01 15:13:07 narten Exp $ Purdue CS";
                      6: #endif
                      7: /*********************************************************************************
                      8:  *                     Lexical Analysis.
                      9:  *                     Character mapping table,
                     10:  *                     hashtable, Lexinit, nextlex, getlex, getkey,
                     11:  *                     getid, getnum, readstring, printstring, savestring,
                     12:  *                     checkid, serror, fatserror, error, faterror, warn, diagnose
                     13:  *                     fflsbuf, puts, fprintf
                     14:  *                     Testprogram: define LEXDB
                     15:  *********************************************************************************
                     16:  */
                     17: 
                     18: /* Copyright (C) 1982, 1988, 1989 Walter Tichy
                     19:  * All rights reserved.
                     20:  *
                     21:  * Redistribution and use in source and binary forms are permitted
                     22:  * provided that the above copyright notice and this paragraph are
                     23:  * duplicated in all such forms and that any documentation,
                     24:  * advertising materials, and other materials related to such
                     25:  * distribution and use acknowledge that the software was developed
                     26:  * by Walter Tichy.
                     27:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     28:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     29:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     30:  *
                     31:  * Report all problems and direct all questions to:
                     32:  *   [email protected]
                     33:  * 
                     34: 
                     35: 
                     36: 
                     37: 
                     38: 
                     39: 
                     40: 
                     41: */
                     42: 
                     43: 
                     44: 
                     45: /* $Log:       rcslex.c,v $
                     46:  * Revision 4.6  89/05/01  15:13:07  narten
                     47:  * changed copyright header to reflect current distribution rules
                     48:  * 
                     49:  * Revision 4.5  88/11/08  12:00:54  narten
                     50:  * changes from  [email protected] (Paul Eggert)
                     51:  * 
                     52:  * Revision 4.5  88/08/28  15:01:12  eggert
                     53:  * Don't loop when writing error messages to a full filesystem.
                     54:  * Flush stderr/stdout when mixing output.
                     55:  * Yield exit status compatible with diff(1).
                     56:  * Shrink stdio code size; allow cc -R; remove lint.
                     57:  * 
                     58:  * Revision 4.4  87/12/18  11:44:47  narten
                     59:  * fixed to use "varargs" in "fprintf"; this is required if it is to
                     60:  * work on a SPARC machine such as a Sun-4
                     61:  * 
                     62:  * Revision 4.3  87/10/18  10:37:18  narten
                     63:  * Updating version numbers. Changes relative to 1.1 actually relative
                     64:  * to version 4.1
                     65:  * 
                     66:  * Revision 1.3  87/09/24  14:00:17  narten
                     67:  * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
                     68:  * warnings)
                     69:  * 
                     70:  * Revision 1.2  87/03/27  14:22:33  jenkins
                     71:  * Port to suns
                     72:  * 
                     73:  * Revision 1.1  84/01/23  14:50:33  kcs
                     74:  * Initial revision
                     75:  * 
                     76:  * Revision 4.1  83/03/25  18:12:51  wft
                     77:  * Only changed $Header to $Id.
                     78:  * 
                     79:  * Revision 3.3  82/12/10  16:22:37  wft
                     80:  * Improved error messages, changed exit status on error to 1.
                     81:  *
                     82:  * Revision 3.2  82/11/28  21:27:10  wft
                     83:  * Renamed ctab to map and included EOFILE; ctab is now a macro in rcsbase.h.
                     84:  * Added fflsbuf(), fputs(), and fprintf(), which abort the RCS operations
                     85:  * properly in case there is an IO-error (e.g., file system full).
                     86:  *
                     87:  * Revision 3.1  82/10/11  19:43:56  wft
                     88:  * removed unused label out:;
                     89:  * made sure all calls to getc() return into an integer, not a char.
                     90:  */
                     91: 
                     92: 
                     93: /*
                     94: #define LEXDB
                     95: /* version LEXDB is for testing the lexical analyzer. The testprogram
                     96:  * reads a stream of lexemes, enters the revision numbers into the
                     97:  * hashtable, and prints the recognized tokens. Keywords are recognized
                     98:  * as identifiers.
                     99:  */
                    100: 
                    101: 
                    102: 
                    103: #include "rcsbase.h"
                    104: #include <varargs.h>
                    105: 
                    106: 
                    107: 
                    108: /* character mapping table */
                    109: enum tokens map[] = {
                    110:         EOFILE,         /* this will end up at ctab[-1] */
                    111:         UNKN,   INSERT, UNKN,   UNKN,   UNKN,   UNKN,   UNKN,   UNKN,
                    112:         UNKN,   SPACE,  NEWLN,  UNKN,   SPACE,  UNKN,   UNKN,   UNKN,
                    113:         UNKN,   UNKN,   UNKN,   UNKN,   UNKN,   UNKN,   UNKN,   UNKN,
                    114:         UNKN,   UNKN,   UNKN,   UNKN,   UNKN,   UNKN,   UNKN,   UNKN,
                    115:         SPACE,  EXCLA,  DQUOTE, HASH,   DOLLAR, PERCNT, AMPER,  SQUOTE,
                    116:         LPARN,  RPARN,  TIMES,  PLUS,   COMMA,  MINUS,  PERIOD, DIVIDE,
                    117:         DIGIT,  DIGIT,  DIGIT,  DIGIT,  DIGIT,  DIGIT,  DIGIT,  DIGIT,
                    118:         DIGIT,  DIGIT,  COLON,  SEMI,   LESS,   EQUAL,  GREAT,  QUEST,
                    119:         AT,     LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
                    120:         LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
                    121:         LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
                    122:         LETTER, LETTER, LETTER, LBRACK, BACKSL, RBRACK, UPARR,  UNDER,
                    123:         ACCENT, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
                    124:         LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
                    125:         LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
                    126:         LETTER, LETTER, LETTER, LBRACE, BAR,    RBRACE, TILDE,  UNKN
                    127: };
                    128: 
                    129: 
                    130: 
                    131: 
                    132: struct hshentry * nexthsh;  /*pointer to next hashtable-entry, set by lookup*/
                    133: 
                    134: enum tokens     nexttok;    /*next token, set by nextlex                    */
                    135: 
                    136: int             hshenter;   /*if true, next suitable lexeme will be entered */
                    137:                             /*into the symbol table. Handle with care.      */
                    138: int             nextc;      /*next input character, initialized by Lexinit  */
                    139: 
                    140: int             eof;        /*end-of-file indicator, set to >0 on end of file*/
                    141: int             line;       /*current line-number of input                  */
                    142: int             nerror;     /*counter for errors                            */
                    143: int             nwarn;      /*counter for warnings                          */
                    144: char *          cmdid;      /*command identification for error messages     */
                    145: int             quietflag;  /*indicates quiet mode                          */
                    146: FILE *          finptr;     /*input file descriptor                         */
                    147: 
                    148: FILE *          frewrite;   /*file descriptor for echoing input             */
                    149: 
                    150: int             rewriteflag;/*indicates whether to echo to frewrite         */
                    151: 
                    152: char            StringTab[strtsize]; /* string table and heap               */
                    153: 
                    154: char *          NextString;         /*pointer to next identifier in StringTab*/
                    155: char *          Topchar;            /*pointer to next free byte in StringTab*/
                    156:                                     /*set by nextlex, lookup                */
                    157: struct hshentry hshtab[hshsize];    /*hashtable                             */
                    158: 
                    159: 
                    160: 
                    161: 
                    162: 
                    163: lookup() {
                    164: 
                    165: /* Function: Looks up the character string pointed to by NextString in the
                    166:  * hashtable. If the string is not present, a new entry for it is created.
                    167:  * If the string is present, TopChar is moved back to save the space for
                    168:  * the string, and NextString is set to point to the original string.
                    169:  * In any case, the address of the corresponding hashtable entry is placed
                    170:  * into nexthsh.
                    171:  * Algorithm: Quadratic hash, covering all entries.
                    172:  * Assumptions: NextString points at the first character of the string.
                    173:  * Topchar points at the first empty byte after the string.
                    174:  */
                    175: 
                    176:         register int     ihash;      /* index into hashtable */
                    177:         register char    * sp, * np;
                    178:         int              c, delta, final, FirstScan; /*loop control*/
                    179: 
                    180:         /* calculate hash code */
                    181:         sp = NextString;
                    182:         ihash = 0;
                    183:         while (*sp) ihash += *sp++;
                    184: 
                    185:         /* set up first search loop (c=0,step=1,until (hshsiz-1)/2 */
                    186:         c=0;delta=1;final=(hshsize-1)/2;
                    187:         FirstScan=true;   /*first loop */
                    188: 
                    189:         for (;;) {
                    190:                 ihash = (ihash+c)%hshsize;   /*next index*/
                    191: 
                    192:                 if (hshtab[ihash].num == nil) {
                    193:                         /*empty slot found*/
                    194:                         hshtab[ihash].num = NextString;
                    195:                         nexthsh= &hshtab[ihash];/*save hashtable address*/
                    196: #                       ifdef LEXDB
                    197:                         VOID printf("\nEntered: %s at %d ",nexthsh->num, ihash);
                    198: #                       endif
                    199:                         return;
                    200:                 }
                    201:                 /* compare strings */
                    202:                 sp=NextString;np=hshtab[ihash].num;
                    203:                 while (*sp == *np++) {
                    204:                         if (*sp == 0) {
                    205:                                 /* match found */
                    206:                                 nexthsh= &hshtab[ihash];
                    207:                                 Topchar = NextString;
                    208:                                 NextString = nexthsh->num;
                    209:                                 return;
                    210:                         } else sp++;
                    211:                 }
                    212: 
                    213:                 /* neither empty slot nor string found */
                    214:                 /* calculate next index and repeat */
                    215:                 if (c != final)
                    216:                         c += delta;
                    217:                 else {
                    218:                         if (FirstScan) {
                    219:                                 /*set up second sweep*/
                    220:                                 delta = -1; final = 1; FirstScan= false;
                    221:                         } else {
                    222:                                 fatserror("Hashtable overflow");
                    223:                         }
                    224:                 }
                    225:         }
                    226: };
                    227: 
                    228: 
                    229: 
                    230: 
                    231: 
                    232: 
                    233: Lexinit()
                    234: /* Function: Initialization of lexical analyzer:
                    235:  * initializes the hastable,
                    236:  * initializes nextc, nexttok if finptr != NULL
                    237:  */
                    238: {       register int            c;
                    239: 
                    240:         for (c=hshsize-1; c>=0; c--) {
                    241:                 hshtab[c].num = nil;
                    242:         }
                    243: 
                    244:         hshenter=true; eof=0; line=1; nerror=0; nwarn=0;
                    245:         NextString=nil; Topchar = &StringTab[0];
                    246:         if (finptr) {
                    247:                 nextc = GETC(finptr,frewrite,rewriteflag); /*initial character*/
                    248:                 nextlex();            /*initial token*/
                    249:         } else {
                    250:                 nextc = '\0';
                    251:                 nexttok=EOFILE;
                    252:         }
                    253: }
                    254: 
                    255: 
                    256: 
                    257: 
                    258: 
                    259: 
                    260: 
                    261: nextlex()
                    262: 
                    263: /* Function: Reads the next token and sets nexttok to the next token code.
                    264:  * Only if the hshenter==true, a revision number is entered into the
                    265:  * hashtable and a pointer to it is placed into nexthsh.
                    266:  * This is useful for avoiding that dates are placed into the hashtable.
                    267:  * For ID's and NUM's, NextString is set to the character string in the
                    268:  * string table. Assumption: nextc contains the next character.
                    269:  */
                    270: {       register c;
                    271:        register FILE * fin, * frew;
                    272:         register char * sp;
                    273:         register enum tokens d;
                    274: 
                    275:         if (eof) {
                    276:                 nexttok=EOFILE;
                    277:                 return;
                    278:         }
                    279:        fin=finptr; frew=frewrite;
                    280: loop:
                    281:         switch(nexttok=ctab[nextc]) {
                    282: 
                    283:         case UNKN:
                    284:         case IDCHAR:
                    285:         case PERIOD:
                    286:                 serror("unknown Character: %c",nextc);
                    287:                 nextc=GETC(fin,frew,rewriteflag);
                    288:                 goto loop;
                    289: 
                    290:         case NEWLN:
                    291:                 line++;
                    292: #               ifdef LEXDB
                    293:                 VOID putchar('\n');
                    294: #               endif
                    295:                 /* Note: falls into next case */
                    296: 
                    297:         case SPACE:
                    298:                 nextc=GETC(fin,frew,rewriteflag);
                    299:                 goto loop;
                    300: 
                    301:         case EOFILE:
                    302:                 eof++;
                    303:                 nexttok=EOFILE;
                    304:                 return;
                    305: 
                    306:         case DIGIT:
                    307:                 NextString = sp = Topchar;
                    308:                 *sp++ = nextc;
                    309:                 while ((d=ctab[c=GETC(fin,frew,rewriteflag)])==DIGIT ||
                    310:                         d==PERIOD) {
                    311:                         *sp++ = c;         /* 1.2. and 1.2 are different */
                    312:                 }
                    313:                 *sp++ = '\0';
                    314:                 if (sp >= StringTab+strtsize) {
                    315:                         /*may have written outside stringtable already*/
                    316:                         fatserror("Stringtable overflow");
                    317:                 }
                    318:                 Topchar = sp;
                    319:                 nextc = c;
                    320:                 if (hshenter == true)
                    321:                         lookup();      /* lookup updates NextString, Topchar*/
                    322:                 nexttok = NUM;
                    323:                 return;
                    324: 
                    325: 
                    326:         case LETTER:
                    327:                 NextString = sp = Topchar;
                    328:                 *sp++ = nextc;
                    329:                 while ((d=ctab[c=GETC(fin,frew,rewriteflag)])==LETTER ||
                    330:                         d==DIGIT || d==IDCHAR) {
                    331:                         *sp++ = c;
                    332:                 }
                    333:                 *sp++ = '\0';
                    334:                 if (sp >= StringTab+strtsize) {
                    335:                         /*may have written outside stringtable already*/
                    336:                         fatserror("Stringtable overflow");
                    337:                 }
                    338:                 Topchar = sp;
                    339:                 nextc = c;
                    340:                 nexttok = ID;  /* may be ID or keyword */
                    341:                 return;
                    342: 
                    343:         case SBEGIN: /* long string */
                    344:                 nexttok = STRING;
                    345:                 /* note: only the initial SBEGIN has been read*/
                    346:                 /* read the string, and reset nextc afterwards*/
                    347:                 return;
                    348: 
                    349:         default:
                    350:                 nextc=GETC(fin,frew,rewriteflag);
                    351:                 return;
                    352:         }
                    353: }
                    354: 
                    355: 
                    356: int getlex(token)
                    357: enum tokens token;
                    358: /* Function: Checks if nexttok is the same as token. If so,
                    359:  * advances the input by calling nextlex and returns true.
                    360:  * otherwise returns false.
                    361:  * Doesn't work for strings and keywords; loses the character string for ids.
                    362:  */
                    363: {
                    364:         if (nexttok==token) {
                    365:                 nextlex();
                    366:                 return(true);
                    367:         } else  return(false);
                    368: }
                    369: 
                    370: int getkey (key)
                    371: char * key;
                    372: /* Function: If the current token is a keyword identical to key,
                    373:  * getkey advances the input by calling nextlex and returns true;
                    374:  * otherwise returns false.
                    375:  */
                    376: {
                    377:         register char *s1,*s2;
                    378: 
                    379:         if (nexttok==ID) {
                    380:                 s1=key; s2=NextString;
                    381:                 while(*s1 == *s2++)
                    382:                      if (*s1++ == '\0') {
                    383:                          /* match found */
                    384:                          Topchar = NextString; /*reset Topchar */
                    385:                          nextlex();
                    386:                          return(true);
                    387:                      }
                    388:         }
                    389:         return(false);
                    390: }
                    391: 
                    392: 
                    393: 
                    394: char * getid()
                    395: /* Function: Checks if nexttok is an identifier. If so,
                    396:  * advances the input by calling nextlex and returns a pointer
                    397:  * to the identifier; otherwise returns nil.
                    398:  * Treats keywords as identifiers.
                    399:  */
                    400: {
                    401:         register char * name;
                    402:         if (nexttok==ID) {
                    403:                 name = NextString;
                    404:                 nextlex();
                    405:                 return name;
                    406:         } else  return nil;
                    407: }
                    408: 
                    409: 
                    410: struct hshentry * getnum()
                    411: /* Function: Checks if nexttok is a number. If so,
                    412:  * advances the input by calling nextlex and returns a pointer
                    413:  * to the hashtable entry. Otherwise returns nil.
                    414:  * Doesn't work if hshenter is false.
                    415:  */
                    416: {
                    417:         register struct hshentry * num;
                    418:         if (nexttok==NUM) {
                    419:                 num=nexthsh;
                    420:                 nextlex();
                    421:                 return num;
                    422:         } else  return nil;
                    423: }
                    424: 
                    425: 
                    426: readstring()
                    427: /* skip over characters until terminating single SDELIM        */
                    428: /* if rewriteflag==true, copy every character read to frewrite.*/
                    429: /* Does not advance nextlex at the end.                        */
                    430: {       register c;
                    431:        register FILE * fin,  * frew;
                    432:        fin=finptr; frew=frewrite;
                    433:         if (rewriteflag) {
                    434:                 /* copy string verbatim to frewrite */
                    435:                 while ((c=getc(fin)) != EOF) {
                    436:                        VOID putc(c,frew);
                    437:                         if (c==SDELIM) {
                    438:                                 if ((c=getc(fin)) == EOF || putc(c,frew) != SDELIM) {
                    439:                                         /* end of string */
                    440:                                         nextc=c;
                    441:                                         return;
                    442:                                 }
                    443:                         }
                    444:                 }
                    445:         } else {
                    446:                 /* skip string */
                    447:                 while ((c=getc(fin)) != EOF) {
                    448:                         if (c==SDELIM) {
                    449:                                 if ((c=getc(fin)) != SDELIM) {
                    450:                                         /* end of string */
                    451:                                         nextc=c;
                    452:                                         return;
                    453:                                 }
                    454:                         }
                    455:                 }
                    456:         }
                    457:         nextc = c;
                    458:         error("Unterminated string");
                    459: }
                    460: 
                    461: 
                    462: printstring()
                    463: /* Function: copy a string to stdout, until terminated with a single SDELIM.
                    464:  * Does not advance nextlex at the end.
                    465:  */
                    466: {
                    467:         register c;
                    468:        register FILE * fin;
                    469:        fin=finptr;
                    470:        while ((c=getc(fin)) != EOF) {
                    471:                 if (c==SDELIM) {
                    472:                        if ((c=getc(fin)) != SDELIM) {
                    473:                                 /* end of string */
                    474:                                 nextc=c;
                    475:                                 return;
                    476:                         }
                    477:                 }
                    478:                 VOID putchar(c);
                    479:         }
                    480:         nextc = c;
                    481:         error("Unterminated string");
                    482: }
                    483: 
                    484: 
                    485: 
                    486: savestring(target,length)
                    487: char * target; int length;
                    488: /* copies a string terminated with SDELIM from file finptr to buffer target,
                    489:  * but not more than length bytes. If the string is longer than length,
                    490:  * the extra characters are skipped. The string may be empty, in which
                    491:  * case a '\0' is placed into target.
                    492:  * Double SDELIM is replaced with SDELIM.
                    493:  * If rewriteflag==true, the string is also copied unchanged to frewrite.
                    494:  * Returns the length of the saved string.
                    495:  * Does not advance nextlex at the end.
                    496:  */
                    497: {
                    498:         register c;
                    499:        register FILE * fin, * frew;
                    500:         register char * tp, * max;
                    501: 
                    502:        fin=finptr; frew=frewrite;
                    503:         tp=target; max= target+length; /*max is one too large*/
                    504:         while ((c=GETC(fin,frew,rewriteflag))!=EOF) {
                    505:                *tp++ =c;
                    506:                 if (c== SDELIM) {
                    507:                         if ((c=GETC(fin,frew,rewriteflag))!=SDELIM) {
                    508:                                 /* end of string */
                    509:                                 *(tp-1)='\0';
                    510:                                 nextc=c;
                    511:                                 return;
                    512:                         }
                    513:                 }
                    514:                 if (tp >= max) {
                    515:                         /* overflow */
                    516:                         error("string buffer overflow -- truncating string");
                    517:                         target[length-1]='\0';
                    518:                         /* skip rest of string */
                    519:                         while ((c=GETC(fin,frew,rewriteflag))!=EOF) {
                    520:                                 if ((c==SDELIM) && ((c=GETC(fin,frew,rewriteflag))!=SDELIM)) {
                    521:                                         /* end of string */
                    522:                                         nextc=c;
                    523:                                         return;
                    524:                                 }
                    525:                         }
                    526:                         nextc = c;
                    527:                         error("Can't find %c to terminate string before end of file",SDELIM);
                    528:                         return;
                    529:                 }
                    530:         }
                    531:         nextc = c;
                    532:         error("Can't find %c to terminate string before end of file",SDELIM);
                    533: }
                    534: 
                    535: 
                    536: char  *checkid(id, delim)
                    537: char    *id, delim;
                    538: /*   Function:  check whether the string starting at id is an   */
                    539: /*              identifier and return a pointer to the last char*/
                    540: /*              of the identifer. White space, delim and '\0'   */
                    541: /*              are legal delimeters. Aborts the program if not */
                    542: /*              a legal identifier. Useful for checking commands*/
                    543: {
                    544:         register enum  tokens  d;
                    545:         register char    *temp;
                    546:         register char    c,tc;
                    547: 
                    548:         temp = id;
                    549:         if ( ctab[*id] == LETTER ) {
                    550:             while( (d=ctab[c=(*++id)]) == LETTER || d==DIGIT || d==IDCHAR) ;
                    551:             if ( c!=' ' && c!='\t' && c!='\n' && c!='\0' && c!=delim) {
                    552:                 /* append \0 to end of id before error message */
                    553:                 tc = c;
                    554:                 while( (c=(*++id))!=' ' && c!='\t' && c!='\n' && c!='\0' && c!=delim) ;
                    555:                 *id = '\0';
                    556:                 faterror("Invalid character %c in identifier %s",tc,temp);
                    557:                 return nil ;
                    558:             } else
                    559:                 return id;
                    560:         } else {
                    561:             /* append \0 to end of id before error message */
                    562:             while( (c=(*++id))!=' ' && c!='\t' && c!='\n' && c!='\0' && c!=delim) ;
                    563:             *id = '\0';
                    564:             faterror("Identifier %s does not start with letter",temp);
                    565:             return nil;
                    566:         }
                    567: }
                    568: 
                    569: writeerror()
                    570: {
                    571:        static looping;
                    572:        if (looping)
                    573:                exit(2);
                    574:        looping = 1;
                    575:        faterror("write error");
                    576: }
                    577: 
                    578: nlflush(iop)
                    579: register FILE * iop;
                    580: {
                    581:        if (putc('\n',iop)==EOF || fflush(iop)==EOF)
                    582:                 writeerror();
                    583: }
                    584: 
                    585: 
                    586: /*VARARGS1*/
                    587: serror(e,e1,e2,e3,e4,e5)
                    588: char * e, * e1, * e2, * e3, * e4, * e5;
                    589: /* non-fatal syntax error */
                    590: {       nerror++;
                    591:         VOID fprintf(stderr,"%s error, line %d: ", cmdid, line);
                    592:         VOID fprintf(stderr,e, e1, e2, e3, e4, e5);
                    593:         nlflush(stderr);
                    594: }
                    595: 
                    596: /*VARARGS1*/
                    597: error(e,e1,e2,e3,e4,e5)
                    598: char * e, * e1, * e2, * e3, * e4, * e5;
                    599: /* non-fatal error */
                    600: {       nerror++;
                    601:         VOID fprintf(stderr,"%s error: ",cmdid);
                    602:         VOID fprintf(stderr,e, e1, e2, e3, e4, e5);
                    603:         nlflush(stderr);
                    604: }
                    605: 
                    606: /*VARARGS1*/
                    607: fatserror(e,e1,e2,e3,e4,e5)
                    608: char * e, * e1, * e2, * e3, * e4, * e5;
                    609: /* fatal syntax error */
                    610: {       nerror++;
                    611:         VOID fprintf(stderr,"%s error, line %d: ", cmdid,line);
                    612:         VOID fprintf(stderr,e, e1, e2, e3, e4, e5);
                    613:         VOID fprintf(stderr,"\n%s aborted\n",cmdid);
                    614:         VOID cleanup();
                    615:         exit(2);
                    616: }
                    617: 
                    618: /*VARARGS1*/
                    619: faterror(e,e1,e2,e3,e4,e5)
                    620: char * e, * e1, * e2, * e3, * e4, * e5;
                    621: /* fatal error, terminates program after cleanup */
                    622: {       nerror++;
                    623:         VOID fprintf(stderr,"%s error: ",cmdid);
                    624:         VOID fprintf(stderr,e, e1, e2, e3, e4, e5);
                    625:         VOID fprintf(stderr,"\n%s aborted\n",cmdid);
                    626:         VOID cleanup();
                    627:         exit(2);
                    628: }
                    629: 
                    630: /*VARARGS1*/
                    631: warn(e,e1,e2,e3,e4,e5)
                    632: char * e, * e1, * e2, * e3, * e4, * e5;
                    633: /* prints a warning message */
                    634: {       nwarn++;
                    635:         VOID fprintf(stderr,"%s warning: ",cmdid);
                    636:         VOID fprintf(stderr,e, e1, e2, e3, e4, e5);
                    637:         nlflush(stderr);
                    638: }
                    639: 
                    640: 
                    641: /*VARARGS1*/
                    642: diagnose(e,e1,e2,e3,e4,e5)
                    643: char * e, * e1, * e2, * e3, * e4, * e5;
                    644: /* prints a diagnostic message */
                    645: {
                    646:         if (!quietflag) {
                    647:                 VOID fprintf(stderr,e, e1, e2, e3, e4, e5);
                    648:                 nlflush(stderr);
                    649:         }
                    650: }
                    651: 
                    652: 
                    653: 
                    654: fflsbuf(c, iop)
                    655: unsigned c; register FILE * iop;
                    656: /* Function: Flush iop.
                    657:  * Same routine as _flsbuf in stdio, but aborts program on error.
                    658:  */
                    659: {       register result;
                    660:         if ((result=_flsbuf(c,iop))==EOF)
                    661:                 writeerror();
                    662:         return result;
                    663: }
                    664: 
                    665: 
                    666: fputs(s, iop)
                    667: register char *s;
                    668: register FILE *iop;
                    669: /* Function: Put string s on file iop, abort on error.
                    670:  * Same as puts in stdio, but with different putc macro.
                    671:  */
                    672: {
                    673:        register r;
                    674:        register c;
                    675: 
                    676:        while (c = *s++)
                    677:                r = putc(c, iop);
                    678:        return(r);
                    679: }
                    680: 
                    681: 
                    682: 
                    683: fprintf(iop, fmt, va_alist)
                    684: FILE *iop;
                    685: char *fmt;
                    686: va_dcl
                    687: /* Function: formatted output. Same as fprintf in stdio,
                    688:  * but aborts program on error
                    689:  */
                    690: {
                    691:        register int value;
                    692:        va_list ap;
                    693: 
                    694:        va_start(ap);
                    695: #ifdef VFPRINTF
                    696:        VOID vfprintf(iop, fmt, ap);
                    697: #else
                    698:        _doprnt(fmt, ap, iop);
                    699: #endif
                    700:         if (ferror(iop)) {
                    701:                writeerror();
                    702:                 value = EOF;
                    703:         } else value = 0;
                    704:        va_end(ap);
                    705:        return value;
                    706: }
                    707: 
                    708: 
                    709: 
                    710: #ifdef LEXDB
                    711: /* test program reading a stream of lexems and printing the tokens.
                    712:  */
                    713: 
                    714: 
                    715: 
                    716: main(argc,argv)
                    717: int argc; char * argv[];
                    718: {
                    719:         cmdid="lextest";
                    720:         if (argc<2) {
                    721:                 VOID fputs("No input file\n",stderr);
                    722:                 exit(1);
                    723:         }
                    724:         if ((finptr=fopen(argv[1], "r")) == NULL) {
                    725:                 faterror("Can't open input file %s\n",argv[1]);
                    726:         }
                    727:         Lexinit();
                    728:         rewriteflag=false;
                    729:         while (nexttok != EOFILE) {
                    730:         switch (nexttok) {
                    731: 
                    732:         case ID:
                    733:                 VOID printf("ID: %s",NextString);
                    734:                 break;
                    735: 
                    736:         case NUM:
                    737:                 if (hshenter==true)
                    738:                    VOID printf("NUM: %s, index: %d",nexthsh->num, nexthsh-hshtab);
                    739:                 else
                    740:                    VOID printf("NUM, unentered: %s",NextString);
                    741:                 hshenter = !hshenter; /*alternate between dates and numbers*/
                    742:                 break;
                    743: 
                    744:         case COLON:
                    745:                 VOID printf("COLON"); break;
                    746: 
                    747:         case SEMI:
                    748:                 VOID printf("SEMI"); break;
                    749: 
                    750:         case STRING:
                    751:                 readstring();
                    752:                 VOID printf("STRING"); break;
                    753: 
                    754:         case UNKN:
                    755:                 VOID printf("UNKN"); break;
                    756: 
                    757:         default:
                    758:                 VOID printf("DEFAULT"); break;
                    759:         }
                    760:         VOID printf(" | ");
                    761:         nextlex();
                    762:         }
                    763:         VOID printf("\nEnd of lexical analyzer test\n");
                    764: }
                    765: 
                    766: cleanup()
                    767: /* dummy */
                    768: {}
                    769: 
                    770: 
                    771: #endif

unix.superglobalmegacorp.com

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