xref: /dragonfly/gnu/usr.bin/rcs/lib/rcslex.c (revision 86d7f5d3)
1*86d7f5d3SJohn Marino /* lexical analysis of RCS files */
2*86d7f5d3SJohn Marino 
3*86d7f5d3SJohn Marino /******************************************************************************
4*86d7f5d3SJohn Marino  *                     Lexical Analysis.
5*86d7f5d3SJohn Marino  *                     hashtable, Lexinit, nextlex, getlex, getkey,
6*86d7f5d3SJohn Marino  *                     getid, getnum, readstring, printstring, savestring,
7*86d7f5d3SJohn Marino  *                     checkid, fatserror, error, faterror, warn, diagnose
8*86d7f5d3SJohn Marino  *                     Testprogram: define LEXDB
9*86d7f5d3SJohn Marino  ******************************************************************************
10*86d7f5d3SJohn Marino  */
11*86d7f5d3SJohn Marino 
12*86d7f5d3SJohn Marino /* Copyright 1982, 1988, 1989 Walter Tichy
13*86d7f5d3SJohn Marino    Copyright 1990, 1991, 1992, 1993, 1994, 1995 Paul Eggert
14*86d7f5d3SJohn Marino    Distributed under license by the Free Software Foundation, Inc.
15*86d7f5d3SJohn Marino 
16*86d7f5d3SJohn Marino This file is part of RCS.
17*86d7f5d3SJohn Marino 
18*86d7f5d3SJohn Marino RCS is free software; you can redistribute it and/or modify
19*86d7f5d3SJohn Marino it under the terms of the GNU General Public License as published by
20*86d7f5d3SJohn Marino the Free Software Foundation; either version 2, or (at your option)
21*86d7f5d3SJohn Marino any later version.
22*86d7f5d3SJohn Marino 
23*86d7f5d3SJohn Marino RCS is distributed in the hope that it will be useful,
24*86d7f5d3SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
25*86d7f5d3SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26*86d7f5d3SJohn Marino GNU General Public License for more details.
27*86d7f5d3SJohn Marino 
28*86d7f5d3SJohn Marino You should have received a copy of the GNU General Public License
29*86d7f5d3SJohn Marino along with RCS; see the file COPYING.
30*86d7f5d3SJohn Marino If not, write to the Free Software Foundation,
31*86d7f5d3SJohn Marino 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32*86d7f5d3SJohn Marino 
33*86d7f5d3SJohn Marino Report problems and direct all questions to:
34*86d7f5d3SJohn Marino 
35*86d7f5d3SJohn Marino     rcs-bugs@cs.purdue.edu
36*86d7f5d3SJohn Marino 
37*86d7f5d3SJohn Marino */
38*86d7f5d3SJohn Marino 
39*86d7f5d3SJohn Marino 
40*86d7f5d3SJohn Marino 
41*86d7f5d3SJohn Marino /*
42*86d7f5d3SJohn Marino  * $FreeBSD: src/gnu/usr.bin/rcs/lib/rcslex.c,v 1.8 1999/08/27 23:36:47 peter Exp $
43*86d7f5d3SJohn Marino  * $DragonFly: src/gnu/usr.bin/rcs/lib/rcslex.c,v 1.2 2003/06/17 04:25:47 dillon Exp $
44*86d7f5d3SJohn Marino  *
45*86d7f5d3SJohn Marino  * Revision 5.19  1995/06/16 06:19:24  eggert
46*86d7f5d3SJohn Marino  * Update FSF address.
47*86d7f5d3SJohn Marino  *
48*86d7f5d3SJohn Marino  * Revision 5.18  1995/06/01 16:23:43  eggert
49*86d7f5d3SJohn Marino  * (map_fd_deallocate,mmap_deallocate,read_deallocate,nothing_to_deallocate):
50*86d7f5d3SJohn Marino  * New functions.
51*86d7f5d3SJohn Marino  * (Iclose): If large_memory and maps_memory, use them to deallocate mapping.
52*86d7f5d3SJohn Marino  * (fd2RILE): Use map_fd if available.
53*86d7f5d3SJohn Marino  * If one mapping method fails, try the next instead of giving up;
54*86d7f5d3SJohn Marino  * if they all fail, fall back on ordinary read.
55*86d7f5d3SJohn Marino  * Work around bug: root mmap over NFS succeeds, but accessing dumps core.
56*86d7f5d3SJohn Marino  * Use MAP_FAILED macro for mmap failure, and `char *' instead of caddr_t.
57*86d7f5d3SJohn Marino  * (advise_access): Use madvise only if this instance used mmap.
58*86d7f5d3SJohn Marino  * (Iopen): Use fdSafer to get safer file descriptor.
59*86d7f5d3SJohn Marino  * (aflush): Moved here from rcsedit.c.
60*86d7f5d3SJohn Marino  *
61*86d7f5d3SJohn Marino  * Revision 5.17  1994/03/20 04:52:58  eggert
62*86d7f5d3SJohn Marino  * Don't worry if madvise fails.  Add Orewind.  Remove lint.
63*86d7f5d3SJohn Marino  *
64*86d7f5d3SJohn Marino  * Revision 5.16  1993/11/09 17:55:29  eggert
65*86d7f5d3SJohn Marino  * Fix `label: }' typo.
66*86d7f5d3SJohn Marino  *
67*86d7f5d3SJohn Marino  * Revision 5.15  1993/11/03 17:42:27  eggert
68*86d7f5d3SJohn Marino  * Improve quality of diagnostics by putting file names in them more often.
69*86d7f5d3SJohn Marino  * Don't discard ignored phrases.
70*86d7f5d3SJohn Marino  *
71*86d7f5d3SJohn Marino  * Revision 5.14  1992/07/28  16:12:44  eggert
72*86d7f5d3SJohn Marino  * Identifiers may now start with a digit and (unless they are symbolic names)
73*86d7f5d3SJohn Marino  * may contain `.'.  Avoid `unsigned'.  Statement macro names now end in _.
74*86d7f5d3SJohn Marino  *
75*86d7f5d3SJohn Marino  * Revision 5.13  1992/02/17  23:02:27  eggert
76*86d7f5d3SJohn Marino  * Work around NFS mmap SIGBUS problem.
77*86d7f5d3SJohn Marino  *
78*86d7f5d3SJohn Marino  * Revision 5.12  1992/01/06  02:42:34  eggert
79*86d7f5d3SJohn Marino  * Use OPEN_O_BINARY if mode contains 'b'.
80*86d7f5d3SJohn Marino  *
81*86d7f5d3SJohn Marino  * Revision 5.11  1991/11/03  03:30:44  eggert
82*86d7f5d3SJohn Marino  * Fix porting bug to ancient hosts lacking vfprintf.
83*86d7f5d3SJohn Marino  *
84*86d7f5d3SJohn Marino  * Revision 5.10  1991/10/07  17:32:46  eggert
85*86d7f5d3SJohn Marino  * Support piece tables even if !has_mmap.
86*86d7f5d3SJohn Marino  *
87*86d7f5d3SJohn Marino  * Revision 5.9  1991/09/24  00:28:42  eggert
88*86d7f5d3SJohn Marino  * Don't export errsay().
89*86d7f5d3SJohn Marino  *
90*86d7f5d3SJohn Marino  * Revision 5.8  1991/08/19  03:13:55  eggert
91*86d7f5d3SJohn Marino  * Add eoflex(), mmap support.  Tune.
92*86d7f5d3SJohn Marino  *
93*86d7f5d3SJohn Marino  * Revision 5.7  1991/04/21  11:58:26  eggert
94*86d7f5d3SJohn Marino  * Add MS-DOS support.
95*86d7f5d3SJohn Marino  *
96*86d7f5d3SJohn Marino  * Revision 5.6  1991/02/25  07:12:42  eggert
97*86d7f5d3SJohn Marino  * Work around fputs bug.  strsave -> str_save (DG/UX name clash)
98*86d7f5d3SJohn Marino  *
99*86d7f5d3SJohn Marino  * Revision 5.5  1990/12/04  05:18:47  eggert
100*86d7f5d3SJohn Marino  * Use -I for prompts and -q for diagnostics.
101*86d7f5d3SJohn Marino  *
102*86d7f5d3SJohn Marino  * Revision 5.4  1990/11/19  20:05:28  hammer
103*86d7f5d3SJohn Marino  * no longer gives warning about unknown keywords if -q is specified
104*86d7f5d3SJohn Marino  *
105*86d7f5d3SJohn Marino  * Revision 5.3  1990/11/01  05:03:48  eggert
106*86d7f5d3SJohn Marino  * When ignoring unknown phrases, copy them to the output RCS file.
107*86d7f5d3SJohn Marino  *
108*86d7f5d3SJohn Marino  * Revision 5.2  1990/09/04  08:02:27  eggert
109*86d7f5d3SJohn Marino  * Count RCS lines better.
110*86d7f5d3SJohn Marino  *
111*86d7f5d3SJohn Marino  * Revision 5.1  1990/08/29  07:14:03  eggert
112*86d7f5d3SJohn Marino  * Work around buggy compilers with defective argument promotion.
113*86d7f5d3SJohn Marino  *
114*86d7f5d3SJohn Marino  * Revision 5.0  1990/08/22  08:12:55  eggert
115*86d7f5d3SJohn Marino  * Remove compile-time limits; use malloc instead.
116*86d7f5d3SJohn Marino  * Report errno-related errors with perror().
117*86d7f5d3SJohn Marino  * Ansify and Posixate.  Add support for ISO 8859.
118*86d7f5d3SJohn Marino  * Use better hash function.
119*86d7f5d3SJohn Marino  *
120*86d7f5d3SJohn Marino  * Revision 4.6  89/05/01  15:13:07  narten
121*86d7f5d3SJohn Marino  * changed copyright header to reflect current distribution rules
122*86d7f5d3SJohn Marino  *
123*86d7f5d3SJohn Marino  * Revision 4.5  88/08/28  15:01:12  eggert
124*86d7f5d3SJohn Marino  * Don't loop when writing error messages to a full filesystem.
125*86d7f5d3SJohn Marino  * Flush stderr/stdout when mixing output.
126*86d7f5d3SJohn Marino  * Yield exit status compatible with diff(1).
127*86d7f5d3SJohn Marino  * Shrink stdio code size; allow cc -R; remove lint.
128*86d7f5d3SJohn Marino  *
129*86d7f5d3SJohn Marino  * Revision 4.4  87/12/18  11:44:47  narten
130*86d7f5d3SJohn Marino  * fixed to use "varargs" in "fprintf"; this is required if it is to
131*86d7f5d3SJohn Marino  * work on a SPARC machine such as a Sun-4
132*86d7f5d3SJohn Marino  *
133*86d7f5d3SJohn Marino  * Revision 4.3  87/10/18  10:37:18  narten
134*86d7f5d3SJohn Marino  * Updating version numbers. Changes relative to 1.1 actually relative
135*86d7f5d3SJohn Marino  * to version 4.1
136*86d7f5d3SJohn Marino  *
137*86d7f5d3SJohn Marino  * Revision 1.3  87/09/24  14:00:17  narten
138*86d7f5d3SJohn Marino  * Sources now pass through lint (if you ignore printf/sprintf/fprintf
139*86d7f5d3SJohn Marino  * warnings)
140*86d7f5d3SJohn Marino  *
141*86d7f5d3SJohn Marino  * Revision 1.2  87/03/27  14:22:33  jenkins
142*86d7f5d3SJohn Marino  * Port to suns
143*86d7f5d3SJohn Marino  *
144*86d7f5d3SJohn Marino  * Revision 4.1  83/03/25  18:12:51  wft
145*86d7f5d3SJohn Marino  * Only changed $Header to $Id.
146*86d7f5d3SJohn Marino  *
147*86d7f5d3SJohn Marino  * Revision 3.3  82/12/10  16:22:37  wft
148*86d7f5d3SJohn Marino  * Improved error messages, changed exit status on error to 1.
149*86d7f5d3SJohn Marino  *
150*86d7f5d3SJohn Marino  * Revision 3.2  82/11/28  21:27:10  wft
151*86d7f5d3SJohn Marino  * Renamed ctab to map and included EOFILE; ctab is now a macro in rcsbase.h.
152*86d7f5d3SJohn Marino  * Added fflsbuf(), fputs(), and fprintf(), which abort the RCS operations
153*86d7f5d3SJohn Marino  * properly in case there is an IO-error (e.g., file system full).
154*86d7f5d3SJohn Marino  *
155*86d7f5d3SJohn Marino  * Revision 3.1  82/10/11  19:43:56  wft
156*86d7f5d3SJohn Marino  * removed unused label out:;
157*86d7f5d3SJohn Marino  * made sure all calls to getc() return into an integer, not a char.
158*86d7f5d3SJohn Marino  */
159*86d7f5d3SJohn Marino 
160*86d7f5d3SJohn Marino 
161*86d7f5d3SJohn Marino /*
162*86d7f5d3SJohn Marino #define LEXDB
163*86d7f5d3SJohn Marino */
164*86d7f5d3SJohn Marino /* version LEXDB is for testing the lexical analyzer. The testprogram
165*86d7f5d3SJohn Marino  * reads a stream of lexemes, enters the revision numbers into the
166*86d7f5d3SJohn Marino  * hashtable, and prints the recognized tokens. Keywords are recognized
167*86d7f5d3SJohn Marino  * as identifiers.
168*86d7f5d3SJohn Marino  */
169*86d7f5d3SJohn Marino 
170*86d7f5d3SJohn Marino 
171*86d7f5d3SJohn Marino 
172*86d7f5d3SJohn Marino #include "rcsbase.h"
173*86d7f5d3SJohn Marino 
174*86d7f5d3SJohn Marino libId(lexId, "$DragonFly: src/gnu/usr.bin/rcs/lib/rcslex.c,v 1.2 2003/06/17 04:25:47 dillon Exp $")
175*86d7f5d3SJohn Marino 
176*86d7f5d3SJohn Marino static char *checkidentifier P((char*,int,int));
177*86d7f5d3SJohn Marino static void errsay P((char const*));
178*86d7f5d3SJohn Marino static void fatsay P((char const*));
179*86d7f5d3SJohn Marino static void lookup P((char const*));
180*86d7f5d3SJohn Marino static void startsay P((const char*,const char*));
181*86d7f5d3SJohn Marino static void warnsay P((char const*));
182*86d7f5d3SJohn Marino 
183*86d7f5d3SJohn Marino static struct hshentry *nexthsh;  /*pointer to next hash entry, set by lookup*/
184*86d7f5d3SJohn Marino 
185*86d7f5d3SJohn Marino enum tokens     nexttok;    /*next token, set by nextlex                    */
186*86d7f5d3SJohn Marino 
187*86d7f5d3SJohn Marino int             hshenter;   /*if true, next suitable lexeme will be entered */
188*86d7f5d3SJohn Marino                             /*into the symbol table. Handle with care.      */
189*86d7f5d3SJohn Marino int             nextc;      /*next input character, initialized by Lexinit  */
190*86d7f5d3SJohn Marino 
191*86d7f5d3SJohn Marino long		rcsline;    /*current line-number of input		    */
192*86d7f5d3SJohn Marino int             nerror;     /*counter for errors                            */
193*86d7f5d3SJohn Marino int             quietflag;  /*indicates quiet mode                          */
194*86d7f5d3SJohn Marino RILE *		finptr;	    /*input file descriptor			    */
195*86d7f5d3SJohn Marino 
196*86d7f5d3SJohn Marino FILE *          frewrite;   /*file descriptor for echoing input             */
197*86d7f5d3SJohn Marino 
198*86d7f5d3SJohn Marino FILE *		foutptr;    /* copy of frewrite, but 0 to suppress echo  */
199*86d7f5d3SJohn Marino 
200*86d7f5d3SJohn Marino static struct buf tokbuf;   /* token buffer				    */
201*86d7f5d3SJohn Marino 
202*86d7f5d3SJohn Marino char const *    NextString; /* next token				    */
203*86d7f5d3SJohn Marino 
204*86d7f5d3SJohn Marino /*
205*86d7f5d3SJohn Marino  * Our hash algorithm is h[0] = 0, h[i+1] = 4*h[i] + c,
206*86d7f5d3SJohn Marino  * so hshsize should be odd.
207*86d7f5d3SJohn Marino  * See B J McKenzie, R Harries & T Bell, Selecting a hashing algorithm,
208*86d7f5d3SJohn Marino  * Software--practice & experience 20, 2 (Feb 1990), 209-224.
209*86d7f5d3SJohn Marino  */
210*86d7f5d3SJohn Marino #ifndef hshsize
211*86d7f5d3SJohn Marino #	define hshsize 511
212*86d7f5d3SJohn Marino #endif
213*86d7f5d3SJohn Marino 
214*86d7f5d3SJohn Marino static struct hshentry *hshtab[hshsize]; /*hashtable			    */
215*86d7f5d3SJohn Marino 
216*86d7f5d3SJohn Marino static int ignored_phrases; /* have we ignored phrases in this RCS file? */
217*86d7f5d3SJohn Marino 
218*86d7f5d3SJohn Marino     void
warnignore()219*86d7f5d3SJohn Marino warnignore()
220*86d7f5d3SJohn Marino {
221*86d7f5d3SJohn Marino     if (!ignored_phrases) {
222*86d7f5d3SJohn Marino 	ignored_phrases = true;
223*86d7f5d3SJohn Marino 	rcswarn("Unknown phrases like `%s ...;' are present.", NextString);
224*86d7f5d3SJohn Marino     }
225*86d7f5d3SJohn Marino }
226*86d7f5d3SJohn Marino 
227*86d7f5d3SJohn Marino 
228*86d7f5d3SJohn Marino 
229*86d7f5d3SJohn Marino 	static void
lookup(str)230*86d7f5d3SJohn Marino lookup(str)
231*86d7f5d3SJohn Marino 	char const *str;
232*86d7f5d3SJohn Marino /* Function: Looks up the character string pointed to by str in the
233*86d7f5d3SJohn Marino  * hashtable. If the string is not present, a new entry for it is created.
234*86d7f5d3SJohn Marino  * In any case, the address of the corresponding hashtable entry is placed
235*86d7f5d3SJohn Marino  * into nexthsh.
236*86d7f5d3SJohn Marino  */
237*86d7f5d3SJohn Marino {
238*86d7f5d3SJohn Marino 	register unsigned ihash;  /* index into hashtable */
239*86d7f5d3SJohn Marino 	register char const *sp;
240*86d7f5d3SJohn Marino 	register struct hshentry *n, **p;
241*86d7f5d3SJohn Marino 
242*86d7f5d3SJohn Marino         /* calculate hash code */
243*86d7f5d3SJohn Marino 	sp = str;
244*86d7f5d3SJohn Marino         ihash = 0;
245*86d7f5d3SJohn Marino 	while (*sp)
246*86d7f5d3SJohn Marino 		ihash  =  (ihash<<2) + *sp++;
247*86d7f5d3SJohn Marino 	ihash %= hshsize;
248*86d7f5d3SJohn Marino 
249*86d7f5d3SJohn Marino 	for (p = &hshtab[ihash];  ;  p = &n->nexthsh)
250*86d7f5d3SJohn Marino 		if (!(n = *p)) {
251*86d7f5d3SJohn Marino 			/* empty slot found */
252*86d7f5d3SJohn Marino 			*p = n = ftalloc(struct hshentry);
253*86d7f5d3SJohn Marino 			n->num = fstr_save(str);
254*86d7f5d3SJohn Marino 			n->nexthsh = 0;
255*86d7f5d3SJohn Marino #			ifdef LEXDB
256*86d7f5d3SJohn Marino 				VOID printf("\nEntered: %s at %u ", str, ihash);
257*86d7f5d3SJohn Marino #			endif
258*86d7f5d3SJohn Marino 			break;
259*86d7f5d3SJohn Marino 		} else if (strcmp(str, n->num) == 0)
260*86d7f5d3SJohn Marino 			/* match found */
261*86d7f5d3SJohn Marino 			break;
262*86d7f5d3SJohn Marino 	nexthsh = n;
263*86d7f5d3SJohn Marino 	NextString = n->num;
264*86d7f5d3SJohn Marino }
265*86d7f5d3SJohn Marino 
266*86d7f5d3SJohn Marino 
267*86d7f5d3SJohn Marino 
268*86d7f5d3SJohn Marino 
269*86d7f5d3SJohn Marino 
270*86d7f5d3SJohn Marino 
271*86d7f5d3SJohn Marino 	void
Lexinit()272*86d7f5d3SJohn Marino Lexinit()
273*86d7f5d3SJohn Marino /* Function: Initialization of lexical analyzer:
274*86d7f5d3SJohn Marino  * initializes the hashtable,
275*86d7f5d3SJohn Marino  * initializes nextc, nexttok if finptr != 0
276*86d7f5d3SJohn Marino  */
277*86d7f5d3SJohn Marino {       register int            c;
278*86d7f5d3SJohn Marino 
279*86d7f5d3SJohn Marino 	for (c = hshsize;  0 <= --c;  ) {
280*86d7f5d3SJohn Marino 		hshtab[c] = 0;
281*86d7f5d3SJohn Marino         }
282*86d7f5d3SJohn Marino 
283*86d7f5d3SJohn Marino 	nerror = 0;
284*86d7f5d3SJohn Marino 	if (finptr) {
285*86d7f5d3SJohn Marino 		foutptr = 0;
286*86d7f5d3SJohn Marino 		hshenter = true;
287*86d7f5d3SJohn Marino 		ignored_phrases = false;
288*86d7f5d3SJohn Marino 		rcsline = 1;
289*86d7f5d3SJohn Marino 		bufrealloc(&tokbuf, 2);
290*86d7f5d3SJohn Marino 		Iget_(finptr, nextc)
291*86d7f5d3SJohn Marino                 nextlex();            /*initial token*/
292*86d7f5d3SJohn Marino         }
293*86d7f5d3SJohn Marino }
294*86d7f5d3SJohn Marino 
295*86d7f5d3SJohn Marino 
296*86d7f5d3SJohn Marino 
297*86d7f5d3SJohn Marino 
298*86d7f5d3SJohn Marino 
299*86d7f5d3SJohn Marino 
300*86d7f5d3SJohn Marino 
301*86d7f5d3SJohn Marino 	void
nextlex()302*86d7f5d3SJohn Marino nextlex()
303*86d7f5d3SJohn Marino 
304*86d7f5d3SJohn Marino /* Function: Reads the next token and sets nexttok to the next token code.
305*86d7f5d3SJohn Marino  * Only if hshenter is set, a revision number is entered into the
306*86d7f5d3SJohn Marino  * hashtable and a pointer to it is placed into nexthsh.
307*86d7f5d3SJohn Marino  * This is useful for avoiding that dates are placed into the hashtable.
308*86d7f5d3SJohn Marino  * For ID's and NUM's, NextString is set to the character string.
309*86d7f5d3SJohn Marino  * Assumption: nextc contains the next character.
310*86d7f5d3SJohn Marino  */
311*86d7f5d3SJohn Marino {       register int c;
312*86d7f5d3SJohn Marino 	declarecache;
313*86d7f5d3SJohn Marino 	register FILE *frew;
314*86d7f5d3SJohn Marino         register char * sp;
315*86d7f5d3SJohn Marino 	char const *limit;
316*86d7f5d3SJohn Marino         register enum tokens d;
317*86d7f5d3SJohn Marino 	register RILE *fin;
318*86d7f5d3SJohn Marino 
319*86d7f5d3SJohn Marino 	fin=finptr; frew=foutptr;
320*86d7f5d3SJohn Marino 	setupcache(fin); cache(fin);
321*86d7f5d3SJohn Marino 	c = nextc;
322*86d7f5d3SJohn Marino 
323*86d7f5d3SJohn Marino 	for (;;) { switch ((d = ctab[c])) {
324*86d7f5d3SJohn Marino 
325*86d7f5d3SJohn Marino 	default:
326*86d7f5d3SJohn Marino 		fatserror("unknown character `%c'", c);
327*86d7f5d3SJohn Marino 		/*NOTREACHED*/
328*86d7f5d3SJohn Marino 
329*86d7f5d3SJohn Marino         case NEWLN:
330*86d7f5d3SJohn Marino 		++rcsline;
331*86d7f5d3SJohn Marino #               ifdef LEXDB
332*86d7f5d3SJohn Marino 		afputc('\n',stdout);
333*86d7f5d3SJohn Marino #               endif
334*86d7f5d3SJohn Marino                 /* Note: falls into next case */
335*86d7f5d3SJohn Marino 
336*86d7f5d3SJohn Marino         case SPACE:
337*86d7f5d3SJohn Marino 		GETC_(frew, c)
338*86d7f5d3SJohn Marino 		continue;
339*86d7f5d3SJohn Marino 
340*86d7f5d3SJohn Marino 	case IDCHAR:
341*86d7f5d3SJohn Marino 	case LETTER:
342*86d7f5d3SJohn Marino 	case Letter:
343*86d7f5d3SJohn Marino 		d = ID;
344*86d7f5d3SJohn Marino 		/* fall into */
345*86d7f5d3SJohn Marino 	case DIGIT:
346*86d7f5d3SJohn Marino 	case PERIOD:
347*86d7f5d3SJohn Marino 		sp = tokbuf.string;
348*86d7f5d3SJohn Marino 		limit = sp + tokbuf.size;
349*86d7f5d3SJohn Marino 		*sp++ = c;
350*86d7f5d3SJohn Marino 		for (;;) {
351*86d7f5d3SJohn Marino 			GETC_(frew, c)
352*86d7f5d3SJohn Marino 			switch (ctab[c]) {
353*86d7f5d3SJohn Marino 			    case IDCHAR:
354*86d7f5d3SJohn Marino 			    case LETTER:
355*86d7f5d3SJohn Marino 			    case Letter:
356*86d7f5d3SJohn Marino 				d = ID;
357*86d7f5d3SJohn Marino 				/* fall into */
358*86d7f5d3SJohn Marino 			    case DIGIT:
359*86d7f5d3SJohn Marino 			    case PERIOD:
360*86d7f5d3SJohn Marino 				*sp++ = c;
361*86d7f5d3SJohn Marino 				if (limit <= sp)
362*86d7f5d3SJohn Marino 					sp = bufenlarge(&tokbuf, &limit);
363*86d7f5d3SJohn Marino 				continue;
364*86d7f5d3SJohn Marino 
365*86d7f5d3SJohn Marino 			    default:
366*86d7f5d3SJohn Marino 				break;
367*86d7f5d3SJohn Marino 			}
368*86d7f5d3SJohn Marino 			break;
369*86d7f5d3SJohn Marino                 }
370*86d7f5d3SJohn Marino 		*sp = 0;
371*86d7f5d3SJohn Marino 		if (d == DIGIT  ||  d == PERIOD) {
372*86d7f5d3SJohn Marino 			d = NUM;
373*86d7f5d3SJohn Marino 			if (hshenter) {
374*86d7f5d3SJohn Marino 				lookup(tokbuf.string);
375*86d7f5d3SJohn Marino 				break;
376*86d7f5d3SJohn Marino 			}
377*86d7f5d3SJohn Marino 		}
378*86d7f5d3SJohn Marino 		NextString = fstr_save(tokbuf.string);
379*86d7f5d3SJohn Marino 		break;
380*86d7f5d3SJohn Marino 
381*86d7f5d3SJohn Marino         case SBEGIN: /* long string */
382*86d7f5d3SJohn Marino 		d = STRING;
383*86d7f5d3SJohn Marino                 /* note: only the initial SBEGIN has been read*/
384*86d7f5d3SJohn Marino                 /* read the string, and reset nextc afterwards*/
385*86d7f5d3SJohn Marino 		break;
386*86d7f5d3SJohn Marino 
387*86d7f5d3SJohn Marino 	case COLON:
388*86d7f5d3SJohn Marino 	case SEMI:
389*86d7f5d3SJohn Marino 		GETC_(frew, c)
390*86d7f5d3SJohn Marino 		break;
391*86d7f5d3SJohn Marino 	} break; }
392*86d7f5d3SJohn Marino 	nextc = c;
393*86d7f5d3SJohn Marino 	nexttok = d;
394*86d7f5d3SJohn Marino 	uncache(fin);
395*86d7f5d3SJohn Marino }
396*86d7f5d3SJohn Marino 
397*86d7f5d3SJohn Marino 	int
eoflex()398*86d7f5d3SJohn Marino eoflex()
399*86d7f5d3SJohn Marino /*
400*86d7f5d3SJohn Marino  * Yield true if we look ahead to the end of the input, false otherwise.
401*86d7f5d3SJohn Marino  * nextc becomes undefined at end of file.
402*86d7f5d3SJohn Marino  */
403*86d7f5d3SJohn Marino {
404*86d7f5d3SJohn Marino 	register int c;
405*86d7f5d3SJohn Marino 	declarecache;
406*86d7f5d3SJohn Marino 	register FILE *fout;
407*86d7f5d3SJohn Marino 	register RILE *fin;
408*86d7f5d3SJohn Marino 
409*86d7f5d3SJohn Marino 	c = nextc;
410*86d7f5d3SJohn Marino 	fin = finptr;
411*86d7f5d3SJohn Marino 	fout = foutptr;
412*86d7f5d3SJohn Marino 	setupcache(fin); cache(fin);
413*86d7f5d3SJohn Marino 
414*86d7f5d3SJohn Marino 	for (;;) {
415*86d7f5d3SJohn Marino 		switch (ctab[c]) {
416*86d7f5d3SJohn Marino 			default:
417*86d7f5d3SJohn Marino 				nextc = c;
418*86d7f5d3SJohn Marino 				uncache(fin);
419*86d7f5d3SJohn Marino 				return false;
420*86d7f5d3SJohn Marino 
421*86d7f5d3SJohn Marino 			case NEWLN:
422*86d7f5d3SJohn Marino 				++rcsline;
423*86d7f5d3SJohn Marino 				/* fall into */
424*86d7f5d3SJohn Marino 			case SPACE:
425*86d7f5d3SJohn Marino 				cachegeteof_(c, {uncache(fin);return true;})
426*86d7f5d3SJohn Marino 				break;
427*86d7f5d3SJohn Marino 		}
428*86d7f5d3SJohn Marino 		if (fout)
429*86d7f5d3SJohn Marino 			aputc_(c, fout)
430*86d7f5d3SJohn Marino 	}
431*86d7f5d3SJohn Marino }
432*86d7f5d3SJohn Marino 
433*86d7f5d3SJohn Marino 
getlex(token)434*86d7f5d3SJohn Marino int getlex(token)
435*86d7f5d3SJohn Marino enum tokens token;
436*86d7f5d3SJohn Marino /* Function: Checks if nexttok is the same as token. If so,
437*86d7f5d3SJohn Marino  * advances the input by calling nextlex and returns true.
438*86d7f5d3SJohn Marino  * otherwise returns false.
439*86d7f5d3SJohn Marino  * Doesn't work for strings and keywords; loses the character string for ids.
440*86d7f5d3SJohn Marino  */
441*86d7f5d3SJohn Marino {
442*86d7f5d3SJohn Marino         if (nexttok==token) {
443*86d7f5d3SJohn Marino                 nextlex();
444*86d7f5d3SJohn Marino                 return(true);
445*86d7f5d3SJohn Marino         } else  return(false);
446*86d7f5d3SJohn Marino }
447*86d7f5d3SJohn Marino 
448*86d7f5d3SJohn Marino 	int
getkeyopt(key)449*86d7f5d3SJohn Marino getkeyopt(key)
450*86d7f5d3SJohn Marino 	char const *key;
451*86d7f5d3SJohn Marino /* Function: If the current token is a keyword identical to key,
452*86d7f5d3SJohn Marino  * advances the input by calling nextlex and returns true;
453*86d7f5d3SJohn Marino  * otherwise returns false.
454*86d7f5d3SJohn Marino  */
455*86d7f5d3SJohn Marino {
456*86d7f5d3SJohn Marino 	if (nexttok==ID  &&  strcmp(key,NextString) == 0) {
457*86d7f5d3SJohn Marino 		 /* match found */
458*86d7f5d3SJohn Marino 		 ffree1(NextString);
459*86d7f5d3SJohn Marino 		 nextlex();
460*86d7f5d3SJohn Marino 		 return(true);
461*86d7f5d3SJohn Marino         }
462*86d7f5d3SJohn Marino         return(false);
463*86d7f5d3SJohn Marino }
464*86d7f5d3SJohn Marino 
465*86d7f5d3SJohn Marino 	void
getkey(key)466*86d7f5d3SJohn Marino getkey(key)
467*86d7f5d3SJohn Marino 	char const *key;
468*86d7f5d3SJohn Marino /* Check that the current input token is a keyword identical to key,
469*86d7f5d3SJohn Marino  * and advance the input by calling nextlex.
470*86d7f5d3SJohn Marino  */
471*86d7f5d3SJohn Marino {
472*86d7f5d3SJohn Marino 	if (!getkeyopt(key))
473*86d7f5d3SJohn Marino 		fatserror("missing '%s' keyword", key);
474*86d7f5d3SJohn Marino }
475*86d7f5d3SJohn Marino 
476*86d7f5d3SJohn Marino 	void
getkeystring(key)477*86d7f5d3SJohn Marino getkeystring(key)
478*86d7f5d3SJohn Marino 	char const *key;
479*86d7f5d3SJohn Marino /* Check that the current input token is a keyword identical to key,
480*86d7f5d3SJohn Marino  * and advance the input by calling nextlex; then look ahead for a string.
481*86d7f5d3SJohn Marino  */
482*86d7f5d3SJohn Marino {
483*86d7f5d3SJohn Marino 	getkey(key);
484*86d7f5d3SJohn Marino 	if (nexttok != STRING)
485*86d7f5d3SJohn Marino 		fatserror("missing string after '%s' keyword", key);
486*86d7f5d3SJohn Marino }
487*86d7f5d3SJohn Marino 
488*86d7f5d3SJohn Marino 
489*86d7f5d3SJohn Marino 	char const *
getid()490*86d7f5d3SJohn Marino getid()
491*86d7f5d3SJohn Marino /* Function: Checks if nexttok is an identifier. If so,
492*86d7f5d3SJohn Marino  * advances the input by calling nextlex and returns a pointer
493*86d7f5d3SJohn Marino  * to the identifier; otherwise returns 0.
494*86d7f5d3SJohn Marino  * Treats keywords as identifiers.
495*86d7f5d3SJohn Marino  */
496*86d7f5d3SJohn Marino {
497*86d7f5d3SJohn Marino 	register char const *name;
498*86d7f5d3SJohn Marino         if (nexttok==ID) {
499*86d7f5d3SJohn Marino                 name = NextString;
500*86d7f5d3SJohn Marino                 nextlex();
501*86d7f5d3SJohn Marino                 return name;
502*86d7f5d3SJohn Marino 	} else
503*86d7f5d3SJohn Marino 		return 0;
504*86d7f5d3SJohn Marino }
505*86d7f5d3SJohn Marino 
506*86d7f5d3SJohn Marino 
getnum()507*86d7f5d3SJohn Marino struct hshentry * getnum()
508*86d7f5d3SJohn Marino /* Function: Checks if nexttok is a number. If so,
509*86d7f5d3SJohn Marino  * advances the input by calling nextlex and returns a pointer
510*86d7f5d3SJohn Marino  * to the hashtable entry.  Otherwise returns 0.
511*86d7f5d3SJohn Marino  * Doesn't work if hshenter is false.
512*86d7f5d3SJohn Marino  */
513*86d7f5d3SJohn Marino {
514*86d7f5d3SJohn Marino         register struct hshentry * num;
515*86d7f5d3SJohn Marino         if (nexttok==NUM) {
516*86d7f5d3SJohn Marino                 num=nexthsh;
517*86d7f5d3SJohn Marino                 nextlex();
518*86d7f5d3SJohn Marino                 return num;
519*86d7f5d3SJohn Marino 	} else
520*86d7f5d3SJohn Marino 		return 0;
521*86d7f5d3SJohn Marino }
522*86d7f5d3SJohn Marino 
523*86d7f5d3SJohn Marino 	struct cbuf
getphrases(key)524*86d7f5d3SJohn Marino getphrases(key)
525*86d7f5d3SJohn Marino 	char const *key;
526*86d7f5d3SJohn Marino /*
527*86d7f5d3SJohn Marino * Get a series of phrases that do not start with KEY.  Yield resulting buffer.
528*86d7f5d3SJohn Marino * Stop when the next phrase starts with a token that is not an identifier,
529*86d7f5d3SJohn Marino * or is KEY.  Copy input to foutptr if it is set.  Unlike ignorephrases(),
530*86d7f5d3SJohn Marino * this routine assumes nextlex() has already been invoked before we start.
531*86d7f5d3SJohn Marino */
532*86d7f5d3SJohn Marino {
533*86d7f5d3SJohn Marino     declarecache;
534*86d7f5d3SJohn Marino     register int c;
535*86d7f5d3SJohn Marino     register char const *kn;
536*86d7f5d3SJohn Marino     struct cbuf r;
537*86d7f5d3SJohn Marino     register RILE *fin;
538*86d7f5d3SJohn Marino     register FILE *frew;
539*86d7f5d3SJohn Marino #   if large_memory
540*86d7f5d3SJohn Marino #	define savech_(c) ;
541*86d7f5d3SJohn Marino #   else
542*86d7f5d3SJohn Marino 	register char *p;
543*86d7f5d3SJohn Marino 	char const *limit;
544*86d7f5d3SJohn Marino 	struct buf b;
545*86d7f5d3SJohn Marino #	define savech_(c) {if (limit<=p)p=bufenlarge(&b,&limit); *p++ =(c);}
546*86d7f5d3SJohn Marino #   endif
547*86d7f5d3SJohn Marino 
548*86d7f5d3SJohn Marino     if (nexttok!=ID  ||  strcmp(NextString,key) == 0)
549*86d7f5d3SJohn Marino 	clear_buf(&r);
550*86d7f5d3SJohn Marino     else {
551*86d7f5d3SJohn Marino 	warnignore();
552*86d7f5d3SJohn Marino 	fin = finptr;
553*86d7f5d3SJohn Marino 	frew = foutptr;
554*86d7f5d3SJohn Marino 	setupcache(fin); cache(fin);
555*86d7f5d3SJohn Marino #	if large_memory
556*86d7f5d3SJohn Marino 	    r.string = (char const*)cacheptr() - strlen(NextString) - 1;
557*86d7f5d3SJohn Marino #	else
558*86d7f5d3SJohn Marino 	    bufautobegin(&b);
559*86d7f5d3SJohn Marino 	    bufscpy(&b, NextString);
560*86d7f5d3SJohn Marino 	    p = b.string + strlen(b.string);
561*86d7f5d3SJohn Marino 	    limit = b.string + b.size;
562*86d7f5d3SJohn Marino #	endif
563*86d7f5d3SJohn Marino 	ffree1(NextString);
564*86d7f5d3SJohn Marino 	c = nextc;
565*86d7f5d3SJohn Marino 	for (;;) {
566*86d7f5d3SJohn Marino 	    for (;;) {
567*86d7f5d3SJohn Marino 		savech_(c)
568*86d7f5d3SJohn Marino 		switch (ctab[c]) {
569*86d7f5d3SJohn Marino 		    default:
570*86d7f5d3SJohn Marino 			fatserror("unknown character `%c'", c);
571*86d7f5d3SJohn Marino 			/*NOTREACHED*/
572*86d7f5d3SJohn Marino 		    case NEWLN:
573*86d7f5d3SJohn Marino 			++rcsline;
574*86d7f5d3SJohn Marino 			/* fall into */
575*86d7f5d3SJohn Marino 		    case COLON: case DIGIT: case LETTER: case Letter:
576*86d7f5d3SJohn Marino 		    case PERIOD: case SPACE:
577*86d7f5d3SJohn Marino 			GETC_(frew, c)
578*86d7f5d3SJohn Marino 			continue;
579*86d7f5d3SJohn Marino 		    case SBEGIN: /* long string */
580*86d7f5d3SJohn Marino 			for (;;) {
581*86d7f5d3SJohn Marino 			    for (;;) {
582*86d7f5d3SJohn Marino 				GETC_(frew, c)
583*86d7f5d3SJohn Marino 				savech_(c)
584*86d7f5d3SJohn Marino 				switch (c) {
585*86d7f5d3SJohn Marino 				    case '\n':
586*86d7f5d3SJohn Marino 					++rcsline;
587*86d7f5d3SJohn Marino 					/* fall into */
588*86d7f5d3SJohn Marino 				    default:
589*86d7f5d3SJohn Marino 					continue;
590*86d7f5d3SJohn Marino 
591*86d7f5d3SJohn Marino 				    case SDELIM:
592*86d7f5d3SJohn Marino 					break;
593*86d7f5d3SJohn Marino 				}
594*86d7f5d3SJohn Marino 				break;
595*86d7f5d3SJohn Marino 			    }
596*86d7f5d3SJohn Marino 			    GETC_(frew, c)
597*86d7f5d3SJohn Marino 			    if (c != SDELIM)
598*86d7f5d3SJohn Marino 				break;
599*86d7f5d3SJohn Marino 			    savech_(c)
600*86d7f5d3SJohn Marino 			}
601*86d7f5d3SJohn Marino 			continue;
602*86d7f5d3SJohn Marino 		    case SEMI:
603*86d7f5d3SJohn Marino 			cacheget_(c)
604*86d7f5d3SJohn Marino 			if (ctab[c] == NEWLN) {
605*86d7f5d3SJohn Marino 			    if (frew)
606*86d7f5d3SJohn Marino 				aputc_(c, frew)
607*86d7f5d3SJohn Marino 			    ++rcsline;
608*86d7f5d3SJohn Marino 			    savech_(c)
609*86d7f5d3SJohn Marino 			    cacheget_(c)
610*86d7f5d3SJohn Marino 			}
611*86d7f5d3SJohn Marino #			if large_memory
612*86d7f5d3SJohn Marino 			    r.size = (char const*)cacheptr() - 1 - r.string;
613*86d7f5d3SJohn Marino #			endif
614*86d7f5d3SJohn Marino 			for (;;) {
615*86d7f5d3SJohn Marino 			    switch (ctab[c]) {
616*86d7f5d3SJohn Marino 				case NEWLN:
617*86d7f5d3SJohn Marino 					++rcsline;
618*86d7f5d3SJohn Marino 					/* fall into */
619*86d7f5d3SJohn Marino 				case SPACE:
620*86d7f5d3SJohn Marino 					cacheget_(c)
621*86d7f5d3SJohn Marino 					continue;
622*86d7f5d3SJohn Marino 
623*86d7f5d3SJohn Marino 				default: break;
624*86d7f5d3SJohn Marino 			    }
625*86d7f5d3SJohn Marino 			    break;
626*86d7f5d3SJohn Marino 			}
627*86d7f5d3SJohn Marino 			if (frew)
628*86d7f5d3SJohn Marino 			    aputc_(c, frew)
629*86d7f5d3SJohn Marino 			break;
630*86d7f5d3SJohn Marino 		}
631*86d7f5d3SJohn Marino 		break;
632*86d7f5d3SJohn Marino 	    }
633*86d7f5d3SJohn Marino 	    if (ctab[c] == Letter) {
634*86d7f5d3SJohn Marino 		    for (kn = key;  c && *kn==c;  kn++)
635*86d7f5d3SJohn Marino 			GETC_(frew, c)
636*86d7f5d3SJohn Marino 		    if (!*kn)
637*86d7f5d3SJohn Marino 			switch (ctab[c]) {
638*86d7f5d3SJohn Marino 			    case DIGIT: case LETTER: case Letter:
639*86d7f5d3SJohn Marino 			    case IDCHAR: case PERIOD:
640*86d7f5d3SJohn Marino 				break;
641*86d7f5d3SJohn Marino 			    default:
642*86d7f5d3SJohn Marino 				nextc = c;
643*86d7f5d3SJohn Marino 				NextString = fstr_save(key);
644*86d7f5d3SJohn Marino 				nexttok = ID;
645*86d7f5d3SJohn Marino 				uncache(fin);
646*86d7f5d3SJohn Marino 				goto returnit;
647*86d7f5d3SJohn Marino 			}
648*86d7f5d3SJohn Marino #		    if !large_memory
649*86d7f5d3SJohn Marino 			{
650*86d7f5d3SJohn Marino 			    register char const *ki;
651*86d7f5d3SJohn Marino 			    for (ki=key; ki<kn; )
652*86d7f5d3SJohn Marino 				savech_(*ki++)
653*86d7f5d3SJohn Marino 			}
654*86d7f5d3SJohn Marino #		    endif
655*86d7f5d3SJohn Marino 	    } else {
656*86d7f5d3SJohn Marino 		    nextc = c;
657*86d7f5d3SJohn Marino 		    uncache(fin);
658*86d7f5d3SJohn Marino 		    nextlex();
659*86d7f5d3SJohn Marino 		    break;
660*86d7f5d3SJohn Marino 	    }
661*86d7f5d3SJohn Marino 	}
662*86d7f5d3SJohn Marino     returnit:;
663*86d7f5d3SJohn Marino #	if !large_memory
664*86d7f5d3SJohn Marino 	    return bufremember(&b, (size_t)(p - b.string));
665*86d7f5d3SJohn Marino #	endif
666*86d7f5d3SJohn Marino     }
667*86d7f5d3SJohn Marino     return r;
668*86d7f5d3SJohn Marino }
669*86d7f5d3SJohn Marino 
670*86d7f5d3SJohn Marino 
671*86d7f5d3SJohn Marino 	void
readstring()672*86d7f5d3SJohn Marino readstring()
673*86d7f5d3SJohn Marino /* skip over characters until terminating single SDELIM        */
674*86d7f5d3SJohn Marino /* If foutptr is set, copy every character read to foutptr.    */
675*86d7f5d3SJohn Marino /* Does not advance nextlex at the end.                        */
676*86d7f5d3SJohn Marino {       register int c;
677*86d7f5d3SJohn Marino 	declarecache;
678*86d7f5d3SJohn Marino 	register FILE *frew;
679*86d7f5d3SJohn Marino 	register RILE *fin;
680*86d7f5d3SJohn Marino 	fin=finptr; frew=foutptr;
681*86d7f5d3SJohn Marino 	setupcache(fin); cache(fin);
682*86d7f5d3SJohn Marino 	for (;;) {
683*86d7f5d3SJohn Marino 		GETC_(frew, c)
684*86d7f5d3SJohn Marino 		switch (c) {
685*86d7f5d3SJohn Marino 		    case '\n':
686*86d7f5d3SJohn Marino 			++rcsline;
687*86d7f5d3SJohn Marino 			break;
688*86d7f5d3SJohn Marino 
689*86d7f5d3SJohn Marino 		    case SDELIM:
690*86d7f5d3SJohn Marino 			GETC_(frew, c)
691*86d7f5d3SJohn Marino 			if (c != SDELIM) {
692*86d7f5d3SJohn Marino 				/* end of string */
693*86d7f5d3SJohn Marino 				nextc = c;
694*86d7f5d3SJohn Marino 				uncache(fin);
695*86d7f5d3SJohn Marino 				return;
696*86d7f5d3SJohn Marino 			}
697*86d7f5d3SJohn Marino 			break;
698*86d7f5d3SJohn Marino 		}
699*86d7f5d3SJohn Marino 	}
700*86d7f5d3SJohn Marino }
701*86d7f5d3SJohn Marino 
702*86d7f5d3SJohn Marino 
703*86d7f5d3SJohn Marino 	void
printstring()704*86d7f5d3SJohn Marino printstring()
705*86d7f5d3SJohn Marino /* Function: copy a string to stdout, until terminated with a single SDELIM.
706*86d7f5d3SJohn Marino  * Does not advance nextlex at the end.
707*86d7f5d3SJohn Marino  */
708*86d7f5d3SJohn Marino {
709*86d7f5d3SJohn Marino         register int c;
710*86d7f5d3SJohn Marino 	declarecache;
711*86d7f5d3SJohn Marino 	register FILE *fout;
712*86d7f5d3SJohn Marino 	register RILE *fin;
713*86d7f5d3SJohn Marino 	fin=finptr;
714*86d7f5d3SJohn Marino 	fout = stdout;
715*86d7f5d3SJohn Marino 	setupcache(fin); cache(fin);
716*86d7f5d3SJohn Marino 	for (;;) {
717*86d7f5d3SJohn Marino 		cacheget_(c)
718*86d7f5d3SJohn Marino 		switch (c) {
719*86d7f5d3SJohn Marino 		    case '\n':
720*86d7f5d3SJohn Marino 			++rcsline;
721*86d7f5d3SJohn Marino 			break;
722*86d7f5d3SJohn Marino 		    case SDELIM:
723*86d7f5d3SJohn Marino 			cacheget_(c)
724*86d7f5d3SJohn Marino 			if (c != SDELIM) {
725*86d7f5d3SJohn Marino                                 nextc=c;
726*86d7f5d3SJohn Marino 				uncache(fin);
727*86d7f5d3SJohn Marino                                 return;
728*86d7f5d3SJohn Marino                         }
729*86d7f5d3SJohn Marino 			break;
730*86d7f5d3SJohn Marino                 }
731*86d7f5d3SJohn Marino 		aputc_(c,fout)
732*86d7f5d3SJohn Marino         }
733*86d7f5d3SJohn Marino }
734*86d7f5d3SJohn Marino 
735*86d7f5d3SJohn Marino 
736*86d7f5d3SJohn Marino 
737*86d7f5d3SJohn Marino 	struct cbuf
savestring(target)738*86d7f5d3SJohn Marino savestring(target)
739*86d7f5d3SJohn Marino 	struct buf *target;
740*86d7f5d3SJohn Marino /* Copies a string terminated with SDELIM from file finptr to buffer target.
741*86d7f5d3SJohn Marino  * Double SDELIM is replaced with SDELIM.
742*86d7f5d3SJohn Marino  * If foutptr is set, the string is also copied unchanged to foutptr.
743*86d7f5d3SJohn Marino  * Does not advance nextlex at the end.
744*86d7f5d3SJohn Marino  * Yield a copy of *TARGET, except with exact length.
745*86d7f5d3SJohn Marino  */
746*86d7f5d3SJohn Marino {
747*86d7f5d3SJohn Marino         register int c;
748*86d7f5d3SJohn Marino 	declarecache;
749*86d7f5d3SJohn Marino 	register FILE *frew;
750*86d7f5d3SJohn Marino 	register char *tp;
751*86d7f5d3SJohn Marino 	register RILE *fin;
752*86d7f5d3SJohn Marino 	char const *limit;
753*86d7f5d3SJohn Marino 	struct cbuf r;
754*86d7f5d3SJohn Marino 
755*86d7f5d3SJohn Marino 	fin=finptr; frew=foutptr;
756*86d7f5d3SJohn Marino 	setupcache(fin); cache(fin);
757*86d7f5d3SJohn Marino 	tp = target->string;  limit = tp + target->size;
758*86d7f5d3SJohn Marino 	for (;;) {
759*86d7f5d3SJohn Marino 		GETC_(frew, c)
760*86d7f5d3SJohn Marino 		switch (c) {
761*86d7f5d3SJohn Marino 		    case '\n':
762*86d7f5d3SJohn Marino 			++rcsline;
763*86d7f5d3SJohn Marino 			break;
764*86d7f5d3SJohn Marino 		    case SDELIM:
765*86d7f5d3SJohn Marino 			GETC_(frew, c)
766*86d7f5d3SJohn Marino 			if (c != SDELIM) {
767*86d7f5d3SJohn Marino                                 /* end of string */
768*86d7f5d3SJohn Marino                                 nextc=c;
769*86d7f5d3SJohn Marino 				r.string = target->string;
770*86d7f5d3SJohn Marino 				r.size = tp - r.string;
771*86d7f5d3SJohn Marino 				uncache(fin);
772*86d7f5d3SJohn Marino 				return r;
773*86d7f5d3SJohn Marino                         }
774*86d7f5d3SJohn Marino 			break;
775*86d7f5d3SJohn Marino                 }
776*86d7f5d3SJohn Marino 		if (tp == limit)
777*86d7f5d3SJohn Marino 			tp = bufenlarge(target, &limit);
778*86d7f5d3SJohn Marino 		*tp++ = c;
779*86d7f5d3SJohn Marino         }
780*86d7f5d3SJohn Marino }
781*86d7f5d3SJohn Marino 
782*86d7f5d3SJohn Marino 
783*86d7f5d3SJohn Marino 	static char *
checkidentifier(id,delimiter,dotok)784*86d7f5d3SJohn Marino checkidentifier(id, delimiter, dotok)
785*86d7f5d3SJohn Marino 	register char *id;
786*86d7f5d3SJohn Marino 	int delimiter;
787*86d7f5d3SJohn Marino 	register int dotok;
788*86d7f5d3SJohn Marino /*   Function:  check whether the string starting at id is an   */
789*86d7f5d3SJohn Marino /*		identifier and return a pointer to the delimiter*/
790*86d7f5d3SJohn Marino /*		after the identifier.  White space, delim and 0 */
791*86d7f5d3SJohn Marino /*              are legal delimiters.  Aborts the program if not*/
792*86d7f5d3SJohn Marino /*              a legal identifier. Useful for checking commands*/
793*86d7f5d3SJohn Marino /*		If !delim, the only delimiter is 0.		*/
794*86d7f5d3SJohn Marino /*		Allow '.' in identifier only if DOTOK is set.   */
795*86d7f5d3SJohn Marino {
796*86d7f5d3SJohn Marino         register char    *temp;
797*86d7f5d3SJohn Marino 	register char c;
798*86d7f5d3SJohn Marino 	register char delim = delimiter;
799*86d7f5d3SJohn Marino 	int isid = false;
800*86d7f5d3SJohn Marino 
801*86d7f5d3SJohn Marino 	temp = id;
802*86d7f5d3SJohn Marino 	for (;;  id++) {
803*86d7f5d3SJohn Marino 		switch (ctab[(unsigned char)(c = *id)]) {
804*86d7f5d3SJohn Marino 			case IDCHAR:
805*86d7f5d3SJohn Marino 			case LETTER:
806*86d7f5d3SJohn Marino 			case Letter:
807*86d7f5d3SJohn Marino 				isid = true;
808*86d7f5d3SJohn Marino 				continue;
809*86d7f5d3SJohn Marino 
810*86d7f5d3SJohn Marino 			case DIGIT:
811*86d7f5d3SJohn Marino 				continue;
812*86d7f5d3SJohn Marino 
813*86d7f5d3SJohn Marino 			case PERIOD:
814*86d7f5d3SJohn Marino 				if (dotok)
815*86d7f5d3SJohn Marino 					continue;
816*86d7f5d3SJohn Marino 				break;
817*86d7f5d3SJohn Marino 
818*86d7f5d3SJohn Marino 			default:
819*86d7f5d3SJohn Marino 				break;
820*86d7f5d3SJohn Marino 		}
821*86d7f5d3SJohn Marino 		break;
822*86d7f5d3SJohn Marino 	}
823*86d7f5d3SJohn Marino 	if (	 ! isid
824*86d7f5d3SJohn Marino 	    ||	 (c  &&  (!delim || (c!=delim && c!=' ' && c!='\t' && c!='\n')))
825*86d7f5d3SJohn Marino 	) {
826*86d7f5d3SJohn Marino                 /* append \0 to end of id before error message */
827*86d7f5d3SJohn Marino 		while ((c = *id) && c!=' ' && c!='\t' && c!='\n' && c!=delim)
828*86d7f5d3SJohn Marino 		    id++;
829*86d7f5d3SJohn Marino                 *id = '\0';
830*86d7f5d3SJohn Marino 		faterror("invalid %s `%s'",
831*86d7f5d3SJohn Marino 			dotok ? "identifier" : "symbol", temp
832*86d7f5d3SJohn Marino 		);
833*86d7f5d3SJohn Marino 	}
834*86d7f5d3SJohn Marino 	return id;
835*86d7f5d3SJohn Marino }
836*86d7f5d3SJohn Marino 
837*86d7f5d3SJohn Marino 	char *
checkid(id,delimiter)838*86d7f5d3SJohn Marino checkid(id, delimiter)
839*86d7f5d3SJohn Marino 	char *id;
840*86d7f5d3SJohn Marino 	int delimiter;
841*86d7f5d3SJohn Marino {
842*86d7f5d3SJohn Marino 	return checkidentifier(id, delimiter, true);
843*86d7f5d3SJohn Marino }
844*86d7f5d3SJohn Marino 
845*86d7f5d3SJohn Marino 	char *
checksym(sym,delimiter)846*86d7f5d3SJohn Marino checksym(sym, delimiter)
847*86d7f5d3SJohn Marino 	char *sym;
848*86d7f5d3SJohn Marino 	int delimiter;
849*86d7f5d3SJohn Marino {
850*86d7f5d3SJohn Marino 	return checkidentifier(sym, delimiter, false);
851*86d7f5d3SJohn Marino }
852*86d7f5d3SJohn Marino 
853*86d7f5d3SJohn Marino 	void
checksid(id)854*86d7f5d3SJohn Marino checksid(id)
855*86d7f5d3SJohn Marino 	char *id;
856*86d7f5d3SJohn Marino /* Check whether the string ID is an identifier.  */
857*86d7f5d3SJohn Marino {
858*86d7f5d3SJohn Marino 	VOID checkid(id, 0);
859*86d7f5d3SJohn Marino }
860*86d7f5d3SJohn Marino 
861*86d7f5d3SJohn Marino 	void
checkssym(sym)862*86d7f5d3SJohn Marino checkssym(sym)
863*86d7f5d3SJohn Marino 	char *sym;
864*86d7f5d3SJohn Marino {
865*86d7f5d3SJohn Marino 	VOID checksym(sym, 0);
866*86d7f5d3SJohn Marino }
867*86d7f5d3SJohn Marino 
868*86d7f5d3SJohn Marino 
869*86d7f5d3SJohn Marino #if !large_memory
870*86d7f5d3SJohn Marino #   define Iclose(f) fclose(f)
871*86d7f5d3SJohn Marino #else
872*86d7f5d3SJohn Marino # if !maps_memory
873*86d7f5d3SJohn Marino     static int Iclose P((RILE *));
874*86d7f5d3SJohn Marino 	static int
Iclose(f)875*86d7f5d3SJohn Marino     Iclose(f)
876*86d7f5d3SJohn Marino 	register RILE *f;
877*86d7f5d3SJohn Marino     {
878*86d7f5d3SJohn Marino 	tfree(f->base);
879*86d7f5d3SJohn Marino 	f->base = 0;
880*86d7f5d3SJohn Marino 	return fclose(f->stream);
881*86d7f5d3SJohn Marino     }
882*86d7f5d3SJohn Marino # else
883*86d7f5d3SJohn Marino     static int Iclose P((RILE *));
884*86d7f5d3SJohn Marino 	static int
Iclose(f)885*86d7f5d3SJohn Marino     Iclose(f)
886*86d7f5d3SJohn Marino 	register RILE *f;
887*86d7f5d3SJohn Marino     {
888*86d7f5d3SJohn Marino 	(* f->deallocate) (f);
889*86d7f5d3SJohn Marino 	f->base = 0;
890*86d7f5d3SJohn Marino 	return close(f->fd);
891*86d7f5d3SJohn Marino     }
892*86d7f5d3SJohn Marino 
893*86d7f5d3SJohn Marino #   if has_map_fd
894*86d7f5d3SJohn Marino 	static void map_fd_deallocate P((RILE *));
895*86d7f5d3SJohn Marino 	    static void
map_fd_deallocate(f)896*86d7f5d3SJohn Marino 	map_fd_deallocate(f)
897*86d7f5d3SJohn Marino 	    register RILE *f;
898*86d7f5d3SJohn Marino 	{
899*86d7f5d3SJohn Marino 	    if (vm_deallocate(
900*86d7f5d3SJohn Marino 		task_self(),
901*86d7f5d3SJohn Marino 		(vm_address_t) f->base,
902*86d7f5d3SJohn Marino 		(vm_size_t) (f->lim - f->base)
903*86d7f5d3SJohn Marino 	    ) != KERN_SUCCESS)
904*86d7f5d3SJohn Marino 		efaterror("vm_deallocate");
905*86d7f5d3SJohn Marino 	}
906*86d7f5d3SJohn Marino #   endif
907*86d7f5d3SJohn Marino #   if has_mmap
908*86d7f5d3SJohn Marino 	static void mmap_deallocate P((RILE *));
909*86d7f5d3SJohn Marino 	    static void
mmap_deallocate(f)910*86d7f5d3SJohn Marino 	mmap_deallocate(f)
911*86d7f5d3SJohn Marino 	    register RILE *f;
912*86d7f5d3SJohn Marino 	{
913*86d7f5d3SJohn Marino 	    if (munmap((char *) f->base, (size_t) (f->lim - f->base)) != 0)
914*86d7f5d3SJohn Marino 		efaterror("munmap");
915*86d7f5d3SJohn Marino 	}
916*86d7f5d3SJohn Marino #   endif
917*86d7f5d3SJohn Marino     static void read_deallocate P((RILE *));
918*86d7f5d3SJohn Marino 	static void
read_deallocate(f)919*86d7f5d3SJohn Marino     read_deallocate(f)
920*86d7f5d3SJohn Marino 	RILE *f;
921*86d7f5d3SJohn Marino     {
922*86d7f5d3SJohn Marino 	tfree(f->base);
923*86d7f5d3SJohn Marino     }
924*86d7f5d3SJohn Marino 
925*86d7f5d3SJohn Marino     static void nothing_to_deallocate P((RILE *));
926*86d7f5d3SJohn Marino 	static void
nothing_to_deallocate(f)927*86d7f5d3SJohn Marino     nothing_to_deallocate(f)
928*86d7f5d3SJohn Marino 	RILE *f;
929*86d7f5d3SJohn Marino     {
930*86d7f5d3SJohn Marino     }
931*86d7f5d3SJohn Marino # endif
932*86d7f5d3SJohn Marino #endif
933*86d7f5d3SJohn Marino 
934*86d7f5d3SJohn Marino 
935*86d7f5d3SJohn Marino #if large_memory && maps_memory
936*86d7f5d3SJohn Marino 	static RILE *fd2_RILE P((int,char const*,struct stat*));
937*86d7f5d3SJohn Marino 	static RILE *
fd2_RILE(fd,name,status)938*86d7f5d3SJohn Marino fd2_RILE(fd, name, status)
939*86d7f5d3SJohn Marino #else
940*86d7f5d3SJohn Marino 	static RILE *fd2RILE P((int,char const*,char const*,struct stat*));
941*86d7f5d3SJohn Marino 	static RILE *
942*86d7f5d3SJohn Marino fd2RILE(fd, name, type, status)
943*86d7f5d3SJohn Marino 	char const *type;
944*86d7f5d3SJohn Marino #endif
945*86d7f5d3SJohn Marino 	int fd;
946*86d7f5d3SJohn Marino 	char const *name;
947*86d7f5d3SJohn Marino 	register struct stat *status;
948*86d7f5d3SJohn Marino {
949*86d7f5d3SJohn Marino 	struct stat st;
950*86d7f5d3SJohn Marino 
951*86d7f5d3SJohn Marino 	if (!status)
952*86d7f5d3SJohn Marino 		status = &st;
953*86d7f5d3SJohn Marino 	if (fstat(fd, status) != 0)
954*86d7f5d3SJohn Marino 		efaterror(name);
955*86d7f5d3SJohn Marino 	if (!S_ISREG(status->st_mode)) {
956*86d7f5d3SJohn Marino 		error("`%s' is not a regular file", name);
957*86d7f5d3SJohn Marino 		VOID close(fd);
958*86d7f5d3SJohn Marino 		errno = EINVAL;
959*86d7f5d3SJohn Marino 		return 0;
960*86d7f5d3SJohn Marino 	} else {
961*86d7f5d3SJohn Marino 
962*86d7f5d3SJohn Marino #	    if !(large_memory && maps_memory)
963*86d7f5d3SJohn Marino 		FILE *stream;
964*86d7f5d3SJohn Marino 		if (!(stream = fdopen(fd, type)))
965*86d7f5d3SJohn Marino 			efaterror(name);
966*86d7f5d3SJohn Marino #	    endif
967*86d7f5d3SJohn Marino 
968*86d7f5d3SJohn Marino #	    if !large_memory
969*86d7f5d3SJohn Marino 		return stream;
970*86d7f5d3SJohn Marino #	    else
971*86d7f5d3SJohn Marino #		define RILES 3
972*86d7f5d3SJohn Marino 	      {
973*86d7f5d3SJohn Marino 		static RILE rilebuf[RILES];
974*86d7f5d3SJohn Marino 
975*86d7f5d3SJohn Marino 		register RILE *f;
976*86d7f5d3SJohn Marino 		size_t s = status->st_size;
977*86d7f5d3SJohn Marino 
978*86d7f5d3SJohn Marino 		if (s != status->st_size)
979*86d7f5d3SJohn Marino 			faterror("%s: too large", name);
980*86d7f5d3SJohn Marino 		for (f = rilebuf;  f->base;  f++)
981*86d7f5d3SJohn Marino 			if (f == rilebuf+RILES)
982*86d7f5d3SJohn Marino 				faterror("too many RILEs");
983*86d7f5d3SJohn Marino #		if maps_memory
984*86d7f5d3SJohn Marino 			f->deallocate = nothing_to_deallocate;
985*86d7f5d3SJohn Marino #		endif
986*86d7f5d3SJohn Marino 		if (!s) {
987*86d7f5d3SJohn Marino 		    static unsigned char nothing;
988*86d7f5d3SJohn Marino 		    f->base = &nothing; /* Any nonzero address will do.  */
989*86d7f5d3SJohn Marino 		} else {
990*86d7f5d3SJohn Marino 		    f->base = 0;
991*86d7f5d3SJohn Marino #		    if has_map_fd
992*86d7f5d3SJohn Marino 			map_fd(
993*86d7f5d3SJohn Marino 				fd, (vm_offset_t)0, (vm_address_t*) &f->base,
994*86d7f5d3SJohn Marino 				TRUE, (vm_size_t)s
995*86d7f5d3SJohn Marino 			);
996*86d7f5d3SJohn Marino 			f->deallocate = map_fd_deallocate;
997*86d7f5d3SJohn Marino #		    endif
998*86d7f5d3SJohn Marino #		    if has_mmap
999*86d7f5d3SJohn Marino 			if (!f->base) {
1000*86d7f5d3SJohn Marino 			    catchmmapints();
1001*86d7f5d3SJohn Marino 			    f->base = (unsigned char *) mmap(
1002*86d7f5d3SJohn Marino 				(char *)0, s, PROT_READ, MAP_SHARED,
1003*86d7f5d3SJohn Marino 				fd, (off_t)0
1004*86d7f5d3SJohn Marino 			    );
1005*86d7f5d3SJohn Marino #			    ifndef MAP_FAILED
1006*86d7f5d3SJohn Marino #			    define MAP_FAILED (-1)
1007*86d7f5d3SJohn Marino #			    endif
1008*86d7f5d3SJohn Marino 			    if (f->base == (unsigned char *) MAP_FAILED)
1009*86d7f5d3SJohn Marino 				f->base = 0;
1010*86d7f5d3SJohn Marino 			    else {
1011*86d7f5d3SJohn Marino #				if has_NFS && mmap_signal
1012*86d7f5d3SJohn Marino 				    /*
1013*86d7f5d3SJohn Marino 				    * On many hosts, the superuser
1014*86d7f5d3SJohn Marino 				    * can mmap an NFS file it can't read.
1015*86d7f5d3SJohn Marino 				    * So access the first page now, and print
1016*86d7f5d3SJohn Marino 				    * a nice message if a bus error occurs.
1017*86d7f5d3SJohn Marino 				    */
1018*86d7f5d3SJohn Marino 				    readAccessFilenameBuffer(name, f->base);
1019*86d7f5d3SJohn Marino #				endif
1020*86d7f5d3SJohn Marino 			    }
1021*86d7f5d3SJohn Marino 			    f->deallocate = mmap_deallocate;
1022*86d7f5d3SJohn Marino 			}
1023*86d7f5d3SJohn Marino #		    endif
1024*86d7f5d3SJohn Marino 		    if (!f->base) {
1025*86d7f5d3SJohn Marino 			f->base = tnalloc(unsigned char, s);
1026*86d7f5d3SJohn Marino #			if maps_memory
1027*86d7f5d3SJohn Marino 			{
1028*86d7f5d3SJohn Marino 			    /*
1029*86d7f5d3SJohn Marino 			    * We can't map the file into memory for some reason.
1030*86d7f5d3SJohn Marino 			    * Read it into main memory all at once; this is
1031*86d7f5d3SJohn Marino 			    * the simplest substitute for memory mapping.
1032*86d7f5d3SJohn Marino 			    */
1033*86d7f5d3SJohn Marino 			    char *bufptr = (char *) f->base;
1034*86d7f5d3SJohn Marino 			    size_t bufsiz = s;
1035*86d7f5d3SJohn Marino 			    do {
1036*86d7f5d3SJohn Marino 				ssize_t r = read(fd, bufptr, bufsiz);
1037*86d7f5d3SJohn Marino 				switch (r) {
1038*86d7f5d3SJohn Marino 				    case -1:
1039*86d7f5d3SJohn Marino 					efaterror(name);
1040*86d7f5d3SJohn Marino 
1041*86d7f5d3SJohn Marino 				    case 0:
1042*86d7f5d3SJohn Marino 					/* The file must have shrunk!  */
1043*86d7f5d3SJohn Marino 					status->st_size = s -= bufsiz;
1044*86d7f5d3SJohn Marino 					bufsiz = 0;
1045*86d7f5d3SJohn Marino 					break;
1046*86d7f5d3SJohn Marino 
1047*86d7f5d3SJohn Marino 				    default:
1048*86d7f5d3SJohn Marino 					bufptr += r;
1049*86d7f5d3SJohn Marino 					bufsiz -= r;
1050*86d7f5d3SJohn Marino 					break;
1051*86d7f5d3SJohn Marino 				}
1052*86d7f5d3SJohn Marino 			    } while (bufsiz);
1053*86d7f5d3SJohn Marino 			    if (lseek(fd, (off_t)0, SEEK_SET) == -1)
1054*86d7f5d3SJohn Marino 				efaterror(name);
1055*86d7f5d3SJohn Marino 			    f->deallocate = read_deallocate;
1056*86d7f5d3SJohn Marino 			}
1057*86d7f5d3SJohn Marino #			endif
1058*86d7f5d3SJohn Marino 		    }
1059*86d7f5d3SJohn Marino 		}
1060*86d7f5d3SJohn Marino 		f->ptr = f->base;
1061*86d7f5d3SJohn Marino 		f->lim = f->base + s;
1062*86d7f5d3SJohn Marino 		f->fd = fd;
1063*86d7f5d3SJohn Marino #		if !maps_memory
1064*86d7f5d3SJohn Marino 		    f->readlim = f->base;
1065*86d7f5d3SJohn Marino 		    f->stream = stream;
1066*86d7f5d3SJohn Marino #		endif
1067*86d7f5d3SJohn Marino 		if_advise_access(s, f, MADV_SEQUENTIAL);
1068*86d7f5d3SJohn Marino 		return f;
1069*86d7f5d3SJohn Marino 	      }
1070*86d7f5d3SJohn Marino #	    endif
1071*86d7f5d3SJohn Marino 	}
1072*86d7f5d3SJohn Marino }
1073*86d7f5d3SJohn Marino 
1074*86d7f5d3SJohn Marino #if !maps_memory && large_memory
1075*86d7f5d3SJohn Marino 	int
Igetmore(f)1076*86d7f5d3SJohn Marino Igetmore(f)
1077*86d7f5d3SJohn Marino 	register RILE *f;
1078*86d7f5d3SJohn Marino {
1079*86d7f5d3SJohn Marino 	register fread_type r;
1080*86d7f5d3SJohn Marino 	register size_t s = f->lim - f->readlim;
1081*86d7f5d3SJohn Marino 
1082*86d7f5d3SJohn Marino 	if (BUFSIZ < s)
1083*86d7f5d3SJohn Marino 		s = BUFSIZ;
1084*86d7f5d3SJohn Marino 	if (!(r = Fread(f->readlim, sizeof(*f->readlim), s, f->stream))) {
1085*86d7f5d3SJohn Marino 		testIerror(f->stream);
1086*86d7f5d3SJohn Marino 		f->lim = f->readlim;  /* The file might have shrunk!  */
1087*86d7f5d3SJohn Marino 		return 0;
1088*86d7f5d3SJohn Marino 	}
1089*86d7f5d3SJohn Marino 	f->readlim += r;
1090*86d7f5d3SJohn Marino 	return 1;
1091*86d7f5d3SJohn Marino }
1092*86d7f5d3SJohn Marino #endif
1093*86d7f5d3SJohn Marino 
1094*86d7f5d3SJohn Marino #if has_madvise && has_mmap && large_memory
1095*86d7f5d3SJohn Marino 	void
advise_access(f,advice)1096*86d7f5d3SJohn Marino advise_access(f, advice)
1097*86d7f5d3SJohn Marino 	register RILE *f;
1098*86d7f5d3SJohn Marino 	int advice;
1099*86d7f5d3SJohn Marino {
1100*86d7f5d3SJohn Marino     if (f->deallocate == mmap_deallocate)
1101*86d7f5d3SJohn Marino 	VOID madvise((char *)f->base, (size_t)(f->lim - f->base), advice);
1102*86d7f5d3SJohn Marino 	/* Don't worry if madvise fails; it's only advisory.  */
1103*86d7f5d3SJohn Marino }
1104*86d7f5d3SJohn Marino #endif
1105*86d7f5d3SJohn Marino 
1106*86d7f5d3SJohn Marino 	RILE *
1107*86d7f5d3SJohn Marino #if large_memory && maps_memory
I_open(name,status)1108*86d7f5d3SJohn Marino I_open(name, status)
1109*86d7f5d3SJohn Marino #else
1110*86d7f5d3SJohn Marino Iopen(name, type, status)
1111*86d7f5d3SJohn Marino 	char const *type;
1112*86d7f5d3SJohn Marino #endif
1113*86d7f5d3SJohn Marino 	char const *name;
1114*86d7f5d3SJohn Marino 	struct stat *status;
1115*86d7f5d3SJohn Marino /* Open NAME for reading, yield its descriptor, and set *STATUS.  */
1116*86d7f5d3SJohn Marino {
1117*86d7f5d3SJohn Marino 	int fd = fdSafer(open(name, O_RDONLY
1118*86d7f5d3SJohn Marino #		if OPEN_O_BINARY
1119*86d7f5d3SJohn Marino 			|  (strchr(type,'b') ? OPEN_O_BINARY : 0)
1120*86d7f5d3SJohn Marino #		endif
1121*86d7f5d3SJohn Marino 	));
1122*86d7f5d3SJohn Marino 
1123*86d7f5d3SJohn Marino 	if (fd < 0)
1124*86d7f5d3SJohn Marino 		return 0;
1125*86d7f5d3SJohn Marino #	if large_memory && maps_memory
1126*86d7f5d3SJohn Marino 		return fd2_RILE(fd, name, status);
1127*86d7f5d3SJohn Marino #	else
1128*86d7f5d3SJohn Marino 		return fd2RILE(fd, name, type, status);
1129*86d7f5d3SJohn Marino #	endif
1130*86d7f5d3SJohn Marino }
1131*86d7f5d3SJohn Marino 
1132*86d7f5d3SJohn Marino 
1133*86d7f5d3SJohn Marino static int Oerrloop;
1134*86d7f5d3SJohn Marino 
1135*86d7f5d3SJohn Marino 	void
Oerror()1136*86d7f5d3SJohn Marino Oerror()
1137*86d7f5d3SJohn Marino {
1138*86d7f5d3SJohn Marino 	if (Oerrloop)
1139*86d7f5d3SJohn Marino 		exiterr();
1140*86d7f5d3SJohn Marino 	Oerrloop = true;
1141*86d7f5d3SJohn Marino 	efaterror("output error");
1142*86d7f5d3SJohn Marino }
1143*86d7f5d3SJohn Marino 
Ieof()1144*86d7f5d3SJohn Marino void Ieof() { fatserror("unexpected end of file"); }
Ierror()1145*86d7f5d3SJohn Marino void Ierror() { efaterror("input error"); }
testIerror(f)1146*86d7f5d3SJohn Marino void testIerror(f) FILE *f; { if (ferror(f)) Ierror(); }
testOerror(o)1147*86d7f5d3SJohn Marino void testOerror(o) FILE *o; { if (ferror(o)) Oerror(); }
1148*86d7f5d3SJohn Marino 
Ifclose(f)1149*86d7f5d3SJohn Marino void Ifclose(f) RILE *f; { if (f && Iclose(f)!=0) Ierror(); }
Ofclose(f)1150*86d7f5d3SJohn Marino void Ofclose(f) FILE *f; { if (f && fclose(f)!=0) Oerror(); }
Izclose(p)1151*86d7f5d3SJohn Marino void Izclose(p) RILE **p; { Ifclose(*p); *p = 0; }
Ozclose(p)1152*86d7f5d3SJohn Marino void Ozclose(p) FILE **p; { Ofclose(*p); *p = 0; }
1153*86d7f5d3SJohn Marino 
1154*86d7f5d3SJohn Marino #if !large_memory
1155*86d7f5d3SJohn Marino 	void
testIeof(f)1156*86d7f5d3SJohn Marino testIeof(f)
1157*86d7f5d3SJohn Marino 	FILE *f;
1158*86d7f5d3SJohn Marino {
1159*86d7f5d3SJohn Marino 	testIerror(f);
1160*86d7f5d3SJohn Marino 	if (feof(f))
1161*86d7f5d3SJohn Marino 		Ieof();
1162*86d7f5d3SJohn Marino }
Irewind(f)1163*86d7f5d3SJohn Marino void Irewind(f) FILE *f; { if (fseek(f,0L,SEEK_SET) != 0) Ierror(); }
1164*86d7f5d3SJohn Marino #endif
1165*86d7f5d3SJohn Marino 
Orewind(f)1166*86d7f5d3SJohn Marino void Orewind(f) FILE *f; { if (fseek(f,0L,SEEK_SET) != 0) Oerror(); }
1167*86d7f5d3SJohn Marino 
aflush(f)1168*86d7f5d3SJohn Marino void aflush(f) FILE *f; { if (fflush(f) != 0) Oerror(); }
eflush()1169*86d7f5d3SJohn Marino void eflush() { if (fflush(stderr)!=0 && !Oerrloop) Oerror(); }
oflush()1170*86d7f5d3SJohn Marino void oflush()
1171*86d7f5d3SJohn Marino {
1172*86d7f5d3SJohn Marino 	if (fflush(workstdout ? workstdout : stdout) != 0  &&  !Oerrloop)
1173*86d7f5d3SJohn Marino 		Oerror();
1174*86d7f5d3SJohn Marino }
1175*86d7f5d3SJohn Marino 
1176*86d7f5d3SJohn Marino 	void
fatcleanup(already_newline)1177*86d7f5d3SJohn Marino fatcleanup(already_newline)
1178*86d7f5d3SJohn Marino 	int already_newline;
1179*86d7f5d3SJohn Marino {
1180*86d7f5d3SJohn Marino 	VOID fprintf(stderr, already_newline+"\n%s aborted\n", cmdid);
1181*86d7f5d3SJohn Marino 	exiterr();
1182*86d7f5d3SJohn Marino }
1183*86d7f5d3SJohn Marino 
1184*86d7f5d3SJohn Marino 	static void
startsay(s,t)1185*86d7f5d3SJohn Marino startsay(s, t)
1186*86d7f5d3SJohn Marino 	const char *s, *t;
1187*86d7f5d3SJohn Marino {
1188*86d7f5d3SJohn Marino 	oflush();
1189*86d7f5d3SJohn Marino 	if (s)
1190*86d7f5d3SJohn Marino 	    aprintf(stderr, "%s: %s: %s", cmdid, s, t);
1191*86d7f5d3SJohn Marino 	else
1192*86d7f5d3SJohn Marino 	    aprintf(stderr, "%s: %s", cmdid, t);
1193*86d7f5d3SJohn Marino }
1194*86d7f5d3SJohn Marino 
1195*86d7f5d3SJohn Marino 	static void
fatsay(s)1196*86d7f5d3SJohn Marino fatsay(s)
1197*86d7f5d3SJohn Marino 	char const *s;
1198*86d7f5d3SJohn Marino {
1199*86d7f5d3SJohn Marino 	startsay(s, "");
1200*86d7f5d3SJohn Marino }
1201*86d7f5d3SJohn Marino 
1202*86d7f5d3SJohn Marino 	static void
errsay(s)1203*86d7f5d3SJohn Marino errsay(s)
1204*86d7f5d3SJohn Marino 	char const *s;
1205*86d7f5d3SJohn Marino {
1206*86d7f5d3SJohn Marino 	fatsay(s);
1207*86d7f5d3SJohn Marino 	nerror++;
1208*86d7f5d3SJohn Marino }
1209*86d7f5d3SJohn Marino 
1210*86d7f5d3SJohn Marino 	static void
warnsay(s)1211*86d7f5d3SJohn Marino warnsay(s)
1212*86d7f5d3SJohn Marino 	char const *s;
1213*86d7f5d3SJohn Marino {
1214*86d7f5d3SJohn Marino 	startsay(s, "warning: ");
1215*86d7f5d3SJohn Marino }
1216*86d7f5d3SJohn Marino 
eerror(s)1217*86d7f5d3SJohn Marino void eerror(s) char const *s; { enerror(errno,s); }
1218*86d7f5d3SJohn Marino 
1219*86d7f5d3SJohn Marino 	void
enerror(e,s)1220*86d7f5d3SJohn Marino enerror(e,s)
1221*86d7f5d3SJohn Marino 	int e;
1222*86d7f5d3SJohn Marino 	char const *s;
1223*86d7f5d3SJohn Marino {
1224*86d7f5d3SJohn Marino 	errsay((char const*)0);
1225*86d7f5d3SJohn Marino 	errno = e;
1226*86d7f5d3SJohn Marino 	perror(s);
1227*86d7f5d3SJohn Marino 	eflush();
1228*86d7f5d3SJohn Marino }
1229*86d7f5d3SJohn Marino 
efaterror(s)1230*86d7f5d3SJohn Marino void efaterror(s) char const *s; { enfaterror(errno,s); }
1231*86d7f5d3SJohn Marino 
1232*86d7f5d3SJohn Marino 	void
enfaterror(e,s)1233*86d7f5d3SJohn Marino enfaterror(e,s)
1234*86d7f5d3SJohn Marino 	int e;
1235*86d7f5d3SJohn Marino 	char const *s;
1236*86d7f5d3SJohn Marino {
1237*86d7f5d3SJohn Marino 	fatsay((char const*)0);
1238*86d7f5d3SJohn Marino 	errno = e;
1239*86d7f5d3SJohn Marino 	perror(s);
1240*86d7f5d3SJohn Marino 	fatcleanup(true);
1241*86d7f5d3SJohn Marino }
1242*86d7f5d3SJohn Marino 
1243*86d7f5d3SJohn Marino #if has_prototypes
1244*86d7f5d3SJohn Marino 	void
error(char const * format,...)1245*86d7f5d3SJohn Marino error(char const *format,...)
1246*86d7f5d3SJohn Marino #else
1247*86d7f5d3SJohn Marino 	/*VARARGS1*/ void error(format, va_alist) char const *format; va_dcl
1248*86d7f5d3SJohn Marino #endif
1249*86d7f5d3SJohn Marino /* non-fatal error */
1250*86d7f5d3SJohn Marino {
1251*86d7f5d3SJohn Marino 	va_list args;
1252*86d7f5d3SJohn Marino 	errsay((char const*)0);
1253*86d7f5d3SJohn Marino 	vararg_start(args, format);
1254*86d7f5d3SJohn Marino 	fvfprintf(stderr, format, args);
1255*86d7f5d3SJohn Marino 	va_end(args);
1256*86d7f5d3SJohn Marino 	afputc('\n',stderr);
1257*86d7f5d3SJohn Marino 	eflush();
1258*86d7f5d3SJohn Marino }
1259*86d7f5d3SJohn Marino 
1260*86d7f5d3SJohn Marino #if has_prototypes
1261*86d7f5d3SJohn Marino 	void
rcserror(char const * format,...)1262*86d7f5d3SJohn Marino rcserror(char const *format,...)
1263*86d7f5d3SJohn Marino #else
1264*86d7f5d3SJohn Marino 	/*VARARGS1*/ void rcserror(format, va_alist) char const *format; va_dcl
1265*86d7f5d3SJohn Marino #endif
1266*86d7f5d3SJohn Marino /* non-fatal RCS file error */
1267*86d7f5d3SJohn Marino {
1268*86d7f5d3SJohn Marino 	va_list args;
1269*86d7f5d3SJohn Marino 	errsay(RCSname);
1270*86d7f5d3SJohn Marino 	vararg_start(args, format);
1271*86d7f5d3SJohn Marino 	fvfprintf(stderr, format, args);
1272*86d7f5d3SJohn Marino 	va_end(args);
1273*86d7f5d3SJohn Marino 	afputc('\n',stderr);
1274*86d7f5d3SJohn Marino 	eflush();
1275*86d7f5d3SJohn Marino }
1276*86d7f5d3SJohn Marino 
1277*86d7f5d3SJohn Marino #if has_prototypes
1278*86d7f5d3SJohn Marino 	void
workerror(char const * format,...)1279*86d7f5d3SJohn Marino workerror(char const *format,...)
1280*86d7f5d3SJohn Marino #else
1281*86d7f5d3SJohn Marino 	/*VARARGS1*/ void workerror(format, va_alist) char const *format; va_dcl
1282*86d7f5d3SJohn Marino #endif
1283*86d7f5d3SJohn Marino /* non-fatal working file error */
1284*86d7f5d3SJohn Marino {
1285*86d7f5d3SJohn Marino 	va_list args;
1286*86d7f5d3SJohn Marino 	errsay(workname);
1287*86d7f5d3SJohn Marino 	vararg_start(args, format);
1288*86d7f5d3SJohn Marino 	fvfprintf(stderr, format, args);
1289*86d7f5d3SJohn Marino 	va_end(args);
1290*86d7f5d3SJohn Marino 	afputc('\n',stderr);
1291*86d7f5d3SJohn Marino 	eflush();
1292*86d7f5d3SJohn Marino }
1293*86d7f5d3SJohn Marino 
1294*86d7f5d3SJohn Marino #if has_prototypes
1295*86d7f5d3SJohn Marino 	void
fatserror(char const * format,...)1296*86d7f5d3SJohn Marino fatserror(char const *format,...)
1297*86d7f5d3SJohn Marino #else
1298*86d7f5d3SJohn Marino 	/*VARARGS1*/ void
1299*86d7f5d3SJohn Marino 	fatserror(format, va_alist) char const *format; va_dcl
1300*86d7f5d3SJohn Marino #endif
1301*86d7f5d3SJohn Marino /* fatal RCS file syntax error */
1302*86d7f5d3SJohn Marino {
1303*86d7f5d3SJohn Marino 	va_list args;
1304*86d7f5d3SJohn Marino 	oflush();
1305*86d7f5d3SJohn Marino 	VOID fprintf(stderr, "%s: %s:%ld: ", cmdid, RCSname, rcsline);
1306*86d7f5d3SJohn Marino 	vararg_start(args, format);
1307*86d7f5d3SJohn Marino 	fvfprintf(stderr, format, args);
1308*86d7f5d3SJohn Marino 	va_end(args);
1309*86d7f5d3SJohn Marino 	fatcleanup(false);
1310*86d7f5d3SJohn Marino }
1311*86d7f5d3SJohn Marino 
1312*86d7f5d3SJohn Marino #if has_prototypes
1313*86d7f5d3SJohn Marino 	void
faterror(char const * format,...)1314*86d7f5d3SJohn Marino faterror(char const *format,...)
1315*86d7f5d3SJohn Marino #else
1316*86d7f5d3SJohn Marino 	/*VARARGS1*/ void faterror(format, va_alist)
1317*86d7f5d3SJohn Marino 	char const *format; va_dcl
1318*86d7f5d3SJohn Marino #endif
1319*86d7f5d3SJohn Marino /* fatal error, terminates program after cleanup */
1320*86d7f5d3SJohn Marino {
1321*86d7f5d3SJohn Marino 	va_list args;
1322*86d7f5d3SJohn Marino 	fatsay((char const*)0);
1323*86d7f5d3SJohn Marino 	vararg_start(args, format);
1324*86d7f5d3SJohn Marino 	fvfprintf(stderr, format, args);
1325*86d7f5d3SJohn Marino 	va_end(args);
1326*86d7f5d3SJohn Marino 	fatcleanup(false);
1327*86d7f5d3SJohn Marino }
1328*86d7f5d3SJohn Marino 
1329*86d7f5d3SJohn Marino #if has_prototypes
1330*86d7f5d3SJohn Marino 	void
rcsfaterror(char const * format,...)1331*86d7f5d3SJohn Marino rcsfaterror(char const *format,...)
1332*86d7f5d3SJohn Marino #else
1333*86d7f5d3SJohn Marino 	/*VARARGS1*/ void rcsfaterror(format, va_alist)
1334*86d7f5d3SJohn Marino 	char const *format; va_dcl
1335*86d7f5d3SJohn Marino #endif
1336*86d7f5d3SJohn Marino /* fatal RCS file error, terminates program after cleanup */
1337*86d7f5d3SJohn Marino {
1338*86d7f5d3SJohn Marino 	va_list args;
1339*86d7f5d3SJohn Marino 	fatsay(RCSname);
1340*86d7f5d3SJohn Marino 	vararg_start(args, format);
1341*86d7f5d3SJohn Marino 	fvfprintf(stderr, format, args);
1342*86d7f5d3SJohn Marino 	va_end(args);
1343*86d7f5d3SJohn Marino 	fatcleanup(false);
1344*86d7f5d3SJohn Marino }
1345*86d7f5d3SJohn Marino 
1346*86d7f5d3SJohn Marino #if has_prototypes
1347*86d7f5d3SJohn Marino 	void
warn(char const * format,...)1348*86d7f5d3SJohn Marino warn(char const *format,...)
1349*86d7f5d3SJohn Marino #else
1350*86d7f5d3SJohn Marino 	/*VARARGS1*/ void warn(format, va_alist) char const *format; va_dcl
1351*86d7f5d3SJohn Marino #endif
1352*86d7f5d3SJohn Marino /* warning */
1353*86d7f5d3SJohn Marino {
1354*86d7f5d3SJohn Marino 	va_list args;
1355*86d7f5d3SJohn Marino 	if (!quietflag) {
1356*86d7f5d3SJohn Marino 		warnsay((char *)0);
1357*86d7f5d3SJohn Marino 		vararg_start(args, format);
1358*86d7f5d3SJohn Marino 		fvfprintf(stderr, format, args);
1359*86d7f5d3SJohn Marino 		va_end(args);
1360*86d7f5d3SJohn Marino 		afputc('\n', stderr);
1361*86d7f5d3SJohn Marino 		eflush();
1362*86d7f5d3SJohn Marino 	}
1363*86d7f5d3SJohn Marino }
1364*86d7f5d3SJohn Marino 
1365*86d7f5d3SJohn Marino #if has_prototypes
1366*86d7f5d3SJohn Marino 	void
rcswarn(char const * format,...)1367*86d7f5d3SJohn Marino rcswarn(char const *format,...)
1368*86d7f5d3SJohn Marino #else
1369*86d7f5d3SJohn Marino 	/*VARARGS1*/ void rcswarn(format, va_alist) char const *format; va_dcl
1370*86d7f5d3SJohn Marino #endif
1371*86d7f5d3SJohn Marino /* RCS file warning */
1372*86d7f5d3SJohn Marino {
1373*86d7f5d3SJohn Marino 	va_list args;
1374*86d7f5d3SJohn Marino 	if (!quietflag) {
1375*86d7f5d3SJohn Marino 		warnsay(RCSname);
1376*86d7f5d3SJohn Marino 		vararg_start(args, format);
1377*86d7f5d3SJohn Marino 		fvfprintf(stderr, format, args);
1378*86d7f5d3SJohn Marino 		va_end(args);
1379*86d7f5d3SJohn Marino 		afputc('\n', stderr);
1380*86d7f5d3SJohn Marino 		eflush();
1381*86d7f5d3SJohn Marino 	}
1382*86d7f5d3SJohn Marino }
1383*86d7f5d3SJohn Marino 
1384*86d7f5d3SJohn Marino #if has_prototypes
1385*86d7f5d3SJohn Marino 	void
workwarn(char const * format,...)1386*86d7f5d3SJohn Marino workwarn(char const *format,...)
1387*86d7f5d3SJohn Marino #else
1388*86d7f5d3SJohn Marino 	/*VARARGS1*/ void workwarn(format, va_alist) char const *format; va_dcl
1389*86d7f5d3SJohn Marino #endif
1390*86d7f5d3SJohn Marino /* working file warning */
1391*86d7f5d3SJohn Marino {
1392*86d7f5d3SJohn Marino 	va_list args;
1393*86d7f5d3SJohn Marino 	if (!quietflag) {
1394*86d7f5d3SJohn Marino 		warnsay(workname);
1395*86d7f5d3SJohn Marino 		vararg_start(args, format);
1396*86d7f5d3SJohn Marino 		fvfprintf(stderr, format, args);
1397*86d7f5d3SJohn Marino 		va_end(args);
1398*86d7f5d3SJohn Marino 		afputc('\n', stderr);
1399*86d7f5d3SJohn Marino 		eflush();
1400*86d7f5d3SJohn Marino 	}
1401*86d7f5d3SJohn Marino }
1402*86d7f5d3SJohn Marino 
1403*86d7f5d3SJohn Marino 	void
redefined(c)1404*86d7f5d3SJohn Marino redefined(c)
1405*86d7f5d3SJohn Marino 	int c;
1406*86d7f5d3SJohn Marino {
1407*86d7f5d3SJohn Marino 	warn("redefinition of -%c option", c);
1408*86d7f5d3SJohn Marino }
1409*86d7f5d3SJohn Marino 
1410*86d7f5d3SJohn Marino #if has_prototypes
1411*86d7f5d3SJohn Marino 	void
diagnose(char const * format,...)1412*86d7f5d3SJohn Marino diagnose(char const *format,...)
1413*86d7f5d3SJohn Marino #else
1414*86d7f5d3SJohn Marino 	/*VARARGS1*/ void diagnose(format, va_alist) char const *format; va_dcl
1415*86d7f5d3SJohn Marino #endif
1416*86d7f5d3SJohn Marino /* prints a diagnostic message */
1417*86d7f5d3SJohn Marino /* Unlike the other routines, it does not append a newline. */
1418*86d7f5d3SJohn Marino /* This lets some callers suppress the newline, and is faster */
1419*86d7f5d3SJohn Marino /* in implementations that flush stderr just at the end of each printf. */
1420*86d7f5d3SJohn Marino {
1421*86d7f5d3SJohn Marino 	va_list args;
1422*86d7f5d3SJohn Marino         if (!quietflag) {
1423*86d7f5d3SJohn Marino 		oflush();
1424*86d7f5d3SJohn Marino 		vararg_start(args, format);
1425*86d7f5d3SJohn Marino 		fvfprintf(stderr, format, args);
1426*86d7f5d3SJohn Marino 		va_end(args);
1427*86d7f5d3SJohn Marino 		eflush();
1428*86d7f5d3SJohn Marino         }
1429*86d7f5d3SJohn Marino }
1430*86d7f5d3SJohn Marino 
1431*86d7f5d3SJohn Marino 
1432*86d7f5d3SJohn Marino 
1433*86d7f5d3SJohn Marino 	void
afputc(c,f)1434*86d7f5d3SJohn Marino afputc(c, f)
1435*86d7f5d3SJohn Marino /* afputc(c,f); acts like aputc_(c,f) but is smaller and slower.  */
1436*86d7f5d3SJohn Marino 	int c;
1437*86d7f5d3SJohn Marino 	register FILE *f;
1438*86d7f5d3SJohn Marino {
1439*86d7f5d3SJohn Marino 	aputc_(c,f)
1440*86d7f5d3SJohn Marino }
1441*86d7f5d3SJohn Marino 
1442*86d7f5d3SJohn Marino 
1443*86d7f5d3SJohn Marino 	void
aputs(s,iop)1444*86d7f5d3SJohn Marino aputs(s, iop)
1445*86d7f5d3SJohn Marino 	char const *s;
1446*86d7f5d3SJohn Marino 	FILE *iop;
1447*86d7f5d3SJohn Marino /* Function: Put string s on file iop, abort on error.
1448*86d7f5d3SJohn Marino  */
1449*86d7f5d3SJohn Marino {
1450*86d7f5d3SJohn Marino #if has_fputs
1451*86d7f5d3SJohn Marino 	if (fputs(s, iop) < 0)
1452*86d7f5d3SJohn Marino 		Oerror();
1453*86d7f5d3SJohn Marino #else
1454*86d7f5d3SJohn Marino 	awrite(s, strlen(s), iop);
1455*86d7f5d3SJohn Marino #endif
1456*86d7f5d3SJohn Marino }
1457*86d7f5d3SJohn Marino 
1458*86d7f5d3SJohn Marino 
1459*86d7f5d3SJohn Marino 
1460*86d7f5d3SJohn Marino 	void
1461*86d7f5d3SJohn Marino #if has_prototypes
fvfprintf(FILE * stream,char const * format,va_list args)1462*86d7f5d3SJohn Marino fvfprintf(FILE *stream, char const *format, va_list args)
1463*86d7f5d3SJohn Marino #else
1464*86d7f5d3SJohn Marino 	fvfprintf(stream,format,args) FILE *stream; char *format; va_list args;
1465*86d7f5d3SJohn Marino #endif
1466*86d7f5d3SJohn Marino /* like vfprintf, except abort program on error */
1467*86d7f5d3SJohn Marino {
1468*86d7f5d3SJohn Marino #if has_vfprintf
1469*86d7f5d3SJohn Marino 	if (vfprintf(stream, format, args) < 0)
1470*86d7f5d3SJohn Marino 		Oerror();
1471*86d7f5d3SJohn Marino #else
1472*86d7f5d3SJohn Marino #	if has__doprintf
1473*86d7f5d3SJohn Marino 		_doprintf(stream, format, args);
1474*86d7f5d3SJohn Marino #	else
1475*86d7f5d3SJohn Marino #	if has__doprnt
1476*86d7f5d3SJohn Marino 		_doprnt(format, args, stream);
1477*86d7f5d3SJohn Marino #	else
1478*86d7f5d3SJohn Marino 		int *a = (int *)args;
1479*86d7f5d3SJohn Marino 		VOID fprintf(stream, format,
1480*86d7f5d3SJohn Marino 			a[0], a[1], a[2], a[3], a[4],
1481*86d7f5d3SJohn Marino 			a[5], a[6], a[7], a[8], a[9]
1482*86d7f5d3SJohn Marino 		);
1483*86d7f5d3SJohn Marino #	endif
1484*86d7f5d3SJohn Marino #	endif
1485*86d7f5d3SJohn Marino 	if (ferror(stream))
1486*86d7f5d3SJohn Marino 		Oerror();
1487*86d7f5d3SJohn Marino #endif
1488*86d7f5d3SJohn Marino }
1489*86d7f5d3SJohn Marino 
1490*86d7f5d3SJohn Marino #if has_prototypes
1491*86d7f5d3SJohn Marino 	void
aprintf(FILE * iop,char const * fmt,...)1492*86d7f5d3SJohn Marino aprintf(FILE *iop, char const *fmt, ...)
1493*86d7f5d3SJohn Marino #else
1494*86d7f5d3SJohn Marino 	/*VARARGS2*/ void
1495*86d7f5d3SJohn Marino aprintf(iop, fmt, va_alist)
1496*86d7f5d3SJohn Marino FILE *iop;
1497*86d7f5d3SJohn Marino char const *fmt;
1498*86d7f5d3SJohn Marino va_dcl
1499*86d7f5d3SJohn Marino #endif
1500*86d7f5d3SJohn Marino /* Function: formatted output. Same as fprintf in stdio,
1501*86d7f5d3SJohn Marino  * but aborts program on error
1502*86d7f5d3SJohn Marino  */
1503*86d7f5d3SJohn Marino {
1504*86d7f5d3SJohn Marino 	va_list ap;
1505*86d7f5d3SJohn Marino 	vararg_start(ap, fmt);
1506*86d7f5d3SJohn Marino 	fvfprintf(iop, fmt, ap);
1507*86d7f5d3SJohn Marino 	va_end(ap);
1508*86d7f5d3SJohn Marino }
1509*86d7f5d3SJohn Marino 
1510*86d7f5d3SJohn Marino 
1511*86d7f5d3SJohn Marino 
1512*86d7f5d3SJohn Marino #ifdef LEXDB
1513*86d7f5d3SJohn Marino /* test program reading a stream of lexemes and printing the tokens.
1514*86d7f5d3SJohn Marino  */
1515*86d7f5d3SJohn Marino 
1516*86d7f5d3SJohn Marino 
1517*86d7f5d3SJohn Marino 
1518*86d7f5d3SJohn Marino 	int
main(argc,argv)1519*86d7f5d3SJohn Marino main(argc,argv)
1520*86d7f5d3SJohn Marino int argc; char * argv[];
1521*86d7f5d3SJohn Marino {
1522*86d7f5d3SJohn Marino         cmdid="lextest";
1523*86d7f5d3SJohn Marino         if (argc<2) {
1524*86d7f5d3SJohn Marino 		aputs("No input file\n",stderr);
1525*86d7f5d3SJohn Marino 		exitmain(EXIT_FAILURE);
1526*86d7f5d3SJohn Marino         }
1527*86d7f5d3SJohn Marino 	if (!(finptr=Iopen(argv[1], FOPEN_R, (struct stat*)0))) {
1528*86d7f5d3SJohn Marino 		faterror("can't open input file %s",argv[1]);
1529*86d7f5d3SJohn Marino         }
1530*86d7f5d3SJohn Marino         Lexinit();
1531*86d7f5d3SJohn Marino 	while (!eoflex()) {
1532*86d7f5d3SJohn Marino         switch (nexttok) {
1533*86d7f5d3SJohn Marino 
1534*86d7f5d3SJohn Marino         case ID:
1535*86d7f5d3SJohn Marino                 VOID printf("ID: %s",NextString);
1536*86d7f5d3SJohn Marino                 break;
1537*86d7f5d3SJohn Marino 
1538*86d7f5d3SJohn Marino         case NUM:
1539*86d7f5d3SJohn Marino 		if (hshenter)
1540*86d7f5d3SJohn Marino                    VOID printf("NUM: %s, index: %d",nexthsh->num, nexthsh-hshtab);
1541*86d7f5d3SJohn Marino                 else
1542*86d7f5d3SJohn Marino                    VOID printf("NUM, unentered: %s",NextString);
1543*86d7f5d3SJohn Marino                 hshenter = !hshenter; /*alternate between dates and numbers*/
1544*86d7f5d3SJohn Marino                 break;
1545*86d7f5d3SJohn Marino 
1546*86d7f5d3SJohn Marino         case COLON:
1547*86d7f5d3SJohn Marino                 VOID printf("COLON"); break;
1548*86d7f5d3SJohn Marino 
1549*86d7f5d3SJohn Marino         case SEMI:
1550*86d7f5d3SJohn Marino                 VOID printf("SEMI"); break;
1551*86d7f5d3SJohn Marino 
1552*86d7f5d3SJohn Marino         case STRING:
1553*86d7f5d3SJohn Marino                 readstring();
1554*86d7f5d3SJohn Marino                 VOID printf("STRING"); break;
1555*86d7f5d3SJohn Marino 
1556*86d7f5d3SJohn Marino         case UNKN:
1557*86d7f5d3SJohn Marino                 VOID printf("UNKN"); break;
1558*86d7f5d3SJohn Marino 
1559*86d7f5d3SJohn Marino         default:
1560*86d7f5d3SJohn Marino                 VOID printf("DEFAULT"); break;
1561*86d7f5d3SJohn Marino         }
1562*86d7f5d3SJohn Marino         VOID printf(" | ");
1563*86d7f5d3SJohn Marino         nextlex();
1564*86d7f5d3SJohn Marino         }
1565*86d7f5d3SJohn Marino 	exitmain(EXIT_SUCCESS);
1566*86d7f5d3SJohn Marino }
1567*86d7f5d3SJohn Marino 
exiterr()1568*86d7f5d3SJohn Marino void exiterr() { _exit(EXIT_FAILURE); }
1569*86d7f5d3SJohn Marino 
1570*86d7f5d3SJohn Marino 
1571*86d7f5d3SJohn Marino #endif
1572