Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20140829180225

Diff

Diff from 1.118 to:

Annotations

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

Annotated File View

ragge
1.118
1 /*      $Id: token.c,v 1.118 2014/08/29 18:02:25 ragge 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.118
602                                 if ((spechr[ch = inch()] & C_DIGIT) == 0)
603                                         break/* only digits allowed */
604                                 unch(ch);
ragge
1.13
605                                 continue;
606                         }
ragge
1.19
607                         if ((spechr[ch] & C_ID) || ch == '.') {
gmcgarry
1.26
608                                 yytext[yyp++] = (usch)ch;
ragge
1.13
609                                 continue;
plunky
1.113
610                         }
ragge
1.13
611                         break;
612                 }
ragge
1.19
613                 unch(ch);
ragge
1.13
614                 yytext[yyp] = 0;
ragge
1.19
615                 return NUMBER;
ragge
1.13
616
617         case '\'':
plunky
1.113
618 chlit:
ragge
1.13
619                 for (;;) {
ragge
1.19
620                         if ((ch = inch()) == '\\') {
plunky
1.114
621                                 if (chkucn())
622                                         continue;
gmcgarry
1.26
623                                 yytext[yyp++] = (usch)ch;
plunky
1.108
624                                 ch = inch();
625                         } else if (ch == '\'')
626                                 break;
627                         if (ch == -1 || ch == '\n') {
ragge
1.13
628                                 /* not a constant */
629                                 while (yyp > 1)
ragge
1.19
630                                         unch(yytext[--yyp]);
ragge
1.13
631                                 goto any;
plunky
1.108
632                         }
633                         yytext[yyp++] = (usch)ch;
ragge
1.13
634                 }
plunky
1.108
635                 yytext[yyp++] = (usch)'\'';
ragge
1.13
636                 yytext[yyp] = 0;
plunky
1.74
637                 return NUMBER;
ragge
1.13
638
639         case ' ':
640         case '\t':
ragge
1.19
641                 while ((ch = inch()) == ' ' || ch == '\t')
gmcgarry
1.26
642                         yytext[yyp++] = (usch)ch;
ragge
1.19
643                 unch(ch);
644                 yytext[yyp] = 0;
plunky
1.74
645                 return WSPACE;
ragge
1.13
646
647         case '/':
plunky
1.108
648                 if ((ch = inch()) == '/') {     /* C++ comment */
ragge
1.13
649                         do {
gmcgarry
1.26
650                                 yytext[yyp++] = (usch)ch;
ragge
1.19
651                                 ch = inch();
plunky
1.94
652                         } while (ch != -1 && ch != '\n');
ragge
1.13
653                         yytext[yyp] = 0;
654                         unch(ch);
655                         goto zagain;
plunky
1.108
656                 } else if (ch == '*') {         /* C comment */
ragge
1.13
657                         int cwrn;
658                         extern int readmac;
659
ragge
1.33
660                         if (Cflag && !flslvl && readmac) {
661                                 unch(ch);
ragge
1.34
662                                 yytext[yyp] = 0;
ragge
1.13
663                                 return CMNT;
ragge
1.33
664                         }
ragge
1.13
665
666                         wrn = 0;
plunky
1.94
667                 more:   while ((c = inch()) != '*') {
668                                 if (c == -1)
plunky
1.113
669                                         return 0;
ragge
1.13
670                                 if (c == '\n')
671                                         putch(c), ifiles->lineno++;
ragge
1.48
672                                 else if (c == EBLOCK) {
ragge
1.46
673                                         (void)inch();
ragge
1.48
674                                         (void)inch();
plunky
1.96
675                                 } else if (c == WARN)
ragge
1.13
676                                         wrn = 1;
677                         }
plunky
1.94
678                         if ((c = inch()) == -1)
ragge
1.13
679                                 return 0;
plunky
1.94
680                         if (c != '/') {
ragge
1.19
681                                 unch(c);
ragge
1.13
682                                 goto more;
683                         }
684                         if (!tflag && !Cflag && !flslvl)
ragge
1.19
685                                 unch(' ');
ragge
1.13
686                         if (wrn)
plunky
1.96
687                                 unch(WARN);
ragge
1.13
688                         goto zagain;
689                 }
690                 unch(ch);
691                 goto any;
692
ragge
1.19
693         case '.':
plunky
1.94
694                 if ((ch = inch()) == -1)
plunky
1.108
695                         goto any;
plunky
1.97
696                 if ((spechr[ch] & C_DIGIT)) {
gmcgarry
1.26
697                         yytext[yyp++] = (usch)ch;
ragge
1.19
698                         goto ppnum;
ragge
1.13
699                 }
plunky
1.108
700                 unch(ch);
ragge
1.19
701                 goto any;
ragge
1.13
702
703         case '\"':
ragge
1.62
704                 if (tflag && defining)
ragge
1.42
705                         goto any;
ragge
1.13
706         strng:
707                 for (;;) {
ragge
1.19
708                         if ((ch = inch()) == '\\') {
plunky
1.114
709                                 if (chkucn())
710                                         continue;
gmcgarry
1.26
711                                 yytext[yyp++] = (usch)ch;
plunky
1.108
712                                 ch = inch();
713                         } else if (ch == '\"') {
gmcgarry
1.26
714                                 yytext[yyp++] = (usch)ch;
ragge
1.13
715                                 break;
plunky
1.108
716                         }
717                         if (ch == -1 || ch == '\n') {
718                                 warning("unterminated string");
719                                 unch(ch);
720                                 break;  // XXX the STRING does not have a closing quote
721                         }
722                         yytext[yyp++] = (usch)ch;
ragge
1.13
723                 }
724                 yytext[yyp] = 0;
plunky
1.74
725                 return STRING;
ragge
1.13
726
plunky
1.114
727         case '\\':
728                 if (chkucn()) {
729                         --yyp;
730                         goto ident;
731                 }
732                 goto any;
733
ragge
1.13
734         case 'L':
ragge
1.42
735                 if ((ch = inch()) == '\"' && !tflag) {
gmcgarry
1.26
736                         yytext[yyp++] = (usch)ch;
ragge
1.13
737                         goto strng;
ragge
1.42
738                 } else if (ch == '\'' && !tflag) {
gmcgarry
1.26
739                         yytext[yyp++] = (usch)ch;
ragge
1.13
740                         goto chlit;
741                 }
ragge
1.19
742                 unch(ch);
ragge
1.13
743                 /* FALLTHROUGH */
744
745         /* Yetch, all identifiers */
plunky
1.113
746         case 'a'case 'b'case 'c'case 'd'case 'e'case 'f':
747         case 'g'case 'h'case 'i'case 'j'case 'k'case 'l':
748         case 'm'case 'n'case 'o'case 'p'case 'q'case 'r':
749         case 's'case 't'case 'u'case 'v'case 'w'case 'x':
ragge
1.13
750         case 'y'case 'z':
plunky
1.113
751         case 'A'case 'B'case 'C'case 'D'case 'E'case 'F':
ragge
1.13
752         case 'G'case 'H'case 'I'case 'J'case 'K':
plunky
1.113
753         case 'M'case 'N'case 'O'case 'P'case 'Q'case 'R':
754         case 'S'case 'T'case 'U'case 'V'case 'W'case 'X':
ragge
1.13
755         case 'Y'case 'Z':
ragge
1.19
756         case '_'/* {L}({L}|{D})* */
ragge
1.13
757
plunky
1.114
758         ident:
ragge
1.13
759                 for (;;) { /* get chars */
plunky
1.94
760                         if ((ch = inch()) == -1)
761                                 break;
plunky
1.114
762                         if (ch == '\\') {
763                                 if (chkucn())
764                                         continue;
765                                 unch('\\');
766                                 break;
767                         }
768                         if ((spechr[ch] & C_ID) == 0) {
plunky
1.94
769                                 unch(ch);
ragge
1.13
770                                 break;
ragge
1.14
771                         }
plunky
1.114
772                         yytext[yyp++] = (usch)ch;
ragge
1.13
773                 }
774                 yytext[yyp] = 0/* need already string */
plunky
1.108
775                 return IDENT;
ragge
1.13
776
777         default:
plunky
1.114
778                 if ((ch & 0x80))
779                         goto ident;
780
ragge
1.13
781         any:
782                 yytext[yyp] = 0;
ragge
1.19
783                 return yytext[0];
plunky
1.108
784         } /* endcase */
ragge
1.3
785
plunky
1.108
786         /* NOTREACHED */
ragge
1.3
787 }
788
ragge
1.19
789 int
plunky
1.64
790 yylex(void)
ragge
1.19
791 {
792         static int ifdefnoex;
793         struct symtab *nl;
794         int chc2;
795
796         while ((ch = sloscan()) == WSPACE)
797                 ;
plunky
1.97
798         if (ch < 128 && (spechr[ch] & C_2))
plunky
1.102
799                 c2 = inch();
ragge
1.19
800         else
801                 c2 = 0;
802
803         switch (ch) {
plunky
1.97
804         case '=':
805                 if (c2 == '='return EQ;
806                 break;
807         case '!':
808                 if (c2 == '='return NE;
809                 break;
810         case '|':
811                 if (c2 == '|'return OROR;
812                 break;
813         case '&':
814                 if (c2 == '&'return ANDAND;
815                 break;
ragge
1.19
816         case '<':
817                 if (c2 == '<'return LS;
818                 if (c2 == '='return LE;
819                 break;
820         case '>':
821                 if (c2 == '>'return RS;
822                 if (c2 == '='return GE;
823                 break;
824         case '+':
825         case '-':
826                 if (ch == c2)
plunky
1.78
827                         error("invalid preprocessor operator %c%c"chc2);
ragge
1.19
828                 break;
ragge
1.27
829
ragge
1.33
830         case '/':
831                 if (Cflag == 0 || c2 != '*')
832                         break;
833                 /* Found comment that need to be skipped */
834                 for (;;) {
plunky
1.102
835                         ch = inch();
ragge
1.33
836                 c1:     if (ch != '*')
837                                 continue;
plunky
1.102
838                         if ((ch = inch()) == '/')
ragge
1.33
839                                 break;
840                         goto c1;
841                 }
842                 return yylex();
843
ragge
1.19
844         case NUMBER:
ragge
1.27
845                 if (yytext[0] == '\'') {
846                         yylval.node.op = NUMBER;
plunky
1.73
847                         yylval.node.nd_val = charcon(yytext);
ragge
1.27
848                 } else
849                         cvtdig(yytext[0] != '0' ? 10 :
850                             yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
ragge
1.19
851                 return NUMBER;
ragge
1.27
852
ragge
1.19
853         case IDENT:
ragge
1.44
854                 if (strcmp((char *)yytext"defined") == 0) {
ragge
1.19
855                         ifdef = 1;
856                         return DEFINED;
857                 }
plunky
1.73
858                 nl = lookup(yytextFIND);
ragge
1.19
859                 if (ifdef) {
860                         yylval.node.nd_val = nl != NULL;
861                         ifdef = 0;
862                 } else if (nl && noex == 0) {
ragge
1.43
863                         usch *och = stringbuf;
864                         int i;
ragge
1.19
865
ragge
1.43
866                         i = kfind(nl);
867                         unch(WARN);
868                         if (i)
869                                 unpstr(stringbuf);
870                         else
871                                 unpstr(nl->namep);
ragge
1.19
872                         stringbuf = och;
873                         noex = 1;
874                         return yylex();
875                 } else {
876                         yylval.node.nd_val = 0;
877                 }
878                 yylval.node.op = NUMBER;
879                 return NUMBER;
ragge
1.43
880         case WARN:
ragge
1.19
881                 noex = 0;
ragge
1.70
882                 /* FALLTHROUGH */
883         case PHOLD:
ragge
1.19
884                 return yylex();
885         default:
886                 return ch;
887         }
888         unch(c2);
889         return ch;
890 }
891
ragge
1.13
892 /*
893  * Let the command-line args be faked defines at beginning of file.
894  */
895 static void
896 prinit(struct initar *itstruct includ *ic)
ragge
1.1
897 {
ragge
1.31
898         const char *pre, *post;
899         char *a;
ragge
1.1
900
ragge
1.13
901         if (it->next)
902                 prinit(it->nextic);
903         pre = post = NULL/* XXX gcc */
904         switch (it->type) {
905         case 'D':
906                 pre = "#define ";
907                 if ((a = strchr(it->str'=')) != NULL) {
908                &nbs