Annotation of 43BSDReno/contrib/rcs/src/rcslex.c, revision 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.