Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:plunky:20121102105545

Diff

Diff from 1.101 to:

Annotations

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

Annotated File View

plunky
1.101
1 /*      $Id: token.c,v 1.101 2012/11/02 10:55:45 plunky Exp $   */
ragge
1.1
2
3 /*
ragge
1.13
4  * Copyright (c) 2004,2009 Anders Magnusson. All rights reserved.
ragge
1.1
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
ragge
1.19
27 /*
28  * Tokenizer for the C preprocessor.
29  * There are three main routines:
30  *      - fastscan() loops over the input stream searching for magic
31  *              characters that may require actions.
32  *      - sloscan() tokenize the input stream and returns tokens.
33  *              It may recurse into itself during expansion.
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>
ragge
1.13
47 #ifdef HAVE_UNISTD_H
ragge
1.2
48 #include <unistd.h>
ragge
1.13
49 #endif
ragge
1.2
50 #include <fcntl.h>
ragge
1.1
51
ragge
1.13
52 #include "compat.h"
ragge
1.1
53 #include "cpp.h"
plunky
1.72
54 #include "cpy.h"
ragge
1.13
55
56 static void cvtdig(int rad);
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);
64 static void pragmastmt(void);
65 static void undefstmt(void);
ragge
1.39
66 static void cppwarning(void);
ragge
1.13
67 static void elifstmt(void);
ragge
1.19
68 static int chktg(void);
69 static int inpch(void);
ragge
1.13
70 static int inch(void);
71
ragge
1.19
72 #define PUTCH(ch) if (!flslvl) putch(ch)
ragge
1.13
73 /* protection against recursion in #include */
74 #define MAX_INCLEVEL    100
75 static int inclevel;
76
ragge
1.19
77 /* get next character unaltered */
78 #define NXTCH() (ifiles->curptr < ifiles->maxread ? *ifiles->curptr++ : inpch())
ragge
1.1
79
ragge
1.44
80 usch yytext[CPPBUF];
gmcgarry
1.16
81
plunky
1.81
82 struct includ *ifiles;
83
plunky
1.97
84 /* some common special combos for init */
85 #define C_NL    (C_SPEC|C_WSNL)
86 #define C_DX    (C_SPEC|C_ID|C_DIGIT|C_HEX)
87 #define C_I     (C_SPEC|C_ID|C_ID0)
88 #define C_IP    (C_SPEC|C_ID|C_ID0|C_EP)
89 #define C_IX    (C_SPEC|C_ID|C_ID0|C_HEX)
90 #define C_IXE   (C_SPEC|C_ID|C_ID0|C_HEX|C_EP)
91
92 usch spechr[256] = {
ragge
1.43
93         0,      0,      0,      0,      C_SPECC_SPEC0,      0,
plunky
1.97
94         0,      C_WSNLC_NL,   0,      0,      C_WSNL0,      0,
ragge
1.19
95         0,      0,      0,      0,      0,      0,      0,      0,
96         0,      0,      0,      0,      0,      0,      0,      0,
97
ragge
1.43
98         C_WSNLC_2,    C_SPEC0,      0,      0,      C_2,    C_SPEC,
ragge
1.33
99         0,      0,      0,      C_2,    0,      C_2,    0,      C_SPEC|C_2,
plunky
1.97
100         C_DX,   C_DX,   C_DX,   C_DX,   C_DX,   C_DX,   C_DX,   C_DX,
101         C_DX,   C_DX,   0,      0,      C_2,    C_2,    C_2,    C_SPEC,
ragge
1.19
102
plunky
1.97
103         0,      C_IX,   C_IX,   C_IX,   C_IX,   C_IXE,  C_IX,   C_I,
ragge
1.19
104         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
plunky
1.97
105         C_IP,   C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
ragge
1.51
106         C_I,    C_I,    C_I,    0,      C_SPEC0,      0,      C_I,
ragge
1.19
107
plunky
1.97
108         0,      C_IX,   C_IX,   C_IX,   C_IX,   C_IXE,  C_IX,   C_I,
ragge
1.19
109         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
plunky
1.97
110         C_IP,   C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
ragge
1.19
111         C_I,    C_I,    C_I,    0,      C_2,    0,      0,      0,
112 };
ragge
1.1
113
ragge
1.13
114 static void
115 unch(int c)
116 {
plunky
1.93
117         if (c == -1)
118                 return;
ragge
1.15
119                 
120         --ifiles->curptr;
121         if (ifiles->curptr < ifiles->bbuf)
122                 error("pushback buffer full");
gmcgarry
1.26
123         *ifiles->curptr = (usch)c;
ragge
1.13
124 }
ragge
1.1
125
plunky
1.92
126 static void
ragge
1.45
127 eatcmnt(void)
128 {
129         int ch;
130
131         if (Cflag) { PUTCH('/'); PUTCH('*'); }
132         for (;;) {
133                 ch = inch();
134                 if (ch == '\n') {
135                         ifiles->lineno++;
plunky
1.91
136                         if (!CflagPUTCH('\n');
ragge
1.45
137                 }
138                 if (ch == -1)
plunky
1.92
139                         break;
ragge
1.45
140                 if (ch == '*') {
141                         ch = inch();
142                         if (ch == '/') {
143                                 if (Cflag) {
144                                         PUTCH('*');
145                                         PUTCH('/');
146                                 } else
147                                         PUTCH(' ');
148                                 break;
149                         }
150                         unch(ch);
151                         ch = '*';
152                 }
153                 if (CflagPUTCH(ch);
154         }
155 }
156
ragge
1.19
157 /*
158  * Scan quickly the input file searching for:
159  *      - '#' directives
160  *      - keywords (if not flslvl)
161  *      - comments
162  *
163  *      Handle strings, numbers and trigraphs with care.
164  *      Only data from pp files are scanned here, never any rescans.
165  *      TODO: Only print out strings before calling other functions.
166  */
167 static void
168 fastscan(void)
169 {
170         struct symtab *nl;
gmcgarry
1.57
171         int chi = 0;
ragge
1.52
172         int nnl = 0;
ragge
1.49
173         usch *cp;
ragge
1.19
174
175         goto run;
176         for (;;) {
177                 ch = NXTCH();
178 xloop:          if (ch == -1)
179                         return;
plunky
1.60
180 #ifdef PCC_DEBUG
ragge
1.43
181                 if (dflag>1)
182                         printf("fastscan ch %d (%c)\n"chch > 31 ? ch : '@');
plunky
1.60
183 #endif
ragge
1.19
184                 if ((spechr[ch] & C_SPEC) == 0) {
185                         PUTCH(ch);
186                         continue;
187                 }
188                 switch (ch) {
ragge
1.44
189                 case EBLOCK:
ragge
1.43
190                 case WARN:
191                 case CONC:
192                         error("bad char passed");
193                         break;
194
ragge
1.19
195                 case '/'/* Comments */
196                         if ((ch = inch()) == '/') {
ragge
1.45
197 cppcmt:                         if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
ragge
1.19
198                                 do {
199                                         if (CflagPUTCH(ch);
200                                         ch = inch();
201                                 } while (ch != -1 && ch != '\n');
202                                 goto xloop;
203                         } else if (ch == '*') {
plunky
1.92
204                                 eatcmnt();
205                                 continue;
ragge
1.19
206                         } else {
207                                 PUTCH('/');
208                                 goto xloop;
209                         }
210                         break;
211
212                 case '?':  /* trigraphs */
213                         if ((ch = chktg()))
214                                 goto xloop;
215                         PUTCH('?');
216                         break;
217
ragge
1.37
218                 case '\\':
219                         if ((ch = NXTCH()) == '\n') {
220                                 ifiles->lineno++;
221                                 continue;
222                         }
plunky
1.92
223                         PUTCH('\\');
ragge
1.37
224                         goto xloop;
225
ragge
1.19
226                 case '\n'/* newlines, for pp directives */
plunky
1.88
227                         while (nnl > 0) { PUTCH('\n'); nnl--; ifiles->lineno++; }
ragge
1.50
228 run2:                   ifiles->lineno++;
ragge
1.19
229                         do {
230                                 PUTCH(ch);
231 run:                            ch = NXTCH();
ragge
1.45
232                                 if (ch == '/') {
233                                         ch = NXTCH();
234                                         if (ch == '/')
235                                                 goto cppcmt;
236                                         if (ch == '*') {
plunky
1.92
237                                                 eatcmnt();
ragge
1.45
238                                                 goto run;
plunky
1.92
239                                         }
ragge
1.45
240                                         unch(ch);
241                                         ch = '/';
242                                 }
ragge
1.19
243                         } while (ch == ' ' || ch == '\t');
ragge
1.50
244                         if (ch == '\\') {
245                                 ch = NXTCH();
246                                 if (ch == '\n')
247                                         goto run2;
248                                 unch(ch);
249                                 ch = '\\';
250                         }
ragge
1.19
251                         if (ch == '#') {
252                                 ppdir();
253                                 continue;
ragge
1.40
254                         } else if (ch == '%') {
255                                 ch = NXTCH();
256                                 if (ch == ':') {
257                                         ppdir();
258                                         continue;
259                                 }
plunky
1.92
260                                 unch(ch);
261                                 ch = '%';
ragge
1.55
262                         } else if (ch == '?') {
263                                 if ((ch = chktg()) == '#') {
264                                         ppdir();
265                                         continue;
266                                 } else if (ch == 0
267                                         ch = '?';
ragge
1.19
268                         }
269                         goto xloop;
270
271                 case '\"'/* strings */
ragge
1.21
272 str:                    PUTCH(ch);
ragge
1.53
273                         while ((ch = NXTCH()) != '\"') {
274                                 if (ch == '\n')
275                                         goto xloop;
ragge
1.19
276                                 if (ch == '\\') {
ragge
1.53
277                                         if ((ch = NXTCH()) != '\n') {
278                                                 PUTCH('\\');
279                                                 PUTCH(ch);
280                                         } else
281                                                 nnl++;
282                                         continue;
283                                 }
plunky
1.90
284                                 if (ch == -1)
ragge
1.19
285                                         return;
ragge
1.53
286                                 PUTCH(ch);
ragge
1.21
287                         }
ragge
1.19
288                         PUTCH(ch);
289                         break;
290
291                 case '.':  /* for pp-number */
292                         PUTCH(ch);
293                         ch = NXTCH();
294                         if (ch < '0' || ch > '9')
295                                 goto xloop;
296                         /* FALLTHROUGH */
297                 case '0'case '1'case '2'case '3'case '4':
298                 case '5'case '6'case '7'case '8'case '9':
299                         do {
plunky
1.99
300 nxp:                            PUTCH(ch);
ragge
1.47
301 nxt:                            ch = NXTCH();
302                                 if (ch == '\\') {
303                                         ch = NXTCH();
304                                         if (ch == '\n') {
plunky
1.89
305                                                 nnl++;
ragge
1.47
306                                                 goto nxt;
307                                         }
plunky
1.92
308                                         unch(ch);
309                                         ch = '\\';
ragge
1.47
310                                 }
plunky
1.94
311                                 if (ch == -1)
312                                         return;
ragge
1.19
313                                 if (spechr[ch] & C_EP) {
314                                         PUTCH(ch);
315                                         ch = NXTCH();
316                                         if (ch == '-' || ch == '+')
plunky
1.99
317                                                 goto nxp;
plunky
1.94
318                                         if (ch == -1)
319                                                 return;
ragge
1.19
320                                 }
321                         } while ((spechr[ch] & C_ID) || (ch == '.'));
322                         goto xloop;
323
324                 case '\''/* character literal */
ragge
1.21
325 con:                    PUTCH(ch);
ragge
1.23
326                         if (tflag)
327                                 continue/* character constants ignored */
ragge
1.21
328                         while ((ch = NXTCH()) != '\'') {
ragge
1.52
329                                 if (ch == '\n')
330                                         goto xloop;
ragge
1.19
331                                 if (ch == '\\') {
ragge
1.52
332                                         if ((ch = NXTCH()) != '\n') {
333                                                 PUTCH('\\');
334                                                 PUTCH(ch);
335                                         } else
336                                                 nnl++;
337                                         continue;
338                                 }
plunky
1.90
339                                 if (ch == -1)
ragge
1.19
340                                         return;
ragge
1.52
341                                 PUTCH(ch);
ragge
1.21
342                         }
ragge
1.19
343                         PUTCH(ch);
344                         break;
ragge
1.21
345
ragge
1.19
346                 case 'L':
347                         ch = NXTCH();
348                         if (ch == '\"') {
349                                 PUTCH('L');
350                                 goto str;
351                         }
352                         if (ch == '\'') {
353                                 PUTCH('L');
354                                 goto con;
355                         }
356                         unch(ch);
357                         ch = 'L';
358                         /* FALLTHROUGH */
359                 default:
360                         if ((spechr[ch] & C_ID) == 0)
361                                 error("fastscan");
362                         if (flslvl) {
plunky
1.95
363                                 while (ch != -1 && (spechr[ch] & C_ID))
ragge
1.19
364                                         ch = NXTCH();
365                                 goto xloop;
366                         }
gmcgarry
1.58
367                         i = 0;
ragge
1.19
368                         do {
gmcgarry
1.26
369                                 yytext[i++] = (usch)ch;
ragge
1.19
370                                 ch = NXTCH();
ragge
1.36
371                                 if (ch == '\\') {
372                                         ch = NXTCH();
373                                         if (ch != '\n') {
ragge
1.51
374                                                 unch(ch);
ragge
1.36
375                                                 ch = '\\';
376                                         } else {
ragge
1.51
377                                                 putch('\n');
ragge
1.36
378                                                 ifiles->lineno++;
379                                                 ch = NXTCH();
380                                         }
381                                 }
plunky
1.90
382                                 if (ch == -1)
ragge
1.19
383                                         return;
384                         } while (spechr[ch] & C_ID);
ragge
1.43
385
ragge
1.19
386                         yytext[i] = 0;
387                         unch(ch);
ragge
1.43
388
ragge
1.49
389                         cp = stringbuf;
plunky
1.73
390                         if ((nl = lookup(yytextFIND)) && kfind(nl)) {
ragge
1.43
391                                 putstr(stringbuf);
ragge
1.19
392                         } else
plunky
1.73
393                                 putstr(yytext);
ragge
1.49
394                         stringbuf = cp;
ragge
1.43
395
ragge
1.19
396                         break;
397                 }
398         }
399 }
ragge
1.1
400
ragge
1.13
401 int
plunky
1.64
402 sloscan(void)
ragge
1.3
403 {
ragge
1.13
404         int ch;
405         int yyp;
406
407 zagain:
408         yyp = 0;
gmcgarry
1.26
409         ch = inch();
410         yytext[yyp++] = (usch)ch;
ragge
1.13
411         switch (ch) {
ragge
1.14
412         case -1:
413                 return 0;
ragge
1.13
414         case '\n':
ragge
1.19
415                 /* sloscan() never passes \n, that's up to fastscan() */
416                 unch(ch);
plunky
1.94
417                 yytext[yyp] = 0;
418                 return ch;
ragge
1.13
419
420         case '\r'/* Ignore CR's */
421                 yyp = 0;
422                 break;
423
424         case '0'case '1'case '2'case '3'case '4'case '5'
425         case '6'case '7'case '8'case '9':
426                 /* readin a "pp-number" */
427 ppnum:          for (;;) {
ragge
1.19
428                         ch = inch();
plunky
1.94
429                         if (ch == -1)
430                                 break;
ragge
1.19
431                         if (spechr[ch] & C_EP) {
gmcgarry
1.26
432                                 yytext[yyp++] = (usch)ch;
ragge
1.19
433                                 ch = inch();
ragge
1.13
434                                 if (ch == '-' || ch == '+') {
gmcgarry
1.26
435                                         yytext[yyp++] = (usch)ch;
ragge
1.13
436                                 } else
ragge
1.19
437                                         unch(ch);
ragge
1.13
438                                 continue;
439                         }
ragge
1.19
440                         if ((spechr[ch] & C_ID) || ch == '.') {
gmcgarry
1.26
441                                 yytext[yyp++] = (usch)ch;
ragge
1.13
442                                 continue;
443                         } 
444                         break;
445                 }
ragge
1.19
446                 unch(ch);
ragge
1.13
447                 yytext[yyp] = 0;
448
ragge
1.19
449                 return NUMBER;
ragge
1.13
450
451         case '\'':
ragge
1.19
452 chlit:          
ragge
1.13
453                 for (;;) {
ragge
1.19
454                         if ((ch = inch()) == '\\') {
gmcgarry
1.26
455                                 yytext[yyp++] = (usch)ch;
456                                 yytext[yyp++] = (usch)inch();
ragge
1.13
457                                 continue;
plunky
1.94
458                         } else if (ch == -1 || ch == '\n') {
ragge
1.13
459                                 /* not a constant */
460                                 while (yyp > 1)
ragge
1.19
461                                         unch(yytext[--yyp]);
ragge
1.13
462                                 ch = '\'';
463                                 goto any;
464                         } else
gmcgarry
1.26
465                                 yytext[yyp++] = (usch)ch;
ragge
1.13
466                         if (ch == '\'')
467                                 break;
468                 }
469                 yytext[yyp] = 0;
470
plunky
1.74
471                 return NUMBER;
ragge
1.13
472
473         case ' ':
474         case '\t':
ragge
1.19
475                 while ((ch = inch()) == ' ' || ch == '\t')
gmcgarry
1.26
476                         yytext[yyp++] = (usch)ch;
ragge
1.19
477                 unch(ch);
478                 yytext[yyp] = 0;
plunky
1.74
479                 return WSPACE;
ragge
1.13
480
481         case '/':
ragge
1.19
482                 if ((ch = inch()) == '/') {
ragge
1.13
483                         do {
gmcgarry
1.26
484                                 yytext[yyp++] = (usch)ch;
ragge
1.19
485                                 ch = inch();
plunky
1.94
486                         } while (ch != -1 && ch != '\n');
ragge
1.13
487                         yytext[yyp] = 0;
488                         unch(ch);
489                         goto zagain;
490                 } else if (ch == '*') {
491                         int cwrn;
492                         extern int readmac;
493
ragge
1.33
494                         if (Cflag && !flslvl && readmac) {
495                                 unch(ch);
ragge
1.34
496                                 yytext[yyp] = 0;
ragge
1.13
497                                 return CMNT;
ragge
1.33
498                         }
ragge
1.13
499
500                         wrn = 0;
plunky
1.94
501                 more:   while ((c = inch()) != '*') {
502                                 if (c == -1)
503                                         return 0;       
ragge
1.13
504                                 if (c == '\n')
505                                         putch(c), ifiles->lineno++;
ragge
1.48
506                                 else if (c == EBLOCK) {
ragge
1.46
507                                         (void)inch();
ragge
1.48
508                                         (void)inch();
plunky
1.96
509                                 } else if (c == WARN)
ragge
1.13
510                                         wrn = 1;
511                         }
plunky
1.94
512                         if ((c = inch()) == -1)
ragge
1.13
513                                 return 0;
plunky
1.94
514                         if (c != '/') {
ragge
1.19
515                                 unch(c);
ragge
1.13
516                                 goto more;
517                         }
518                         if (!tflag && !Cflag && !flslvl)
ragge
1.19
519                                 unch(' ');
ragge
1.13
520                         if (wrn)
plunky
1.96
521                                 unch(WARN);
ragge
1.13
522                         goto zagain;
523                 }
524                 unch(ch);
525                 ch = '/';
526                 goto any;
527
ragge
1.19
528         case '.':
plunky
1.94
529                 if ((ch = inch()) == -1)
530                         return 0;
plunky
1.97
531                 if ((spechr[ch] & C_DIGIT)) {
gmcgarry
1.26
532                         yytext[yyp++] = (usch)ch;
ragge
1.19
533                         goto ppnum;
ragge
1.13
534                 } else {
ragge
1.19
535                         unch(ch);
ragge
1.13
536                         ch = '.';
537                 }
ragge
1.19
538                 goto any;
ragge
1.13
539
540         case '\"':
ragge
1.62
541                 if (tflag && defining)
ragge
1.42
542                         goto any;
ragge
1.13
543         strng:
544                 for (;;) {
ragge
1.19
545                         if ((ch = inch()) == '\\') {
gmcgarry
1.26
546                                 yytext[yyp++] = (usch)ch;
547                                 yytext[yyp++] = (usch)inch();
ragge
1.13
548                                 continue;
plunky
1.94
549                         } else if (ch == -1) {
550                                 break;
ragge
1.13
551                         } else 
gmcgarry
1.26
552                                 yytext[yyp++] = (usch)ch;
ragge
1.13
553                         if (ch == '\"')
554                                 break;
555                 }
556                 yytext[yyp] = 0;
plunky
1.74
557                 return STRING;
ragge
1.13
558
559         case 'L':
ragge
1.42
560                 if ((ch = inch()) == '\"' && !tflag) {
gmcgarry
1.26
561                         yytext[yyp++] = (usch)ch;
ragge
1.13
562                         goto strng;
ragge
1.42
563                 } else if (ch == '\'' && !tflag) {
gmcgarry
1.26
564                         yytext[yyp++] = (usch)ch;
ragge
1.13
565                         goto chlit;
566                 }
ragge
1.19
567                 unch(ch);
ragge
1.13
568                 /* FALLTHROUGH */
569
570         /* Yetch, all identifiers */
571         case 'a'case 'b'case 'c'case 'd'case 'e'case 'f'
572         case 'g'case 'h'case 'i'case 'j'case 'k'case 'l'
573         case 'm'case 'n'case 'o'case 'p'case 'q'case 'r'
574         case 's'case 't'case 'u'case 'v'case 'w'case 'x'
575         case 'y'case 'z':
576         case 'A'case 'B'case 'C'case 'D'case 'E'case 'F'
577         case 'G'case 'H'case 'I'case 'J'case 'K':
578         case 'M'case 'N'case 'O'case 'P'case 'Q'case 'R'
579         case 'S'case 'T'case 'U'case 'V'case 'W'case 'X'
580         case 'Y'case 'Z':
ragge
1.19
581         case '_'/* {L}({L}|{D})* */
ragge
1.13
582
583                 /* Special hacks */
584                 for (;;) { /* get chars */
plunky
1.94
585                         if ((ch = inch()) == -1)
586                                 break;
plunky
1.97
587                         if ((spechr[ch] & C_ID)) {
gmcgarry
1.26
588                                 yytext[yyp++] = (usch)ch;
ragge
1.14
589                         } else {
plunky
1.94
590                                 unch(ch);
ragge
1.13
591                                 break;
ragge
1.14
592                         }
ragge
1.13
593                 }
594                 yytext[yyp] = 0/* need already string */
595                 /* end special hacks */
596
ragge
1.19
597                 return IDENT;
ragge
1.13
598         default:
599         any:
600                 yytext[yyp] = 0;
ragge
1.19
601                 return yytext[0];
ragge
1.3
602
ragge
1.13
603         } /* endcase */
ragge
1.14
604         goto zagain;
ragge
1.3
605 }
606
ragge
1.19
607 int
plunky
1.64
608 yylex(void)
ragge
1.19
609 {
610         static int ifdefnoex;
611         struct symtab *nl;
612         int chc2;
613
614         while ((ch = sloscan()) == WSPACE)
615                 ;
plunky
1.97
616         if (ch < 128 && (spechr[ch] & C_2))
ragge
1.19
617                 c2 = inpch();
618         else
619                 c2 = 0;
620
621         switch (ch) {
plunky
1.97
622         case '=':
623                 if (c2 == '='return EQ;
624                 break;
625         case '!':
626                 if (c2 == '='return NE;
627                 break;
628         case '|':
629                 if (c2 == '|'return OROR;
630                 break;
631         case '&':
632                 if (c2 == '&'return ANDAND;
633                 break;
ragge
1.19
634         case '<':
635                 if (c2 == '<'return LS;
636                 if (c2 == '='return LE;
637                 break;
638         case '>':
639                 if (c2 == '>'return RS;
640                 if (c2 == '='return GE;
641                 break;
642         case '+':
643         case '-':
644                 if (ch == c2)
plunky
1.78
645                         error("invalid preprocessor operator %c%c"chc2);
ragge
1.19
646                 break;
ragge
1.27
647
ragge
1.33
648         case '/':
649                 if (Cflag == 0 || c2 != '*')
650                         break;
651                 /* Found comment that need to be skipped */
652                 for (;;) {
653                         ch = inpch();
654                 c1:     if (ch != '*')
655                                 continue;
656                         if ((ch = inpch()) == '/')
657                                 break;
658                         goto c1;
659                 }
660                 return yylex();
661
ragge
1.19
662         case NUMBER:
ragge
1.27
663                 if (yytext[0] == '\'') {
664                         yylval.node.op = NUMBER;
plunky
1.73
665                         yylval.node.nd_val = charcon(yytext);
ragge
1.27
666                 } else
667                         cvtdig(yytext[0] != '0' ? 10 :
668                             yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
ragge
1.19
669                 return NUMBER;
ragge
1.27
670
ragge
1.19
671         case IDENT:
ragge
1.44
672                 if (strcmp((char *)yytext"defined") == 0) {
ragge
1.19
673                         ifdef = 1;
674                         return DEFINED;
675                 }
plunky
1.73
676                 nl = lookup(yytextFIND);
ragge
1.19
677                 if (ifdef) {
678                         yylval.node.nd_val = nl != NULL;
679                         ifdef = 0;
680                 } else if (nl && noex == 0) {
ragge
1.43
681                         usch *och = stringbuf;
682                         int i;
ragge
1.19
683
ragge
1.43
684                         i = kfind(nl);
685                         unch(WARN);
686                         if (i)
687                                 unpstr(stringbuf);
688                         else
689                                 unpstr(nl->namep);
ragge
1.19
690                         stringbuf = och;
691                         noex = 1;
692                         return yylex();
693                 } else {
694                         yylval.node.nd_val = 0;
695                 }
696                 yylval.node.op = NUMBER;
697                 return NUMBER;
ragge
1.43
698         case WARN:
ragge
1.19
699                 noex = 0;
ragge
1.70
700                 /* FALLTHROUGH */
701         case PHOLD:
ragge
1.19
702                 return yylex();
703         default:
704                 return ch;
705         }
706         unch(c2);
707         return ch;
708 }
709
ragge
1.2
710 static int
ragge
1.13
711 inpch(void)
ragge
1.2
712 {
ragge
1.6
713         int len;
ragge
1.3
714
ragge
1.11
715         if (ifiles->curptr < ifiles->maxread)
ragge
1.2
716                 return *ifiles->curptr++;
ragge
1.11
717
ragge
1.38
718         if (ifiles->infil == -1)
719                 return -1;
ragge
1.6
720         if ((len = read(ifiles->infilifiles->bufferCPPBUF)) < 0)
ragge
1.13
721                 error("read error on file %s"ifiles->orgfn);
ragge
1.6
722         if (len == 0)
ragge
1.3
723                 return -1;
ragge
1.67
724         ifiles->buffer[len] = 0;
ragge
1.3
725         ifiles->curptr = ifiles->buffer;
ragge
1.6
726         ifiles->maxread = ifiles->buffer + len;
ragge
1.13
727         return inpch();
ragge
1.2
728 }
ragge
1.1
729
730 static int
ragge
1.13
731 inch(void)
ragge
1.1
732 {
733         int c;
734
ragge
1.13
735 again:  switch (c = inpch()) {
ragge
1.1
736         case '\\'/* continued lines */
ragge
1.13
737 msdos:          if ((c = inpch()) == '\n') {
ragge
1.1
738                         ifiles->lineno++;
ragge
1.66
739                         putch('\n');
ragge
1.1
740                         goto again;
ragge
1.13
741                 } else if (c == '\r')
742                         goto msdos;
743                 unch(c);
ragge
1.1
744                 return '\\';
745         case '?'/* trigraphs */
ragge
1.19
746                 if ((c = chktg())) {
ragge
1.13
747                         unch(c);
ragge
1.19
748                         goto again;
ragge
1.1
749                 }
ragge
1.19
750                 return '?';
ragge
1.1
751         default:
752                 return c;
753         }
754 }
755
ragge
1.13
756 /*
757  * Let the command-line args be faked defines at beginning of file.
758  */
759 static void
760 prinit(struct initar *itstruct includ *ic)
ragge
1.1
761 {
ragge
1.31
762         const char *pre, *post;
763         char *a;
ragge
1.1
764
ragge
1.13
765         if (it->next)
766                 prinit(it->nextic);
767         pre = post = NULL/* XXX gcc */
768         switch (it->type) {
769         case 'D':
770                 pre = "#define ";
771                 if ((a = strchr(it->str'=')) != NULL) {
772                         *a = ' ';
773                         post = "\n";
ragge
1.1
774                 } else
ragge
1.13
775                         post = " 1\n";
ragge
1.1
776                 break;
ragge
1.13
777         case 'U':
778                 pre = "#undef ";
779                 post = "\n";
ragge
1.1
780                 break;
ragge
1.13
781         case 'i':
782                 pre = "#include \"";
783                 post = "\"\n";
ragge
1.1
784                 break;
785         default:
ragge
1.13
786                 error("prinit");
ragge
1.1
787         }
ragge
1.13
788         strlcat((char *)ic->bufferpreCPPBUF+1);
789         strlcat((char *)ic->bufferit->strCPPBUF+1);
790         if (strlcat((char *)ic->bufferpostCPPBUF+1) >= CPPBUF+1)
791                 error("line exceeds buffer size");
792
793         ic->lineno--;
794         while (*ic->maxread)
795                 ic->maxread++;
ragge
1.1
796 }
797
ragge
1.4
798 /*
ragge
1.6
799  * A new file included.
800  * If ifiles == NULL, this is the first file and already opened (stdin).
ragge
1.13
801  * Return 0 on success, -1 if file to be included is not found.
ragge
1.4
802  */
803 int
ragge
1.31
804 pushfile(const usch *fileconst usch *fnint idxvoid *incs)
ragge
1.4
805 {
ragge
1.13
806         extern struct initar *initar;
ragge
1.6
807         struct includ ibuf;
808         struct includ *ic;
plunky
1.82
809         int otrulvl;
ragge
1.6
810
811         ic = &ibuf;
ragge
1.13
812         ic->next = ifiles;
ragge
1.4
813
ragge
1.6
814         if (file != NULL) {
ragge
1.31
815                 if ((ic->infil = open((const char *)fileO_RDONLY)) < 0)
ragge
1.4
816                         return -1;
ragge
1.13
817                 ic->orgfn = ic->fname = file;
818                 if (++inclevel > MAX_INCLEVEL)
819                         error("Limit for nested includes exceeded");
ragge
1.6
820         } else {
821                 ic->infil = 0;
ragge
1.31
822                 ic->orgfn = ic->fname = (const usch *)"<stdin>";
ragge
1.6
823         }
ragge
1.49
824 #ifndef BUF_STACK
825         ic->bbuf = malloc(BBUFSZ);
826 #endif
ragge
1.6
827         ic->buffer = ic->bbuf+NAMEMAX;
ragge
1.4
828         ic->curptr = ic->buffer;
829         ifiles = ic;
ragge
1.13
830         ic->lineno = 1;
ragge
1.6
831         ic->maxread = ic->curptr;
ragge
1.29
832         ic->idx = idx;
833         ic->incs = incs;
834         ic->fn = fn;
ragge
1.13
835         prtline();
836         if (initar) {
ragge
1.38
837                 int oin = ic->infil;
838                 ic->infil = -1;
ragge
1.13
839                 *ic->maxread = 0;
840                 prinit(initaric);
ragge
1.41
841                 initar = NULL;
ragge
1.13
842                 if (dMflag)
plunky
1.82
843                         xwrite(ofdic->bufferstrlen((char *)ic->buffer));
ragge
1.38
844                 fastscan();
845                 prtline();
846                 ic->infil = oin;
ragge
1.13
847         }
ragge
1.4
848
ragge
1.13
849         otrulvl = trulvl;
ragge
1.4
850
ragge
1.19
851         fastscan();
ragge
1.13
852
853         if (otrulvl != trulvl || flslvl)
ragge
1.6
854                 error("unterminated conditional");
ragge
1.4
855
ragge
1.49
856 #ifndef BUF_STACK
857         free(ic->bbuf);
858 #endif
ragge
1.13
859         ifiles = ic->next;
ragge
1.6
860         close(ic->infil);
ragge
1.13
861         inclevel--;
ragge
1.6
862         return 0;
ragge
1.4
863 }
ragge
1.1
864
865 /*
866  * Print current position to output file.
867  */
868 void
plunky
1.64
869 prtline(void)
ragge
1.1
870 {
plunky
1.83
871         usch *sb = stringbuf;
ragge
1.13
872
873         if (Mflag) {
874                 if (dMflag)
875                         return/* no output */
876