Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20110102092728

Diff

Diff from 1.42 to:

Annotations

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

Annotated File View

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