Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:plunky:20140606153253

Diff

Diff from 1.116 to:

Annotations

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

Annotated File View

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