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