Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20110204072701

Diff

Diff from 1.46 to:

Annotations

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

Annotated File View

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