Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20160501092443

Diff

Diff from 1.173 to:

Annotations

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

Annotated File View

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