1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski *
3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file
5*b1cdbd2cSJim Jagielski * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file
7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski *
11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski *
13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the
17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski * under the License.
19*b1cdbd2cSJim Jagielski *
20*b1cdbd2cSJim Jagielski *************************************************************/
21*b1cdbd2cSJim Jagielski
22*b1cdbd2cSJim Jagielski
23*b1cdbd2cSJim Jagielski
24*b1cdbd2cSJim Jagielski #include <stdio.h>
25*b1cdbd2cSJim Jagielski #include <ctype.h>
26*b1cdbd2cSJim Jagielski #include <string.h>
27*b1cdbd2cSJim Jagielski #include "cppdef.h"
28*b1cdbd2cSJim Jagielski #include "cpp.h"
29*b1cdbd2cSJim Jagielski
30*b1cdbd2cSJim Jagielski /*ER evaluate macros to pDefOut */
31*b1cdbd2cSJim Jagielski
32*b1cdbd2cSJim Jagielski /*
33*b1cdbd2cSJim Jagielski * skipnl() skips over input text to the end of the line.
34*b1cdbd2cSJim Jagielski * skipws() skips over "whitespace" (spaces or tabs), but
35*b1cdbd2cSJim Jagielski * not skip over the end of the line. It skips over
36*b1cdbd2cSJim Jagielski * TOK_SEP, however (though that shouldn't happen).
37*b1cdbd2cSJim Jagielski * scanid() reads the next token (C identifier) into token[].
38*b1cdbd2cSJim Jagielski * The caller has already read the first character of
39*b1cdbd2cSJim Jagielski * the identifier. Unlike macroid(), the token is
40*b1cdbd2cSJim Jagielski * never expanded.
41*b1cdbd2cSJim Jagielski * macroid() reads the next token (C identifier) into token[].
42*b1cdbd2cSJim Jagielski * If it is a #defined macro, it is expanded, and
43*b1cdbd2cSJim Jagielski * macroid() returns TRUE, otherwise, FALSE.
44*b1cdbd2cSJim Jagielski * catenate() Does the dirty work of token concatenation, TRUE if it did.
45*b1cdbd2cSJim Jagielski * scanstring() Reads a string from the input stream, calling
46*b1cdbd2cSJim Jagielski * a user-supplied function for each character.
47*b1cdbd2cSJim Jagielski * This function may be output() to write the
48*b1cdbd2cSJim Jagielski * string to the output file, or save() to save
49*b1cdbd2cSJim Jagielski * the string in the work buffer.
50*b1cdbd2cSJim Jagielski * scannumber() Reads a C numeric constant from the input stream,
51*b1cdbd2cSJim Jagielski * calling the user-supplied function for each
52*b1cdbd2cSJim Jagielski * character. (output() or save() as noted above.)
53*b1cdbd2cSJim Jagielski * save() Save one character in the work[] buffer.
54*b1cdbd2cSJim Jagielski * savestring() Saves a string in malloc() memory.
55*b1cdbd2cSJim Jagielski * getfile() Initialize a new FILEINFO structure, called when
56*b1cdbd2cSJim Jagielski * #include opens a new file, or a macro is to be
57*b1cdbd2cSJim Jagielski * expanded.
58*b1cdbd2cSJim Jagielski * getmem() Get a specified number of bytes from malloc memory.
59*b1cdbd2cSJim Jagielski * output() Write one character to stdout (calling PUTCHAR) --
60*b1cdbd2cSJim Jagielski * implemented as a function so its address may be
61*b1cdbd2cSJim Jagielski * passed to scanstring() and scannumber().
62*b1cdbd2cSJim Jagielski * lookid() Scans the next token (identifier) from the input
63*b1cdbd2cSJim Jagielski * stream. Looks for it in the #defined symbol table.
64*b1cdbd2cSJim Jagielski * Returns a pointer to the definition, if found, or NULL
65*b1cdbd2cSJim Jagielski * if not present. The identifier is stored in token[].
66*b1cdbd2cSJim Jagielski * defnedel() Define enter/delete subroutine. Updates the
67*b1cdbd2cSJim Jagielski * symbol table.
68*b1cdbd2cSJim Jagielski * get() Read the next byte from the current input stream,
69*b1cdbd2cSJim Jagielski * handling end of (macro/file) input and embedded
70*b1cdbd2cSJim Jagielski * comments appropriately. Note that the global
71*b1cdbd2cSJim Jagielski * instring is -- essentially -- a parameter to get().
72*b1cdbd2cSJim Jagielski * cget() Like get(), but skip over TOK_SEP.
73*b1cdbd2cSJim Jagielski * unget() Push last gotten character back on the input stream.
74*b1cdbd2cSJim Jagielski * cerror(), cwarn(), cfatal(), cierror(), ciwarn()
75*b1cdbd2cSJim Jagielski * These routines format an print messages to the user.
76*b1cdbd2cSJim Jagielski * cerror & cwarn take a format and a single string argument.
77*b1cdbd2cSJim Jagielski * cierror & ciwarn take a format and a single int (char) argument.
78*b1cdbd2cSJim Jagielski * cfatal takes a format and a single string argument.
79*b1cdbd2cSJim Jagielski */
80*b1cdbd2cSJim Jagielski
81*b1cdbd2cSJim Jagielski /*
82*b1cdbd2cSJim Jagielski * This table must be rewritten for a non-Ascii machine.
83*b1cdbd2cSJim Jagielski *
84*b1cdbd2cSJim Jagielski * Note that several "non-visible" characters have special meaning:
85*b1cdbd2cSJim Jagielski * Hex 1D DEF_MAGIC -- a flag to prevent #define recursion.
86*b1cdbd2cSJim Jagielski * Hex 1E TOK_SEP -- a delimiter for token concatenation
87*b1cdbd2cSJim Jagielski * Hex 1F COM_SEP -- a zero-width whitespace for comment concatenation
88*b1cdbd2cSJim Jagielski */
89*b1cdbd2cSJim Jagielski #if TOK_SEP != 0x1E || COM_SEP != 0x1F || DEF_MAGIC != 0x1D
90*b1cdbd2cSJim Jagielski << error type table is not correct >>
91*b1cdbd2cSJim Jagielski #endif
92*b1cdbd2cSJim Jagielski
93*b1cdbd2cSJim Jagielski #if OK_DOLLAR
94*b1cdbd2cSJim Jagielski #define DOL LET
95*b1cdbd2cSJim Jagielski #else
96*b1cdbd2cSJim Jagielski #define DOL 000
97*b1cdbd2cSJim Jagielski #endif
98*b1cdbd2cSJim Jagielski
99*b1cdbd2cSJim Jagielski #ifdef EBCDIC
100*b1cdbd2cSJim Jagielski
101*b1cdbd2cSJim Jagielski char type[256] = { /* Character type codes Hex */
102*b1cdbd2cSJim Jagielski END, 000, 000, 000, 000, SPA, 000, 000, /* 00 */
103*b1cdbd2cSJim Jagielski 000, 000, 000, 000, 000, 000, 000, 000, /* 08 */
104*b1cdbd2cSJim Jagielski 000, 000, 000, 000, 000, 000, 000, 000, /* 10 */
105*b1cdbd2cSJim Jagielski 000, 000, 000, 000, 000, LET, 000, SPA, /* 18 */
106*b1cdbd2cSJim Jagielski 000, 000, 000, 000, 000, 000, 000, 000, /* 20 */
107*b1cdbd2cSJim Jagielski 000, 000, 000, 000, 000, 000, 000, 000, /* 28 */
108*b1cdbd2cSJim Jagielski 000, 000, 000, 000, 000, 000, 000, 000, /* 30 */
109*b1cdbd2cSJim Jagielski 000, 000, 000, 000, 000, 000, 000, 000, /* 38 */
110*b1cdbd2cSJim Jagielski SPA, 000, 000, 000, 000, 000, 000, 000, /* 40 */
111*b1cdbd2cSJim Jagielski 000, 000, 000, DOT, OP_LT,OP_LPA,OP_ADD, OP_OR, /* 48 .<(+| */
112*b1cdbd2cSJim Jagielski OP_AND, 000, 000, 000, 000, 000, 000, 000, /* 50 & */
113*b1cdbd2cSJim Jagielski 000, 000,OP_NOT, DOL,OP_MUL,OP_RPA, 000,OP_XOR, /* 58 !$*);^ */
114*b1cdbd2cSJim Jagielski OP_SUB,OP_DIV, 000, 000, 000, 000, 000, 000, /* 60 -/ */
115*b1cdbd2cSJim Jagielski 000, 000, 000, 000,OP_MOD, LET, OP_GT,OP_QUE, /* 68 ,%_>? */
116*b1cdbd2cSJim Jagielski 000, 000, 000, 000, 000, 000, 000, 000, /* 70 */
117*b1cdbd2cSJim Jagielski 000, 000,OP_COL, 000, 000, QUO, OP_EQ, QUO, /* 78 `:#@'=" */
118*b1cdbd2cSJim Jagielski 000, LET, LET, LET, LET, LET, LET, LET, /* 80 abcdefg */
119*b1cdbd2cSJim Jagielski LET, LET, 000, 000, 000, 000, 000, 000, /* 88 hi */
120*b1cdbd2cSJim Jagielski 000, LET, LET, LET, LET, LET, LET, LET, /* 90 jklmnop */
121*b1cdbd2cSJim Jagielski LET, LET, 000, 000, 000, 000, 000, 000, /* 98 qr */
122*b1cdbd2cSJim Jagielski 000,OP_NOT, LET, LET, LET, LET, LET, LET, /* A0 ~stuvwx */
123*b1cdbd2cSJim Jagielski LET, LET, 000, 000, 000, 000, 000, 000, /* A8 yz [ */
124*b1cdbd2cSJim Jagielski 000, 000, 000, 000, 000, 000, 000, 000, /* B0 */
125*b1cdbd2cSJim Jagielski 000, 000, 000, 000, 000, 000, 000, 000, /* B8 ] */
126*b1cdbd2cSJim Jagielski 000, LET, LET, LET, LET, LET, LET, LET, /* C0 {ABCDEFG */
127*b1cdbd2cSJim Jagielski LET, LET, 000, 000, 000, 000, 000, 000, /* C8 HI */
128*b1cdbd2cSJim Jagielski 000, LET, LET, LET, LET, LET, LET, LET, /* D0 }JKLMNOP */
129*b1cdbd2cSJim Jagielski LET, LET, 000, 000, 000, 000, 000, 000, /* D8 QR */
130*b1cdbd2cSJim Jagielski BSH, 000, LET, LET, LET, LET, LET, LET, /* E0 \ STUVWX */
131*b1cdbd2cSJim Jagielski LET, LET, 000, 000, 000, 000, 000, 000, /* E8 YZ */
132*b1cdbd2cSJim Jagielski DIG, DIG, DIG, DIG, DIG, DIG, DIG, DIG, /* F0 01234567 */
133*b1cdbd2cSJim Jagielski DIG, DIG, 000, 000, 000, 000, 000, 000, /* F8 89 */
134*b1cdbd2cSJim Jagielski };
135*b1cdbd2cSJim Jagielski
136*b1cdbd2cSJim Jagielski #else
137*b1cdbd2cSJim Jagielski
138*b1cdbd2cSJim Jagielski char type[256] = { /* Character type codes Hex */
139*b1cdbd2cSJim Jagielski END, 000, 000, 000, 000, 000, 000, 000, /* 00 */
140*b1cdbd2cSJim Jagielski 000, SPA, 000, 000, 000, 000, 000, 000, /* 08 */
141*b1cdbd2cSJim Jagielski 000, 000, 000, 000, 000, 000, 000, 000, /* 10 */
142*b1cdbd2cSJim Jagielski 000, 000, 000, 000, 000, LET, 000, SPA, /* 18 */
143*b1cdbd2cSJim Jagielski SPA,OP_NOT, QUO, 000, DOL,OP_MOD,OP_AND, QUO, /* 20 !"#$%&' */
144*b1cdbd2cSJim Jagielski OP_LPA,OP_RPA,OP_MUL,OP_ADD, 000,OP_SUB, DOT,OP_DIV, /* 28 ()*+,-./ */
145*b1cdbd2cSJim Jagielski DIG, DIG, DIG, DIG, DIG, DIG, DIG, DIG, /* 30 01234567 */
146*b1cdbd2cSJim Jagielski DIG, DIG,OP_COL, 000, OP_LT, OP_EQ, OP_GT,OP_QUE, /* 38 89:;<=>? */
147*b1cdbd2cSJim Jagielski 000, LET, LET, LET, LET, LET, LET, LET, /* 40 @ABCDEFG */
148*b1cdbd2cSJim Jagielski LET, LET, LET, LET, LET, LET, LET, LET, /* 48 HIJKLMNO */
149*b1cdbd2cSJim Jagielski LET, LET, LET, LET, LET, LET, LET, LET, /* 50 PQRSTUVW */
150*b1cdbd2cSJim Jagielski LET, LET, LET, 000, BSH, 000,OP_XOR, LET, /* 58 XYZ[\]^_ */
151*b1cdbd2cSJim Jagielski 000, LET, LET, LET, LET, LET, LET, LET, /* 60 `abcdefg */
152*b1cdbd2cSJim Jagielski LET, LET, LET, LET, LET, LET, LET, LET, /* 68 hijklmno */
153*b1cdbd2cSJim Jagielski LET, LET, LET, LET, LET, LET, LET, LET, /* 70 pqrstuvw */
154*b1cdbd2cSJim Jagielski LET, LET, LET, 000, OP_OR, 000,OP_NOT, 000, /* 78 xyz{|}~ */
155*b1cdbd2cSJim Jagielski 000, 000, 000, 000, 000, 000, 000, 000, /* 80 .. FF */
156*b1cdbd2cSJim Jagielski 000, 000, 000, 000, 000, 000, 000, 000, /* 80 .. FF */
157*b1cdbd2cSJim Jagielski 000, 000, 000, 000, 000, 000, 000, 000, /* 80 .. FF */
158*b1cdbd2cSJim Jagielski 000, 000, 000, 000, 000, 000, 000, 000, /* 80 .. FF */
159*b1cdbd2cSJim Jagielski 000, 000, 000, 000, 000, 000, 000, 000, /* 80 .. FF */
160*b1cdbd2cSJim Jagielski 000, 000, 000, 000, 000, 000, 000, 000, /* 80 .. FF */
161*b1cdbd2cSJim Jagielski 000, 000, 000, 000, 000, 000, 000, 000, /* 80 .. FF */
162*b1cdbd2cSJim Jagielski 000, 000, 000, 000, 000, 000, 000, 000, /* 80 .. FF */
163*b1cdbd2cSJim Jagielski };
164*b1cdbd2cSJim Jagielski
165*b1cdbd2cSJim Jagielski #endif
166*b1cdbd2cSJim Jagielski
167*b1cdbd2cSJim Jagielski
168*b1cdbd2cSJim Jagielski /*
169*b1cdbd2cSJim Jagielski * C P P S y m b o l T a b l e s
170*b1cdbd2cSJim Jagielski */
171*b1cdbd2cSJim Jagielski
172*b1cdbd2cSJim Jagielski /*
173*b1cdbd2cSJim Jagielski * SBSIZE defines the number of hash-table slots for the symbol table.
174*b1cdbd2cSJim Jagielski * It must be a power of 2.
175*b1cdbd2cSJim Jagielski */
176*b1cdbd2cSJim Jagielski #ifndef SBSIZE
177*b1cdbd2cSJim Jagielski #define SBSIZE 64
178*b1cdbd2cSJim Jagielski #endif
179*b1cdbd2cSJim Jagielski #define SBMASK (SBSIZE - 1)
180*b1cdbd2cSJim Jagielski #if (SBSIZE ^ SBMASK) != ((SBSIZE * 2) - 1)
181*b1cdbd2cSJim Jagielski << error, SBSIZE must be a power of 2 >>
182*b1cdbd2cSJim Jagielski #endif
183*b1cdbd2cSJim Jagielski
184*b1cdbd2cSJim Jagielski
185*b1cdbd2cSJim Jagielski static DEFBUF *symtab[SBSIZE]; /* Symbol table queue headers */
186*b1cdbd2cSJim Jagielski
InitCpp6()187*b1cdbd2cSJim Jagielski void InitCpp6()
188*b1cdbd2cSJim Jagielski {
189*b1cdbd2cSJim Jagielski int i;
190*b1cdbd2cSJim Jagielski for( i = 0; i < SBSIZE; i++ )
191*b1cdbd2cSJim Jagielski symtab[ i ] = NULL;
192*b1cdbd2cSJim Jagielski }
193*b1cdbd2cSJim Jagielski
194*b1cdbd2cSJim Jagielski
195*b1cdbd2cSJim Jagielski
skipnl()196*b1cdbd2cSJim Jagielski void skipnl()
197*b1cdbd2cSJim Jagielski /*
198*b1cdbd2cSJim Jagielski * Skip to the end of the current input line.
199*b1cdbd2cSJim Jagielski */
200*b1cdbd2cSJim Jagielski {
201*b1cdbd2cSJim Jagielski register int c;
202*b1cdbd2cSJim Jagielski
203*b1cdbd2cSJim Jagielski do { /* Skip to newline */
204*b1cdbd2cSJim Jagielski c = get();
205*b1cdbd2cSJim Jagielski } while (c != '\n' && c != EOF_CHAR);
206*b1cdbd2cSJim Jagielski }
207*b1cdbd2cSJim Jagielski
208*b1cdbd2cSJim Jagielski int
skipws()209*b1cdbd2cSJim Jagielski skipws()
210*b1cdbd2cSJim Jagielski /*
211*b1cdbd2cSJim Jagielski * Skip over whitespace
212*b1cdbd2cSJim Jagielski */
213*b1cdbd2cSJim Jagielski {
214*b1cdbd2cSJim Jagielski register int c;
215*b1cdbd2cSJim Jagielski
216*b1cdbd2cSJim Jagielski do { /* Skip whitespace */
217*b1cdbd2cSJim Jagielski c = get();
218*b1cdbd2cSJim Jagielski #if COMMENT_INVISIBLE
219*b1cdbd2cSJim Jagielski } while (type[c] == SPA || c == COM_SEP);
220*b1cdbd2cSJim Jagielski #else
221*b1cdbd2cSJim Jagielski } while (type[c] == SPA);
222*b1cdbd2cSJim Jagielski #endif
223*b1cdbd2cSJim Jagielski return (c);
224*b1cdbd2cSJim Jagielski }
225*b1cdbd2cSJim Jagielski
scanid(int c)226*b1cdbd2cSJim Jagielski void scanid(int c)
227*b1cdbd2cSJim Jagielski /*
228*b1cdbd2cSJim Jagielski * Get the next token (an id) into the token buffer.
229*b1cdbd2cSJim Jagielski * Note: this code is duplicated in lookid().
230*b1cdbd2cSJim Jagielski * Change one, change both.
231*b1cdbd2cSJim Jagielski */
232*b1cdbd2cSJim Jagielski {
233*b1cdbd2cSJim Jagielski register char *bp;
234*b1cdbd2cSJim Jagielski
235*b1cdbd2cSJim Jagielski if (c == DEF_MAGIC) /* Eat the magic token */
236*b1cdbd2cSJim Jagielski c = get(); /* undefiner. */
237*b1cdbd2cSJim Jagielski bp = token;
238*b1cdbd2cSJim Jagielski do {
239*b1cdbd2cSJim Jagielski if (bp < &token[IDMAX]) /* token dim is IDMAX+1 */
240*b1cdbd2cSJim Jagielski *bp++ = (char)c;
241*b1cdbd2cSJim Jagielski c = get();
242*b1cdbd2cSJim Jagielski } while (type[c] == LET || type[c] == DIG);
243*b1cdbd2cSJim Jagielski unget();
244*b1cdbd2cSJim Jagielski *bp = EOS;
245*b1cdbd2cSJim Jagielski }
246*b1cdbd2cSJim Jagielski
247*b1cdbd2cSJim Jagielski int
macroid(int c)248*b1cdbd2cSJim Jagielski macroid(int c)
249*b1cdbd2cSJim Jagielski /*
250*b1cdbd2cSJim Jagielski * If c is a letter, scan the id. if it's #defined, expand it and scan
251*b1cdbd2cSJim Jagielski * the next character and try again.
252*b1cdbd2cSJim Jagielski *
253*b1cdbd2cSJim Jagielski * Else, return the character. If type[c] is a LET, the token is in token.
254*b1cdbd2cSJim Jagielski */
255*b1cdbd2cSJim Jagielski {
256*b1cdbd2cSJim Jagielski register DEFBUF *dp;
257*b1cdbd2cSJim Jagielski
258*b1cdbd2cSJim Jagielski if (infile != NULL && infile->fp != NULL)
259*b1cdbd2cSJim Jagielski recursion = 0;
260*b1cdbd2cSJim Jagielski while (type[c] == LET && (dp = lookid(c)) != NULL) {
261*b1cdbd2cSJim Jagielski expand(dp);
262*b1cdbd2cSJim Jagielski c = get();
263*b1cdbd2cSJim Jagielski }
264*b1cdbd2cSJim Jagielski return (c);
265*b1cdbd2cSJim Jagielski }
266*b1cdbd2cSJim Jagielski
267*b1cdbd2cSJim Jagielski int
catenate()268*b1cdbd2cSJim Jagielski catenate()
269*b1cdbd2cSJim Jagielski /*
270*b1cdbd2cSJim Jagielski * A token was just read (via macroid).
271*b1cdbd2cSJim Jagielski * If the next character is TOK_SEP, concatenate the next token
272*b1cdbd2cSJim Jagielski * return TRUE -- which should recall macroid after refreshing
273*b1cdbd2cSJim Jagielski * macroid's argument. If it is not TOK_SEP, unget() the character
274*b1cdbd2cSJim Jagielski * and return FALSE.
275*b1cdbd2cSJim Jagielski */
276*b1cdbd2cSJim Jagielski {
277*b1cdbd2cSJim Jagielski register int c;
278*b1cdbd2cSJim Jagielski register char *token1;
279*b1cdbd2cSJim Jagielski
280*b1cdbd2cSJim Jagielski #if OK_CONCAT
281*b1cdbd2cSJim Jagielski if (get() != TOK_SEP) { /* Token concatenation */
282*b1cdbd2cSJim Jagielski unget();
283*b1cdbd2cSJim Jagielski return (FALSE);
284*b1cdbd2cSJim Jagielski }
285*b1cdbd2cSJim Jagielski else {
286*b1cdbd2cSJim Jagielski token1 = savestring(token); /* Save first token */
287*b1cdbd2cSJim Jagielski c = macroid(get()); /* Scan next token */
288*b1cdbd2cSJim Jagielski switch(type[c]) { /* What was it? */
289*b1cdbd2cSJim Jagielski case LET: /* An identifier, ... */
290*b1cdbd2cSJim Jagielski if (strlen(token1) + strlen(token) >= NWORK)
291*b1cdbd2cSJim Jagielski cfatal("work buffer overflow doing %s #", token1);
292*b1cdbd2cSJim Jagielski sprintf(work, "%s%s", token1, token);
293*b1cdbd2cSJim Jagielski break;
294*b1cdbd2cSJim Jagielski
295*b1cdbd2cSJim Jagielski case DIG: /* A digit string */
296*b1cdbd2cSJim Jagielski strcpy(work, token1);
297*b1cdbd2cSJim Jagielski workp = work + strlen(work);
298*b1cdbd2cSJim Jagielski do {
299*b1cdbd2cSJim Jagielski save(c);
300*b1cdbd2cSJim Jagielski } while ((c = get()) != TOK_SEP);
301*b1cdbd2cSJim Jagielski /*
302*b1cdbd2cSJim Jagielski * The trailing TOK_SEP is no longer needed.
303*b1cdbd2cSJim Jagielski */
304*b1cdbd2cSJim Jagielski save(EOS);
305*b1cdbd2cSJim Jagielski break;
306*b1cdbd2cSJim Jagielski
307*b1cdbd2cSJim Jagielski default: /* An error, ... */
308*b1cdbd2cSJim Jagielski #if ! COMMENT_INVISIBLE
309*b1cdbd2cSJim Jagielski if (isprint(c))
310*b1cdbd2cSJim Jagielski cierror("Strange character '%c' after #", c);
311*b1cdbd2cSJim Jagielski else
312*b1cdbd2cSJim Jagielski cierror("Strange character (%d.) after #", c);
313*b1cdbd2cSJim Jagielski #endif
314*b1cdbd2cSJim Jagielski strcpy(work, token1);
315*b1cdbd2cSJim Jagielski unget();
316*b1cdbd2cSJim Jagielski break;
317*b1cdbd2cSJim Jagielski }
318*b1cdbd2cSJim Jagielski /*
319*b1cdbd2cSJim Jagielski * work has the concatenated token and token1 has
320*b1cdbd2cSJim Jagielski * the first token (no longer needed). Unget the
321*b1cdbd2cSJim Jagielski * new (concatenated) token after freeing token1.
322*b1cdbd2cSJim Jagielski * Finally, setup to read the new token.
323*b1cdbd2cSJim Jagielski */
324*b1cdbd2cSJim Jagielski free(token1); /* Free up memory */
325*b1cdbd2cSJim Jagielski ungetstring(work); /* Unget the new thing, */
326*b1cdbd2cSJim Jagielski return (TRUE);
327*b1cdbd2cSJim Jagielski }
328*b1cdbd2cSJim Jagielski #else
329*b1cdbd2cSJim Jagielski return (FALSE); /* Not supported */
330*b1cdbd2cSJim Jagielski #endif
331*b1cdbd2cSJim Jagielski }
332*b1cdbd2cSJim Jagielski
333*b1cdbd2cSJim Jagielski int
scanstring(int delim,void (* outfun)(int))334*b1cdbd2cSJim Jagielski scanstring(int delim,
335*b1cdbd2cSJim Jagielski #ifndef _NO_PROTO
336*b1cdbd2cSJim Jagielski void (*outfun)( int ) /* BP */ /* Output function */
337*b1cdbd2cSJim Jagielski #else
338*b1cdbd2cSJim Jagielski void (*outfun)() /* BP */
339*b1cdbd2cSJim Jagielski #endif
340*b1cdbd2cSJim Jagielski )
341*b1cdbd2cSJim Jagielski /*
342*b1cdbd2cSJim Jagielski * Scan off a string. Warning if terminated by newline or EOF.
343*b1cdbd2cSJim Jagielski * outfun() outputs the character -- to a buffer if in a macro.
344*b1cdbd2cSJim Jagielski * TRUE if ok, FALSE if error.
345*b1cdbd2cSJim Jagielski */
346*b1cdbd2cSJim Jagielski {
347*b1cdbd2cSJim Jagielski register int c;
348*b1cdbd2cSJim Jagielski
349*b1cdbd2cSJim Jagielski instring = TRUE; /* Don't strip comments */
350*b1cdbd2cSJim Jagielski (*outfun)(delim);
351*b1cdbd2cSJim Jagielski while ((c = get()) != delim
352*b1cdbd2cSJim Jagielski && c != '\n'
353*b1cdbd2cSJim Jagielski && c != EOF_CHAR) {
354*b1cdbd2cSJim Jagielski
355*b1cdbd2cSJim Jagielski if (c != DEF_MAGIC)
356*b1cdbd2cSJim Jagielski (*outfun)(c);
357*b1cdbd2cSJim Jagielski if (c == '\\')
358*b1cdbd2cSJim Jagielski (*outfun)(get());
359*b1cdbd2cSJim Jagielski }
360*b1cdbd2cSJim Jagielski instring = FALSE;
361*b1cdbd2cSJim Jagielski if (c == delim) {
362*b1cdbd2cSJim Jagielski (*outfun)(c);
363*b1cdbd2cSJim Jagielski return (TRUE);
364*b1cdbd2cSJim Jagielski }
365*b1cdbd2cSJim Jagielski else {
366*b1cdbd2cSJim Jagielski cerror("Unterminated string", NULLST);
367*b1cdbd2cSJim Jagielski unget();
368*b1cdbd2cSJim Jagielski return (FALSE);
369*b1cdbd2cSJim Jagielski }
370*b1cdbd2cSJim Jagielski }
371*b1cdbd2cSJim Jagielski
scannumber(int c,register void (* outfun)(int))372*b1cdbd2cSJim Jagielski void scannumber(int c,
373*b1cdbd2cSJim Jagielski #ifndef _NO_PROTO
374*b1cdbd2cSJim Jagielski register void (*outfun)( int ) /* BP */ /* Output/store func */
375*b1cdbd2cSJim Jagielski #else
376*b1cdbd2cSJim Jagielski register void (*outfun)() /* BP */
377*b1cdbd2cSJim Jagielski #endif
378*b1cdbd2cSJim Jagielski )
379*b1cdbd2cSJim Jagielski /*
380*b1cdbd2cSJim Jagielski * Process a number. We know that c is from 0 to 9 or dot.
381*b1cdbd2cSJim Jagielski * Algorithm from Dave Conroy's Decus C.
382*b1cdbd2cSJim Jagielski */
383*b1cdbd2cSJim Jagielski {
384*b1cdbd2cSJim Jagielski register int radix; /* 8, 10, or 16 */
385*b1cdbd2cSJim Jagielski int expseen; /* 'e' seen in floater */
386*b1cdbd2cSJim Jagielski int signseen; /* '+' or '-' seen */
387*b1cdbd2cSJim Jagielski int octal89; /* For bad octal test */
388*b1cdbd2cSJim Jagielski int dotflag; /* TRUE if '.' was seen */
389*b1cdbd2cSJim Jagielski
390*b1cdbd2cSJim Jagielski expseen = FALSE; /* No exponent seen yet */
391*b1cdbd2cSJim Jagielski signseen = TRUE; /* No +/- allowed yet */
392*b1cdbd2cSJim Jagielski octal89 = FALSE; /* No bad octal yet */
393*b1cdbd2cSJim Jagielski radix = 10; /* Assume decimal */
394*b1cdbd2cSJim Jagielski if ((dotflag = (c == '.')) != FALSE) { /* . something? */
395*b1cdbd2cSJim Jagielski (*outfun)('.'); /* Always out the dot */
396*b1cdbd2cSJim Jagielski if (type[(c = get())] != DIG) { /* If not a float numb, */
397*b1cdbd2cSJim Jagielski unget(); /* Rescan strange char */
398*b1cdbd2cSJim Jagielski return; /* All done for now */
399*b1cdbd2cSJim Jagielski }
400*b1cdbd2cSJim Jagielski } /* End of float test */
401*b1cdbd2cSJim Jagielski else if (c == '0') { /* Octal or hex? */
402*b1cdbd2cSJim Jagielski (*outfun)(c); /* Stuff initial zero */
403*b1cdbd2cSJim Jagielski radix = 8; /* Assume it's octal */
404*b1cdbd2cSJim Jagielski c = get(); /* Look for an 'x' */
405*b1cdbd2cSJim Jagielski if (c == 'x' || c == 'X') { /* Did we get one? */
406*b1cdbd2cSJim Jagielski radix = 16; /* Remember new radix */
407*b1cdbd2cSJim Jagielski (*outfun)(c); /* Stuff the 'x' */
408*b1cdbd2cSJim Jagielski c = get(); /* Get next character */
409*b1cdbd2cSJim Jagielski }
410*b1cdbd2cSJim Jagielski }
411*b1cdbd2cSJim Jagielski for (;;) { /* Process curr. char. */
412*b1cdbd2cSJim Jagielski /*
413*b1cdbd2cSJim Jagielski * Note that this algorithm accepts "012e4" and "03.4"
414*b1cdbd2cSJim Jagielski * as legitimate floating-point numbers.
415*b1cdbd2cSJim Jagielski */
416*b1cdbd2cSJim Jagielski if (radix != 16 && (c == 'e' || c == 'E')) {
417*b1cdbd2cSJim Jagielski if (expseen) /* Already saw 'E'? */
418*b1cdbd2cSJim Jagielski break; /* Exit loop, bad nbr. */
419*b1cdbd2cSJim Jagielski expseen = TRUE; /* Set exponent seen */
420*b1cdbd2cSJim Jagielski signseen = FALSE; /* We can read '+' now */
421*b1cdbd2cSJim Jagielski radix = 10; /* Decimal exponent */
422*b1cdbd2cSJim Jagielski }
423*b1cdbd2cSJim Jagielski else if (radix != 16 && c == '.') {
424*b1cdbd2cSJim Jagielski if (dotflag) /* Saw dot already? */
425*b1cdbd2cSJim Jagielski break; /* Exit loop, two dots */
426*b1cdbd2cSJim Jagielski dotflag = TRUE; /* Remember the dot */
427*b1cdbd2cSJim Jagielski radix = 10; /* Decimal fraction */
428*b1cdbd2cSJim Jagielski }
429*b1cdbd2cSJim Jagielski else if (c == '+' || c == '-') { /* 1.0e+10 */
430*b1cdbd2cSJim Jagielski if (signseen) /* Sign in wrong place? */
431*b1cdbd2cSJim Jagielski break; /* Exit loop, not nbr. */
432*b1cdbd2cSJim Jagielski /* signseen = TRUE; */ /* Remember we saw it */
433*b1cdbd2cSJim Jagielski }
434*b1cdbd2cSJim Jagielski else { /* Check the digit */
435*b1cdbd2cSJim Jagielski switch (c) {
436*b1cdbd2cSJim Jagielski case '8': case '9': /* Sometimes wrong */
437*b1cdbd2cSJim Jagielski octal89 = TRUE; /* Do check later */
438*b1cdbd2cSJim Jagielski case '0': case '1': case '2': case '3':
439*b1cdbd2cSJim Jagielski case '4': case '5': case '6': case '7':
440*b1cdbd2cSJim Jagielski break; /* Always ok */
441*b1cdbd2cSJim Jagielski
442*b1cdbd2cSJim Jagielski case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
443*b1cdbd2cSJim Jagielski case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
444*b1cdbd2cSJim Jagielski if (radix == 16) /* Alpha's are ok only */
445*b1cdbd2cSJim Jagielski break; /* if reading hex. */
446*b1cdbd2cSJim Jagielski default: /* At number end */
447*b1cdbd2cSJim Jagielski goto done; /* Break from for loop */
448*b1cdbd2cSJim Jagielski } /* End of switch */
449*b1cdbd2cSJim Jagielski } /* End general case */
450*b1cdbd2cSJim Jagielski (*outfun)(c); /* Accept the character */
451*b1cdbd2cSJim Jagielski signseen = TRUE; /* Don't read sign now */
452*b1cdbd2cSJim Jagielski c = get(); /* Read another char */
453*b1cdbd2cSJim Jagielski } /* End of scan loop */
454*b1cdbd2cSJim Jagielski /*
455*b1cdbd2cSJim Jagielski * When we break out of the scan loop, c contains the first
456*b1cdbd2cSJim Jagielski * character (maybe) not in the number. If the number is an
457*b1cdbd2cSJim Jagielski * integer, allow a trailing 'L' for long and/or a trailing 'U'
458*b1cdbd2cSJim Jagielski * for unsigned. If not those, push the trailing character back
459*b1cdbd2cSJim Jagielski * on the input stream. Floating point numbers accept a trailing
460*b1cdbd2cSJim Jagielski * 'L' for "long double".
461*b1cdbd2cSJim Jagielski */
462*b1cdbd2cSJim Jagielski done: if (dotflag || expseen) { /* Floating point? */
463*b1cdbd2cSJim Jagielski if (c == 'l' || c == 'L') {
464*b1cdbd2cSJim Jagielski (*outfun)(c);
465*b1cdbd2cSJim Jagielski c = get(); /* Ungotten later */
466*b1cdbd2cSJim Jagielski }
467*b1cdbd2cSJim Jagielski }
468*b1cdbd2cSJim Jagielski else { /* Else it's an integer */
469*b1cdbd2cSJim Jagielski /*
470*b1cdbd2cSJim Jagielski * We know that dotflag and expseen are both zero, now:
471*b1cdbd2cSJim Jagielski * dotflag signals "saw 'L'", and
472*b1cdbd2cSJim Jagielski * expseen signals "saw 'U'".
473*b1cdbd2cSJim Jagielski */
474*b1cdbd2cSJim Jagielski for (;;) {
475*b1cdbd2cSJim Jagielski switch (c) {
476*b1cdbd2cSJim Jagielski case 'l':
477*b1cdbd2cSJim Jagielski case 'L':
478*b1cdbd2cSJim Jagielski if (dotflag)
479*b1cdbd2cSJim Jagielski goto nomore;
480*b1cdbd2cSJim Jagielski dotflag = TRUE;
481*b1cdbd2cSJim Jagielski break;
482*b1cdbd2cSJim Jagielski
483*b1cdbd2cSJim Jagielski case 'u':
484*b1cdbd2cSJim Jagielski case 'U':
485*b1cdbd2cSJim Jagielski if (expseen)
486*b1cdbd2cSJim Jagielski goto nomore;
487*b1cdbd2cSJim Jagielski expseen = TRUE;
488*b1cdbd2cSJim Jagielski break;
489*b1cdbd2cSJim Jagielski
490*b1cdbd2cSJim Jagielski default:
491*b1cdbd2cSJim Jagielski goto nomore;
492*b1cdbd2cSJim Jagielski }
493*b1cdbd2cSJim Jagielski (*outfun)(c); /* Got 'L' or 'U'. */
494*b1cdbd2cSJim Jagielski c = get(); /* Look at next, too. */
495*b1cdbd2cSJim Jagielski }
496*b1cdbd2cSJim Jagielski }
497*b1cdbd2cSJim Jagielski nomore: unget(); /* Not part of a number */
498*b1cdbd2cSJim Jagielski if (octal89 && radix == 8)
499*b1cdbd2cSJim Jagielski cwarn("Illegal digit in octal number", NULLST);
500*b1cdbd2cSJim Jagielski }
501*b1cdbd2cSJim Jagielski
save(int c)502*b1cdbd2cSJim Jagielski void save(int c)
503*b1cdbd2cSJim Jagielski {
504*b1cdbd2cSJim Jagielski if (workp >= &work[NWORK]) {
505*b1cdbd2cSJim Jagielski work[NWORK-1] = '\0';
506*b1cdbd2cSJim Jagielski cfatal("Work buffer overflow: %s", work);
507*b1cdbd2cSJim Jagielski }
508*b1cdbd2cSJim Jagielski else *workp++ = (char)c;
509*b1cdbd2cSJim Jagielski }
510*b1cdbd2cSJim Jagielski
511*b1cdbd2cSJim Jagielski char *
savestring(char * text)512*b1cdbd2cSJim Jagielski savestring(char* text)
513*b1cdbd2cSJim Jagielski /*
514*b1cdbd2cSJim Jagielski * Store a string into free memory.
515*b1cdbd2cSJim Jagielski */
516*b1cdbd2cSJim Jagielski {
517*b1cdbd2cSJim Jagielski register char *result;
518*b1cdbd2cSJim Jagielski
519*b1cdbd2cSJim Jagielski result = getmem(strlen(text) + 1);
520*b1cdbd2cSJim Jagielski strcpy(result, text);
521*b1cdbd2cSJim Jagielski return (result);
522*b1cdbd2cSJim Jagielski }
523*b1cdbd2cSJim Jagielski
524*b1cdbd2cSJim Jagielski FILEINFO *
getfile(int bufsize,char * name)525*b1cdbd2cSJim Jagielski getfile(int bufsize, char* name)
526*b1cdbd2cSJim Jagielski /*
527*b1cdbd2cSJim Jagielski * Common FILEINFO buffer initialization for a new file or macro.
528*b1cdbd2cSJim Jagielski */
529*b1cdbd2cSJim Jagielski {
530*b1cdbd2cSJim Jagielski register FILEINFO *file;
531*b1cdbd2cSJim Jagielski register int size;
532*b1cdbd2cSJim Jagielski
533*b1cdbd2cSJim Jagielski size = strlen(name); /* File/macro name */
534*b1cdbd2cSJim Jagielski file = (FILEINFO *) getmem(sizeof (FILEINFO) + bufsize + size);
535*b1cdbd2cSJim Jagielski file->parent = infile; /* Chain files together */
536*b1cdbd2cSJim Jagielski file->fp = NULL; /* No file yet */
537*b1cdbd2cSJim Jagielski file->filename = savestring(name); /* Save file/macro name */
538*b1cdbd2cSJim Jagielski file->progname = NULL; /* No #line seen yet */
539*b1cdbd2cSJim Jagielski file->unrecur = 0; /* No macro fixup */
540*b1cdbd2cSJim Jagielski file->bptr = file->buffer; /* Initialize line ptr */
541*b1cdbd2cSJim Jagielski file->buffer[0] = EOS; /* Force first read */
542*b1cdbd2cSJim Jagielski file->line = 0; /* (Not used just yet) */
543*b1cdbd2cSJim Jagielski if (infile != NULL) /* If #include file */
544*b1cdbd2cSJim Jagielski infile->line = line; /* Save current line */
545*b1cdbd2cSJim Jagielski infile = file; /* New current file */
546*b1cdbd2cSJim Jagielski line = 1; /* Note first line */
547*b1cdbd2cSJim Jagielski return (file); /* All done. */
548*b1cdbd2cSJim Jagielski }
549*b1cdbd2cSJim Jagielski
550*b1cdbd2cSJim Jagielski char *
getmem(int size)551*b1cdbd2cSJim Jagielski getmem(int size)
552*b1cdbd2cSJim Jagielski /*
553*b1cdbd2cSJim Jagielski * Get a block of free memory.
554*b1cdbd2cSJim Jagielski */
555*b1cdbd2cSJim Jagielski {
556*b1cdbd2cSJim Jagielski register char *result;
557*b1cdbd2cSJim Jagielski
558*b1cdbd2cSJim Jagielski if ((result = malloc((unsigned) size)) == NULL)
559*b1cdbd2cSJim Jagielski cfatal("Out of memory", NULLST);
560*b1cdbd2cSJim Jagielski return (result);
561*b1cdbd2cSJim Jagielski }
562*b1cdbd2cSJim Jagielski
563*b1cdbd2cSJim Jagielski
564*b1cdbd2cSJim Jagielski DEFBUF *
lookid(int c)565*b1cdbd2cSJim Jagielski lookid(int c)
566*b1cdbd2cSJim Jagielski /*
567*b1cdbd2cSJim Jagielski * Look for the next token in the symbol table. Returns token in "token".
568*b1cdbd2cSJim Jagielski * If found, returns the table pointer; Else returns NULL.
569*b1cdbd2cSJim Jagielski */
570*b1cdbd2cSJim Jagielski {
571*b1cdbd2cSJim Jagielski register int nhash;
572*b1cdbd2cSJim Jagielski register DEFBUF *dp;
573*b1cdbd2cSJim Jagielski register char *np;
574*b1cdbd2cSJim Jagielski int temp = 0;
575*b1cdbd2cSJim Jagielski int isrecurse; /* For #define foo foo */
576*b1cdbd2cSJim Jagielski
577*b1cdbd2cSJim Jagielski np = token;
578*b1cdbd2cSJim Jagielski nhash = 0;
579*b1cdbd2cSJim Jagielski if (0 != (isrecurse = (c == DEF_MAGIC))) /* If recursive macro */
580*b1cdbd2cSJim Jagielski c = get(); /* hack, skip DEF_MAGIC */
581*b1cdbd2cSJim Jagielski do {
582*b1cdbd2cSJim Jagielski if (np < &token[IDMAX]) { /* token dim is IDMAX+1 */
583*b1cdbd2cSJim Jagielski *np++ = (char)c; /* Store token byte */
584*b1cdbd2cSJim Jagielski nhash += c; /* Update hash value */
585*b1cdbd2cSJim Jagielski }
586*b1cdbd2cSJim Jagielski c = get(); /* And get another byte */
587*b1cdbd2cSJim Jagielski } while (type[c] == LET || type[c] == DIG);
588*b1cdbd2cSJim Jagielski unget(); /* Rescan terminator */
589*b1cdbd2cSJim Jagielski *np = EOS; /* Terminate token */
590*b1cdbd2cSJim Jagielski if (isrecurse) /* Recursive definition */
591*b1cdbd2cSJim Jagielski return (NULL); /* undefined just now */
592*b1cdbd2cSJim Jagielski nhash += (np - token); /* Fix hash value */
593*b1cdbd2cSJim Jagielski dp = symtab[nhash & SBMASK]; /* Starting bucket */
594*b1cdbd2cSJim Jagielski while (dp != (DEFBUF *) NULL) { /* Search symbol table */
595*b1cdbd2cSJim Jagielski if (dp->hash == nhash /* Fast precheck */
596*b1cdbd2cSJim Jagielski && (temp = strcmp(dp->name, token)) >= 0)
597*b1cdbd2cSJim Jagielski break;
598*b1cdbd2cSJim Jagielski dp = dp->link; /* Nope, try next one */
599*b1cdbd2cSJim Jagielski }
600*b1cdbd2cSJim Jagielski return ((temp == 0) ? dp : NULL);
601*b1cdbd2cSJim Jagielski }
602*b1cdbd2cSJim Jagielski
603*b1cdbd2cSJim Jagielski DEFBUF *
defendel(char * name,int delete)604*b1cdbd2cSJim Jagielski defendel(char* name, int delete)
605*b1cdbd2cSJim Jagielski /*
606*b1cdbd2cSJim Jagielski * Enter this name in the lookup table (delete = FALSE)
607*b1cdbd2cSJim Jagielski * or delete this name (delete = TRUE).
608*b1cdbd2cSJim Jagielski * Returns a pointer to the define block (delete = FALSE)
609*b1cdbd2cSJim Jagielski * Returns NULL if the symbol wasn't defined (delete = TRUE).
610*b1cdbd2cSJim Jagielski */
611*b1cdbd2cSJim Jagielski {
612*b1cdbd2cSJim Jagielski register DEFBUF *dp;
613*b1cdbd2cSJim Jagielski register DEFBUF **prevp;
614*b1cdbd2cSJim Jagielski register char *np;
615*b1cdbd2cSJim Jagielski int nhash;
616*b1cdbd2cSJim Jagielski int temp;
617*b1cdbd2cSJim Jagielski int size;
618*b1cdbd2cSJim Jagielski
619*b1cdbd2cSJim Jagielski for (nhash = 0, np = name; *np != EOS;)
620*b1cdbd2cSJim Jagielski nhash += *np++;
621*b1cdbd2cSJim Jagielski size = (np - name);
622*b1cdbd2cSJim Jagielski nhash += size;
623*b1cdbd2cSJim Jagielski prevp = &symtab[nhash & SBMASK];
624*b1cdbd2cSJim Jagielski while ((dp = *prevp) != (DEFBUF *) NULL) {
625*b1cdbd2cSJim Jagielski if (dp->hash == nhash
626*b1cdbd2cSJim Jagielski && (temp = strcmp(dp->name, name)) >= 0) {
627*b1cdbd2cSJim Jagielski if (temp > 0)
628*b1cdbd2cSJim Jagielski dp = NULL; /* Not found */
629*b1cdbd2cSJim Jagielski else {
630*b1cdbd2cSJim Jagielski *prevp = dp->link; /* Found, unlink and */
631*b1cdbd2cSJim Jagielski if (dp->repl != NULL) /* Free the replacement */
632*b1cdbd2cSJim Jagielski free(dp->repl); /* if any, and then */
633*b1cdbd2cSJim Jagielski free((char *) dp); /* Free the symbol */
634*b1cdbd2cSJim Jagielski }
635*b1cdbd2cSJim Jagielski break;
636*b1cdbd2cSJim Jagielski }
637*b1cdbd2cSJim Jagielski prevp = &dp->link;
638*b1cdbd2cSJim Jagielski }
639*b1cdbd2cSJim Jagielski if (!delete) {
640*b1cdbd2cSJim Jagielski dp = (DEFBUF *) getmem(sizeof (DEFBUF) + size);
641*b1cdbd2cSJim Jagielski dp->link = *prevp;
642*b1cdbd2cSJim Jagielski *prevp = dp;
643*b1cdbd2cSJim Jagielski dp->hash = nhash;
644*b1cdbd2cSJim Jagielski dp->repl = NULL;
645*b1cdbd2cSJim Jagielski dp->nargs = 0;
646*b1cdbd2cSJim Jagielski strcpy(dp->name, name);
647*b1cdbd2cSJim Jagielski }
648*b1cdbd2cSJim Jagielski return (dp);
649*b1cdbd2cSJim Jagielski }
650*b1cdbd2cSJim Jagielski
651*b1cdbd2cSJim Jagielski #if OSL_DEBUG_LEVEL > 1
652*b1cdbd2cSJim Jagielski
dumpdef(char * why)653*b1cdbd2cSJim Jagielski void dumpdef(char *why)
654*b1cdbd2cSJim Jagielski {
655*b1cdbd2cSJim Jagielski register DEFBUF *dp;
656*b1cdbd2cSJim Jagielski register DEFBUF **syp;
657*b1cdbd2cSJim Jagielski FILE *pRememberOut = NULL;
658*b1cdbd2cSJim Jagielski
659*b1cdbd2cSJim Jagielski if ( bDumpDefs ) /*ER */
660*b1cdbd2cSJim Jagielski {
661*b1cdbd2cSJim Jagielski pRememberOut = pCppOut;
662*b1cdbd2cSJim Jagielski pCppOut = pDefOut;
663*b1cdbd2cSJim Jagielski }
664*b1cdbd2cSJim Jagielski fprintf( pCppOut, "CPP symbol table dump %s\n", why);
665*b1cdbd2cSJim Jagielski for (syp = symtab; syp < &symtab[SBSIZE]; syp++) {
666*b1cdbd2cSJim Jagielski if ((dp = *syp) != (DEFBUF *) NULL) {
667*b1cdbd2cSJim Jagielski fprintf( pCppOut, "symtab[%d]\n", (syp - symtab));
668*b1cdbd2cSJim Jagielski do {
669*b1cdbd2cSJim Jagielski dumpadef((char *) NULL, dp);
670*b1cdbd2cSJim Jagielski } while ((dp = dp->link) != (DEFBUF *) NULL);
671*b1cdbd2cSJim Jagielski }
672*b1cdbd2cSJim Jagielski }
673*b1cdbd2cSJim Jagielski if ( bDumpDefs )
674*b1cdbd2cSJim Jagielski {
675*b1cdbd2cSJim Jagielski fprintf( pCppOut, "\n");
676*b1cdbd2cSJim Jagielski pCppOut = pRememberOut;
677*b1cdbd2cSJim Jagielski }
678*b1cdbd2cSJim Jagielski }
679*b1cdbd2cSJim Jagielski
dumpadef(char * why,register DEFBUF * dp)680*b1cdbd2cSJim Jagielski void dumpadef(char *why, register DEFBUF *dp)
681*b1cdbd2cSJim Jagielski {
682*b1cdbd2cSJim Jagielski register char *cp;
683*b1cdbd2cSJim Jagielski register int c;
684*b1cdbd2cSJim Jagielski FILE *pRememberOut = NULL;
685*b1cdbd2cSJim Jagielski
686*b1cdbd2cSJim Jagielski /*ER dump #define's to pDefOut */
687*b1cdbd2cSJim Jagielski if ( bDumpDefs )
688*b1cdbd2cSJim Jagielski {
689*b1cdbd2cSJim Jagielski pRememberOut = pCppOut;
690*b1cdbd2cSJim Jagielski pCppOut = pDefOut;
691*b1cdbd2cSJim Jagielski }
692*b1cdbd2cSJim Jagielski fprintf( pCppOut, " \"%s\" [%d]", dp->name, dp->nargs);
693*b1cdbd2cSJim Jagielski if (why != NULL)
694*b1cdbd2cSJim Jagielski fprintf( pCppOut, " (%s)", why);
695*b1cdbd2cSJim Jagielski if (dp->repl != NULL) {
696*b1cdbd2cSJim Jagielski fprintf( pCppOut, " => ");
697*b1cdbd2cSJim Jagielski for (cp = dp->repl; (c = *cp++ & 0xFF) != EOS;) {
698*b1cdbd2cSJim Jagielski #ifdef SOLAR
699*b1cdbd2cSJim Jagielski if (c == DEL) {
700*b1cdbd2cSJim Jagielski c = *cp++ & 0xFF;
701*b1cdbd2cSJim Jagielski if( c == EOS ) break;
702*b1cdbd2cSJim Jagielski fprintf( pCppOut, "<%%%d>", c - MAC_PARM);
703*b1cdbd2cSJim Jagielski }
704*b1cdbd2cSJim Jagielski #else
705*b1cdbd2cSJim Jagielski if (c >= MAC_PARM && c <= (MAC_PARM + PAR_MAC))
706*b1cdbd2cSJim Jagielski fprintf( pCppOut, "<%%%d>", c - MAC_PARM);
707*b1cdbd2cSJim Jagielski #endif
708*b1cdbd2cSJim Jagielski else if (isprint(c) || c == '\n' || c == '\t')
709*b1cdbd2cSJim Jagielski PUTCHAR(c);
710*b1cdbd2cSJim Jagielski else if (c < ' ')
711*b1cdbd2cSJim Jagielski fprintf( pCppOut, "<^%c>", c + '@');
712*b1cdbd2cSJim Jagielski else
713*b1cdbd2cSJim Jagielski fprintf( pCppOut, "<\\0%o>", c);
714*b1cdbd2cSJim Jagielski }
715*b1cdbd2cSJim Jagielski /*ER evaluate macros to pDefOut */
716*b1cdbd2cSJim Jagielski #ifdef EVALDEFS
717*b1cdbd2cSJim Jagielski if ( bDumpDefs && !bIsInEval && dp->nargs <= 0 )
718*b1cdbd2cSJim Jagielski {
719*b1cdbd2cSJim Jagielski FILEINFO *infileSave = infile;
720*b1cdbd2cSJim Jagielski char *tokenSave = savestring( token );
721*b1cdbd2cSJim Jagielski char *workSave = savestring( work );
722*b1cdbd2cSJim Jagielski int lineSave = line;
723*b1cdbd2cSJim Jagielski int wronglineSave = wrongline;
724*b1cdbd2cSJim Jagielski int recursionSave = recursion;
725*b1cdbd2cSJim Jagielski FILEINFO *file;
726*b1cdbd2cSJim Jagielski EVALTYPE valEval;
727*b1cdbd2cSJim Jagielski
728*b1cdbd2cSJim Jagielski bIsInEval = 1;
729*b1cdbd2cSJim Jagielski infile = NULL; /* start from scrap */
730*b1cdbd2cSJim Jagielski line = 0;
731*b1cdbd2cSJim Jagielski wrongline = 0;
732*b1cdbd2cSJim Jagielski *token = EOS;
733*b1cdbd2cSJim Jagielski *work = EOS;
734*b1cdbd2cSJim Jagielski recursion = 0;
735*b1cdbd2cSJim Jagielski file = getfile( strlen( dp->repl ), dp->name );
736*b1cdbd2cSJim Jagielski strcpy( file->buffer, dp->repl );
737*b1cdbd2cSJim Jagielski fprintf( pCppOut, " ===> ");
738*b1cdbd2cSJim Jagielski nEvalOff = 0;
739*b1cdbd2cSJim Jagielski cppmain(); /* get() frees also *file */
740*b1cdbd2cSJim Jagielski valEval = 0;
741*b1cdbd2cSJim Jagielski if ( 0 == evaluate( EvalBuf, &valEval ) )
742*b1cdbd2cSJim Jagielski {
743*b1cdbd2cSJim Jagielski #ifdef EVALFLOATS
744*b1cdbd2cSJim Jagielski if ( valEval != (EVALTYPE)((long)valEval ) )
745*b1cdbd2cSJim Jagielski fprintf( pCppOut, " ==eval=> %f", valEval );
746*b1cdbd2cSJim Jagielski else
747*b1cdbd2cSJim Jagielski #endif
748*b1cdbd2cSJim Jagielski fprintf( pCppOut, " ==eval=> %ld", (long)valEval );
749*b1cdbd2cSJim Jagielski }
750*b1cdbd2cSJim Jagielski recursion = recursionSave;
751*b1cdbd2cSJim Jagielski wrongline = wronglineSave;
752*b1cdbd2cSJim Jagielski line = lineSave;
753*b1cdbd2cSJim Jagielski strcpy( work, workSave );
754*b1cdbd2cSJim Jagielski free( workSave );
755*b1cdbd2cSJim Jagielski strcpy( token, tokenSave );
756*b1cdbd2cSJim Jagielski free( tokenSave );
757*b1cdbd2cSJim Jagielski infile = infileSave;
758*b1cdbd2cSJim Jagielski bIsInEval = 0;
759*b1cdbd2cSJim Jagielski }
760*b1cdbd2cSJim Jagielski #endif
761*b1cdbd2cSJim Jagielski }
762*b1cdbd2cSJim Jagielski else {
763*b1cdbd2cSJim Jagielski fprintf( pCppOut, ", no replacement.");
764*b1cdbd2cSJim Jagielski }
765*b1cdbd2cSJim Jagielski PUTCHAR('\n');
766*b1cdbd2cSJim Jagielski if ( bDumpDefs )
767*b1cdbd2cSJim Jagielski pCppOut = pRememberOut;
768*b1cdbd2cSJim Jagielski }
769*b1cdbd2cSJim Jagielski #endif
770*b1cdbd2cSJim Jagielski
771*b1cdbd2cSJim Jagielski /*
772*b1cdbd2cSJim Jagielski * G E T
773*b1cdbd2cSJim Jagielski */
774*b1cdbd2cSJim Jagielski
775*b1cdbd2cSJim Jagielski int
get()776*b1cdbd2cSJim Jagielski get()
777*b1cdbd2cSJim Jagielski /*
778*b1cdbd2cSJim Jagielski * Return the next character from a macro or the current file.
779*b1cdbd2cSJim Jagielski * Handle end of file from #include files.
780*b1cdbd2cSJim Jagielski */
781*b1cdbd2cSJim Jagielski {
782*b1cdbd2cSJim Jagielski register int c;
783*b1cdbd2cSJim Jagielski register FILEINFO *file;
784*b1cdbd2cSJim Jagielski register int popped; /* Recursion fixup */
785*b1cdbd2cSJim Jagielski
786*b1cdbd2cSJim Jagielski popped = 0;
787*b1cdbd2cSJim Jagielski get_from_file:
788*b1cdbd2cSJim Jagielski if ((file = infile) == NULL)
789*b1cdbd2cSJim Jagielski return (EOF_CHAR);
790*b1cdbd2cSJim Jagielski newline:
791*b1cdbd2cSJim Jagielski #if 0
792*b1cdbd2cSJim Jagielski fprintf( pCppOut, "get(%s), recursion %d, line %d, bptr = %d, buffer \"%s\"\n",
793*b1cdbd2cSJim Jagielski file->filename, recursion, line,
794*b1cdbd2cSJim Jagielski file->bptr - file->buffer, file->buffer);
795*b1cdbd2cSJim Jagielski #endif
796*b1cdbd2cSJim Jagielski /*
797*b1cdbd2cSJim Jagielski * Read a character from the current input line or macro.
798*b1cdbd2cSJim Jagielski * At EOS, either finish the current macro (freeing temp.
799*b1cdbd2cSJim Jagielski * storage) or read another line from the current input file.
800*b1cdbd2cSJim Jagielski * At EOF, exit the current file (#include) or, at EOF from
801*b1cdbd2cSJim Jagielski * the cpp input file, return EOF_CHAR to finish processing.
802*b1cdbd2cSJim Jagielski */
803*b1cdbd2cSJim Jagielski if ((c = *file->bptr++ & 0xFF) == EOS) {
804*b1cdbd2cSJim Jagielski /*
805*b1cdbd2cSJim Jagielski * Nothing in current line or macro. Get next line (if
806*b1cdbd2cSJim Jagielski * input from a file), or do end of file/macro processing.
807*b1cdbd2cSJim Jagielski * In the latter case, jump back to restart from the top.
808*b1cdbd2cSJim Jagielski */
809*b1cdbd2cSJim Jagielski if (file->fp == NULL) { /* NULL if macro */
810*b1cdbd2cSJim Jagielski popped++;
811*b1cdbd2cSJim Jagielski recursion -= file->unrecur;
812*b1cdbd2cSJim Jagielski if (recursion < 0)
813*b1cdbd2cSJim Jagielski recursion = 0;
814*b1cdbd2cSJim Jagielski infile = file->parent; /* Unwind file chain */
815*b1cdbd2cSJim Jagielski }
816*b1cdbd2cSJim Jagielski else { /* Else get from a file */
817*b1cdbd2cSJim Jagielski if ((file->bptr = fgets(file->buffer, NBUFF, file->fp))
818*b1cdbd2cSJim Jagielski != NULL) {
819*b1cdbd2cSJim Jagielski #if OSL_DEBUG_LEVEL > 1
820*b1cdbd2cSJim Jagielski if (debug > 1) { /* Dump it to stdout */
821*b1cdbd2cSJim Jagielski fprintf( pCppOut, "\n#line %d (%s), %s",
822*b1cdbd2cSJim Jagielski line, file->filename, file->buffer);
823*b1cdbd2cSJim Jagielski }
824*b1cdbd2cSJim Jagielski #endif
825*b1cdbd2cSJim Jagielski goto newline; /* process the line */
826*b1cdbd2cSJim Jagielski }
827*b1cdbd2cSJim Jagielski else {
828*b1cdbd2cSJim Jagielski if( file->fp != stdin )
829*b1cdbd2cSJim Jagielski fclose(file->fp); /* Close finished file */
830*b1cdbd2cSJim Jagielski if ((infile = file->parent) != NULL) {
831*b1cdbd2cSJim Jagielski /*
832*b1cdbd2cSJim Jagielski * There is an "ungotten" newline in the current
833*b1cdbd2cSJim Jagielski * infile buffer (set there by doinclude() in
834*b1cdbd2cSJim Jagielski * cpp1.c). Thus, we know that the mainline code
835*b1cdbd2cSJim Jagielski * is skipping over blank lines and will do a
836*b1cdbd2cSJim Jagielski * #line at its convenience.
837*b1cdbd2cSJim Jagielski */
838*b1cdbd2cSJim Jagielski wrongline = TRUE; /* Need a #line now */
839*b1cdbd2cSJim Jagielski }
840*b1cdbd2cSJim Jagielski }
841*b1cdbd2cSJim Jagielski }
842*b1cdbd2cSJim Jagielski /*
843*b1cdbd2cSJim Jagielski * Free up space used by the (finished) file or macro and
844*b1cdbd2cSJim Jagielski * restart input from the parent file/macro, if any.
845*b1cdbd2cSJim Jagielski */
846*b1cdbd2cSJim Jagielski free(file->filename); /* Free name and */
847*b1cdbd2cSJim Jagielski if (file->progname != NULL) /* if a #line was seen, */
848*b1cdbd2cSJim Jagielski free(file->progname); /* free it, too. */
849*b1cdbd2cSJim Jagielski free((char *) file); /* Free file space */
850*b1cdbd2cSJim Jagielski if (infile == NULL) /* If at end of file */
851*b1cdbd2cSJim Jagielski return (EOF_CHAR); /* Return end of file */
852*b1cdbd2cSJim Jagielski line = infile->line; /* Reset line number */
853*b1cdbd2cSJim Jagielski goto get_from_file; /* Get from the top. */
854*b1cdbd2cSJim Jagielski }
855*b1cdbd2cSJim Jagielski /*
856*b1cdbd2cSJim Jagielski * Common processing for the new character.
857*b1cdbd2cSJim Jagielski */
858*b1cdbd2cSJim Jagielski if (c == DEF_MAGIC && file->fp != NULL) /* Don't allow delete */
859*b1cdbd2cSJim Jagielski goto newline; /* from a file */
860*b1cdbd2cSJim Jagielski if (file->parent != NULL) { /* Macro or #include */
861*b1cdbd2cSJim Jagielski if (popped != 0)
862*b1cdbd2cSJim Jagielski file->parent->unrecur += popped;
863*b1cdbd2cSJim Jagielski else {
864*b1cdbd2cSJim Jagielski recursion -= file->parent->unrecur;
865*b1cdbd2cSJim Jagielski if (recursion < 0)
866*b1cdbd2cSJim Jagielski recursion = 0;
867*b1cdbd2cSJim Jagielski file->parent->unrecur = 0;
868*b1cdbd2cSJim Jagielski }
869*b1cdbd2cSJim Jagielski }
870*b1cdbd2cSJim Jagielski #if (HOST == SYS_UNIX)
871*b1cdbd2cSJim Jagielski /*ER*/ if (c == '\r')
872*b1cdbd2cSJim Jagielski /*ER*/ return get(); /* DOS fuck */
873*b1cdbd2cSJim Jagielski #endif
874*b1cdbd2cSJim Jagielski if (c == '\n') /* Maintain current */
875*b1cdbd2cSJim Jagielski ++line; /* line counter */
876*b1cdbd2cSJim Jagielski if (instring) /* Strings just return */
877*b1cdbd2cSJim Jagielski return (c); /* the character. */
878*b1cdbd2cSJim Jagielski else if (c == '/') { /* Comment? */
879*b1cdbd2cSJim Jagielski instring = TRUE; /* So get() won't loop */
880*b1cdbd2cSJim Jagielski /*MM c++ comments */
881*b1cdbd2cSJim Jagielski /*MM*/ c = get();
882*b1cdbd2cSJim Jagielski /*MM*/ if ((c != '*') && (c != '/')) { /* Next byte '*'? */
883*b1cdbd2cSJim Jagielski instring = FALSE; /* Nope, no comment */
884*b1cdbd2cSJim Jagielski unget(); /* Push the char. back */
885*b1cdbd2cSJim Jagielski return ('/'); /* Return the slash */
886*b1cdbd2cSJim Jagielski }
887*b1cdbd2cSJim Jagielski if (keepcomments) { /* If writing comments */
888*b1cdbd2cSJim Jagielski PUTCHAR('/'); /* Write out the */
889*b1cdbd2cSJim Jagielski /* initializer */
890*b1cdbd2cSJim Jagielski /*MM*/ if( '*' == c )
891*b1cdbd2cSJim Jagielski PUTCHAR('*');
892*b1cdbd2cSJim Jagielski /*MM*/ else
893*b1cdbd2cSJim Jagielski /*MM*/ PUTCHAR('/');
894*b1cdbd2cSJim Jagielski
895*b1cdbd2cSJim Jagielski }
896*b1cdbd2cSJim Jagielski /*MM*/ if( '*' == c ){
897*b1cdbd2cSJim Jagielski for (;;) { /* Eat a comment */
898*b1cdbd2cSJim Jagielski c = get();
899*b1cdbd2cSJim Jagielski test: if (keepcomments && c != EOF_CHAR)
900*b1cdbd2cSJim Jagielski cput(c);
901*b1cdbd2cSJim Jagielski switch (c) {
902*b1cdbd2cSJim Jagielski case EOF_CHAR:
903*b1cdbd2cSJim Jagielski cerror("EOF in comment", NULLST);
904*b1cdbd2cSJim Jagielski return (EOF_CHAR);
905*b1cdbd2cSJim Jagielski
906*b1cdbd2cSJim Jagielski case '/':
907*b1cdbd2cSJim Jagielski if ((c = get()) != '*') /* Don't let comments */
908*b1cdbd2cSJim Jagielski goto test; /* Nest. */
909*b1cdbd2cSJim Jagielski #ifdef STRICT_COMMENTS
910*b1cdbd2cSJim Jagielski cwarn("Nested comments", NULLST);
911*b1cdbd2cSJim Jagielski #endif
912*b1cdbd2cSJim Jagielski /* Fall into * stuff */
913*b1cdbd2cSJim Jagielski case '*':
914*b1cdbd2cSJim Jagielski if ((c = get()) != '/') /* If comment doesn't */
915*b1cdbd2cSJim Jagielski goto test; /* end, look at next */
916*b1cdbd2cSJim Jagielski instring = FALSE; /* End of comment, */
917*b1cdbd2cSJim Jagielski if (keepcomments) { /* Put out the comment */
918*b1cdbd2cSJim Jagielski cput(c); /* terminator, too */
919*b1cdbd2cSJim Jagielski }
920*b1cdbd2cSJim Jagielski /*
921*b1cdbd2cSJim Jagielski * A comment is syntactically "whitespace" --
922*b1cdbd2cSJim Jagielski * however, there are certain strange sequences
923*b1cdbd2cSJim Jagielski * such as
924*b1cdbd2cSJim Jagielski * #define foo(x) (something)
925*b1cdbd2cSJim Jagielski * foo|* comment *|(123)
926*b1cdbd2cSJim Jagielski * these are '/' ^ ^
927*b1cdbd2cSJim Jagielski * where just returning space (or COM_SEP) will cause
928*b1cdbd2cSJim Jagielski * problems. This can be "fixed" by overwriting the
929*b1cdbd2cSJim Jagielski * '/' in the input line buffer with ' ' (or COM_SEP)
930*b1cdbd2cSJim Jagielski * but that may mess up an error message.
931*b1cdbd2cSJim Jagielski * So, we peek ahead -- if the next character is
932*b1cdbd2cSJim Jagielski * "whitespace" we just get another character, if not,
933*b1cdbd2cSJim Jagielski * we modify the buffer. All in the name of purity.
934*b1cdbd2cSJim Jagielski */
935*b1cdbd2cSJim Jagielski if (*file->bptr == '\n'
936*b1cdbd2cSJim Jagielski || type[*file->bptr & 0xFF] == SPA)
937*b1cdbd2cSJim Jagielski goto newline;
938*b1cdbd2cSJim Jagielski #if COMMENT_INVISIBLE
939*b1cdbd2cSJim Jagielski /*
940*b1cdbd2cSJim Jagielski * Return magic (old-fashioned) syntactic space.
941*b1cdbd2cSJim Jagielski */
942*b1cdbd2cSJim Jagielski return ((file->bptr[-1] = COM_SEP));
943*b1cdbd2cSJim Jagielski #else
944*b1cdbd2cSJim Jagielski return ((file->bptr[-1] = ' '));
945*b1cdbd2cSJim Jagielski #endif
946*b1cdbd2cSJim Jagielski
947*b1cdbd2cSJim Jagielski case '\n': /* we'll need a #line */
948*b1cdbd2cSJim Jagielski if (!keepcomments)
949*b1cdbd2cSJim Jagielski wrongline = TRUE; /* later... */
950*b1cdbd2cSJim Jagielski default: /* Anything else is */
951*b1cdbd2cSJim Jagielski break; /* Just a character */
952*b1cdbd2cSJim Jagielski } /* End switch */
953*b1cdbd2cSJim Jagielski } /* End comment loop */
954*b1cdbd2cSJim Jagielski }
955*b1cdbd2cSJim Jagielski else{ /* c++ comment */
956*b1cdbd2cSJim Jagielski /*MM c++ comment*/
957*b1cdbd2cSJim Jagielski for (;;) { /* Eat a comment */
958*b1cdbd2cSJim Jagielski c = get();
959*b1cdbd2cSJim Jagielski if (keepcomments && c != EOF_CHAR)
960*b1cdbd2cSJim Jagielski cput(c);
961*b1cdbd2cSJim Jagielski if( EOF_CHAR == c )
962*b1cdbd2cSJim Jagielski return (EOF_CHAR);
963*b1cdbd2cSJim Jagielski else if( '\n' == c ){
964*b1cdbd2cSJim Jagielski instring = FALSE; /* End of comment, */
965*b1cdbd2cSJim Jagielski return( c );
966*b1cdbd2cSJim Jagielski }
967*b1cdbd2cSJim Jagielski }
968*b1cdbd2cSJim Jagielski }
969*b1cdbd2cSJim Jagielski } /* End if in comment */
970*b1cdbd2cSJim Jagielski else if (!inmacro && c == '\\') { /* If backslash, peek */
971*b1cdbd2cSJim Jagielski if ((c = get()) == '\n') { /* for a <nl>. If so, */
972*b1cdbd2cSJim Jagielski wrongline = TRUE;
973*b1cdbd2cSJim Jagielski goto newline;
974*b1cdbd2cSJim Jagielski }
975*b1cdbd2cSJim Jagielski else { /* Backslash anything */
976*b1cdbd2cSJim Jagielski unget(); /* Get it later */
977*b1cdbd2cSJim Jagielski return ('\\'); /* Return the backslash */
978*b1cdbd2cSJim Jagielski }
979*b1cdbd2cSJim Jagielski }
980*b1cdbd2cSJim Jagielski else if (c == '\f' || c == VT) /* Form Feed, Vertical */
981*b1cdbd2cSJim Jagielski c = ' '; /* Tab are whitespace */
982*b1cdbd2cSJim Jagielski else if (c == 0xef) /* eat up UTF-8 BOM */
983*b1cdbd2cSJim Jagielski {
984*b1cdbd2cSJim Jagielski if((c = get()) == 0xbb)
985*b1cdbd2cSJim Jagielski {
986*b1cdbd2cSJim Jagielski if((c = get()) == 0xbf)
987*b1cdbd2cSJim Jagielski {
988*b1cdbd2cSJim Jagielski c = get();
989*b1cdbd2cSJim Jagielski return c;
990*b1cdbd2cSJim Jagielski }
991*b1cdbd2cSJim Jagielski else
992*b1cdbd2cSJim Jagielski {
993*b1cdbd2cSJim Jagielski unget();
994*b1cdbd2cSJim Jagielski unget();
995*b1cdbd2cSJim Jagielski return 0xef;
996*b1cdbd2cSJim Jagielski }
997*b1cdbd2cSJim Jagielski }
998*b1cdbd2cSJim Jagielski else
999*b1cdbd2cSJim Jagielski {
1000*b1cdbd2cSJim Jagielski unget();
1001*b1cdbd2cSJim Jagielski return 0xef;
1002*b1cdbd2cSJim Jagielski }
1003*b1cdbd2cSJim Jagielski }
1004*b1cdbd2cSJim Jagielski return (c); /* Just return the char */
1005*b1cdbd2cSJim Jagielski }
1006*b1cdbd2cSJim Jagielski
unget()1007*b1cdbd2cSJim Jagielski void unget()
1008*b1cdbd2cSJim Jagielski /*
1009*b1cdbd2cSJim Jagielski * Backup the pointer to reread the last character. Fatal error
1010*b1cdbd2cSJim Jagielski * (code bug) if we backup too far. unget() may be called,
1011*b1cdbd2cSJim Jagielski * without problems, at end of file. Only one character may
1012*b1cdbd2cSJim Jagielski * be ungotten. If you need to unget more, call ungetstring().
1013*b1cdbd2cSJim Jagielski */
1014*b1cdbd2cSJim Jagielski {
1015*b1cdbd2cSJim Jagielski register FILEINFO *file;
1016*b1cdbd2cSJim Jagielski
1017*b1cdbd2cSJim Jagielski if ((file = infile) == NULL)
1018*b1cdbd2cSJim Jagielski return; /* Unget after EOF */
1019*b1cdbd2cSJim Jagielski if (--file->bptr < file->buffer)
1020*b1cdbd2cSJim Jagielski cfatal("Too much pushback", NULLST);
1021*b1cdbd2cSJim Jagielski if (*file->bptr == '\n') /* Ungetting a newline? */
1022*b1cdbd2cSJim Jagielski --line; /* Unget the line number, too */
1023*b1cdbd2cSJim Jagielski }
1024*b1cdbd2cSJim Jagielski
ungetstring(char * text)1025*b1cdbd2cSJim Jagielski void ungetstring(char* text)
1026*b1cdbd2cSJim Jagielski /*
1027*b1cdbd2cSJim Jagielski * Push a string back on the input stream. This is done by treating
1028*b1cdbd2cSJim Jagielski * the text as if it were a macro.
1029*b1cdbd2cSJim Jagielski */
1030*b1cdbd2cSJim Jagielski {
1031*b1cdbd2cSJim Jagielski register FILEINFO *file;
1032*b1cdbd2cSJim Jagielski #ifndef ZTC /* BP */
1033*b1cdbd2cSJim Jagielski extern FILEINFO *getfile();
1034*b1cdbd2cSJim Jagielski #endif
1035*b1cdbd2cSJim Jagielski file = getfile(strlen(text) + 1, "");
1036*b1cdbd2cSJim Jagielski strcpy(file->buffer, text);
1037*b1cdbd2cSJim Jagielski }
1038*b1cdbd2cSJim Jagielski
1039*b1cdbd2cSJim Jagielski int
cget()1040*b1cdbd2cSJim Jagielski cget()
1041*b1cdbd2cSJim Jagielski /*
1042*b1cdbd2cSJim Jagielski * Get one character, absorb "funny space" after comments or
1043*b1cdbd2cSJim Jagielski * token concatenation
1044*b1cdbd2cSJim Jagielski */
1045*b1cdbd2cSJim Jagielski {
1046*b1cdbd2cSJim Jagielski register int c;
1047*b1cdbd2cSJim Jagielski
1048*b1cdbd2cSJim Jagielski do {
1049*b1cdbd2cSJim Jagielski c = get();
1050*b1cdbd2cSJim Jagielski #if COMMENT_INVISIBLE
1051*b1cdbd2cSJim Jagielski } while (c == TOK_SEP || c == COM_SEP);
1052*b1cdbd2cSJim Jagielski #else
1053*b1cdbd2cSJim Jagielski } while (c == TOK_SEP);
1054*b1cdbd2cSJim Jagielski #endif
1055*b1cdbd2cSJim Jagielski return (c);
1056*b1cdbd2cSJim Jagielski }
1057*b1cdbd2cSJim Jagielski
1058*b1cdbd2cSJim Jagielski /*
1059*b1cdbd2cSJim Jagielski * Error messages and other hacks. The first byte of severity
1060*b1cdbd2cSJim Jagielski * is 'S' for string arguments and 'I' for int arguments. This
1061*b1cdbd2cSJim Jagielski * is needed for portability with machines that have int's that
1062*b1cdbd2cSJim Jagielski * are shorter than char *'s.
1063*b1cdbd2cSJim Jagielski */
1064*b1cdbd2cSJim Jagielski
domsg(char * severity,char * format,void * arg)1065*b1cdbd2cSJim Jagielski static void domsg(char* severity, char* format, void* arg)
1066*b1cdbd2cSJim Jagielski /*
1067*b1cdbd2cSJim Jagielski * Print filenames, macro names, and line numbers for error messages.
1068*b1cdbd2cSJim Jagielski */
1069*b1cdbd2cSJim Jagielski {
1070*b1cdbd2cSJim Jagielski register char *tp;
1071*b1cdbd2cSJim Jagielski register FILEINFO *file;
1072*b1cdbd2cSJim Jagielski
1073*b1cdbd2cSJim Jagielski fprintf(stderr, "%sline %d, %s: ", MSG_PREFIX, line, &severity[1]);
1074*b1cdbd2cSJim Jagielski if (*severity == 'S')
1075*b1cdbd2cSJim Jagielski fprintf(stderr, format, (char *)arg);
1076*b1cdbd2cSJim Jagielski else
1077*b1cdbd2cSJim Jagielski fprintf(stderr, format, *((int *)arg) );
1078*b1cdbd2cSJim Jagielski putc('\n', stderr);
1079*b1cdbd2cSJim Jagielski if ((file = infile) == NULL)
1080*b1cdbd2cSJim Jagielski return; /* At end of file */
1081*b1cdbd2cSJim Jagielski if (file->fp != NULL) {
1082*b1cdbd2cSJim Jagielski tp = file->buffer; /* Print current file */
1083*b1cdbd2cSJim Jagielski fprintf(stderr, "%s", tp); /* name, making sure */
1084*b1cdbd2cSJim Jagielski if (tp[strlen(tp) - 1] != '\n') /* there's a newline */
1085*b1cdbd2cSJim Jagielski putc('\n', stderr);
1086*b1cdbd2cSJim Jagielski }
1087*b1cdbd2cSJim Jagielski while ((file = file->parent) != NULL) { /* Print #includes, too */
1088*b1cdbd2cSJim Jagielski if (file->fp == NULL)
1089*b1cdbd2cSJim Jagielski fprintf(stderr, "from macro %s\n", file->filename);
1090*b1cdbd2cSJim Jagielski else {
1091*b1cdbd2cSJim Jagielski tp = file->buffer;
1092*b1cdbd2cSJim Jagielski fprintf(stderr, "from file %s, line %d:\n%s",
1093*b1cdbd2cSJim Jagielski (file->progname != NULL)
1094*b1cdbd2cSJim Jagielski ? file->progname : file->filename,
1095*b1cdbd2cSJim Jagielski file->line, tp);
1096*b1cdbd2cSJim Jagielski if (tp[strlen(tp) - 1] != '\n')
1097*b1cdbd2cSJim Jagielski putc('\n', stderr);
1098*b1cdbd2cSJim Jagielski }
1099*b1cdbd2cSJim Jagielski }
1100*b1cdbd2cSJim Jagielski }
1101*b1cdbd2cSJim Jagielski
cerror(char * format,char * sarg)1102*b1cdbd2cSJim Jagielski void cerror(char* format, char* sarg)
1103*b1cdbd2cSJim Jagielski /*
1104*b1cdbd2cSJim Jagielski * Print a normal error message, string argument.
1105*b1cdbd2cSJim Jagielski */
1106*b1cdbd2cSJim Jagielski {
1107*b1cdbd2cSJim Jagielski domsg("SError", format, sarg);
1108*b1cdbd2cSJim Jagielski errors++;
1109*b1cdbd2cSJim Jagielski }
1110*b1cdbd2cSJim Jagielski
cierror(char * format,int narg)1111*b1cdbd2cSJim Jagielski void cierror(char* format, int narg)
1112*b1cdbd2cSJim Jagielski /*
1113*b1cdbd2cSJim Jagielski * Print a normal error message, numeric argument.
1114*b1cdbd2cSJim Jagielski */
1115*b1cdbd2cSJim Jagielski {
1116*b1cdbd2cSJim Jagielski domsg("IError", format, &narg);
1117*b1cdbd2cSJim Jagielski errors++;
1118*b1cdbd2cSJim Jagielski }
1119*b1cdbd2cSJim Jagielski
cfatal(char * format,char * sarg)1120*b1cdbd2cSJim Jagielski void cfatal(char* format, char* sarg)
1121*b1cdbd2cSJim Jagielski /*
1122*b1cdbd2cSJim Jagielski * A real disaster
1123*b1cdbd2cSJim Jagielski */
1124*b1cdbd2cSJim Jagielski {
1125*b1cdbd2cSJim Jagielski domsg("SFatal error", format, sarg);
1126*b1cdbd2cSJim Jagielski exit(IO_ERROR);
1127*b1cdbd2cSJim Jagielski }
1128*b1cdbd2cSJim Jagielski
cwarn(char * format,char * sarg)1129*b1cdbd2cSJim Jagielski void cwarn(char* format, char* sarg)
1130*b1cdbd2cSJim Jagielski /*
1131*b1cdbd2cSJim Jagielski * A non-fatal error, string argument.
1132*b1cdbd2cSJim Jagielski */
1133*b1cdbd2cSJim Jagielski {
1134*b1cdbd2cSJim Jagielski domsg("SWarning", format, sarg);
1135*b1cdbd2cSJim Jagielski }
1136*b1cdbd2cSJim Jagielski
ciwarn(char * format,int narg)1137*b1cdbd2cSJim Jagielski void ciwarn(char* format, int narg)
1138*b1cdbd2cSJim Jagielski /*
1139*b1cdbd2cSJim Jagielski * A non-fatal error, numeric argument.
1140*b1cdbd2cSJim Jagielski */
1141*b1cdbd2cSJim Jagielski {
1142*b1cdbd2cSJim Jagielski domsg("IWarning", format, &narg);
1143*b1cdbd2cSJim Jagielski }
1144*b1cdbd2cSJim Jagielski
1145