Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20160516184350

Diff

Diff from 1.177 to:

Annotations

Annotate by Age | Author | Mixed | None
/fisheye/browse/pcc/pcc/cc/cpp/token.c

Annotated File View

ragge
1.177
1 /*      $Id: token.c,v 1.177 2016/05/16 18:43:50 ragge Exp $    */
ragge
1.1
2
3 /*
ragge
1.13
4  * Copyright (c) 2004,2009 Anders Magnusson. All rights reserved.
ragge
1.1
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
ragge
1.19
27 /*
28  * Tokenizer for the C preprocessor.
29  * There are three main routines:
30  *      - fastscan() loops over the input stream searching for magic
31  *              characters that may require actions.
plunky
1.113
32  *      - yylex() returns something from the input stream that
ragge
1.19
33  *              is suitable for yacc.
34  *
35  *      Other functions of common use:
36  *      - inpch() returns a raw character from the current input stream.
37  *      - inch() is like inpch but \\n and trigraphs are expanded.
38  *      - unch() pushes back a character to the input stream.
ragge
1.125
39  *
40  * Input data can be read from either stdio or a buffer.
ragge
1.132
41  * If a buffer is read, it will return EOF when ended and then jump back
42  * to the previous buffer.
43  *      - setibuf(usch *ptr). Buffer to read from, until NULL, return EOF.
44  *              When EOF returned, pop buffer.
45  *      - setobuf(usch *ptr).  Buffer to write to
ragge
1.125
46  *
47  * There are three places data is read:
48  *      - fastscan() which has a small loop that will scan over input data.
49  *      - flscan() where everything is skipped except directives (flslvl)
ragge
1.132
50  *      - inch() that everything else uses.
ragge
1.125
51  *
52  * 5.1.1.2 Translation phases:
53  *      1) Convert UCN to UTF-8 which is what pcc uses internally (chkucn).
54  *         Remove \r (unwanted)
55  *         Convert trigraphs (chktg)
56  *      2) Remove \\\n.  Need extra care for identifiers and #line.
57  *      3) Tokenize.
58  *         Remove comments (fastcmnt)
ragge
1.19
59  */
60
ragge
1.13
61 #include "config.h"
62
ragge
1.1
63 #include <stdlib.h>
64 #include <string.h>
ragge
1.13
65 #ifdef HAVE_UNISTD_H
ragge
1.2
66 #include <unistd.h>
ragge
1.13
67 #endif
ragge
1.2
68 #include <fcntl.h>
ragge
1.1
69
ragge
1.13
70 #include "compat.h"
ragge
1.1
71 #include "cpp.h"
ragge
1.13
72
ragge
1.136
73 static void cvtdig(usch **);
plunky
1.114
74 static int dig2num(int);
ragge
1.136
75 static int charcon(usch **);
ragge
1.13
76 static void elsestmt(void);
77 static void ifdefstmt(void);
78 static void ifndefstmt(void);
79 static void endifstmt(void);
80 static void ifstmt(void);
81 static void cpperror(void);
plunky
1.102
82 static void cppwarning(void);
83 static void undefstmt(void);
ragge
1.13
84 static void pragmastmt(void);
85 static void elifstmt(void);
86
ragge
1.122
87 static void unch(int c);
88
plunky
1.121
89 #define PUTCH(ch) if (!flslvl) putch(ch)
ragge
1.13
90 /* protection against recursion in #include */
91 #define MAX_INCLEVEL    100
ragge
1.170
92 int inclevel;
ragge
1.175
93 int incmntinstr;
ragge
1.13
94
plunky
1.81
95 struct includ *ifiles;
96
ragge
1.175
97 static void ucn(int n);
ragge
1.174
98 static void fastcmnt2(int);
ragge
1.175
99 static int chktg2(int ch);
ragge
1.174
100
plunky
1.97
101 /* some common special combos for init */
102 #define C_NL    (C_SPEC|C_WSNL)
103 #define C_DX    (C_SPEC|C_ID|C_DIGIT|C_HEX)
104 #define C_I     (C_SPEC|C_ID|C_ID0)
105 #define C_IX    (C_SPEC|C_ID|C_ID0|C_HEX)
106
107 usch spechr[256] = {
ragge
1.174
108         C_SPEC|C_Q0,  0,      0,      C_SPECC_SPEC0,      0,
109         0,      C_WSNLC_NL,   0,      0,      C_WSNL|C_Q0,  0,
ragge
1.19
110         0,      0,      0,      0,      0,      0,      0,      0,
111         0,      0,      0,      0,      0,      0,      0,      0,
112
ragge
1.43
113         C_WSNLC_2,    C_SPEC0,      0,      0,      C_2,    C_SPEC,
ragge
1.174
114         0,      0,      0,      C_2,    0,      C_2,    0,      C_SPEC|C_Q,
plunky
1.97
115         C_DX,   C_DX,   C_DX,   C_DX,   C_DX,   C_DX,   C_DX,   C_DX,
ragge
1.174
116         C_DX,   C_DX,   0,      0,      C_2,    C_2,    C_2,    C_SPEC|C_Q,
ragge
1.19
117
ragge
1.174
118         0,      C_IX,   C_IX,   C_IX,   C_IX,   C_IX,   C_IX,   C_I,
119         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
ragge
1.19
120         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
ragge
1.174
121         C_I,    C_I,    C_I,    0,      C_SPEC|C_Q0,  0,      C_I,
ragge
1.19
122
ragge
1.174
123         0,      C_IX,   C_IX,   C_IX,   C_IX,   C_IX,   C_IX,   C_I,
124         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
ragge
1.19
125         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
126         C_I,    C_I,    C_I,    0,      C_2,    0,      0,      0,
ragge
1.111
127
128 /* utf-8 */
129         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
130         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
131         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
132         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
133
134         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
135         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
136         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
137         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
138
139         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
140         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
141         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
142         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
143
144         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
145         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
146         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
plunky
1.112
147         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
ragge
1.19
148 };
ragge
1.1
149
plunky
1.102
150 /*
151  * fill up the input buffer
ragge
1.174
152  * n tells how nany chars at least.  0 == standard.
153  * 0 if EOF, != 0 if something could fill up buf.
plunky
1.102
154  */
155 static int
ragge
1.174
156 inpbuf(int n)
plunky
1.102
157 {
ragge
1.174
158         struct iobuf *ib = ifiles->ib;
159         int lensz = 0;
160
161         if (n > 0) {
162                 if (ib->bsz > ib->cptr + n)
163                         return 1/* enough in buffer */
164                 sz = ib->bsz - ib->cptr;
165                 memcpy(ib->buf+PBMAX - szib->buf + ib->cptrsz);
166         }
plunky
1.102
167
168         if (ifiles->infil == -1)
169                 return 0;
ragge
1.174
170         len = read(ifiles->infilib->buf+PBMAXCPPBUF-PBMAX);
plunky
1.102
171         if (len == -1)
172                 error("read error on file %s"ifiles->orgfn);
173         if (len > 0) {
ragge
1.174
174                 ib->cptr = PBMAX - sz;
175                 ib->bsz = PBMAX + len + sz;
plunky
1.102
176         }
ragge
1.174
177         return len + sz;
178 }
179
180 /*
181  * Return a quick-cooked character.
182  * If buffer empty; return 0.
183  */
184 static int
185 qcchar(void)
186 {
187         struct iobuf *ib = ifiles->ib;
188         int ch;
189
190 newonedo {
191                 if (ib->cptr < ib->bsz) {
ragge
1.175
192                         if (!ISCQ(ch = ib->buf[ib->cptr++]))
ragge
1.174
193                                 return ch;
194                         break;
195                 }
196         } while ((ch = inpbuf(0)) > 0);
197
198         switch (ch) {
199         case 0:
200                 return 0/* end of file */
201
202         case '\r':
203                 goto newone;
204
205         case '\\':
ragge
1.175
206                 if (ib->cptr == ib->bsz)
207                         inpbuf(0);
208                 switch (ch = ib->buf[ib->cptr]) {
209                 case 'u':
210                 case 'U'
211                         if (incmnt
212                                 return '\\';
213                         ib->cptr++;
214                         ucn(ch == 'u' ? 4 : 8);
215                         break;
ragge
1.174
216                 case '\r':
217                         ib->cptr++;
ragge
1.175
218                         if (ib->cptr == ib->bsz)
219                                 inpbuf(0);
ragge
1.174
220                         /* FALLTHROUGH */
221                 case '\n':
ragge
1.175
222                         ib->cptr++;
ragge
1.174
223                         ifiles->escln++;
224                         break;
225                 default:
226                         return '\\';
227                 }
228                 goto newone;
229
230         case '?':
231                 inpbuf(2);
232                 if (ib->buf[ib->cptr] == '?') {
ragge
1.175
233                         if ((ch = chktg2(ib->buf[ib->cptr+1])) == 0)
234                                 return '?';
235                         ib->buf[++ib->cptr] = ch;
236                         goto newone;
ragge
1.174
237                 }
238                 return '?';
ragge
1.175
239
ragge
1.174
240         case '/':
ragge
1.175
241                 if (Cflag || incmnt || instr)
ragge
1.174
242                         return '/';
243                 incmnt++;
244                 ch = qcchar();
245                 incmnt--;
246                 if (ch == '/' || ch == '*') {
247                         int n = ifiles->lineno;
248                         fastcmnt2(ch);
249                         if (n == ifiles->lineno)
ragge
1.175
250                                 return ' ';
ragge
1.174
251                 } else {
252                         ib->buf[--ib->cptr] = ch;
253                         return '/';
254                 }
255                 goto newone;
256         }
257         error("ch error");
258         return 0/* XXX */
plunky
1.102
259 }
260
261 /*
262  * push a character back to the input stream
263  */
ragge
1.13
264 static void
265 unch(int c)
266 {
plunky
1.93
267         if (c == -1)
268                 return;
plunky
1.113
269
ragge
1.171
270         ifiles->ib->cptr--;
271         if (ifiles->ib->cptr < 0)
ragge
1.15
272                 error("pushback buffer full");
ragge
1.171
273         ifiles->ib->buf[ifiles->ib->cptr] = (usch)c;
ragge
1.13
274 }
ragge
1.1
275
plunky
1.102
276 /*
ragge
1.175
277  * Return trigraph mapping char or 0.
plunky
1.102
278  */
279 static int
ragge
1.174
280 chktg2(int ch)
281 {
282         switch (ch) {
283         case '=':  return '#';
284         case '(':  return '[';
285         case ')':  return ']';
286         case '<':  return '{';
287         case '>':  return '}';
288         case '/':  return '\\';
289         case '\''return '^';
290         case '!':  return '|';
291         case '-':  return '~';
292         }
293         return 0;
294 }
295
296 /*
297  * deal with comments in the fast scanner.
298  */
299 static void
300 fastcmnt2(int ch)
301 {
302
303         incmnt = 1;
304         if (ch == '/') { /* C++ comment */
305                 while ((ch = qcchar()) != '\n')
306                         ;
307                 unch(ch);
308         } else if (ch == '*') {
309                 for (;;) {
310                         if ((ch = qcchar()) == 0)
311                                 break;
312                         if (ch == '*') {
313                                 if ((ch = qcchar()) == '/') {
314                                         break;
315                                 } else
316                                         unch(ch);
317                         } else if (ch == '\n') {
318                                 ifiles->lineno++;
319                                 putch('\n');
320                         }
321                 }
322         } else
323                 error("fastcmnt2");
324         if (ch == 0)
325                 error("file ends in comment");
326         incmnt = 0;
327 }
328
ragge
1.125
329 /*
plunky
1.114
330  * check for universal-character-name on input, and
331  * unput to the pushback buffer encoded as UTF-8.
332  */
ragge
1.175
333 static void
ragge
1.174
334 ucn(int n)
335 {
336         unsigned long cpm;
337         int ch;
338
ragge
1.175
339         if (incmnt) {
340                 struct iobuf *ib = ifiles->ib;
341                 ib->cptr--; /* [uU] */
342                 ib->buf[--ib->cptr] = '\\';
343                 return;
plunky
1.114
344         }
345
346         cp = 0;
347         while (n-- > 0) {
ragge
1.175
348                 if ((ch = qcchar()) == 0 || (spechr[ch] & C_HEX) == 0) {
plunky
1.114
349                         warning("invalid universal character name");
350                         // XXX should actually unput the chars and return 0
351                         unch(ch); // XXX eof
352                         break;
353                 }
354                 cp = cp * 16 + dig2num(ch);
355         }
356
plunky
1.115
357         if ((cp < 0xa0 && cp != 0x24 && cp != 0x40 && cp != 0x60)
358             || (cp >= 0xd800 && cp <= 0xdfff))  /* 6.4.3.2 */
359                 error("universal character name cannot be used");
360
plunky
1.114
361         if (cp > 0x7fffffff)
362                 error("universal character name out of range");
363
364         n = 0;
365         m = 0x7f;
366         while (cp > m) {
367                 unch(0x80 | (cp & 0x3f));
368                 cp >>= 6;
369                 m >>= (n++ ? 1 : 2);
370         }
371         unch(((m << 1) ^ 0xfe) | cp);
372 }
373
ragge
1.122
374 /*
375  * deal with comments when -C is active.
ragge
1.125
376  * Save comments in expanded macros???
ragge
1.122
377  */
ragge
1.177
378 void
ragge
1.174
379 Ccmnt2(void (*d)(int), int ch)
380 {
381
382         if (ch == '/') { /* C++ comment */
383                 d(ch);
384                 do {
385                         d(ch);
ragge
1.175
386                 } while ((ch = qcchar()) && ch != '\n');
ragge
1.174
387                 unch(ch);
388         } else if (ch == '*') {
389                 d('/');
390                 d('*');
391                 for (;;) {
ragge
1.175
392                         ch = qcchar();
ragge
1.174
393                         d(ch);
394                         if (ch == '*') {
ragge
1.175
395                                 if ((ch = qcchar()) == '/') {
ragge
1.174
396                                         d(ch);
397                                         break;
398                                 } else
399                                         unch(ch);
400                         } else if (ch == '\n') {
401                                 ifiles->lineno++;
402                         }
403                 }
404         }
405 }
406
407 /*
ragge
1.125
408  * Traverse over spaces and comments from the input stream,
ragge
1.129
409  * Returns first non-space character.
ragge
1.125
410  */
plunky
1.108
411 static int
ragge
1.129
412 fastspc(void)
ragge
1.45
413 {
414         int ch;
415
ragge
1.175
416         while ((ch = qcchar()), ISWS(ch))
ragge
1.129
417                 ;
ragge
1.125
418         return ch;
ragge
1.45
419 }
420
ragge
1.19
421 /*
ragge
1.164
422  * readin chars and store in buf. Warn about too long names.
423  */
424 usch *
425 bufid(int chstruct iobuf *ob)
426 {
ragge
1.171
427         int n = ob->cptr;
ragge
1.164
428
429         do {
ragge
1.171
430                 if (ob->cptr - n == MAXIDSZ)
ragge
1.164
431                         warning("identifier exceeds C99 5.2.4.1");
432                 if (ob->cptr < ob->bsz)
ragge
1.171
433                         ob->buf[ob->cptr++] = ch;
ragge
1.164
434                 else
435                         putob(obch);
ragge
1.175
436         } while (spechr[ch = qcchar()] & C_ID);
ragge
1.171
437         ob->buf[ob->cptr] = 0/* legal */
ragge
1.164
438         unch(ch);
ragge
1.171
439         return ob->buf+n;
ragge
1.164
440 }
441
ragge
1.161
442 usch idbuf[MAXIDSZ+1];
ragge
1.122
443 /*
ragge
1.159
444  * readin chars and store in buf. Warn about too long names.
ragge
1.131
445  */
ragge
1.134
446 usch *
ragge
1.159
447 readid(int ch)
ragge
1.131
448 {
ragge
1.159
449         int p = 0;
450
ragge
1.131
451         do {
ragge
1.159
452                 if (p == MAXIDSZ)
453                         warning("identifier exceeds C99 5.2.4.1, truncating");
454                 if (p < MAXIDSZ)
455                         idbuf[p] = ch;
456                 p++;
ragge
1.175
457         } while (spechr[ch = qcchar()] & C_ID);
ragge
1.159
458         idbuf[p] = 0;
ragge
1.131
459         unch(ch);
ragge
1.159
460         return idbuf;
ragge
1.131
461 }
462
463 /*
ragge
1.125
464  * get a string or character constant and save it as given by d.
465  */
ragge
1.164
466 struct iobuf *
467 faststr(int bcstruct iobuf *ob)
ragge
1.125
468 {
ragge
1.175
469         struct iobuf *ib = ifiles->ib;
ragge
1.125
470         int ch;
471
ragge
1.164
472         if (ob == NULL)
ragge
1.167
473                 ob = getobuf(BNORMAL);
ragge
1.164
474
ragge
1.175
475         instr = 1;
ragge
1.164
476         putob(obbc);
ragge
1.175
477         for (;;) {
478                 if (ib->bsz == ib->cptr)
479                         ch = qcchar();
480                 else if (ISCQ(ch = ib->buf[ib->cptr]))
481                         ch = qcchar();
482                 else
483                         ib->cptr++;
484                 switch (ch) {
485                 case '\\':
486                         putob(obch);
487                         if (ib->cptr == ib->bsz)
488                                 inpbuf(0);
489                         incmnt = 1;
490                         putob(obqcchar());
491                         incmnt = 0;
492                         continue;
493                 case '\n':
ragge
1.125
494                         warning("unterminated literal");
ragge
1.175
495                         instr = 0;
ragge
1.125
496                         unch(ch);
ragge
1.164
497                         return ob;
ragge
1.125
498                 }
ragge
1.164
499                 putob(obch);
ragge
1.175
500                 if (ch == bc)
501                         break;
ragge
1.125
502         }
ragge
1.171
503         ob->buf[ob->cptr] = 0;
ragge
1.175
504         instr = 0;
ragge
1.164
505         return ob;
ragge
1.125
506 }
507
508 /*
ragge
1.164
509  * get a preprocessing number and save it as given by ob.
ragge
1.125
510  * returns first non-pp-number char.
ragge
1.164
511  * We know that this is a valid number already.
ragge
1.125
512  *
513  *      pp-number:      digit
514  *                      . digit
515  *                      pp-number digit
516  *                      pp-number identifier-nondigit
517  *                      pp-number e sign
518  *                      pp-number E sign
519  *                      pp-number p sign
520  *                      pp-number P sign
521  *                      pp-number .
522  */
ragge
1.134
523 int
ragge
1.164
524 fastnum(int chstruct iobuf *ob)
ragge
1.125
525 {
526         int c2;
527
ragge
1.126
528         if ((spechr[ch] & C_DIGIT) == 0) {
529                 /* not digit, dot */
ragge
1.164
530                 putob(obch);
ragge
1.175
531                 ch = qcchar();
ragge
1.126
532         }
ragge
1.125
533         for (;;) {
ragge
1.164
534                 putob(obch);
ragge
1.175
535                 if ((ch = qcchar()) == 0)
536                         return 0;
ragge
1.174
537                 if ((c2 = (ch & 0337)) == 'E' || c2 == 'P') {
ragge
1.175
538                         if ((c2 = qcchar()) != '-' && c2 != '+') {
539                                 if (c2 > 0)
ragge
1.125
540                                         unch(c2);
541                                 break;
542                         }
ragge
1.164
543                         putob(obch);
ragge
1.125
544                         ch = c2;
545                 } else if (ch == '.' || (spechr[ch] & C_ID)) {
546                         continue;
547                 } else
548                         break;
549         }
550         return ch;
551 }
ragge
1.122
552
553 /*
ragge
1.19
554  * Scan quickly the input file searching for:
555  *      - '#' directives
556  *      - keywords (if not flslvl)
557  *      - comments
558  *
559  *      Handle strings, numbers and trigraphs with care.
560  *      Only data from pp files are scanned here, never any rescans.
ragge
1.125
561  *      This loop is always at trulvl.
ragge
1.19
562  */
ragge
1.168
563 void
ragge
1.19
564 fastscan(void)
565 {
ragge
1.164
566         struct iobuf *obrbs, *rb = &rbs;
ragge
1.167
567         extern struct iobuf pb;
ragge
1.174
568         struct iobuf *ib = ifiles->ib;
ragge
1.19
569         struct symtab *nl;
ragge
1.173
570         int chc2i;
ragge
1.164
571         usch *dp;
572
573 #define IDSIZE  128
ragge
1.171
574         rb->buf = xmalloc(IDSIZE+1);
575         rb->cptr = 0;
576         rb->bsz = IDSIZE;
ragge
1.19
577
578         goto run;
ragge
1.125
579
ragge
1.19
580         for (;;) {
ragge
1.125
581                 /* tight loop to find special chars */
582                 /* should use getchar/putchar here */
583                 for (;;) {
ragge
1.174
584                         if (ib->cptr < ib->bsz)
585                                 ch = ib->buf[ib->cptr++];
586                         else
587                                 ch = qcchar();
588 xloop:                  if (ch < 0ch = 0/* XXX */
ragge
1.125
589                         if ((spechr[ch] & C_SPEC) != 0)
590                                 break;
591                         putch(ch);
ragge
1.19
592                 }
ragge
1.125
593
ragge
1.19
594                 switch (ch) {
ragge
1.174
595                 case 0:
596                         free(rb->buf);
597                         return;
598
ragge
1.43
599                 case WARN:
600                 case CONC:
601                         error("bad char passed");
602                         break;
603
ragge
1.19
604                 case '/'/* Comments */
ragge
1.174
605                         ch = qcchar();
606                         if (ch  == '/' || ch == '*') {
607                                 if (Cflag == 0) {
608                                         int n = ifiles->lineno;
609                                         fastcmnt2(ch);
610                                         if (n == ifiles->lineno)
611                                                 putch(' '); /* 5.1.1.2 p3 */
612                                 } else
613                                         Ccmnt2(putchch);
614                         } else {
ragge
1.173
615                                 putch('/');
616                                 goto xloop;
ragge
1.140
617                         }
ragge
1.19
618                         break;
619
620                 case '\n'/* newlines, for pp directives */
ragge
1.125
621                         /* take care of leftover \n */
plunky
1.102
622                         i = ifiles->escln + 1;
623                         ifiles->lineno += i;
624                         ifiles->escln = 0;
625                         while (i-- > 0)
plunky
1.121
626                                 putch('\n');
ragge
1.125
627
628                         /* search for a # */
ragge
1.174
629 run:                    while ((ch = qcchar()) == '\t' || ch == ' ')
ragge
1.125
630                                 putch(ch);
631                         if (ch == '%') {
ragge
1.174
632                                 if ((c2 = qcchar()) != ':')
ragge
1.125
633                                         unch(c2);
634                                 else
635                                         ch = '#';
ragge
1.50
636                         }
ragge
1.125
637                         if (ch  == '#')
ragge
1.19
638                                 ppdir();
ragge
1.125
639                         else
640                                 goto xloop;
641                         break;
642
ragge
1.140
643                 case '?':
ragge
1.174
644                         if (ib->cptr+1 >= ib->bsz)
645                                 inpbuf(2);
646                         if (ib->buf[ib->cptr] == '?') {
647                                 ib->cptr++;
648                                 if ((ch = chktg2(ib->buf[ib->cptr++])))
649                                         goto xloop;
650                                 ib->cptr -= 2;
651                         }
652                         putch('?');
653                         break;
654
ragge
1.125
655                 case '\''/* character constant */
656                         if (tflag) {
657                                 putch(ch);
658                                 break;  /* character constants ignored */
ragge
1.19
659                         }
ragge
1.125
660                         /* FALLTHROUGH */
ragge
1.19
661                 case '\"'/* strings */
ragge
1.167
662                         faststr(ch, &pb);
ragge
1.19
663                         break;
664
665                 case '.':  /* for pp-number */
ragge
1.175
666                         if ((spechr[c2 = qcchar()] & C_DIGIT) == 0) {
ragge
1.164
667                                 putch('.');
ragge
1.173
668                                 goto xloop;
ragge
1.164
669                         }
ragge
1.173
670                         unch(c2);
ragge
1.19
671                 case '0'case '1'case '2'case '3'case '4':
672                 case '5'case '6'case '7'case '8'case '9':
ragge
1.167
673                         ch = fastnum(ch, &pb);
ragge
1.19
674                         goto xloop;
675
ragge
1.173
676                 case 'L':
677                 case 'U':
ragge
1.150
678                 case 'u':
ragge
1.175
679                         if (ib->cptr+2 >= ib->bsz)
680                                 inpbuf(2);
681                         if ((c2 = ib->buf[ib->cptr]) == '\"' || c2 == '\'') {
ragge
1.150
682                                 putch(ch);
ragge
1.175
683                                 break;
684                         } else if (c2 == '8' && ch == 'u' &&
685                             ib->buf[ib->cptr+1] == '\"') {
686                                 ib->cptr++;
687                                 putstr((usch *)"u8");
688                                 break;
ragge
1.19
689                         }
690                         /* FALLTHROUGH */
691                 default:
plunky
1.102
692 #ifdef PCC_DEBUG
ragge
1.19
693                         if ((spechr[ch] & C_ID) == 0)
694                                 error("fastscan");
plunky
1.102
695 #endif
ragge
1.131
696                         if (flslvl)
697                                 error("fastscan flslvl");
ragge
1.171
698                         rb->cptr = 0;
ragge
1.164
699                         dp = bufid(chrb);
700                         if ((nl = lookup(dpFIND)) != NULL) {
701                                 if ((ob = kfind(nl)) != NULL) {
ragge
1.162
702                                         if (*ob->buf == '-' || *ob->buf == '+')
ragge
1.155
703                                                 putch(' ');
ragge
1.167
704                                         buftobuf(ob, &pb);
ragge
1.171
705                                         if (ob->cptr > 0 &&
706                                             (ob->buf[ob->cptr-1] == '-' ||
707                                             ob->buf[ob->cptr-1] == '+'))
ragge
1.155
708                                                 putch(' ');
ragge
1.161
709                                         bufree(ob);
ragge
1.155
710                                 }
ragge
1.164
711                         } else {
ragge
1.159
712                                 putstr(dp);
ragge
1.164
713                         }
ragge
1.19
714                         break;
plunky
1.114
715
716                 case '\\':
ragge
1.175
717                         ib->buf[--ib->cptr] = '\\';
718                         if ((ch = qcchar()) != '\\')
719                                 goto xloop;
ragge
1.125
720                         putch('\\');
plunky
1.114
721                         break;
ragge
1.19
722                 }
723         }
plunky
1.108
724
ragge
1.131
725 /*eof:*/        warning("unexpected EOF");
plunky
1.121
726         putch('\n');
ragge
1.19
727 }
ragge
1.1
728
ragge
1.136
729 /*
730  * Store an if/elif line on heap for parsing, evaluate macros and 
731  * call yyparse().
732  */
733 static usch *yyinp;
ragge
1.143
734 int inexpr;
ragge
1.136
735 static int
736 exprline(void)
737 {
ragge
1.164
738         extern int nbufused;
739         struct iobuf *ob, *rb;
ragge
1.136
740         struct symtab *nl;
741         int oCflag = Cflag;
ragge
1.165
742         usch *dp;
ragge
1.153
743         int cdifdef;
ragge
1.136
744
ragge
1.167
745         rb = getobuf(BNORMAL);
ragge
1.164
746         nbufused--;
ragge
1.136
747         Cflag = ifdef = 0;
748
ragge
1.164
749         for (;;) {
ragge
1.175
750                 c = qcchar();
ragge
1.164
751 xloop:          if (c == '\n')
752                         break;
753                 if (c == '.') {
754                         putob(rb'.');
ragge
1.175
755                         if ((spechr[c = qcchar()] & C_DIGIT) == 0)
ragge
1.164
756                                 goto xloop;
757                 }
758                 if (ISDIGIT(c)) {
759                         c = fastnum(crb);
760                         goto xloop;
761                 }
ragge
1.148
762                 if (c == '\'' || c == '\"') {
ragge
1.164
763                         faststr(crb);
ragge
1.148
764                         continue;
765                 }
ragge
1.153
766                 if (c == 'L' || c == 'u' || c == 'U') {
ragge
1.175
767                         unch(d = qcchar());
ragge
1.153
768                         if (d == '\'')  /* discard wide designator */
769                                 continue;
770                 }
ragge
1.136
771                 if (ISID0(c)) {
ragge
1.159
772                         dp = readid(c);
773                         nl = lookup(dpFIND);
ragge
1.172
774                         if (nl && nl->type == DEFLOC) {
ragge
1.136
775                                 ifdef = 1;
776                         } else if (ifdef) {
ragge
1.164
777                                 putob(rbnl ? '1' : '0');
ragge
1.136
778                                 ifdef = 0;
779                         } else if (nl != NULL) {
ragge
1.143
780                                 inexpr = 1;
ragge
1.161
781                                 if ((ob = kfind(nl))) {
ragge
1.171
782                                         ob->buf[ob->cptr] = 0;
ragge
1.164
783                                         strtobuf(ob->bufrb);
ragge
1.161
784                                         bufree(ob);
ragge
1.154
785                                 } else
ragge
1.164
786                                         putob(rb'0');
ragge
1.143
787                                 inexpr = 0;
ragge
1.136
788                         } else
ragge
1.164
789                                 putob(rb'0');
ragge
1.136
790                 } else
ragge
1.164
791                         putob(rbc);
ragge
1.136
792         }
ragge
1.171
793         rb->buf[rb->cptr] = 0;
ragge
1.136
794         unch('\n');
ragge
1.164
795         yyinp = rb->buf;
ragge
1.136
796         c = yyparse();
ragge
1.164
797         bufree(rb);
798         nbufused++;
ragge
1.136
799         Cflag = oCflag;
800         return c;
801 }
802
ragge
1.19
803 int
plunky
1.64
804 yylex(void)
ragge
1.19
805 {
ragge
1.136
806         int chc2t;
ragge
1.19
807
ragge
1.136
808         while ((ch = *yyinp++) == ' ' || ch == '\t')
ragge
1.19
809                 ;
ragge
1.136
810         t = ISDIGIT(ch) ? NUMBER : ch;
plunky
1.97
811         if (ch < 128 && (spechr[ch] & C_2))
ragge
1.136
812                 c2 = *yyinp++;
ragge
1.19
813         else
814                 c2 = 0;
815
ragge
1.136
816         switch (t) {
817         case 0return WARN;
plunky
1.97
818         case '=':
819                 if (c2 == '='return EQ;
820                 break;
821         case '!':
822                 if (c2 == '='return NE;
823                 break;
824         case '|':
825                 if (c2 == '|'return OROR;
826                 break;
827         case '&':
828                 if (c2 == '&'return ANDAND;
829                 break;
ragge
1.19
830         case '<':
831                 if (c2 == '<'return LS;
832                 if (c2 == '='return LE;
833                 break;
834         case '>':
835                 if (c2 == '>'return RS;
836                 if (c2 == '='return GE;
837                 break;
838         case '+':
839         case '-':
840                 if (ch == c2)
plunky
1.78
841                         error("invalid preprocessor operator %c%c"chc2);
ragge
1.19
842                 break;
ragge
1.27
843
ragge
1.136
844         case '\'':
845                 yynode.op = NUMBER;
846                 yynode.nd_val = charcon(&yyinp);
847                 return NUMBER;
ragge
1.33
848
ragge
1.19
849         case NUMBER:
ragge
1.136
850                 cvtdig(&yyinp);
ragge
1.19
851                 return NUMBER;
ragge
1.27
852
ragge
1.19
853         default:
ragge
1.143
854                 if (ISID0(t)) {
855                         yyinp--;
856                         while (ISID(*yyinp))
857                                 yyinp++;
858                         yynode.nd_val = 0;
859                         return NUMBER;
860                 }
ragge
1.19
861                 return ch;
862         }
ragge
1.136
863         yyinp--;
ragge
1.19
864         return ch;
865 }
866
ragge
1.13
867 /*
ragge
1.6
868  * A new file included.
869  * If ifiles == NULL, this is the first file and already opened (stdin).
ragge
1.13
870  * Return 0 on success, -1 if file to be included is not found.
ragge
1.4
871  */
872 int
ragge
1.31
873 pushfile(const usch *fileconst usch *fnint idxvoid *incs)
ragge
1.4
874 {
ragge
1.6
875         struct includ ibuf;
876         struct includ *ic;
plunky
1.82
877         int otrulvl;
ragge
1.6
878
879         ic = &ibuf;
ragge
1.13
880         ic->next = ifiles;
ragge
1.4
881
ragge
1.6
882         if (file != NULL) {
ragge
1.31
883                 if ((ic->infil = open((const char *)fileO_RDONLY)) < 0)
ragge
1.4
884                         return -1;
ragge
1.13
885                 ic->orgfn = ic->fname = file;
886                 if (++inclevel > MAX_INCLEVEL)
plunky
1.102
887                         error("limit for nested includes exceeded");
ragge
1.6
888         } else {
889                 ic->infil = 0;
ragge
1.31
890                 ic->orgfn = ic->fname = (const usch *)"<stdin>";
ragge
1.6
891         }
ragge
1.170
892 #if LIBVMF
893         if (ifiles) {
894                 vmmodify(ifiles->vseg);
895                 vmunlock(ifiles->vseg);
896         }
897         ic->vseg = vmmapseg(&ibspcinclevel);