Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:plunky:20140528202054

Diff

Diff from 1.114 to:

Annotations

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

Annotated File View

plunky
1.114
1 /*      $Id: token.c,v 1.114 2014/05/28 20:20:54 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
287         if (cp > 0x7fffffff)
288                 error("universal character name out of range");
289
290         n = 0;
291         m = 0x7f;
292         while (cp > m) {
293                 unch(0x80 | (cp & 0x3f));
294                 cp >>= 6;
295                 m >>= (n++ ? 1 : 2);
296         }
297         unch(((m << 1) ^ 0xfe) | cp);
298         return 1;
299 }
300
plunky
1.108
301 static int
ragge
1.45
302 eatcmnt(void)
303 {
304         int ch;
305
plunky
1.108
306         if (Cflag) {
307                 PUTCH('/'); PUTCH('*');
308         }
ragge
1.45
309         for (;;) {
310                 ch = inch();
311                 if (ch == '\n') {
312                         ifiles->lineno++;
plunky
1.102
313                         putch('\n');
314                         continue;
ragge
1.45
315                 }
316                 if (ch == -1)
plunky
1.108
317                         return -1;
ragge
1.45
318                 if (ch == '*') {
319                         ch = inch();
plunky
1.108
320                         if (ch == '/')
ragge
1.45
321                                 break;
322                         unch(ch);
323                         ch = '*';
324                 }
325                 if (CflagPUTCH(ch);
326         }
plunky
1.108
327         if (Cflag) {
328                 PUTCH('*'); PUTCH('/');
329         } else
330                 PUTCH(' ');
331
332         return 0;
ragge
1.45
333 }
334
ragge
1.19
335 /*
336  * Scan quickly the input file searching for:
337  *      - '#' directives
338  *      - keywords (if not flslvl)
339  *      - comments
340  *
341  *      Handle strings, numbers and trigraphs with care.
342  *      Only data from pp files are scanned here, never any rescans.
343  *      TODO: Only print out strings before calling other functions.
344  */
345 static void
346 fastscan(void)
347 {
348         struct symtab *nl;
plunky
1.102
349         int chi;
ragge
1.49
350         usch *cp;
ragge
1.19
351
352         goto run;
353         for (;;) {
plunky
1.102
354                 ch = inch();
ragge
1.19
355 xloop:          if (ch == -1)
356                         return;
plunky
1.60
357 #ifdef PCC_DEBUG
ragge
1.43
358                 if (dflag>1)
359                         printf("fastscan ch %d (%c)\n"chch > 31 ? ch : '@');
plunky
1.60
360 #endif
ragge
1.19
361                 if ((spechr[ch] & C_SPEC) == 0) {
362                         PUTCH(ch);
363                         continue;
364                 }
365                 switch (ch) {
ragge
1.44
366                 case EBLOCK:
ragge
1.43
367                 case WARN:
368                 case CONC:
369                         error("bad char passed");
370                         break;
371
ragge
1.19
372                 case '/'/* Comments */
373                         if ((ch = inch()) == '/') {
ragge
1.45
374 cppcmt:                         if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
ragge
1.19
375                                 do {
376                                         if (CflagPUTCH(ch);
377                                         ch = inch();
plunky
1.108
378                                         if (ch == -1)
379                                                 goto eof;
380                                 } while (ch != '\n');
ragge
1.19
381                                 goto xloop;
382                         } else if (ch == '*') {
plunky
1.108
383                                 if (eatcmnt() == -1)
384                                         goto eof;
ragge
1.19
385                         } else {
386                                 PUTCH('/');
387                                 goto xloop;
388                         }
389                         break;
390
391                 case '\n'/* newlines, for pp directives */
plunky
1.102
392                         i = ifiles->escln + 1;
393                         ifiles->lineno += i;
394                         ifiles->escln = 0;
395                         while (i-- > 0)
396                                 putch('\n');
397 run:                    for(;;) {
398                                 ch = inch();
ragge
1.45
399                                 if (ch == '/') {
plunky
1.102
400                                         ch = inch();
ragge
1.45
401                                         if (ch == '/')
402                                                 goto cppcmt;
403                                         if (ch == '*') {
plunky
1.108
404                                                 if (eatcmnt() == -1)
405                                                         goto eof;
plunky
1.102
406                                                 continue;
plunky
1.92
407                                         }
ragge
1.45
408                                         unch(ch);
409                                         ch = '/';
410                                 }
plunky
1.102
411                                 if (ch != ' ' && ch != '\t')
412                                         break;
413                                 PUTCH(ch);
ragge
1.50
414                         }
ragge
1.19
415                         if (ch == '#') {
416                                 ppdir();
417                                 continue;
ragge
1.40
418                         } else if (ch == '%') {
plunky
1.102
419                                 ch = inch();
ragge
1.40
420                                 if (ch == ':') {
421                                         ppdir();
422                                         continue;
423                                 }
plunky
1.92
424                                 unch(ch);
425                                 ch = '%';
ragge
1.19
426                         }
427                         goto xloop;
428
429                 case '\"'/* strings */
ragge
1.21
430 str:                    PUTCH(ch);
plunky
1.102
431                         while ((ch = inch()) != '\"') {
432                                 if (ch == '\\') {
plunky
1.114
433                                         if (chkucn())
434                                                 continue;
plunky
1.102
435                                         PUTCH('\\');
436                                         ch = inch();
437                                 }
plunky
1.104
438                                 if (ch == '\n') {
439                                         warning("unterminated string literal");
ragge
1.53
440                                         goto xloop;
plunky
1.104
441                                 }
plunky
1.90
442                                 if (ch == -1)
plunky
1.108
443                                         goto eof;
ragge
1.53
444                                 PUTCH(ch);
ragge
1.21
445                         }
ragge
1.19
446                         PUTCH(ch);
447                         break;
448
449                 case '.':  /* for pp-number */
450                         PUTCH(ch);
plunky
1.102
451                         ch = inch();
ragge
1.19
452                         if (ch < '0' || ch > '9')
453                                 goto xloop;
plunky
1.102
454
ragge
1.19
455                         /* FALLTHROUGH */
456                 case '0'case '1'case '2'case '3'case '4':
457                 case '5'case '6'case '7'case '8'case '9':
458                         do {
plunky
1.99
459 nxp:                            PUTCH(ch);
plunky
1.102
460                                 ch = inch();
plunky
1.94
461                                 if (ch == -1)
plunky
1.108
462                                         goto eof;
plunky
1.112
463                                 if ((spechr[ch] & C_EP)) {
ragge
1.19
464                                         PUTCH(ch);
plunky
1.102
465                                         ch = inch();
ragge
1.19
466                                         if (ch == '-' || ch == '+')
plunky
1.99
467                                                 goto nxp;
plunky
1.94
468                                         if (ch == -1)
plunky
1.108
469                                                 goto eof;
ragge
1.19
470                                 }
471                         } while ((spechr[ch] & C_ID) || (ch == '.'));
472                         goto xloop;
473
plunky
1.104
474                 case '\''/* character constant */
ragge
1.21
475 con:                    PUTCH(ch);
ragge
1.23
476                         if (tflag)
plunky
1.102
477                                 break/* character constants ignored */
478                         while ((ch = inch()) != '\'') {
479                                 if (ch == '\\') {
plunky
1.114
480                                         if (chkucn())
481                                                 continue;
plunky
1.102
482                                         PUTCH('\\');
483                                         ch = inch();
484                                 }
plunky
1.104
485                                 if (ch == '\n') {
486                                         warning("unterminated character constant");
ragge
1.52
487                                         goto xloop;
plunky
1.104
488                                 }
plunky
1.90
489                                 if (ch == -1)
plunky
1.108
490                                         goto eof;
ragge
1.52
491                                 PUTCH(ch);
ragge
1.21
492                         }
ragge
1.19
493                         PUTCH(ch);
494                         break;
ragge
1.21
495
ragge
1.19
496                 case 'L':
plunky
1.102
497                         ch = inch();
ragge
1.19
498                         if (ch == '\"') {
499                                 PUTCH('L');
500                                 goto str;
501                         }
502                         if (ch == '\'') {
503                                 PUTCH('L');
504                                 goto con;
505                         }
506                         unch(ch);
507                         ch = 'L';
plunky
1.102
508
ragge
1.19
509                         /* FALLTHROUGH */
510                 default:
plunky
1.102
511 #ifdef PCC_DEBUG
ragge
1.19
512                         if ((spechr[ch] & C_ID) == 0)
513                                 error("fastscan");
plunky
1.102
514 #endif
plunky
1.114
515                 ident:
gmcgarry
1.58
516                         i = 0;
plunky
1.114
517                         yytext[i++] = (usch)ch;
518                         for (;;) {
519                                 if ((ch = inch()) == -1)
520                                         break;
521                                 if (ch == '\\') {
522                                         if (chkucn())
523                                                 continue;
524                                         unch(ch);
525                                         break;
526                                 }
527                                 if ((spechr[ch] & C_ID) == 0) {
528                                         unch(ch);
529                                         break;
530                                 }
gmcgarry
1.26
531                                 yytext[i++] = (usch)ch;
plunky
1.114
532                         }
ragge
1.19
533                         yytext[i] = 0;
ragge
1.43
534
plunky
1.108
535                         if (flslvl == 0) {
536                                 cp = stringbuf;
537                                 if ((nl = lookup(yytextFIND)) && kfind(nl))
538                                         putstr(stringbuf);
539                                 else
540                                         putstr(yytext);
541                                 stringbuf = cp;
542                         }
543                         if (ch == -1)
544                                 goto eof;
ragge
1.43
545
ragge
1.19
546                         break;
plunky
1.114
547
548                 case '\\':
549                         if (chkucn()) {
550                                 ch = inch();
551                                 goto ident;
552                         }
553
554                         PUTCH('\\');
555                         break;
ragge
1.19
556                 }
557         }
plunky
1.108
558
559 eof:    warning("unexpected EOF");
560         putch('\n');
ragge
1.19
561 }
ragge
1.1
562
ragge
1.13
563 int
plunky
1.64
564 sloscan(void)
ragge
1.3
565 {
ragge
1.13
566         int ch;
567         int yyp;
568
569 zagain:
570         yyp = 0;
plunky
1.113
571         ch = inch();
gmcgarry
1.26
572         yytext[yyp++] = (usch)ch;
ragge
1.13
573         switch (ch) {
plunky
1.108
574         case -1/* EOF */
ragge
1.14
575                 return 0;
plunky
1.108
576
577         case '\n'/* do not pass NL */
ragge
1.19
578                 unch(ch);
plunky
1.94
579                 yytext[yyp] = 0;
580                 return ch;
ragge
1.13
581
plunky
1.108
582         case '\r'/* Ignore CR */
583                 goto zagain;
ragge
1.13
584
plunky
1.113
585         case '0'case '1'case '2'case '3'case '4'case '5':
ragge
1.13
586         case '6'case '7'case '8'case '9':
plunky
1.108
587                 /* reading a "pp-number" */
ragge
1.13
588 ppnum:          for (;;) {
ragge
1.19
589                         ch = inch();
plunky
1.94
590                         if (ch == -1)
591                                 break;
plunky
1.112
592                         if ((spechr[ch] & C_EP)) {
gmcgarry
1.26
593                                 yytext[yyp++] = (usch)ch;
ragge
1.19
594                                 ch = inch();
ragge
1.13
595                                 if (ch == '-' || ch == '+') {
gmcgarry
1.26
596                                         yytext[yyp++] = (usch)ch;
ragge
1.13
597                                 } else
ragge
1.19
598                                         unch(ch);
ragge
1.13
599                                 continue;
600                         }
ragge
1.19
601                         if ((spechr[ch] & C_ID) || ch == '.') {
gmcgarry
1.26
602                                 yytext[yyp++] = (usch)ch;
ragge
1.13
603                                 continue;
plunky
1.113
604                         }
ragge
1.13
605                         break;
606                 }
ragge
1.19
607                 unch(ch);
ragge
1.13
608                 yytext[yyp] = 0;
ragge
1.19
609                 return NUMBER;
ragge
1.13
610
611         case '\'':
plunky
1.113
612 chlit:
ragge
1.13
613                 for (;;) {
ragge
1.19
614                         if ((ch = inch()) == '\\') {
plunky
1.114
615                                 if (chkucn())
616                                         continue;
gmcgarry
1.26
617                                 yytext[yyp++] = (usch)ch;
plunky
1.108
618                                 ch = inch();
619                         } else if (ch == '\'')
620                                 break;
621                         if (ch == -1 || ch == '\n') {
ragge
1.13
622                                 /* not a constant */
623                                 while (yyp > 1)
ragge
1.19
624                                         unch(yytext[--yyp]);
ragge
1.13
625                                 goto any;
plunky
1.108
626                         }
627                         yytext[yyp++] = (usch)ch;
ragge
1.13
628                 }
plunky
1.108
629                 yytext[yyp++] = (usch)'\'';
ragge
1.13
630                 yytext[yyp] = 0;
plunky
1.74
631                 return NUMBER;
ragge
1.13
632
633         case ' ':
634         case '\t':
ragge
1.19
635                 while ((ch = inch()) == ' ' || ch == '\t')
gmcgarry
1.26
636                         yytext[yyp++] = (usch)ch;
ragge
1.19
637                 unch(ch);
638                 yytext[yyp] = 0;
plunky
1.74
639                 return WSPACE;
ragge
1.13
640
641         case '/':
plunky
1.108
642                 if ((ch = inch()) == '/') {     /* C++ comment */
ragge
1.13
643                         do {
gmcgarry
1.26
644                                 yytext[yyp++] = (usch)ch;
ragge
1.19
645                                 ch = inch();
plunky
1.94
646                         } while (ch != -1 && ch != '\n');
ragge
1.13
647                         yytext[yyp] = 0;
648                         unch(ch);
649                         goto zagain;
plunky
1.108
650                 } else if (ch == '*') {         /* C comment */
ragge
1.13
651                         int cwrn;
652                         extern int readmac;
653
ragge
1.33
654                         if (Cflag && !flslvl && readmac) {
655                                 unch(ch);
ragge
1.34
656                                 yytext[yyp] = 0;
ragge
1.13
657                                 return CMNT;
ragge
1.33
658                         }
ragge
1.13
659
660                         wrn = 0;
plunky
1.94
661                 more:   while ((c = inch()) != '*') {
662                                 if (c == -1)
plunky
1.113
663                                         return 0;
ragge
1.13
664                                 if (c == '\n')
665                                         putch(c), ifiles->lineno++;
ragge
1.48
666                                 else if (c == EBLOCK) {
ragge
1.46
667                                         (void)inch();
ragge
1.48
668                                         (void)inch();
plunky
1.96
669                                 } else if (c == WARN)
ragge
1.13
670                                         wrn = 1;
671                         }
plunky
1.94
672                         if ((c = inch()) == -1)
ragge
1.13
673                                 return 0;
plunky
1.94
674                         if (c != '/') {
ragge
1.19
675                                 unch(c);
ragge
1.13
676                                 goto more;
677                         }
678                         if (!tflag && !Cflag && !flslvl)
ragge
1.19
679                                 unch(' ');
ragge
1.13
680                         if (wrn)
plunky
1.96
681                                 unch(WARN);
ragge
1.13
682                         goto zagain;
683                 }
684                 unch(ch);
685                 goto any;
686
ragge
1.19
687         case '.':
plunky
1.94
688                 if ((ch = inch()) == -1)
plunky
1.108
689                         goto any;
plunky
1.97
690                 if ((spechr[ch] & C_DIGIT)) {
gmcgarry
1.26
691                         yytext[yyp++] = (usch)ch;
ragge
1.19
692                         goto ppnum;
ragge
1.13
693                 }
plunky
1.108
694                 unch(ch);
ragge
1.19
695                 goto any;
ragge
1.13
696
697         case '\"':
ragge
1.62
698                 if (tflag && defining)
ragge
1.42
699                         goto any;
ragge
1.13
700         strng:
701                 for (;;) {
ragge
1.19
702                         if ((ch = inch()) == '\\') {
plunky
1.114
703                                 if (chkucn())
704                                         continue;
gmcgarry
1.26
705                                 yytext[yyp++] = (usch)ch;
plunky
1.108
706                                 ch = inch();
707                         } else if (ch == '\"') {
gmcgarry
1.26
708                                 yytext[yyp++] = (usch)ch;
ragge
1.13
709                                 break;
plunky
1.108
710                         }
711                         if (ch == -1 || ch == '\n') {
712                                 warning("unterminated string");
713                                 unch(ch);
714                                 break;  // XXX the STRING does not have a closing quote
715                         }
716                         yytext[yyp++] = (usch)ch;
ragge
1.13
717                 }
718                 yytext[yyp] = 0;
plunky
1.74
719                 return STRING;
ragge
1.13
720
plunky
1.114
721         case '\\':
722                 if (chkucn()) {
723                         --yyp;
724                         goto ident;
725                 }
726                 goto any;
727
ragge
1.13
728         case 'L':
ragge
1.42
729                 if ((ch = inch()) == '\"' && !tflag) {
gmcgarry
1.26
730                         yytext[yyp++] = (usch)ch;
ragge
1.13
731                         goto strng;
ragge
1.42
732                 } else if (ch == '\'' && !tflag) {
gmcgarry
1.26
733                         yytext[yyp++] = (usch)ch;
ragge
1.13
734                         goto chlit;
735                 }
ragge
1.19
736                 unch(ch);
ragge
1.13
737                 /* FALLTHROUGH */
738
739         /* Yetch, all identifiers */
plunky
1.113
740         case 'a'case 'b'case 'c'case 'd'case 'e'case 'f':
741         case 'g'case 'h'case 'i'case 'j'case 'k'case 'l':
742         case 'm'case 'n'case 'o'case 'p'case 'q'case 'r':
743         case 's'case 't'case 'u'case 'v'case 'w'case 'x':
ragge
1.13
744         case 'y'case 'z':
plunky
1.113
745         case 'A'case 'B'case 'C'case 'D'case 'E'case 'F':
ragge
1.13
746         case 'G'case 'H'case 'I'case 'J'case 'K':
plunky
1.113
747         case 'M'case 'N'case 'O'case 'P'case 'Q'case 'R':
748         case 'S'case 'T'case 'U'case 'V'case 'W'case 'X':
ragge
1.13
749         case 'Y'case 'Z':
ragge
1.19
750         case '_'/* {L}({L}|{D})* */
ragge
1.13
751
plunky
1.114
752         ident:
ragge
1.13
753                 for (;;) { /* get chars */
plunky
1.94
754                         if ((ch = inch()) == -1)
755                                 break;
plunky
1.114
756                         if (ch == '\\') {
757                                 if (chkucn())
758                                         continue;
759                                 unch('\\');
760                                 break;
761                         }
762                         if ((spechr[ch] & C_ID) == 0) {
plunky
1.94
763                                 unch(ch);
ragge
1.13
764                                 break;
ragge
1.14
765                         }
plunky
1.114
766                         yytext[yyp++] = (usch)ch;
ragge
1.13
767                 }
768                 yytext[yyp] = 0/* need already string */
plunky
1.108
769                 return IDENT;
ragge
1.13
770
771         default:
plunky
1.114
772                 if ((ch & 0x80))
773                         goto ident;
774
ragge
1.13
775         any:
776                 yytext[yyp] = 0;
ragge
1.19
777                 return yytext[0];
plunky
1.108
778         } /* endcase */
ragge
1.3
779
plunky
1.108
780         /* NOTREACHED */
ragge
1.3
781 }
782
ragge
1.19
783 int
plunky
1.64
784 yylex(void)
ragge
1.19
785 {
786         static int ifdefnoex;
787         struct symtab *nl;
788         int chc2;
789
790         while ((ch = sloscan()) == WSPACE)
791                 ;
plunky
1.97
792         if (ch < 128 && (spechr[ch] & C_2))
plunky
1.102
793                 c2 = inch();
ragge
1.19
794         else
795                 c2 = 0;
796
797         switch (ch) {
plunky
1.97
798         case '=':
799                 if (c2 == '='return EQ;
800                 break;
801         case '!':
802                 if (c2 == '='return NE;
803                 break;
804         case '|':
805                 if (c2 == '|'return OROR;
806                 break;
807         case '&':
808                 if (c2 == '&'return ANDAND;
809                 break;
ragge
1.19
810         case '<':
811                 if (c2 == '<'return LS;
812                 if (c2 == '='return LE;
813                 break;
814         case '>':
815                 if (c2 == '>'return RS;
816                 if (c2 == '='return GE;
817                 break;
818         case '+':
819         case '-':
820                 if (ch == c2)
plunky
1.78
821                         error("invalid preprocessor operator %c%c"chc2);
ragge
1.19
822                 break;
ragge
1.27
823
ragge
1.33
824         case '/':
825                 if (Cflag == 0 || c2 != '*')
826                         break;
827                 /* Found comment that need to be skipped */
828                 for (;;) {
plunky
1.102
829                         ch = inch();
ragge
1.33
830                 c1:     if (ch != '*')
831                                 continue;
plunky
1.102
832                         if ((ch = inch()) == '/')
ragge
1.33
833                                 break;
834                         goto c1;
835                 }
836                 return yylex();
837
ragge
1.19
838         case NUMBER:
ragge
1.27
839                 if (yytext[0] == '\'') {
840                         yylval.node.op = NUMBER;
plunky
1.73
841                         yylval.node.nd_val = charcon(yytext);
ragge
1.27
842                 } else
843                         cvtdig(yytext[0] != '0' ? 10 :
844                             yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
ragge
1.19
845                 return NUMBER;
ragge
1.27
846
ragge
1.19
847         case IDENT:
ragge
1.44
848                 if (strcmp((char *)yytext"defined") == 0) {
ragge
1.19
849                         ifdef = 1;
850                         return DEFINED;
851                 }
plunky
1.73
852                 nl = lookup(yytextFIND);
ragge
1.19
853                 if (ifdef) {
854                         yylval.node.nd_val = nl != NULL;
855                         ifdef = 0;
856                 } else if (nl && noex == 0) {
ragge
1.43
857                         usch *och = stringbuf;
858                         int i;
ragge
1.19
859
ragge
1.43
860                         i = kfind(nl);
861                         unch(WARN);
862                         if (i)
863                                 unpstr(stringbuf);
864                         else
865                                 unpstr(nl->namep);
ragge
1.19
866                         stringbuf = och;
867                         noex = 1;
868                         return yylex();
869                 } else {
870                         yylval.node.nd_val = 0;
871                 }
872                 yylval.node.op = NUMBER;
873                 return NUMBER;
ragge
1.43
874         case WARN:
ragge
1.19
875                 noex = 0;
ragge
1.70
876                 /* FALLTHROUGH */
877         case PHOLD:
ragge
1.19
878                 return yylex();
879         default:
880                 return ch;
881         }
882         unch(c2);
883         return ch;
884 }
885
ragge
1.13
886 /*
887  * Let the command-line args be faked defines at beginning of file.
888  */
889 static void
890 prinit(struct initar *itstruct includ *ic)
ragge
1.1
891 {
ragge
1.31
892         const char *pre, *post;
893         char *a;
ragge
1.1
894
ragge
1.13
895         if (it->next)
896                 prinit(it->nextic);
897         pre = post = NULL/* XXX gcc */
898         switch (it->type) {
899         case 'D':
900                 pre = "#define ";
901                 if ((a = strchr(it->str'=')) != NULL) {
902                         *a = ' ';
903                         post = "\n";
ragge
1.1
904                 } else
ragge
1.13
905                         post = " 1\n";
ragge
1.1
906                 break;
ragge
1.13