Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20160810173323

Diff

Diff from 1.182 to:

Annotations

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

Annotated File View

ragge
1.182
1 /*      $Id: token.c,v 1.182 2016/08/10 17:33:23 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
ragge
1.180
89 #define UNCH(ib, ch)    ib->buf[--ib->cptr] = 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.180
94 extern int skpows;
ragge
1.13
95
plunky
1.81
96 struct includ *ifiles;
97
ragge
1.175
98 static void ucn(int n);
ragge
1.174
99 static void fastcmnt2(int);
ragge
1.175
100 static int chktg2(int ch);
ragge
1.174
101
plunky
1.97
102 /* some common special combos for init */
103 #define C_NL    (C_SPEC|C_WSNL)
104 #define C_DX    (C_SPEC|C_ID|C_DIGIT|C_HEX)
105 #define C_I     (C_SPEC|C_ID|C_ID0)
106 #define C_IX    (C_SPEC|C_ID|C_ID0|C_HEX)
107
108 usch spechr[256] = {
ragge
1.174
109         C_SPEC|C_Q0,  0,      0,      C_SPECC_SPEC0,      0,
110         0,      C_WSNLC_NL,   0,      0,      C_WSNL|C_Q0,  0,
ragge
1.19
111         0,      0,      0,      0,      0,      0,      0,      0,
112         0,      0,      0,      0,      0,      0,      0,      0,
113
ragge
1.43
114         C_WSNLC_2,    C_SPEC0,      0,      0,      C_2,    C_SPEC,
ragge
1.174
115         0,      0,      0,      C_2,    0,      C_2,    0,      C_SPEC|C_Q,
plunky
1.97
116         C_DX,   C_DX,   C_DX,   C_DX,   C_DX,   C_DX,   C_DX,   C_DX,
ragge
1.174
117         C_DX,   C_DX,   0,      0,      C_2,    C_2,    C_2,    C_SPEC|C_Q,
ragge
1.19
118
ragge
1.174
119         0,      C_IX,   C_IX,   C_IX,   C_IX,   C_IX,   C_IX,   C_I,
120         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
ragge
1.19
121         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
ragge
1.174
122         C_I,    C_I,    C_I,    0,      C_SPEC|C_Q0,  0,      C_I,
ragge
1.19
123
ragge
1.174
124         0,      C_IX,   C_IX,   C_IX,   C_IX,   C_IX,   C_IX,   C_I,
125         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
ragge
1.19
126         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
127         C_I,    C_I,    C_I,    0,      C_2,    0,      0,      0,
ragge
1.111
128
129 /* utf-8 */
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         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
134
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         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
139
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         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
144
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,
147         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
plunky
1.112
148         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
ragge
1.19
149 };
ragge
1.1
150
plunky
1.102
151 /*
152  * fill up the input buffer
ragge
1.174
153  * n tells how nany chars at least.  0 == standard.
154  * 0 if EOF, != 0 if something could fill up buf.
plunky
1.102
155  */
156 static int
ragge
1.174
157 inpbuf(int n)
plunky
1.102
158 {
ragge
1.174
159         struct iobuf *ib = ifiles->ib;
160         int lensz = 0;
161
162         if (n > 0) {
163                 if (ib->bsz > ib->cptr + n)
164                         return 1/* enough in buffer */
165                 sz = ib->bsz - ib->cptr;
166                 memcpy(ib->buf+PBMAX - szib->buf + ib->cptrsz);
167         }
plunky
1.102
168
169         if (ifiles->infil == -1)
170                 return 0;
ragge
1.174
171         len = read(ifiles->infilib->buf+PBMAXCPPBUF-PBMAX);
plunky
1.102
172         if (len == -1)
173                 error("read error on file %s"ifiles->orgfn);
174         if (len > 0) {
ragge
1.174
175                 ib->cptr = PBMAX - sz;
ragge
1.178
176                 ib->bsz = PBMAX + len;
plunky
1.102
177         }
ragge
1.174
178         return len + sz;
179 }
180
181 /*
182  * Return a quick-cooked character.
183  * If buffer empty; return 0.
184  */
185 static int
186 qcchar(void)
187 {
188         struct iobuf *ib = ifiles->ib;
189         int ch;
190
191 newonedo {
192                 if (ib->cptr < ib->bsz) {
ragge
1.175
193                         if (!ISCQ(ch = ib->buf[ib->cptr++]))
ragge
1.174
194                                 return ch;
195                         break;
196                 }
197         } while ((ch = inpbuf(0)) > 0);
198
199         switch (ch) {
200         case 0:
201                 return 0/* end of file */
202
203         case '\r':
204                 goto newone;
205
206         case '\\':
ragge
1.175
207                 if (ib->cptr == ib->bsz)
208                         inpbuf(0);
209                 switch (ch = ib->buf[ib->cptr]) {
210                 case 'u':
211                 case 'U'
212                         if (incmnt
213                                 return '\\';
214                         ib->cptr++;
215                         ucn(ch == 'u' ? 4 : 8);
216                         break;
ragge
1.174
217                 case '\r':
218                         ib->cptr++;
ragge
1.175
219                         if (ib->cptr == ib->bsz)
220                                 inpbuf(0);
ragge
1.174
221                         /* FALLTHROUGH */
222                 case '\n':
ragge
1.175
223                         ib->cptr++;
ragge
1.174
224                         ifiles->escln++;
225                         break;
226                 default:
227                         return '\\';
228                 }
229                 goto newone;
230
231         case '?':
232                 inpbuf(2);
233                 if (ib->buf[ib->cptr] == '?') {
ragge
1.175
234                         if ((ch = chktg2(ib->buf[ib->cptr+1])) == 0)
235                                 return '?';
236                         ib->buf[++ib->cptr] = ch;
237                         goto newone;
ragge
1.174
238                 }
239                 return '?';
ragge
1.175
240
ragge
1.174
241         case '/':
ragge
1.175
242                 if (Cflag || incmnt || instr)
ragge
1.174
243                         return '/';
244                 incmnt++;
245                 ch = qcchar();
246                 incmnt--;
247                 if (ch == '/' || ch == '*') {
248                         int n = ifiles->lineno;
249                         fastcmnt2(ch);
250                         if (n == ifiles->lineno)
ragge
1.175
251                                 return ' ';
ragge
1.174
252                 } else {
253                         ib->buf[--ib->cptr] = ch;
254                         return '/';
255                 }
256                 goto newone;
257         }
258         error("ch error");
259         return 0/* XXX */
plunky
1.102
260 }
261
262 /*
263  * push a character back to the input stream
264  */
ragge
1.13
265 static void
266 unch(int c)
267 {
plunky
1.93
268         if (c == -1)
269                 return;
plunky
1.113
270
ragge
1.171
271         ifiles->ib->cptr--;
272         if (ifiles->ib->cptr < 0)
ragge
1.15
273                 error("pushback buffer full");
ragge
1.171
274         ifiles->ib->buf[ifiles->ib->cptr] = (usch)c;
ragge
1.13
275 }
ragge
1.1
276
plunky
1.102
277 /*
ragge
1.175
278  * Return trigraph mapping char or 0.
plunky
1.102
279  */
280 static int
ragge
1.174
281 chktg2(int ch)
282 {
283         switch (ch) {
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         case '-':  return '~';
293         }
294         return 0;
295 }
296
297 /*
298  * deal with comments in the fast scanner.
299  */
300 static void
301 fastcmnt2(int ch)
302 {
303
304         incmnt = 1;
305         if (ch == '/') { /* C++ comment */
306                 while ((ch = qcchar()) != '\n')
307                         ;
308                 unch(ch);
309         } else if (ch == '*') {
310                 for (;;) {
311                         if ((ch = qcchar()) == 0)
312                                 break;
313                         if (ch == '*') {
314                                 if ((ch = qcchar()) == '/') {
315                                         break;
316                                 } else
317                                         unch(ch);
318                         } else if (ch == '\n') {
ragge
1.180
319                                 putch('\n');
ragge
1.174
320                                 ifiles->lineno++;
321                         }
322                 }
323         } else
324                 error("fastcmnt2");
325         if (ch == 0)
326                 error("file ends in comment");
327         incmnt = 0;
328 }
329
ragge
1.125
330 /*
plunky
1.114
331  * check for universal-character-name on input, and
332  * unput to the pushback buffer encoded as UTF-8.
333  */
ragge
1.175
334 static void
ragge
1.174
335 ucn(int n)
336 {
337         unsigned long cpm;
338         int ch;
339
ragge
1.175
340         if (incmnt) {
341                 struct iobuf *ib = ifiles->ib;
342                 ib->cptr--; /* [uU] */
343                 ib->buf[--ib->cptr] = '\\';
344                 return;
plunky
1.114
345         }
346
347         cp = 0;
348         while (n-- > 0) {
ragge
1.175
349                 if ((ch = qcchar()) == 0 || (spechr[ch] & C_HEX) == 0) {
plunky
1.114
350                         warning("invalid universal character name");
351                         // XXX should actually unput the chars and return 0
352                         unch(ch); // XXX eof
353                         break;
354                 }
355                 cp = cp * 16 + dig2num(ch);
356         }
357
plunky
1.115
358         if ((cp < 0xa0 && cp != 0x24 && cp != 0x40 && cp != 0x60)
359             || (cp >= 0xd800 && cp <= 0xdfff))  /* 6.4.3.2 */
360                 error("universal character name cannot be used");
361
plunky
1.114
362         if (cp > 0x7fffffff)
363                 error("universal character name out of range");
364
365         n = 0;
366         m = 0x7f;
367         while (cp > m) {
368                 unch(0x80 | (cp & 0x3f));
369                 cp >>= 6;
370                 m >>= (n++ ? 1 : 2);
371         }
372         unch(((m << 1) ^ 0xfe) | cp);
373 }
374
ragge
1.122
375 /*
376  * deal with comments when -C is active.
ragge
1.125
377  * Save comments in expanded macros???
ragge
1.122
378  */
ragge
1.177
379 void
ragge
1.174
380 Ccmnt2(void (*d)(int), int ch)
381 {
382
383         if (ch == '/') { /* C++ comment */
384                 d(ch);
385                 do {
386                         d(ch);
ragge
1.175
387                 } while ((ch = qcchar()) && ch != '\n');
ragge
1.174
388                 unch(ch);
389         } else if (ch == '*') {
390                 d('/');
391                 d('*');
392                 for (;;) {
ragge
1.175
393                         ch = qcchar();
ragge
1.174
394                         d(ch);
395                         if (ch == '*') {
ragge
1.175
396                                 if ((ch = qcchar()) == '/') {
ragge
1.174
397                                         d(ch);
398                                         break;
399                                 } else
400                                         unch(ch);
401                         } else if (ch == '\n') {
402                                 ifiles->lineno++;
403                         }
404                 }
405         }
406 }
407
408 /*
ragge
1.125
409  * Traverse over spaces and comments from the input stream,
ragge
1.129
410  * Returns first non-space character.
ragge
1.125
411  */
plunky
1.108
412 static int
ragge
1.129
413 fastspc(void)
ragge
1.45
414 {
415         int ch;
416
ragge
1.175
417         while ((ch = qcchar()), ISWS(ch))
ragge
1.129
418                 ;
ragge
1.125
419         return ch;
ragge
1.45
420 }
421
ragge
1.19
422 /*
ragge
1.164
423  * readin chars and store in buf. Warn about too long names.
424  */
425 usch *
426 bufid(int chstruct iobuf *ob)
427 {
ragge
1.171
428         int n = ob->cptr;
ragge
1.164
429
430         do {
ragge
1.171
431                 if (ob->cptr - n == MAXIDSZ)
ragge
1.164
432                         warning("identifier exceeds C99 5.2.4.1");
433                 if (ob->cptr < ob->bsz)
ragge
1.171
434                         ob->buf[ob->cptr++] = ch;
ragge
1.164
435                 else
436                         putob(obch);
ragge
1.175
437         } while (spechr[ch = qcchar()] & C_ID);
ragge
1.171
438         ob->buf[ob->cptr] = 0/* legal */
ragge
1.164
439         unch(ch);
ragge
1.171
440         return ob->buf+n;
ragge
1.164
441 }
442
ragge
1.161
443 usch idbuf[MAXIDSZ+1];
ragge
1.122
444 /*
ragge
1.159
445  * readin chars and store in buf. Warn about too long names.
ragge
1.131
446  */
ragge
1.134
447 usch *
ragge
1.159
448 readid(int ch)
ragge
1.131
449 {
ragge
1.159
450         int p = 0;
451
ragge
1.131
452         do {
ragge
1.159
453                 if (p == MAXIDSZ)
454                         warning("identifier exceeds C99 5.2.4.1, truncating");
455                 if (p < MAXIDSZ)
456                         idbuf[p] = ch;
457                 p++;
ragge
1.175
458         } while (spechr[ch = qcchar()] & C_ID);
ragge
1.159
459         idbuf[p] = 0;
ragge
1.131
460         unch(ch);
ragge
1.159
461         return idbuf;
ragge
1.131
462 }
463
464 /*
ragge
1.125
465  * get a string or character constant and save it as given by d.
466  */
ragge
1.164
467 struct iobuf *
468 faststr(int bcstruct iobuf *ob)
ragge
1.125
469 {
ragge
1.175
470         struct iobuf *ib = ifiles->ib;
ragge
1.125
471         int ch;
472
ragge
1.164
473         if (ob == NULL)
ragge
1.167
474                 ob = getobuf(BNORMAL);
ragge
1.164
475
ragge
1.175
476         instr = 1;
ragge
1.164
477         putob(obbc);
ragge
1.175
478         for (;;) {
479                 if (ib->bsz == ib->cptr)
480                         ch = qcchar();
481                 else if (ISCQ(ch = ib->buf[ib->cptr]))
482                         ch = qcchar();
483                 else
484                         ib->cptr++;
485                 switch (ch) {
486                 case '\\':
487                         putob(obch);
488                         if (ib->cptr == ib->bsz)
489                                 inpbuf(0);
490                         incmnt = 1;
491                         putob(obqcchar());
492                         incmnt = 0;
493                         continue;
494                 case '\n':
ragge
1.125
495                         warning("unterminated literal");
ragge
1.175
496                         instr = 0;
ragge
1.125
497                         unch(ch);
ragge
1.164
498                         return ob;
ragge
1.125
499                 }
ragge
1.164
500                 putob(obch);
ragge
1.175
501                 if (ch == bc)
502                         break;
ragge
1.125
503         }
ragge
1.171
504         ob->buf[ob->cptr] = 0;
ragge
1.175
505         instr = 0;
ragge
1.164
506         return ob;
ragge
1.125
507 }
508
509 /*
ragge
1.164
510  * get a preprocessing number and save it as given by ob.
ragge
1.125
511  * returns first non-pp-number char.
ragge
1.164
512  * We know that this is a valid number already.
ragge
1.125
513  *
514  *      pp-number:      digit
515  *                      . digit
516  *                      pp-number digit
517  *                      pp-number identifier-nondigit
518  *                      pp-number e sign
519  *                      pp-number E sign
520  *                      pp-number p sign
521  *                      pp-number P sign
522  *                      pp-number .
523  */
ragge
1.134
524 int
ragge
1.164
525 fastnum(int chstruct iobuf *ob)
ragge
1.125
526 {
527         int c2;
528
ragge
1.126
529         if ((spechr[ch] & C_DIGIT) == 0) {
530                 /* not digit, dot */
ragge
1.164
531                 putob(obch);
ragge
1.175
532                 ch = qcchar();
ragge
1.126
533         }
ragge
1.125
534         for (;;) {
ragge
1.164
535                 putob(obch);
ragge
1.175
536                 if ((ch = qcchar()) == 0)
537                         return 0;
ragge
1.174
538                 if ((c2 = (ch & 0337)) == 'E' || c2 == 'P') {
ragge
1.175
539                         if ((c2 = qcchar()) != '-' && c2 != '+') {
540                                 if (c2 > 0)
ragge
1.125
541                                         unch(c2);
542                                 break;
543                         }
ragge
1.164
544                         putob(obch);
ragge
1.125
545                         ch = c2;
546                 } else if (ch == '.' || (spechr[ch] & C_ID)) {
547                         continue;
548                 } else
549                         break;
550         }
551         return ch;
552 }
ragge
1.122
553
554 /*
ragge
1.19
555  * Scan quickly the input file searching for:
556  *      - '#' directives
557  *      - keywords (if not flslvl)
558  *      - comments
559  *
560  *      Handle strings, numbers and trigraphs with care.
561  *      Only data from pp files are scanned here, never any rescans.
ragge
1.125
562  *      This loop is always at trulvl.
ragge
1.19
563  */
ragge
1.168
564 void
ragge
1.19
565 fastscan(void)
566 {
ragge
1.164
567         struct iobuf *obrbs, *rb = &rbs;
ragge
1.167
568         extern struct iobuf pb;
ragge
1.174
569         struct iobuf *ib = ifiles->ib;
ragge
1.19
570         struct symtab *nl;
ragge
1.180
571         int chc2;
ragge
1.164
572         usch *dp;
573
574 #define IDSIZE  128
ragge
1.171
575         rb->buf = xmalloc(IDSIZE+1);
576         rb->cptr = 0;
577         rb->bsz = IDSIZE;
ragge
1.19
578
579         goto run;
ragge
1.125
580
ragge
1.19
581         for (;;) {
ragge
1.125
582                 /* tight loop to find special chars */
583                 /* should use getchar/putchar here */
584                 for (;;) {
ragge
1.174
585                         if (ib->cptr < ib->bsz)
586                                 ch = ib->buf[ib->cptr++];
587                         else
588                                 ch = qcchar();
589 xloop:                  if (ch < 0ch = 0/* XXX */
ragge
1.125
590                         if ((spechr[ch] & C_SPEC) != 0)
591                                 break;
592                         putch(ch);
ragge
1.19
593                 }
ragge
1.125
594
ragge
1.19
595                 switch (ch) {
ragge
1.174
596                 case 0:
597                         free(rb->buf);
598                         return;
599
ragge
1.43
600                 case WARN:
601                 case CONC:
602                         error("bad char passed");
603                         break;
604
ragge
1.19
605                 case '/'/* Comments */
ragge
1.174
606                         ch = qcchar();
607                         if (ch  == '/' || ch == '*') {
608                                 if (Cflag == 0) {
609                                         int n = ifiles->lineno;
610                                         fastcmnt2(ch);
611                                         if (n == ifiles->lineno)
612                                                 putch(' '); /* 5.1.1.2 p3 */
613                                 } else
614                                         Ccmnt2(putchch);
615                         } else {
ragge
1.173
616                                 putch('/');
617                                 goto xloop;
ragge
1.140
618                         }
ragge
1.19
619                         break;
620
621                 case '\n'/* newlines, for pp directives */
ragge
1.125
622                         /* take care of leftover \n */
ragge
1.180
623                         while (ifiles->escln > 0) {
plunky
1.121
624                                 putch('\n');
ragge
1.180
625                                 ifiles->escln--;
626                                 ifiles->lineno++;
627                         }
628                         putch('\n');
629                         ifiles->lineno++;
ragge
1.125
630
631                         /* search for a # */
ragge
1.174
632 run:                    while ((ch = qcchar()) == '\t' || ch == ' ')
ragge
1.125
633                                 putch(ch);
634                         if (ch == '%') {
ragge
1.174
635                                 if ((c2 = qcchar()) != ':')
ragge
1.125
636                                         unch(c2);
637                                 else
638                                         ch = '#';
ragge
1.50
639                         }
ragge
1.125
640                         if (ch  == '#')
ragge
1.19
641                                 ppdir();
ragge
1.125
642                         else
643                                 goto xloop;
644                         break;
645
ragge
1.140
646                 case '?':
ragge
1.174
647                         if (ib->cptr+1 >= ib->bsz)
648                                 inpbuf(2);
649                         if (ib->buf[ib->cptr] == '?') {
650                                 ib->cptr++;
651                                 if ((ch = chktg2(ib->buf[ib->cptr++])))
652                                         goto xloop;
653                                 ib->cptr -= 2;
654                         }
655                         putch('?');
656                         break;
657
ragge
1.125
658                 case '\''/* character constant */
659                         if (tflag) {
660                                 putch(ch);
661                                 break;  /* character constants ignored */
ragge
1.19
662                         }
ragge
1.125
663                         /* FALLTHROUGH */
ragge
1.19
664                 case '\"'/* strings */
ragge
1.180
665                         if (skpows)
666                                 cntline();
ragge
1.167
667                         faststr(ch, &pb);
ragge
1.19
668                         break;
669
670                 case '.':  /* for pp-number */
ragge
1.175
671                         if ((spechr[c2 = qcchar()] & C_DIGIT) == 0) {
ragge
1.164
672                                 putch('.');
ragge
1.173
673                                 goto xloop;
ragge
1.164
674                         }
ragge
1.173
675                         unch(c2);
ragge
1.19
676                 case '0'case '1'case '2'case '3'case '4':
677                 case '5'case '6'case '7'case '8'case '9':
ragge
1.180
678                         if (skpows)
679                                 cntline();
ragge
1.167
680                         ch = fastnum(ch, &pb);
ragge
1.19
681                         goto xloop;
682
ragge
1.173
683                 case 'L':
684                 case 'U':
ragge
1.150
685                 case 'u':
ragge
1.175
686                         if (ib->cptr+2 >= ib->bsz)
687                                 inpbuf(2);
688                         if ((c2 = ib->buf[ib->cptr]) == '\"' || c2 == '\'') {
ragge
1.150
689                                 putch(ch);
ragge
1.175
690                                 break;
691                         } else if (c2 == '8' && ch == 'u' &&
692                             ib->buf[ib->cptr+1] == '\"') {
693                                 ib->cptr++;
694                                 putstr((usch *)"u8");
695                                 break;
ragge
1.19
696                         }
697                         /* FALLTHROUGH */
698                 default:
plunky
1.102
699 #ifdef PCC_DEBUG
ragge
1.19
700                         if ((spechr[ch] & C_ID) == 0)
701                                 error("fastscan");
plunky
1.102
702 #endif
ragge
1.131
703                         if (flslvl)
704                                 error("fastscan flslvl");
ragge
1.171
705                         rb->cptr = 0;
ragge
1.164
706                         dp = bufid(chrb);
707                         if ((nl = lookup(dpFIND)) != NULL) {
708                                 if ((ob = kfind(nl)) != NULL) {
ragge
1.162
709                                         if (*ob->buf == '-' || *ob->buf == '+')
ragge
1.155
710                                                 putch(' ');
ragge
1.180
711                                         if (skpows)
712                                                 cntline();
ragge
1.167
713                                         buftobuf(ob, &pb);
ragge
1.171
714                                         if (ob->cptr > 0 &&
715                                             (ob->buf[ob->cptr-1] == '-' ||
716                                             ob->buf[ob->cptr-1] == '+'))
ragge
1.155
717                                                 putch(' ');
ragge
1.161
718                                         bufree(ob);
ragge
1.155
719                                 }
ragge
1.164
720                         } else {
ragge
1.159
721                                 putstr(dp);
ragge
1.164
722                         }
ragge
1.19
723                         break;
plunky
1.114
724
725                 case '\\':
ragge
1.175
726                         ib->buf[--ib->cptr] = '\\';
727                         if ((ch = qcchar()) != '\\')
728                                 goto xloop;
ragge
1.125
729                         putch('\\');
plunky
1.114
730                         break;
ragge
1.19
731                 }
732         }
733 }
ragge
1.1
734
ragge
1.136
735 /*
736  * Store an if/elif line on heap for parsing, evaluate macros and 
737  * call yyparse().
738  */
739 static usch *yyinp;
ragge
1.143
740 int inexpr;
ragge
1.136
741 static int
742 exprline(void)
743 {
ragge
1.164
744         extern int nbufused;
745         struct iobuf *ob, *rb;
ragge
1.136
746         struct symtab *nl;
747         int oCflag = Cflag;
ragge
1.165
748         usch *dp;
ragge
1.153
749         int cdifdef;
ragge
1.136
750
ragge
1.167
751         rb = getobuf(BNORMAL);
ragge
1.164
752         nbufused--;
ragge
1.136
753         Cflag = ifdef = 0;
754
ragge
1.164
755         for (;;) {
ragge
1.175
756                 c = qcchar();
ragge
1.164
757 xloop:          if (c == '\n')
758                         break;
759                 if (c == '.') {
760                         putob(rb'.');
ragge
1.175
761                         if ((spechr[c = qcchar()] & C_DIGIT) == 0)
ragge
1.164
762                                 goto xloop;
763                 }
764                 if (ISDIGIT(c)) {
765                         c = fastnum(crb);
766                         goto xloop;
767                 }
ragge
1.148
768                 if (c == '\'' || c == '\"') {
ragge
1.164
769                         faststr(crb);
ragge
1.148
770                         continue;
771                 }
ragge
1.153
772                 if (c == 'L' || c == 'u' || c == 'U') {
ragge
1.175
773                         unch(d = qcchar());
ragge
1.153
774                         if (d == '\'')  /* discard wide designator */
775                                 continue;
776                 }
ragge
1.136
777                 if (ISID0(c)) {
ragge
1.159
778                         dp = readid(c);
779                         nl = lookup(dpFIND);
ragge
1.172
780                         if (nl && nl->type == DEFLOC) {
ragge
1.136
781                                 ifdef = 1;
782                         } else if (ifdef) {
ragge
1.164
783                                 putob(rbnl ? '1' : '0');
ragge
1.136
784                                 ifdef = 0;
785                         } else if (nl != NULL) {
ragge
1.143
786                                 inexpr = 1;
ragge
1.161
787                                 if ((ob = kfind(nl))) {
ragge
1.171
788                                         ob->buf[ob->cptr] = 0;
ragge
1.164
789                                         strtobuf(ob->bufrb);
ragge
1.161
790                                         bufree(ob);
ragge
1.154
791                                 } else
ragge
1.164
792                                         putob(rb'0');
ragge
1.143
793                                 inexpr = 0;
ragge
1.136
794                         } else
ragge
1.164
795                                 putob(rb'0');
ragge
1.136
796                 } else
ragge
1.164
797                         putob(rbc);
ragge
1.136
798         }
ragge
1.171
799         rb->buf[rb->cptr] = 0;
ragge
1.136
800         unch('\n');
ragge
1.164
801         yyinp = rb->buf;
ragge
1.136
802         c = yyparse();
ragge
1.164
803         bufree(rb);
804         nbufused++;
ragge
1.136
805         Cflag = oCflag;
806         return c;
807 }
808
ragge
1.19
809 int
plunky
1.64
810 yylex(void)
ragge
1.19
811 {
ragge
1.136
812         int chc2t;
ragge
1.19
813
ragge
1.136
814         while ((ch = *yyinp++) == ' ' || ch == '\t')
ragge
1.19
815                 ;
ragge
1.136
816         t = ISDIGIT(ch) ? NUMBER : ch;
plunky
1.97
817         if (ch < 128 && (spechr[ch] & C_2))
ragge
1.136
818                 c2 = *yyinp++;
ragge
1.19
819         else
820                 c2 = 0;
821
ragge
1.136
822         switch (t) {
823         case 0return WARN;
plunky
1.97
824         case '=':
825                 if (c2 == '='return EQ;
826                 break;
827         case '!':
828                 if (c2 == '='return NE;
829                 break;
830         case '|':
831                 if (c2 == '|'return OROR;
832                 break;
833         case '&':
834                 if (c2 == '&'return ANDAND;
835                 break;
ragge
1.19
836         case '<':
837                 if (c2 == '<'return LS;
838                 if (c2 == '='return LE;
839                 break;
840         case '>':
841                 if (c2 == '>'return RS;
842                 if (c2 == '='return GE;
843                 break;
844         case '+':
845         case '-':
846                 if (ch == c2)
plunky
1.78
847                         error("invalid preprocessor operator %c%c"chc2);
ragge
1.19
848                 break;
ragge
1.27
849
ragge
1.136
850         case '\'':
851                 yynode.op = NUMBER;
852                 yynode.nd_val = charcon(&yyinp);
853                 return NUMBER;
ragge
1.33
854
ragge
1.19
855         case NUMBER:
ragge
1.136
856                 cvtdig(&yyinp);
ragge
1.19
857                 return NUMBER;
ragge
1.27
858
ragge
1.19
859         default:
ragge
1.143
860                 if (ISID0(t)) {
861                         yyinp--;
862                         while (ISID(*yyinp))
863                                 yyinp++;
864                         yynode.nd_val = 0;
865                         return NUMBER;
866                 }
ragge
1.19
867                 return ch;
868         }
ragge
1.136
869         yyinp--;
ragge
1.19
870         return ch;
871 }
872
ragge
1.13
873 /*
ragge
1.6
874  * A new file included.
875  * If ifiles == NULL, this is the first file and already opened (stdin).
ragge
1.13
876  * Return 0 on success, -1 if file to be included is not found.
ragge
1.4
877  */
878 int
ragge
1.31
879 pushfile(const usch *fileconst usch *fnint idxvoid *incs)
ragge
1.4
880 {
ragge
1.6
881         struct includ ibuf;
882         struct includ *ic;
plunky
1.82
883         int otrulvl;
ragge
1.6
884
885         ic = &ibuf;
ragge
1.13
886         ic->next = ifiles;
ragge
1.4
887
ragge
1.6
888         if (file != NULL) {
ragge
1.31
889                 if ((ic->infil = open((const char *)fileO_RDONLY)) < 0)
ragge
1.4
890                         return -1;
ragge
1.13
891                 ic->orgfn = ic->fname = file;
892