Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:plunky:20140527182035

Diff

Diff from 1.112 to:

Annotations

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

Annotated File View

plunky
1.112
1 /*      $Id: token.c,v 1.112 2014/05/27 18:20:35 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.
34  *      - yylex() returns something from the input stream that 
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;
ragge
1.15
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;
gmcgarry
1.26
541         ch = inch();
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
555         case '0'case '1'case '2'case '3'case '4'case '5'
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;
574                         } 
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 '\'':
ragge
1.19
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)
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 */
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'
703         case 'y'case 'z':
704         case 'A'case 'B'case 'C'case 'D'case 'E'case 'F'
705         case 'G'case 'H'case 'I'case 'J'case 'K':
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'
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) {
ragge
1.31
899                 if ((ic->infil = open((const char *)fileO_RDONLY)) < 0)
ragge
1.4
900                         return -1;
ragge
1.13
901                 ic->orgfn = ic->fname = file;
902                 if (++inclevel > MAX_INCLEVEL)
plunky
1.102
903                         error("limit for nested includes exceeded");
ragge
1.6
904         } else {
905                 ic->infil = 0;
ragge
1.31
906