Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20141019174036

Diff

Diff from 1.120 to:

Annotations

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

Annotated File View

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