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