Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:plunky:20121029175916

Diff

Diff from 1.96 to:

Annotations

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

Annotated File View

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