Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:plunky:20140528220932

Diff

Diff from 1.115 to:

Annotations

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

Annotated File View

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