Quick Search:

View

Revision:
Expand:  
Changeset: r-1-0-0:ragge:20110226063640

Diff

Diff from 1.48.2.1 to:

Annotations

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

Annotated File View

ragge
1.48.2.1
1 /*      $Id: token.c,v 1.48.2.1 2011/02/26 06:36:40 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.
33  *              It may recurse into itself during expansion.
34  *      - yylex() returns something from the input stream that 
35  *              is suitable for yacc.
36  *
37  *      Other functions of common use:
38  *      - inpch() returns a raw character from the current input stream.
39  *      - inch() is like inpch but \\n and trigraphs are expanded.
40  *      - unch() pushes back a character to the input stream.
41  */
42
ragge
1.13
43 #include "config.h"
44
ragge
1.1
45 #include <stdlib.h>
46 #include <string.h>
47 #include <ctype.h>
ragge
1.13
48 #ifdef HAVE_UNISTD_H
ragge
1.2
49 #include <unistd.h>
ragge
1.13
50 #endif
ragge
1.2
51 #include <fcntl.h>
ragge
1.13
52 #include <errno.h>
ragge
1.1
53
ragge
1.13
54 #include "compat.h"
ragge
1.1
55 #include "cpp.h"
ragge
1.13
56 #include "y.tab.h"
57
58 static void cvtdig(int rad);
59 static int charcon(usch *);
60 static void elsestmt(void);
61 static void ifdefstmt(void);
62 static void ifndefstmt(void);
63 static void endifstmt(void);
64 static void ifstmt(void);
65 static void cpperror(void);
66 static void pragmastmt(void);
67 static void undefstmt(void);
ragge
1.39
68 static void cppwarning(void);
ragge
1.13
69 static void elifstmt(void);
70 static void badop(const char *);
ragge
1.19
71 static int chktg(void);
72 static void ppdir(void);
ragge
1.13
73 void  include(void);
ragge
1.29
74 void  include_next(void);
ragge
1.13
75 void  define(void);
ragge
1.19
76 static int inpch(void);
ragge
1.13
77
78 extern int yyget_lineno (void);
79 extern void yyset_lineno (int);
80
81 static int inch(void);
82
83 int inif;
ragge
1.43
84 extern int dflag;
ragge
1.13
85
ragge
1.19
86 #define PUTCH(ch) if (!flslvl) putch(ch)
ragge
1.13
87 /* protection against recursion in #include */
88 #define MAX_INCLEVEL    100
89 static int inclevel;
90
ragge
1.19
91 /* get next character unaltered */
92 #define NXTCH() (ifiles->curptr < ifiles->maxread ? *ifiles->curptr++ : inpch())
ragge
1.1
93
ragge
1.44
94 usch yytext[CPPBUF];
gmcgarry
1.16
95
ragge
1.43
96 char spechr[256] = {
97         0,      0,      0,      0,      C_SPECC_SPEC0,      0,
98         0,      C_WSNLC_SPEC|C_WSNL,  0,
99         0,      C_WSNL0,      0,
ragge
1.19
100         0,      0,      0,      0,      0,      0,      0,      0,
101         0,      0,      0,      0,      0,      0,      0,      0,
102
ragge
1.43
103         C_WSNLC_2,    C_SPEC0,      0,      0,      C_2,    C_SPEC,
ragge
1.33
104         0,      0,      0,      C_2,    0,      C_2,    0,      C_SPEC|C_2,
ragge
1.19
105         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
106         C_I,    C_I,    0,      0,      C_2,    C_2,    C_2,    C_SPEC,
107
108         0,      C_I,    C_I,    C_I,    C_I,    C_I|C_EPC_I,  C_I,
109         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
110         C_I|C_EPC_I,  C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
ragge
1.37
111         C_I,    C_I,    C_I,    0,      C_I,    0,      0,      C_I,
ragge
1.19
112
113         0,      C_I,    C_I,    C_I,    C_I,    C_I|C_EPC_I,  C_I,
114         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
115         C_I|C_EPC_I,  C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
116         C_I,    C_I,    C_I,    0,      C_2,    0,      0,      0,
117
118 };
ragge
1.1
119
ragge
1.43
120 /*
121  * No-replacement array.  If a macro is found and exists in this array
122  * then no replacement shall occur.  This is a stack.
123  */
124 struct symtab *norep[RECMAX];   /* Symbol table index table */
125 int norepptr = 1;                       /* Top of index table */
ragge
1.48
126 unsigned short bptr[RECMAX];    /* currently active noexpand macro stack */
ragge
1.43
127 int bidx;                       /* Top of bptr stack */
128
ragge
1.13
129 static void
130 unch(int c)
131 {
ragge
1.15
132                 
133         --ifiles->curptr;
134         if (ifiles->curptr < ifiles->bbuf)
135                 error("pushback buffer full");
gmcgarry
1.26
136         *ifiles->curptr = (usch)c;
ragge
1.13
137 }
ragge
1.1
138
ragge
1.45
139 static int
140 eatcmnt(void)
141 {
142         int ch;
143
144         if (Cflag) { PUTCH('/'); PUTCH('*'); }
145         for (;;) {
146                 ch = inch();
147                 if (ch == '\n') {
148                         ifiles->lineno++;
149                         PUTCH('\n');
150                 }
151                 if (ch == -1)
152                         return -1;
153                 if (ch == '*') {
154                         ch = inch();
155                         if (ch == '/') {
156                                 if (Cflag) {
157                                         PUTCH('*');
158                                         PUTCH('/');
159                                 } else
160                                         PUTCH(' ');
161                                 break;
162                         }
163                         unch(ch);
164                         ch = '*';
165                 }
166                 if (CflagPUTCH(ch);
167         }
168         return 0;
169 }
170
ragge
1.19
171 /*
172  * Scan quickly the input file searching for:
173  *      - '#' directives
174  *      - keywords (if not flslvl)
175  *      - comments
176  *
177  *      Handle strings, numbers and trigraphs with care.
178  *      Only data from pp files are scanned here, never any rescans.
179  *      TODO: Only print out strings before calling other functions.
180  */
181 static void
182 fastscan(void)
183 {
184         struct symtab *nl;
ragge
1.43
185         int chiccntonemore;
ragge
1.48.2.1
186         usch *cp;
ragge
1.19
187
188         goto run;
189         for (;;) {
190                 ch = NXTCH();
191 xloop:          if (ch == -1)
192                         return;
ragge
1.43
193                 if (dflag>1)
194                         printf("fastscan ch %d (%c)\n"chch > 31 ? ch : '@');
ragge
1.19
195                 if ((spechr[ch] & C_SPEC) == 0) {
196                         PUTCH(ch);
197                         continue;
198                 }
199                 switch (ch) {
ragge
1.44
200                 case EBLOCK:
ragge
1.43
201                 case WARN:
202                 case CONC:
203                         error("bad char passed");
204                         break;
205
ragge
1.19
206                 case '/'/* Comments */
207                         if ((ch = inch()) == '/') {
ragge
1.45
208 cppcmt:                         if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
ragge
1.19
209                                 do {
210                                         if (CflagPUTCH(ch);
211                                         ch = inch();
212                                 } while (ch != -1 && ch != '\n');
213                                 goto xloop;
214                         } else if (ch == '*') {
ragge
1.45
215                                 if (eatcmnt())
216                                         return;
ragge
1.19
217                         } else {
218                                 PUTCH('/');
219                                 goto xloop;
220                         }
221                         break;
222
223                 case '?':  /* trigraphs */
224                         if ((ch = chktg()))
225                                 goto xloop;
226                         PUTCH('?');
227                         break;
228
ragge
1.37
229                 case '\\':
230                         if ((ch = NXTCH()) == '\n') {
231                                 ifiles->lineno++;
232                                 continue;
233                         } else {
234                                 PUTCH('\\');
235                         }
236                         goto xloop;
237
ragge
1.19
238                 case '\n'/* newlines, for pp directives */
239                         ifiles->lineno++;
240                         do {
241                                 PUTCH(ch);
242 run:                            ch = NXTCH();
ragge
1.45
243                                 if (ch == '/') {
244                                         ch = NXTCH();
245                                         if (ch == '/')
246                                                 goto cppcmt;
247                                         if (ch == '*') {
248                                                 if (eatcmnt())
249                                                         return;
250                                                 goto run;
251                                         } 
252                                         unch(ch);
253                                         ch = '/';
254                                 }
ragge
1.19
255                         } while (ch == ' ' || ch == '\t');
256                         if (ch == '#') {
257                                 ppdir();
258                                 continue;
ragge
1.40
259                         } else if (ch == '%') {
260                                 ch = NXTCH();
261                                 if (ch == ':') {
262                                         ppdir();
263                                         continue;
264                                 } else {
265                                         unch(ch);
266                                         ch = '%';
267                                 }
ragge
1.19
268                         }
269                         goto xloop;
270
271                 case '\"'/* strings */
ragge
1.21
272 str:                    PUTCH(ch);
ragge
1.24
273                         while ((ch = inch()) != '\"') {
ragge
1.43
274                                         PUTCH(ch);
ragge
1.19
275                                 if (ch == '\\') {
ragge
1.24
276                                         ch = inch();
ragge
1.19
277                                         PUTCH(ch);
278                                 }
279                                 if (ch < 0)
280                                         return;
ragge
1.21
281                         }
ragge
1.19
282                         PUTCH(ch);
283                         break;
284
285                 case '.':  /* for pp-number */
286                         PUTCH(ch);
287                         ch = NXTCH();
288                         if (ch < '0' || ch > '9')
289                                 goto xloop;
290                         /* FALLTHROUGH */
291                 case '0'case '1'case '2'case '3'case '4':
292                 case '5'case '6'case '7'case '8'case '9':
293                         do {
294                                 PUTCH(ch);
ragge
1.47
295 nxt:                            ch = NXTCH();
296                                 if (ch == '\\') {
297                                         ch = NXTCH();
298                                         if (ch == '\n') {
299                                                 goto nxt;
300                                         } else {
301                                                 unch(ch);
302                                                 ch = '\\';
303                                         }
304                                 }
ragge
1.19
305                                 if (spechr[ch] & C_EP) {
306                                         PUTCH(ch);
307                                         ch = NXTCH();
308                                         if (ch == '-' || ch == '+')
309                                                 continue;
310                                 }
311                         } while ((spechr[ch] & C_ID) || (ch == '.'));
312                         goto xloop;
313
314                 case '\''/* character literal */
ragge
1.21
315 con:                    PUTCH(ch);
ragge
1.23
316                         if (tflag)
317                                 continue/* character constants ignored */
ragge
1.21
318                         while ((ch = NXTCH()) != '\'') {
ragge
1.19
319                                 PUTCH(ch);
320                                 if (ch == '\\') {
ragge
1.21
321                                         ch = NXTCH();
ragge
1.19
322                                         PUTCH(ch);
ragge
1.21
323                                 } else if (ch < 0)
ragge
1.19
324                                         return;
ragge
1.21
325                                 else if (ch == '\n')
ragge
1.19
326                                         goto xloop;
ragge
1.21
327                         }
ragge
1.19
328                         PUTCH(ch);
329                         break;
ragge
1.21
330
ragge
1.19
331                 case 'L':
332                         ch = NXTCH();
333                         if (ch == '\"') {
334                                 PUTCH('L');
335                                 goto str;
336                         }
337                         if (ch == '\'') {
338                                 PUTCH('L');
339                                 goto con;
340                         }
341                         unch(ch);
342                         ch = 'L';
343                         /* FALLTHROUGH */
344                 default:
345                         if ((spechr[ch] & C_ID) == 0)
346                                 error("fastscan");
347                         if (flslvl) {
348                                 while (spechr[ch] & C_ID)
349                                         ch = NXTCH();
350                                 goto xloop;
351                         }
ragge
1.43
352                         onemore = i = ccnt = 0;
ragge
1.19
353                         do {
gmcgarry
1.26
354                                 yytext[i++] = (usch)ch;
ragge
1.19
355                                 ch = NXTCH();
ragge
1.36
356                                 if (ch == '\\') {
357                                         ch = NXTCH();
358                                         if (ch != '\n') {
359                                                 unch('\n');
360                                                 ch = '\\';
361                                         } else {
362                                                 ifiles->lineno++;
363                                                 ch = NXTCH();
364                                         }
365                                 }
ragge
1.19
366                                 if (ch < 0)
367                                         return;
368                         } while (spechr[ch] & C_ID);
ragge
1.43
369
ragge
1.19
370                         yytext[i] = 0;
371                         unch(ch);
ragge
1.43
372
ragge
1.48.2.1
373                         cp = stringbuf;
ragge
1.43
374                         if ((nl = lookup((usch *)yytextFIND)) && kfind(nl)) {
375                                 putstr(stringbuf);
ragge
1.19
376                         } else
377                                 putstr((usch *)yytext);
ragge
1.48.2.1
378                         stringbuf = cp;
ragge
1.43
379
ragge
1.19
380                         break;
381                 }
382         }
383 }
ragge
1.1
384
ragge
1.13
385 int
ragge
1.19
386 sloscan()
ragge
1.3
387 {
ragge
1.13
388         int ch;
389         int yyp;
390
391 zagain:
392         yyp = 0;
gmcgarry
1.26
393         ch = inch();
394         yytext[yyp++] = (usch)ch;
ragge
1.13
395         switch (ch) {
ragge
1.14
396         case -1:
397                 return 0;
ragge
1.13
398         case '\n':
ragge
1.19
399                 /* sloscan() never passes \n, that's up to fastscan() */
400                 unch(ch);
401                 goto yyret;
ragge
1.13
402
403         case '\r'/* Ignore CR's */
404                 yyp = 0;
405                 break;
406
407         case '0'case '1'case '2'case '3'case '4'case '5'
408         case '6'case '7'case '8'case '9':
409                 /* readin a "pp-number" */
410 ppnum:          for (;;) {
ragge
1.19
411                         ch = inch();
412                         if (spechr[ch] & C_EP) {
gmcgarry
1.26
413                                 yytext[yyp++] = (usch)ch;
ragge
1.19
414                                 ch = inch();
ragge
1.13
415                                 if (ch == '-' || ch == '+') {
gmcgarry
1.26
416                                         yytext[yyp++] = (usch)ch;
ragge
1.13
417                                 } else
ragge
1.19
418                                         unch(ch);
ragge
1.13
419                                 continue;
420                         }
ragge
1.19
421                         if ((spechr[ch] & C_ID) || ch == '.') {
gmcgarry
1.26
422                                 yytext[yyp++] = (usch)ch;
ragge
1.13
423                                 continue;
424                         } 
425                         break;
426                 }
ragge
1.19
427                 unch(ch);
ragge
1.13
428                 yytext[yyp] = 0;
429
ragge
1.19
430                 return NUMBER;
ragge
1.13
431
432         case '\'':
ragge
1.19
433 chlit:          
ragge
1.13
434                 for (;;) {
ragge
1.19
435                         if ((ch = inch()) == '\\') {
gmcgarry
1.26
436                                 yytext[yyp++] = (usch)ch;
437                                 yytext[yyp++] = (usch)inch();
ragge
1.13
438                                 continue;
439                         } else if (ch == '\n') {
440                                 /* not a constant */
441                                 while (yyp > 1)
ragge
1.19
442                                         unch(yytext[--yyp]);
ragge
1.13
443                                 ch = '\'';
444                                 goto any;
445                         } else
gmcgarry
1.26
446                                 yytext[yyp++] = (usch)ch;
ragge
1.13
447                         if (ch == '\'')
448                                 break;
449                 }
450                 yytext[yyp] = 0;
451
ragge
1.19
452                 return (NUMBER);
ragge
1.13
453
454         case ' ':
455         case '\t':
ragge
1.19
456                 while ((ch = inch()) == ' ' || ch == '\t')
gmcgarry
1.26
457                         yytext[yyp++] = (usch)ch;
ragge
1.19
458                 unch(ch);
459                 yytext[yyp] = 0;
460                 return(WSPACE);
ragge
1.13
461
462         case '/':
ragge
1.19
463                 if ((ch = inch()) == '/') {
ragge
1.13
464                         do {
gmcgarry
1.26
465                                 yytext[yyp++] = (usch)ch;
ragge
1.19
466                                 ch = inch();
ragge
1.13
467                         } while (ch && ch != '\n');
468                         yytext[yyp] = 0;
469                         unch(ch);
470                         goto zagain;
471                 } else if (ch == '*') {
472                         int cwrn;
473                         extern int readmac;
474
ragge
1.33
475                         if (Cflag && !flslvl && readmac) {
476                                 unch(ch);
ragge
1.34
477                                 yytext[yyp] = 0;
ragge
1.13
478                                 return CMNT;
ragge
1.33
479                         }
ragge
1.13
480
481                         wrn = 0;
ragge
1.19
482                 more:   while ((c = inch()) && c != '*') {
ragge
1.13
483                                 if (c == '\n')
484                                         putch(c), ifiles->lineno++;
ragge
1.48
485                                 else if (c == EBLOCK) {
ragge
1.46
486                                         (void)inch();
ragge
1.48
487                                         (void)inch();
488                                 } else if (c == 1/* WARN */
ragge
1.13
489                                         wrn = 1;
490                         }
491                         if (c == 0)
492                                 return 0;
ragge
1.19
493                         if ((c = inch()) && c != '/') {
494                                 unch(c);
ragge
1.13
495                                 goto more;
496                         }
497                         if (c == 0)
498                                 return 0;
499                         if (!tflag && !Cflag && !flslvl)
ragge
1.19
500                                 unch(' ');
ragge
1.13
501                         if (wrn)
ragge
1.19
502                                 unch(1);
ragge
1.13
503                         goto zagain;
504                 }
505                 unch(ch);
506                 ch = '/';
507                 goto any;
508
ragge
1.19
509         case '.':
510                 ch = inch();
511                 if (isdigit(ch)) {
gmcgarry
1.26
512                         yytext[yyp++] = (usch)ch;
ragge
1.19
513                         goto ppnum;
ragge
1.13
514                 } else {
ragge
1.19
515                         unch(ch);
ragge
1.13
516                         ch = '.';
517                 }
ragge
1.19
518                 goto any;
ragge
1.13
519
520         case '\"':
ragge
1.42
521                 if (tflag)
522                         goto any;
ragge
1.13
523         strng:
524                 for (;;) {
ragge
1.19
525                         if ((ch = inch()) == '\\') {
gmcgarry
1.26
526                                 yytext[yyp++] = (usch)ch;
527                                 yytext[yyp++] = (usch)inch();
ragge
1.13
528                                 continue;
529                         } else 
gmcgarry
1.26
530                                 yytext[yyp++] = (usch)ch;
ragge
1.13
531                         if (ch == '\"')
532                                 break;
533                 }
534                 yytext[yyp] = 0;
ragge
1.19
535                 return(STRING);
ragge
1.13
536
537         case 'L':
ragge
1.42
538                 if ((ch = inch()) == '\"' && !tflag) {
gmcgarry
1.26
539                         yytext[yyp++] = (usch)ch;
ragge
1.13
540                         goto strng;
ragge
1.42
541                 } else if (ch == '\'' && !tflag) {
gmcgarry
1.26
542                         yytext[yyp++] = (usch)ch;
ragge
1.13
543                         goto chlit;
544                 }
ragge
1.19
545                 unch(ch);
ragge
1.13
546                 /* FALLTHROUGH */
547
548         /* Yetch, all identifiers */
549         case 'a'case 'b'case 'c'case 'd'case 'e'case 'f'
550         case 'g'case 'h'case 'i'case 'j'case 'k'case 'l'
551         case 'm'case 'n'case 'o'case 'p'case 'q'case 'r'
552         case 's'case 't'case 'u'case 'v'case 'w'case 'x'
553         case 'y'case 'z':
554         case 'A'case 'B'case 'C'case 'D'case 'E'case 'F'
555         case 'G'case 'H'case 'I'case 'J'case 'K':
556         case 'M'case 'N'case 'O'case 'P'case 'Q'case 'R'
557         case 'S'case 'T'case 'U'case 'V'case 'W'case 'X'
558         case 'Y'case 'Z':
ragge
1.19
559         case '_'/* {L}({L}|{D})* */
ragge
1.13
560
561                 /* Special hacks */
562                 for (;;) { /* get chars */
ragge
1.19
563                         ch = inch();
ragge
1.14
564                         if (isalpha(ch) || isdigit(ch) || ch == '_') {
gmcgarry
1.26
565                                 yytext[yyp++] = (usch)ch;
ragge
1.14
566                         } else {
ragge
1.19
567                                 unch(ch);
ragge
1.13
568                                 break;
ragge
1.14
569                         }
ragge
1.13
570                 }
571                 yytext[yyp] = 0/* need already string */
572                 /* end special hacks */
573
ragge
1.19
574                 return IDENT;
ragge
1.13
575         default:
576         any:
577                 yytext[yyp] = 0;
ragge
1.19
578                 return yytext[0];
ragge
1.3
579
ragge
1.13
580         } /* endcase */
ragge
1.14
581         goto zagain;
ragge
1.6
582
ragge
1.13
583 yyret:
584         yytext[yyp] = 0;
585         return ch;
ragge
1.3
586 }
587
ragge
1.19
588 int
589 yylex()
590 {
591         static int ifdefnoex;
592         struct symtab *nl;
593         int chc2;
594
595         while ((ch = sloscan()) == WSPACE)
596                 ;
597         if (ch < 128 && spechr[ch] & C_2)
598                 c2 = inpch();
599         else
600                 c2 = 0;
601
602 #define C2(a,b,c) case a: if (c2 == b) return c; break
603         switch (ch) {
604         C2('=''='EQ);
605         C2('!''='NE);
606         C2('|''|'OROR);
607         C2('&''&'ANDAND);
608         case '<':
609                 if (c2 == '<'return LS;
610                 if (c2 == '='return LE;
611                 break;
612         case '>':
613                 if (c2 == '>'return RS;
614                 if (c2 == '='return GE;
615                 break;
616         case '+':
617         case '-':
618                 if (ch == c2)
619                         badop("");
620                 break;
ragge
1.27
621
ragge
1.33
622         case '/':
623                 if (Cflag == 0 || c2 != '*')
624                         break;
625                 /* Found comment that need to be skipped */
626                 for (;;) {
627                         ch = inpch();
628                 c1:     if (ch != '*')
629                                 continue;
630                         if ((ch = inpch()) == '/')
631                                 break;
632                         goto c1;
633                 }
634                 return yylex();
635
ragge
1.19
636         case NUMBER:
ragge
1.27
637                 if (yytext[0] == '\'') {
638                         yylval.node.op = NUMBER;
639                         yylval.node.nd_val = charcon((usch *)yytext);
640                 } else
641                         cvtdig(yytext[0] != '0' ? 10 :
642                             yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
ragge
1.19
643                 return NUMBER;
ragge
1.27
644
ragge
1.19
645         case IDENT:
ragge
1.44
646                 if (strcmp((char *)yytext"defined") == 0) {
ragge
1.19
647                         ifdef = 1;
648                         return DEFINED;
649                 }
650                 nl = lookup((usch *)yytextFIND);
651                 if (ifdef) {
652                         yylval.node.nd_val = nl != NULL;
653                         ifdef = 0;
654                 } else if (nl && noex == 0) {
ragge
1.43
655                         usch *och = stringbuf;
656                         int i;
ragge
1.19
657
ragge
1.43
658                         i = kfind(nl);
659                         unch(WARN);
660                         if (i)
661                                 unpstr(stringbuf);
662                         else
663                                 unpstr(nl->namep);
ragge
1.19
664                         stringbuf = och;
665                         noex = 1;
666                         return yylex();
667                 } else {
668                         yylval.node.nd_val = 0;
669                 }
670                 yylval.node.op = NUMBER;
671                 return NUMBER;
ragge
1.43
672         case WARN:
ragge
1.19
673                 noex = 0;
674                 return yylex();
675         default:
676                 return ch;
677         }
678         unch(c2);
679         return ch;
680 }
681
ragge
1.13
682 usch *yypyybuf[CPPBUF];
683
684 int yywrap(void);
ragge
1.3
685
ragge
1.2
686 static int
ragge
1.13
687 inpch(void)
ragge
1.2
688 {
ragge
1.6
689         int len;
ragge
1.3
690
ragge
1.11
691         if (ifiles->curptr < ifiles->maxread)
ragge
1.2
692                 return *ifiles->curptr++;
ragge
1.11
693
ragge
1.38
694         if (ifiles->infil == -1)
695                 return -1;
ragge
1.6
696         if ((len = read(ifiles->infilifiles->bufferCPPBUF)) < 0)
ragge
1.13
697                 error("read error on file %s"ifiles->orgfn);
ragge
1.6
698         if (len == 0)
ragge
1.3
699                 return -1;
700         ifiles->curptr = ifiles->buffer;
ragge
1.6
701         ifiles->maxread = ifiles->buffer + len;
ragge
1.13
702         return inpch();
ragge
1.2
703 }
ragge
1.1
704
705 static int
ragge
1.13
706 inch(void)
ragge
1.1
707 {
708         int c;
709
ragge
1.13
710 again:  switch (c = inpch()) {
ragge
1.1
711         case '\\'/* continued lines */
ragge
1.13
712 msdos:          if ((c = inpch()) == '\n') {
ragge
1.1
713                         ifiles->lineno++;
714                         goto again;
ragge
1.13
715                 } else if (c == '\r')
716                         goto msdos;
717                 unch(c);
ragge
1.1
718                 return '\\';
719         case '?'/* trigraphs */
ragge
1.19
720                 if ((c = chktg())) {
ragge
1.13
721                         unch(c);
ragge
1.19
722                         goto again;
ragge
1.1
723                 }
ragge
1.19
724                 return '?';
ragge
1.1
725         default:
726                 return c;
727         }
728 }
729
ragge
1.13
730 /*
731  * Let the command-line args be faked defines at beginning of file.
732  */
733 static void
734 prinit(struct initar *itstruct includ *ic)
ragge
1.1
735 {
ragge
1.31
736         const char *pre, *post;
737         char *a;
ragge
1.1
738
ragge
1.13
739         if (it->next)
740                 prinit(it->nextic);
741         pre = post = NULL/* XXX gcc */
742         switch (it->type) {
743         case 'D':
744                 pre = "#define ";
745                 if ((a = strchr(it->str'=')) != NULL) {
746                         *a = ' ';
747                         post = "\n";
ragge
1.1
748                 } else
ragge
1.13
749                         post = " 1\n";
ragge
1.1
750                 break;
ragge
1.13
751         case 'U':
752                 pre = "#undef ";
753                 post = "\n";
ragge
1.1
754                 break;
ragge
1.13
755         case 'i':
756                 pre = "#include \"";
757                 post = "\"\n";
ragge
1.1
758                 break;
759         default:
ragge
1.13
760                 error("prinit");
ragge
1.1
761         }
ragge
1.13
762         strlcat((char *)ic->bufferpreCPPBUF+1);
763         strlcat((char *)ic->bufferit->strCPPBUF+1);
764         if (strlcat((char *)ic->bufferpostCPPBUF+1) >= CPPBUF+1)
765                 error("line exceeds buffer size");
766
767         ic->lineno--;
768         while (*ic->maxread)
769                 ic->maxread++;
ragge
1.1
770 }
771
ragge
1.4
772 /*
ragge
1.6
773  * A new file included.
774  * If ifiles == NULL, this is the first file and already opened (stdin).
ragge
1.13
775  * Return 0 on success, -1 if file to be included is not found.
ragge
1.4
776  */
777 int
ragge
1.31
778 pushfile(const usch *fileconst usch *fnint idxvoid *incs)
ragge
1.4
779 {
ragge
1.13
780         extern struct initar *initar;
ragge
1.6
781         struct includ ibuf;
782         struct includ *ic;
ragge
1.19
783         int otrulvl;
ragge
1.6
784
785         ic = &ibuf;
ragge
1.13
786         ic->next = ifiles;
ragge
1.4
787
ragge
1.6
788         if (file != NULL) {
ragge
1.31
789                 if ((ic->infil = open((const char *)fileO_RDONLY)) < 0)
ragge
1.4
790                         return -1;
ragge
1.13
791                 ic->orgfn = ic->fname = file;
792                 if (++inclevel > MAX_INCLEVEL)
793                         error("Limit for nested includes exceeded");
ragge
1.6
794         } else {
795                 ic->infil = 0;
ragge
1.31
796                 ic->orgfn = ic->fname = (const usch *)"<stdin>";
ragge
1.6
797         }
ragge
1.48.2.1
798 #ifndef BUF_STACK
799         ic->bbuf = malloc(BBUFSZ);
800 #endif
ragge
1.6
801         ic->buffer = ic->bbuf+NAMEMAX;
ragge
1.4
802         ic->curptr = ic->buffer;
803         ifiles = ic;
ragge
1.13
804         ic->lineno = 1;
ragge
1.6
805         ic->maxread = ic->curptr;
ragge
1.29
806         ic->idx = idx;
807         ic->incs = incs;
808         ic->fn = fn;
ragge
1.13
809         prtline();
810         if (initar) {
ragge
1.38
811                 int oin = ic->infil;
812                 ic->infil = -1;
ragge
1.13
813                 *ic->maxread = 0;
814                 prinit(initaric);
ragge
1.41
815                 initar = NULL;
ragge
1.13
816                 if (dMflag)
817                         write(ofdic->bufferstrlen((char *)ic->buffer));
ragge
1.38
818                 fastscan();
819                 prtline();
820                 ic->infil = oin;
ragge
1.13
821         }
ragge
1.4
822
ragge
1.13
823         otrulvl = trulvl;
ragge
1.4
824
ragge
1.19
825         fastscan();
ragge
1.13
826
827         if (otrulvl != trulvl || flslvl)
ragge
1.6
828                 error("unterminated conditional");
ragge
1.4
829
ragge
1.48.2.1
830 #ifndef BUF_STACK
831         free(ic->bbuf);
832 #endif
ragge
1.13
833         ifiles = ic->next;
ragge
1.6
834         close(ic->infil);
ragge
1.13
835         inclevel--;
ragge
1.6
836         return 0;
ragge
1.4
837 }
ragge
1.1
838
839 /*
840  * Print current position to output file.
841  */
842 void
843 prtline()
844 {
ragge
1.13
845         usch *s, *os = stringbuf;
846
847         if (Mflag) {
848                 if (dMflag)
849                         return/* no output */
850                 if (ifiles->lineno == 1) {
851                         s = sheap("%s: %s\n"Mfileifiles->fname);
852                         write(ofdsstrlen((char *)s));
853                 }
854         } else if (!Pflag)
ragge
1.30
855                 putstr(sheap("\n# %d \"%s\"\n"ifiles->linenoifiles->fname));
ragge
1.13
856         stringbuf = os;
ragge
1.1
857 }
858
859 void
860 cunput(int c)
861 {
ragge
1.13
862 #ifdef CPP_DEBUG
ragge
1.43
863 //      extern int dflag;
864 //      if (dflag)printf(": '%c'(%d)\n", c > 31 ? c : ' ', c);
ragge
1.13
865 #endif
ragge
1.19
866 #if 0
867 if (c == 10) {
868         printf("c == 10!!!\n");
869 }
870 #endif
871         unch(c);
ragge
1.1
872 }
873
ragge
1.13
874 int yywrap(void) { return 1; }
875
876 static int
877 dig2num(int c)
878 {
879         if (c >= 'a')
880                 c = c - 'a' + 10;
881         else if (c >= 'A')
882                 c = c - 'A' + 10;
883         else
884                 c = c - '0';
885         return c;
886 }
887
888 /*
889  * Convert string numbers to unsigned long long and check overflow.
890  */
891 static void
892 cvtdig(int rad)
893 {
894         unsigned long long rv = 0;
895         unsigned long long rv2 = 0;
ragge
1.44
896         usch *y = yytext;
ragge
1.13
897         int c;
898
899         c = *y++;
900         if (rad == 16)
901                 y++;
902         while (isxdigit(c)) {
903                 rv = rv * rad + dig2num(c);
904                 /* check overflow */
905                 if (rv / rad < rv2)
906                         error("Constant \"%s\" is out of range"yytext);
907                 rv2 = rv;
908                 c = *y++;
909         }
910         y--;
911         while (*y == 'l' || *y == 'L')
912                 y++;
913         yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER;
914         yylval.node.nd_uval = rv;
915         if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0)
916                 yylval.node.op = UNUMBER;
917         if (yylval.node.op == NUMBER && yylval.node.nd_val < 0)
ragge
1.19
918                 /* too large for signed, see 6.4.4.1 */
ragge
1.13
919                 error("Constant \"%s\" is out of range"yytext);
920 }
921
922 static int
923 charcon(usch *p)
924 {
925         int valc;
926
927         p++; /* skip first ' */
928         val = 0;
929