Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:plunky:20140528085242

Diff

Diff from 1.113 to:

Annotations

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

Annotated File View

plunky
1.113
1 /*      $Id: token.c,v 1.113 2014/05/28 08:52:42 plunky 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.
32  *      - sloscan() tokenize the input stream and returns tokens.
33  *              It may recurse into itself during expansion.
plunky
1.113
34  *      - yylex() returns something from the input stream that
ragge
1.19
35  *              is suitable for yacc.
36  *
37  *      Other functions of common use:
38  *      - inpch() returns a raw character from the current input stream.
39  *      - inch() is like inpch but \\n and trigraphs are expanded.
40  *      - unch() pushes back a character to the input stream.
41  */
42
ragge
1.13
43 #include "config.h"
44
ragge
1.1
45 #include <stdlib.h>
46 #include <string.h>
ragge
1.13
47 #ifdef HAVE_UNISTD_H
ragge
1.2
48 #include <unistd.h>
ragge
1.13
49 #endif
ragge
1.2
50 #include <fcntl.h>
ragge
1.111
51 #include <ctype.h>
ragge
1.1
52
ragge
1.13
53 #include "compat.h"
ragge
1.111
54 #include "unicode.h"
ragge
1.1
55 #include "cpp.h"
plunky
1.72
56 #include "cpy.h"
ragge
1.13
57
plunky
1.112
58 static void cvtdig(int);
ragge
1.13
59 static int charcon(usch *);
60 static void elsestmt(void);
61 static void ifdefstmt(void);
62 static void ifndefstmt(void);
63 static void endifstmt(void);
64 static void ifstmt(void);
65 static void cpperror(void);
plunky
1.102
66 static void cppwarning(void);
67 static void undefstmt(void);
ragge
1.13
68 static void pragmastmt(void);
69 static void elifstmt(void);
70
ragge
1.19
71 #define PUTCH(ch) if (!flslvl) putch(ch)
ragge
1.13
72 /* protection against recursion in #include */
73 #define MAX_INCLEVEL    100
74 static int inclevel;
75
ragge
1.44
76 usch yytext[CPPBUF];
gmcgarry
1.16
77
plunky
1.81
78 struct includ *ifiles;
79
plunky
1.97
80 /* some common special combos for init */
81 #define C_NL    (C_SPEC|C_WSNL)
82 #define C_DX    (C_SPEC|C_ID|C_DIGIT|C_HEX)
83 #define C_I     (C_SPEC|C_ID|C_ID0)
84 #define C_IP    (C_SPEC|C_ID|C_ID0|C_EP)
85 #define C_IX    (C_SPEC|C_ID|C_ID0|C_HEX)
86 #define C_IXE   (C_SPEC|C_ID|C_ID0|C_HEX|C_EP)
87
88 usch spechr[256] = {
ragge
1.43
89         0,      0,      0,      0,      C_SPECC_SPEC0,      0,
plunky
1.97
90         0,      C_WSNLC_NL,   0,      0,      C_WSNL0,      0,
ragge
1.19
91         0,      0,      0,      0,      0,      0,      0,      0,
92         0,      0,      0,      0,      0,      0,      0,      0,
93
ragge
1.43
94         C_WSNLC_2,    C_SPEC0,      0,      0,      C_2,    C_SPEC,
ragge
1.33
95         0,      0,      0,      C_2,    0,      C_2,    0,      C_SPEC|C_2,
plunky
1.97
96         C_DX,   C_DX,   C_DX,   C_DX,   C_DX,   C_DX,   C_DX,   C_DX,
plunky
1.102
97         C_DX,   C_DX,   0,      0,      C_2,    C_2,    C_2,    0,
ragge
1.19
98
plunky
1.97
99         0,      C_IX,   C_IX,   C_IX,   C_IX,   C_IXE,  C_IX,   C_I,
ragge
1.19
100         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
plunky
1.97
101         C_IP,   C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
plunky
1.102
102         C_I,    C_I,    C_I,    0,      0,      0,      0,      C_I,
ragge
1.19
103
plunky
1.97
104         0,      C_IX,   C_IX,   C_IX,   C_IX,   C_IXE,  C_IX,   C_I,
ragge
1.19
105         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
plunky
1.97
106         C_IP,   C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
ragge
1.19
107         C_I,    C_I,    C_I,    0,      C_2,    0,      0,      0,
ragge
1.111
108
109 /* utf-8 */
110         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
111         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
112         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
113         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
114
115         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
116         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
117         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
118         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
119
120         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
121         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
122         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
123         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
124
125         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
126         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
127         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
plunky
1.112
128         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
ragge
1.19
129 };
ragge
1.1
130
plunky
1.102
131 /*
132  * fill up the input buffer
133  */
134 static int
135 inpbuf(void)
136 {
137         int len;
138
139         if (ifiles->infil == -1)
140                 return 0;
141         len = read(ifiles->infilifiles->bufferCPPBUF);
142         if (len == -1)
143                 error("read error on file %s"ifiles->orgfn);
144         if (len > 0) {
145                 ifiles->buffer[len] = 0;
146                 ifiles->curptr = ifiles->buffer;
147                 ifiles->maxread = ifiles->buffer + len;
148         }
149         return len;
150 }
151
152 /*
153  * return a raw character from the input stream
154  */
155 static inline int
156 inpch(void)
157 {
158
159         do {
160                 if (ifiles->curptr < ifiles->maxread)
161                         return *ifiles->curptr++;
162         } while (inpbuf() > 0);
163
164         return -1;
165 }
166
167 /*
168  * push a character back to the input stream
169  */
ragge
1.13
170 static void
171 unch(int c)
172 {
plunky
1.93
173         if (c == -1)
174                 return;
plunky
1.113
175
plunky
1.102
176         ifiles->curptr--;
ragge
1.15
177         if (ifiles->curptr < ifiles->bbuf)
178                 error("pushback buffer full");
gmcgarry
1.26
179         *ifiles->curptr = (usch)c;
ragge
1.13
180 }
ragge
1.1
181
plunky
1.102
182 /*
183  * Check for (and convert) trigraphs.
184  */
185 static int
186 chktg(void)
187 {
188         int ch;
189
190         if ((ch = inpch()) != '?') {
191                 unch(ch);
192                 return 0;
193         }
194
195         switch (ch = inpch()) {
196         case '=':  return '#';
197         case '(':  return '[';
198         case ')':  return ']';
199         case '<':  return '{';
200         case '>':  return '}';
201         case '/':  return '\\';
202         case '\''return '^';
203         case '!':  return '|';
204         case '-':  return '~';
205         }
206
207         unch(ch);
208         unch('?');
209         return 0;
210 }
211
212 /*
213  * check for (and eat) end-of-line
214  */
215 static int
216 chkeol(void)
217 {
218         int ch;
219
220         ch = inpch();
221         if (ch == '\r') {
222                 ch = inpch();
223                 if (ch == '\n')
224                         return '\n';
225
226                 unch(ch);
227                 unch('\r');
228                 return 0;
229         }
230         if (ch == '\n')
231                 return '\n';
232
233         unch(ch);
234         return 0;
235 }
236
ragge
1.111
237 static int
238 chkucn(void)
239 {
240         int chsz;
241
242         ch = inpch();
243         if(ch != '\\'){
244                 unch(ch);
245                 return 0;
246         }
247         ch = inpch();
248     if (ch == 'u') {
249         int iv;
250         sz=4;
251 ucnshort:
252         for(i=0,v=0;i<sz;i++){
253             ch=toupper(inpch());
254             if(ch>='0' && ch<='9'v=(v<<4)+ch-'0';
255             else if(ch>='A' && ch<='F'v=(v<<4)+ch-'A'+10;
256             else {
257                 if(sz>2warning(
258                     "unicode escape %d digits too short",sz-i);
259                 unch(ch);
260                 break;
261             }
262         }
263         char u8str[8],*p=cp2u8(u8str,v);
264         while(--p>u8strunch(*p);
265         return u8str[0];
266     } else if (ch == 'U') {
267         sz=8;
268         goto ucnshort;
269     }
270     unch(ch);
271         unch('\\');
272         return 0;
273 }
274
plunky
1.102
275 /*
276  * return next char, after converting trigraphs and
277  * skipping escaped line endings
278  */
279 static inline int
280 inch(void)
281 {
282         int ch;
283
284         for (;;) {
ragge
1.111
285                 if((ch = chkucn())) return ch;
plunky
1.102
286                 ch = inpch();
287                 if (ch == '?' && (ch = chktg()) == 0)
288                         return '?';
289                 if (ch != '\\' || chkeol() == 0)
290                         return ch;
291                 ifiles->escln++;
292         }
293 }
294
plunky
1.108
295 static int
ragge
1.45
296 eatcmnt(void)
297 {
298         int ch;
299
plunky
1.108
300         if (Cflag) {
301                 PUTCH('/'); PUTCH('*');
302         }
ragge
1.45
303         for (;;) {
304                 ch = inch();
305                 if (ch == '\n') {
306                         ifiles->lineno++;
plunky
1.102
307                         putch('\n');
308                         continue;
ragge
1.45
309                 }
310                 if (ch == -1)
plunky
1.108
311                         return -1;
ragge
1.45
312                 if (ch == '*') {
313                         ch = inch();
plunky
1.108
314                         if (ch == '/')
ragge
1.45
315                                 break;
316                         unch(ch);
317                         ch = '*';
318                 }
319                 if (CflagPUTCH(ch);
320         }
plunky
1.108
321         if (Cflag) {
322                 PUTCH('*'); PUTCH('/');
323         } else
324                 PUTCH(' ');
325
326         return 0;
ragge
1.45
327 }
328
ragge
1.19
329 /*
330  * Scan quickly the input file searching for:
331  *      - '#' directives
332  *      - keywords (if not flslvl)
333  *      - comments
334  *
335  *      Handle strings, numbers and trigraphs with care.
336  *      Only data from pp files are scanned here, never any rescans.
337  *      TODO: Only print out strings before calling other functions.
338  */
339 static void
340 fastscan(void)
341 {
342         struct symtab *nl;
plunky
1.102
343         int chi;
ragge
1.49
344         usch *cp;
ragge
1.19
345
346         goto run;
347         for (;;) {
plunky
1.102
348                 ch = inch();
ragge
1.19
349 xloop:          if (ch == -1)
350                         return;
plunky
1.60
351 #ifdef PCC_DEBUG
ragge
1.43
352                 if (dflag>1)
353                         printf("fastscan ch %d (%c)\n"chch > 31 ? ch : '@');
plunky
1.60
354 #endif
ragge
1.19
355                 if ((spechr[ch] & C_SPEC) == 0) {
356                         PUTCH(ch);
357                         continue;
358                 }
359                 switch (ch) {
ragge
1.44
360                 case EBLOCK:
ragge
1.43
361                 case WARN:
362                 case CONC:
363                         error("bad char passed");
364                         break;
365
ragge
1.19
366                 case '/'/* Comments */
367                         if ((ch = inch()) == '/') {
ragge
1.45
368 cppcmt:                         if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
ragge
1.19
369                                 do {
370                                         if (CflagPUTCH(ch);
371                                         ch = inch();
plunky
1.108
372                                         if (ch == -1)
373                                                 goto eof;
374                                 } while (ch != '\n');
ragge
1.19
375                                 goto xloop;
376                         } else if (ch == '*') {
plunky
1.108
377                                 if (eatcmnt() == -1)
378                                         goto eof;
ragge
1.19
379                         } else {
380                                 PUTCH('/');
381                                 goto xloop;
382                         }
383                         break;
384
385                 case '\n'/* newlines, for pp directives */
plunky
1.102
386                         i = ifiles->escln + 1;
387                         ifiles->lineno += i;
388                         ifiles->escln = 0;
389                         while (i-- > 0)
390                                 putch('\n');
391 run:                    for(;;) {
392                                 ch = inch();
ragge
1.45
393                                 if (ch == '/') {
plunky
1.102
394                                         ch = inch();
ragge
1.45
395                                         if (ch == '/')
396                                                 goto cppcmt;
397                                         if (ch == '*') {
plunky
1.108
398                                                 if (eatcmnt() == -1)
399                                                         goto eof;
plunky
1.102
400                                                 continue;
plunky
1.92
401                                         }
ragge
1.45
402                                         unch(ch);
403                                         ch = '/';
404                                 }
plunky
1.102
405                                 if (ch != ' ' && ch != '\t')
406                                         break;
407                                 PUTCH(ch);
ragge
1.50
408                         }
ragge
1.19
409                         if (ch == '#') {
410                                 ppdir();
411                                 continue;
ragge
1.40
412                         } else if (ch == '%') {
plunky
1.102
413                                 ch = inch();
ragge
1.40
414                                 if (ch == ':') {
415                                         ppdir();
416                                         continue;
417                                 }
plunky
1.92
418                                 unch(ch);
419                                 ch = '%';
ragge
1.19
420                         }
421                         goto xloop;
422
423                 case '\"'/* strings */
ragge
1.21
424 str:                    PUTCH(ch);
plunky
1.102
425                         while ((ch = inch()) != '\"') {
426                                 if (ch == '\\') {
427                                         PUTCH('\\');
428                                         ch = inch();
429                                 }
plunky
1.104
430                                 if (ch == '\n') {
431                                         warning("unterminated string literal");
ragge
1.53
432                                         goto xloop;
plunky
1.104
433                                 }
plunky
1.90
434                                 if (ch == -1)
plunky
1.108
435                                         goto eof;
ragge
1.53
436                                 PUTCH(ch);
ragge
1.21
437                         }
ragge
1.19
438                         PUTCH(ch);
439                         break;
440
441                 case '.':  /* for pp-number */
442                         PUTCH(ch);
plunky
1.102
443                         ch = inch();
ragge
1.19
444                         if (ch < '0' || ch > '9')
445                                 goto xloop;
plunky
1.102
446
ragge
1.19
447                         /* FALLTHROUGH */
448                 case '0'case '1'case '2'case '3'case '4':
449                 case '5'case '6'case '7'case '8'case '9':
450                         do {
plunky
1.99
451 nxp:                            PUTCH(ch);
plunky
1.102
452                                 ch = inch();
plunky
1.94
453                                 if (ch == -1)
plunky
1.108
454                                         goto eof;
plunky
1.112
455                                 if ((spechr[ch] & C_EP)) {
ragge
1.19
456                                         PUTCH(ch);
plunky
1.102
457                                         ch = inch();
ragge
1.19
458                                         if (ch == '-' || ch == '+')
plunky
1.99
459                                                 goto nxp;
plunky
1.94
460                                         if (ch == -1)
plunky
1.108
461                                                 goto eof;
ragge
1.19
462                                 }
463                         } while ((spechr[ch] & C_ID) || (ch == '.'));
464                         goto xloop;
465
plunky
1.104
466                 case '\''/* character constant */
ragge
1.21
467 con:                    PUTCH(ch);
ragge
1.23
468                         if (tflag)
plunky
1.102
469                                 break/* character constants ignored */
470                         while ((ch = inch()) != '\'') {
471                                 if (ch == '\\') {
472                                         PUTCH('\\');
473                                         ch = inch();
474                                 }
plunky
1.104
475                                 if (ch == '\n') {
476                                         warning("unterminated character constant");
ragge
1.52
477                                         goto xloop;
plunky
1.104
478                                 }
plunky
1.90
479                                 if (ch == -1)
plunky
1.108
480                                         goto eof;
ragge
1.52
481                                 PUTCH(ch);
ragge
1.21
482                         }
ragge
1.19
483                         PUTCH(ch);
484                         break;
ragge
1.21
485
ragge
1.19
486                 case 'L':
plunky
1.102
487                         ch = inch();
ragge
1.19
488                         if (ch == '\"') {
489                                 PUTCH('L');
490                                 goto str;
491                         }
492                         if (ch == '\'') {
493                                 PUTCH('L');
494                                 goto con;
495                         }
496                         unch(ch);
497                         ch = 'L';
plunky
1.102
498
ragge
1.19
499                         /* FALLTHROUGH */
500                 default:
plunky
1.102
501 #ifdef PCC_DEBUG
ragge
1.19
502                         if ((spechr[ch] & C_ID) == 0)
503                                 error("fastscan");
plunky
1.102
504 #endif
gmcgarry
1.58
505                         i = 0;
ragge
1.19
506                         do {
gmcgarry
1.26
507                                 yytext[i++] = (usch)ch;
plunky
1.102
508                                 ch = inch();
509                         } while (ch != -1 && (spechr[ch] & C_ID));
510
ragge
1.19
511                         yytext[i] = 0;
512                         unch(ch);
ragge
1.43
513
plunky
1.108
514                         if (flslvl == 0) {
515                                 cp = stringbuf;
516                                 if ((nl = lookup(yytextFIND)) && kfind(nl))
517                                         putstr(stringbuf);
518                                 else
519                                         putstr(yytext);
520                                 stringbuf = cp;
521                         }
522                         if (ch == -1)
523                                 goto eof;
ragge
1.43
524
ragge
1.19
525                         break;
526                 }
527         }
plunky
1.108
528
529 eof:    warning("unexpected EOF");
530         putch('\n');
ragge
1.19
531 }
ragge
1.1
532
ragge
1.13
533 int
plunky
1.64
534 sloscan(void)
ragge
1.3
535 {
ragge
1.13
536         int ch;
537         int yyp;
538
539 zagain:
540         yyp = 0;
plunky
1.113
541         ch = inch();
gmcgarry
1.26
542         yytext[yyp++] = (usch)ch;
ragge
1.13
543         switch (ch) {
plunky
1.108
544         case -1/* EOF */
ragge
1.14
545                 return 0;
plunky
1.108
546
547         case '\n'/* do not pass NL */
ragge
1.19
548                 unch(ch);
plunky
1.94
549                 yytext[yyp] = 0;
550                 return ch;
ragge
1.13
551
plunky
1.108
552         case '\r'/* Ignore CR */
553                 goto zagain;
ragge
1.13
554
plunky
1.113
555         case '0'case '1'case '2'case '3'case '4'case '5':
ragge
1.13
556         case '6'case '7'case '8'case '9':
plunky
1.108
557                 /* reading a "pp-number" */
ragge
1.13
558 ppnum:          for (;;) {
ragge
1.19
559                         ch = inch();
plunky
1.94
560                         if (ch == -1)
561                                 break;
plunky
1.112
562                         if ((spechr[ch] & C_EP)) {
gmcgarry
1.26
563                                 yytext[yyp++] = (usch)ch;
ragge
1.19
564                                 ch = inch();
ragge
1.13
565                                 if (ch == '-' || ch == '+') {
gmcgarry
1.26
566                                         yytext[yyp++] = (usch)ch;
ragge
1.13
567                                 } else
ragge
1.19
568                                         unch(ch);
ragge
1.13
569                                 continue;
570                         }
ragge
1.19
571                         if ((spechr[ch] & C_ID) || ch == '.') {
gmcgarry
1.26
572                                 yytext[yyp++] = (usch)ch;
ragge
1.13
573                                 continue;
plunky
1.113
574                         }
ragge
1.13
575                         break;
576                 }
ragge
1.19
577                 unch(ch);
ragge
1.13
578                 yytext[yyp] = 0;
ragge
1.19
579                 return NUMBER;
ragge
1.13
580
581         case '\'':
plunky
1.113
582 chlit:
ragge
1.13
583                 for (;;) {
ragge
1.19
584                         if ((ch = inch()) == '\\') {
gmcgarry
1.26
585                                 yytext[yyp++] = (usch)ch;
plunky
1.108
586                                 ch = inch();
587                         } else if (ch == '\'')
588                                 break;
589                         if (ch == -1 || ch == '\n') {
ragge
1.13
590                                 /* not a constant */
591                                 while (yyp > 1)
ragge
1.19
592                                         unch(yytext[--yyp]);
ragge
1.13
593                                 goto any;
plunky
1.108
594                         }
595                         yytext[yyp++] = (usch)ch;
ragge
1.13
596                 }
plunky
1.108
597                 yytext[yyp++] = (usch)'\'';
ragge
1.13
598                 yytext[yyp] = 0;
plunky
1.74
599                 return NUMBER;
ragge
1.13
600
601         case ' ':
602         case '\t':
ragge
1.19
603                 while ((ch = inch()) == ' ' || ch == '\t')
gmcgarry
1.26
604                         yytext[yyp++] = (usch)ch;
ragge
1.19
605                 unch(ch);
606                 yytext[yyp] = 0;
plunky
1.74
607                 return WSPACE;
ragge
1.13
608
609         case '/':
plunky
1.108
610                 if ((ch = inch()) == '/') {     /* C++ comment */
ragge
1.13
611                         do {
gmcgarry
1.26
612                                 yytext[yyp++] = (usch)ch;
ragge
1.19
613                                 ch = inch();
plunky
1.94
614                         } while (ch != -1 && ch != '\n');
ragge
1.13
615                         yytext[yyp] = 0;
616                         unch(ch);
617                         goto zagain;
plunky
1.108
618                 } else if (ch == '*') {         /* C comment */
ragge
1.13
619                         int cwrn;
620                         extern int readmac;
621
ragge
1.33
622                         if (Cflag && !flslvl && readmac) {
623                                 unch(ch);
ragge
1.34
624                                 yytext[yyp] = 0;
ragge
1.13
625                                 return CMNT;
ragge
1.33
626                         }
ragge
1.13
627
628                         wrn = 0;
plunky
1.94
629                 more:   while ((c = inch()) != '*') {
630                                 if (c == -1)
plunky
1.113
631                                         return 0;
ragge
1.13
632                                 if (c == '\n')
633                                         putch(c), ifiles->lineno++;
ragge
1.48
634                                 else if (c == EBLOCK) {
ragge
1.46
635                                         (void)inch();
ragge
1.48
636                                         (void)inch();
plunky
1.96
637                                 } else if (c == WARN)
ragge
1.13
638                                         wrn = 1;
639                         }
plunky
1.94
640                         if ((c = inch()) == -1)
ragge
1.13
641                                 return 0;
plunky
1.94
642                         if (c != '/') {
ragge
1.19
643                                 unch(c);
ragge
1.13
644                                 goto more;
645                         }
646                         if (!tflag && !Cflag && !flslvl)
ragge
1.19
647                                 unch(' ');
ragge
1.13
648                         if (wrn)
plunky
1.96
649                                 unch(WARN);
ragge
1.13
650                         goto zagain;
651                 }
652                 unch(ch);
653                 goto any;
654
ragge
1.19
655         case '.':
plunky
1.94
656                 if ((ch = inch()) == -1)
plunky
1.108
657                         goto any;
plunky
1.97
658                 if ((spechr[ch] & C_DIGIT)) {
gmcgarry
1.26
659                         yytext[yyp++] = (usch)ch;
ragge
1.19
660                         goto ppnum;
ragge
1.13
661                 }
plunky
1.108
662                 unch(ch);
ragge
1.19
663                 goto any;
ragge
1.13
664
665         case '\"':
ragge
1.62
666                 if (tflag && defining)
ragge
1.42
667                         goto any;
ragge
1.13
668         strng:
669                 for (;;) {
ragge
1.19
670                         if ((ch = inch()) == '\\') {
gmcgarry
1.26
671                                 yytext[yyp++] = (usch)ch;
plunky
1.108
672                                 ch = inch();
673                         } else if (ch == '\"') {
gmcgarry
1.26
674                                 yytext[yyp++] = (usch)ch;
ragge
1.13
675                                 break;
plunky
1.108
676                         }
677                         if (ch == -1 || ch == '\n') {
678                                 warning("unterminated string");
679                                 unch(ch);
680                                 break;  // XXX the STRING does not have a closing quote
681                         }
682                         yytext[yyp++] = (usch)ch;
ragge
1.13
683                 }
684                 yytext[yyp] = 0;
plunky
1.74
685                 return STRING;
ragge
1.13
686
687         case 'L':
ragge
1.42
688                 if ((ch = inch()) == '\"' && !tflag) {
gmcgarry
1.26
689                         yytext[yyp++] = (usch)ch;
ragge
1.13
690                         goto strng;
ragge
1.42
691                 } else if (ch == '\'' && !tflag) {
gmcgarry
1.26
692                         yytext[yyp++] = (usch)ch;
ragge
1.13
693                         goto chlit;
694                 }
ragge
1.19
695                 unch(ch);
ragge
1.13
696                 /* FALLTHROUGH */
697
698         /* Yetch, all identifiers */
plunky
1.113
699         case 'a'case 'b'case 'c'case 'd'case 'e'case 'f':
700         case 'g'case 'h'case 'i'case 'j'case 'k'case 'l':
701         case 'm'case 'n'case 'o'case 'p'case 'q'case 'r':
702         case 's'case 't'case 'u'case 'v'case 'w'case 'x':
ragge
1.13
703         case 'y'case 'z':
plunky
1.113
704         case 'A'case 'B'case 'C'case 'D'case 'E'case 'F':
ragge
1.13
705         case 'G'case 'H'case 'I'case 'J'case 'K':
plunky
1.113
706         case 'M'case 'N'case 'O'case 'P'case 'Q'case 'R':
707         case 'S'case 'T'case 'U'case 'V'case 'W'case 'X':
ragge
1.13
708         case 'Y'case 'Z':
ragge
1.19
709         case '_'/* {L}({L}|{D})* */
ragge
1.13
710
711                 /* Special hacks */
ragge
1.111
712         hacks:
ragge
1.13
713                 for (;;) { /* get chars */
plunky
1.94
714                         if ((ch = inch()) == -1)
715                                 break;
plunky
1.97
716                         if ((spechr[ch] & C_ID)) {
gmcgarry
1.26
717                                 yytext[yyp++] = (usch)ch;
ragge
1.14
718                         } else {
plunky
1.94
719                                 unch(ch);
ragge
1.13
720                                 break;
ragge
1.14
721                         }
ragge
1.13
722                 }
723                 yytext[yyp] = 0/* need already string */
724                 /* end special hacks */
plunky
1.108
725                 return IDENT;
ragge
1.13
726
727         default:
ragge
1.111
728                 if ((ch&0x80)) goto hacks;
ragge
1.13
729         any:
730                 yytext[yyp] = 0;
ragge
1.19
731                 return yytext[0];
plunky
1.108
732         } /* endcase */
ragge
1.3
733
plunky
1.108
734         /* NOTREACHED */
ragge
1.3
735 }
736
ragge
1.19
737 int
plunky
1.64
738 yylex(void)
ragge
1.19
739 {
740         static int ifdefnoex;
741         struct symtab *nl;
742         int chc2;
743
744         while ((ch = sloscan()) == WSPACE)
745                 ;
plunky
1.97
746         if (ch < 128 && (spechr[ch] & C_2))
plunky
1.102
747                 c2 = inch();
ragge
1.19
748         else
749                 c2 = 0;
750
751         switch (ch) {
plunky
1.97
752         case '=':
753                 if (c2 == '='return EQ;
754                 break;
755         case '!':
756                 if (c2 == '='return NE;
757                 break;
758         case '|':
759                 if (c2 == '|'return OROR;
760                 break;
761         case '&':
762                 if (c2 == '&'return ANDAND;
763                 break;
ragge
1.19
764         case '<':
765                 if (c2 == '<'return LS;
766                 if (c2 == '='return LE;
767                 break;
768         case '>':
769                 if (c2 == '>'return RS;
770                 if (c2 == '='return GE;
771                 break;
772         case '+':
773         case '-':
774                 if (ch == c2)
plunky
1.78
775                         error("invalid preprocessor operator %c%c"chc2);
ragge
1.19
776                 break;
ragge
1.27
777
ragge
1.33
778         case '/':
779                 if (Cflag == 0 || c2 != '*')
780                         break;
781                 /* Found comment that need to be skipped */
782                 for (;;) {
plunky
1.102
783                         ch = inch();
ragge
1.33
784                 c1:     if (ch != '*')
785                                 continue;
plunky
1.102
786                         if ((ch = inch()) == '/')
ragge
1.33
787                                 break;
788                         goto c1;
789                 }
790                 return yylex();
791
ragge
1.19
792         case NUMBER:
ragge
1.27
793                 if (yytext[0] == '\'') {
794                         yylval.node.op = NUMBER;
plunky
1.73
795                         yylval.node.nd_val = charcon(yytext);
ragge
1.27
796                 } else
797                         cvtdig(yytext[0] != '0' ? 10 :
798                             yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
ragge
1.19
799                 return NUMBER;
ragge
1.27
800
ragge
1.19
801         case IDENT:
ragge
1.44
802                 if (strcmp((char *)yytext"defined") == 0) {
ragge
1.19
803                         ifdef = 1;
804                         return DEFINED;
805                 }
plunky
1.73
806                 nl = lookup(yytextFIND);
ragge
1.19
807                 if (ifdef) {
808                         yylval.node.nd_val = nl != NULL;
809                         ifdef = 0;
810                 } else if (nl && noex == 0) {
ragge
1.43
811                         usch *och = stringbuf;
812                         int i;
ragge
1.19
813
ragge
1.43
814                         i = kfind(nl);
815                         unch(WARN);
816                         if (i)
817                                 unpstr(stringbuf);
818                         else
819                                 unpstr(nl->namep);
ragge
1.19
820                         stringbuf = och;
821                         noex = 1;
822                         return yylex();
823                 } else {
824                         yylval.node.nd_val = 0;
825                 }
826                 yylval.node.op = NUMBER;
827                 return NUMBER;
ragge
1.43
828         case WARN:
ragge
1.19
829                 noex = 0;
ragge
1.70
830                 /* FALLTHROUGH */
831         case PHOLD:
ragge
1.19
832                 return yylex();
833         default:
834                 return ch;
835         }
836         unch(c2);
837         return ch;
838 }
839
ragge
1.13
840 /*
841  * Let the command-line args be faked defines at beginning of file.
842  */
843 static void
844 prinit(struct initar *itstruct includ *ic)
ragge
1.1
845 {
ragge
1.31
846         const char *pre, *post;
847         char *a;
ragge
1.1
848
ragge
1.13
849         if (it->next)
850                 prinit(it->nextic);
851         pre = post = NULL/* XXX gcc */
852         switch (it->type) {
853         case 'D':
854                 pre = "#define ";
855                 if ((a = strchr(it->str'=')) != NULL) {
856                         *a = ' ';
857                         post = "\n";
ragge
1.1
858                 } else
ragge
1.13
859                         post = " 1\n";
ragge
1.1
860                 break;
ragge
1.13
861         case 'U':
862                 pre = "#undef ";
863                 post = "\n";
ragge
1.1
864                 break;
ragge
1.13
865         case 'i':
866                 pre = "#include \"";
867                 post = "\"\n";
ragge
1.1
868                 break;
869         default:
ragge
1.13
870                 error("prinit");
ragge
1.1
871         }
ragge
1.13
872         strlcat((char *)ic->bufferpreCPPBUF+1);
873         strlcat((char *)ic->bufferit->strCPPBUF+1);
874         if (strlcat((char *)ic->bufferpostCPPBUF+1) >= CPPBUF+1)
875                 error("line exceeds buffer size");
876
877         ic->lineno--;
878         while (*ic->maxread)
879                 ic->maxread++;
ragge
1.1
880 }
881
ragge
1.4
882 /*
ragge
1.6
883  * A new file included.
884  * If ifiles == NULL, this is the first file and already opened (stdin).
ragge
1.13
885  * Return 0 on success, -1 if file to be included is not found.
ragge
1.4
886  */
887 int
ragge
1.31
888 pushfile(const usch *fileconst usch *fnint idxvoid *incs)
ragge
1.4
889 {
ragge
1.13
890         extern struct initar *initar;
ragge
1.6
891         struct includ ibuf;
892         struct includ *ic;
plunky
1.82
893         int otrulvl;
ragge
1.6
894
895         ic = &ibuf;
ragge
1.13
896         ic->next = ifiles;
ragge
1.4
897
ragge
1.6
898         if (file != NULL) {