Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20090522080011

Diff

Diff from 1.18 to:

Annotations

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

Annotated File View

ragge
1.18
1 /*      $Id: token.c,v 1.18 2009/05/22 08:00:11 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.13
27 #include "config.h"
28
ragge
1.1
29 #include <stdlib.h>
30 #include <string.h>
31 #include <ctype.h>
ragge
1.13
32 #ifdef HAVE_UNISTD_H
ragge
1.2
33 #include <unistd.h>
ragge
1.13
34 #endif
ragge
1.2
35 #include <fcntl.h>
ragge
1.13
36 #include <errno.h>
ragge
1.1
37
ragge
1.13
38 #include "compat.h"
ragge
1.1
39 #include "cpp.h"
ragge
1.13
40 #include "y.tab.h"
41
42 static void cvtdig(int rad);
43 static int charcon(usch *);
44 static void elsestmt(void);
45 static void ifdefstmt(void);
46 static void ifndefstmt(void);
47 static void endifstmt(void);
48 static void ifstmt(void);
49 static void cpperror(void);
50 static void pragmastmt(void);
51 static void undefstmt(void);
52 static void cpperror(void);
53 static void elifstmt(void);
54 static void storepb(void);
55 static void badop(const char *);
56 void  include(void);
57 void  define(void);
58
59 extern int yyget_lineno (void);
60 extern void yyset_lineno (int);
61
62 static int inch(void);
63
64 static int scalegotdefcontr;
65 int inif;
66
67 #undef input
68 #undef unput
69 #define input() inch()
70 #define unput(ch) unch(ch)
71 #define PRTOUT(x) if (YYSTATE || slow) return x; if (!flslvl) putstr((usch *)yytext);
72 /* protection against recursion in #include */
73 #define MAX_INCLEVEL    100
74 static int inclevel;
75
76 #define IFR     1
77 #define CONTR   2
78 #define DEF     3
79 #define COMMENT 4
80 static int state;
81 #define BEGIN state =
82 #define YYSTATE state
ragge
1.1
83
gmcgarry
1.16
84 #ifdef YYTEXT_POINTER
85 static char buf[CPPBUF];
86 char *yytext = buf;
87 #else
ragge
1.13
88 char yytext[CPPBUF];
gmcgarry
1.16
89 #endif
90
ragge
1.15
91 static int owasnlwasnl = 1;
ragge
1.1
92
ragge
1.13
93 static void
94 unch(int c)
95 {
ragge
1.15
96                 
97         --ifiles->curptr;
98         if (ifiles->curptr < ifiles->bbuf)
99                 error("pushback buffer full");
100         *ifiles->curptr = c;
ragge
1.13
101 }
ragge
1.1
102
103
ragge
1.13
104 int
105 yylex()
ragge
1.3
106 {
ragge
1.13
107         int ch;
108         int yyp;
109         int osmixedhaspmd;
110
111 zagain:
112         yyp = 0;
113         yytext[yyp++] = ch = inch();
114         owasnl = wasnl;
115         wasnl = 0;
116         switch (ch) {
ragge
1.14
117         case -1:
118                 return 0;
ragge
1.13
119         case '\n':
120                 os = YYSTATE;
121
122                 wasnl = 1;
123                 if (os != IFR)
124                         BEGIN 0;
125                 ifiles->lineno++;
126                 if (flslvl == 0) {
127                         if (ifiles->lineno == 1)
128                                 prtline();
129                         else
130                                 putch('\n');
131                 }
132                 if ((os != 0 || slow) && !contr)
133                         goto yyret;
134                 contr = 0;
135                 break;
136
137         case '\r'/* Ignore CR's */
138                 yyp = 0;
139                 break;
140
141 #define CHK(x,y) if (state != IFR) goto any; \
142         if ((ch = input()) != y) { unput(ch); ch = xgoto any; } \
143         yytext[yyp++] = ch
144
145         case '+'CHK('+','+'); badop("++"); break;
146         case '-'CHK('-','-'); badop("--"); break;
147         case '='CHK('=','='); ch = EQgoto yyret;
148         case '!'CHK('!','='); ch = NEgoto yyret;
149         case '|'CHK('|','|'); ch = ORORgoto yyret;
150         case '&'CHK('&','&'); ch = ANDANDgoto yyret;
151         case '<':
152                 if (state != IFRgoto any;
153                 if ((ch = inch()) == '=') {
154                         yytext[yyp++] = chch = LEgoto yyret;
155                 }
156                 if (ch == '<') { yytext[yyp++] = chch = LSgoto yyret; }
157                 unch(ch);
158                 ch = '<';
159                 goto any;
160         case '>':
161                 if (state != IFRgoto any;
162                 if ((ch = inch()) == '=') {
163                         yytext[yyp++] = chch = GEgoto yyret;
164                 }
165                 if (ch == '>') { yytext[yyp++] = chch = RSgoto yyret; }
166                 unch(ch);
167                 ch = '>';
168                 goto any;
169
170
171         case '0'case '1'case '2'case '3'case '4'case '5'
172         case '6'case '7'case '8'case '9':
173                 /* readin a "pp-number" */
174                 mixed = haspmd = 0;
175 ppnum:          for (;;) {
176                         ch = input();
177                         if (ch == 'e' || ch == 'E' || ch == 'p' || ch == 'P') {
178                                 yytext[yyp++] = ch;
179                                 mixed = 1;
180                                 ch = input();
181                                 if (ch == '-' || ch == '+') {
182                                         yytext[yyp++] = ch;
183                                         haspmd = 1;
184                                 } else
185                                         unput(ch);
186                                 continue;
187                         }
188                         if (isdigit(ch) || isalpha(ch) ||
189                             ch == '_' || ch == '.') {
190                                 yytext[yyp++] = ch;
191                                 if (ch == '.')
192                                         haspmd = 1;
193                                 if (!isdigit(ch))
194                                         mixed = 1;
195                                 continue;
196                         } 
197                         break;
198                 }
ragge
1.14
199                 unput(ch);
ragge
1.13
200                 yytext[yyp] = 0;
201
ragge
1.15
202                 if (mixed == 1 && slow && (state == 0 || state == DEF))
203                         return IDENT;
204
ragge
1.13
205                 if (mixed == 0) {
206                         if (slow && !YYSTATE)
207                                 return IDENT;
208                         scale = yytext[0] == '0' ? 8 : 10;
209                         goto num;
210                 } else if (yytext[0] == '0' &&
211                     (yytext[1] == 'x' || yytext[1] == 'X')) {
212                         scale = 16;
213 num:                    if (YYSTATE == IFR)
214                                 cvtdig(scale);
215                         PRTOUT(NUMBER);
gmcgarry
1.17
216                 } else if (yytext[0] == '0' && isdigit((int)yytext[1])) {
ragge
1.13
217                         scale = 8goto num;
218                 } else if (haspmd) {
219                         PRTOUT(FPOINT);
220                 } else {
221                         scale = 10goto num;
222                 }
223                 goto zagain;
224
225
226         case '\'':
227 chlit:          if (tflag && !(YYSTATE || slow))
228                         goto any;
229                 for (;;) {
230                         if ((ch = input()) == '\\') {
231                                 yytext[yyp++] = ch;
232                                 yytext[yyp++] = input();
233                                 continue;
234                         } else if (ch == '\n') {
235                                 /* not a constant */
236                                 while (yyp > 1)
237                                         unput(yytext[--yyp]);
238                                 ch = '\'';
239                                 goto any;
240                         } else
241                                 yytext[yyp++] = ch;
242                         if (ch == '\'')
243                                 break;
244                 }
245                 yytext[yyp] = 0;
246
247                 if (YYSTATE || slow) {
248                         yylval.node.op = NUMBER;
249                         yylval.node.nd_val = charcon((usch *)yytext);
250                         return (NUMBER);
251                 }
252                 if (!flslvl)
253                         putstr((usch *)yytext);
254                 goto zagain;
255
256         case ' ':
257         case '\t':
258                 if (state == IFR)
259                         goto zagain;
260
261                 while ((ch = input()) == ' ' || ch == '\t')
262                         yytext[yyp++] = ch;
263                 if (owasnl == 0) {
264 b1:                     unput(ch);
265                         yytext[yyp] = 0;
266                         PRTOUT(WSPACE);
267                 } else if (ch != '#') {
268                         goto b1;
269                 } else {
270                         extern int inmac;
271
ragge
1.14
272 contr:                  while ((ch = input()) == ' ' || ch == '\t')
ragge
1.13
273                                 ;
274                         unch(ch);
275                         if (inmac)
276                                 error("preprocessor directive found "
277                                     "while expanding macro");
278                         contr = 1;
279                         BEGIN CONTR;
280
281                 }
282                 goto zagain;
283
284         case '/':
285                 if ((ch = input()) == '/') {
286                         do {
287                                 yytext[yyp++] = ch;
288                                 ch = input();
289                         } while (ch && ch != '\n');
290                         yytext[yyp] = 0;
291                         unch(ch);
292                         if (Cflag && !flslvl && !slow)
293                                 putstr((usch *)yytext);
294                         else if (!flslvl)
295                                 putch(' ');
296                         goto zagain;
297                 } else if (ch == '*') {
298                         int cwrn;
299                         int prtcm = Cflag && !flslvl && !slow;
300                         extern int readmac;
301
302                         if (Cflag && !flslvl && readmac)
303                                 return CMNT;
304
305                         if (prtcm)
306                                 putstr((usch *)yytext);
307                         wrn = 0;
308                 more:   while ((c = input()) && c != '*') {
309                                 if (c == '\n')
310                                         putch(c), ifiles->lineno++;
311                                 else if (c == 1/* WARN */
312                                         wrn = 1;
313                                 else if (prtcm)
314                                         putch(c);
315                         }
316                         if (c == 0)
317                                 return 0;
318                         if (prtcm)
319                                 putch(c);
320                         if ((c = input()) && c != '/') {
321                                 unput(c);
322                                 goto more;
323                         }
324                         if (prtcm)
325                                 putch(c);
326                         if (c == 0)
327                                 return 0;
328                         if (!tflag && !Cflag && !flslvl)
329                                 unput(' ');
330                         if (wrn)
331                                 unput(1);
332                         goto zagain;
333                 }
334                 unch(ch);
335                 ch = '/';
336                 goto any;
337
338         case '#':
ragge
1.14
339                 if (state != DEF) {
340                         if (owasnl)
341                                 goto contr;
ragge
1.13
342                         goto any;
ragge
1.14
343                 }
ragge
1.13
344                 if ((ch = input()) == '#') {
345                         yytext[yyp++] = ch;
346                         ch = CONCAT;
347                 } else {
348                         unput(ch);
349                         ch = MKSTR;
350                 }
351                 goto yyret;
352                 
353         case '.':
354                 if (state != DEF) {
355                         ch = input();
356                         if (isdigit(ch)) {
357                                 yytext[yyp++] = ch;
358                                 mixed = haspmd = 1;
359                                 goto ppnum;
360                         } else {
361                                 unput(ch);
362                                 ch = '.';
363                         }
364                         goto any;
365                 }
366                 if ((ch = input()) != '.') {
367                         unput(ch);
368                         ch = '.';
369                         goto any;
370                 }
371                 if ((ch = input()) != '.') {
372                         unput(ch);
373                         unput('.');
374                         ch = '.';
375                         goto any;
376                 }
377                 yytext[yyp++] = ch;
378                 yytext[yyp++] = ch;
379                 ch = ELLIPS;
380                 goto yyret;
381
382
383         case '\"':
384         strng:
385                 for (;;) {
386                         if ((ch = input()) == '\\') {
387                                 yytext[yyp++] = ch;
388                                 yytext[yyp++] = input();
389                                 continue;
390                         } else 
391                                 yytext[yyp++] = ch;
392                         if (ch == '\"')
393                                 break;
394                 }
395                 yytext[yyp] = 0;
396                 { PRTOUT(STRING); }
397                 break;
398
399         case 'L':
400                 if ((ch = input()) == '\"') {
401                         yytext[yyp++] = ch;
402                         goto strng;
403                 } else if (ch == '\'') {
404                         yytext[yyp++] = ch;
405                         goto chlit;
406                 }
407                 unput(ch);
408                 /* FALLTHROUGH */
409
410         /* Yetch, all identifiers */
411         case 'a'case 'b'case 'c'case 'd'case 'e'case 'f'
412         case 'g'case 'h'case 'i'case 'j'case 'k'case 'l'
413         case 'm'case 'n'case 'o'case 'p'case 'q'case 'r'
414         case 's'case 't'case 'u'case 'v'case 'w'case 'x'
415         case 'y'case 'z':
416         case 'A'case 'B'case 'C'case 'D'case 'E'case 'F'
417         case 'G'case 'H'case 'I'case 'J'case 'K':
418         case 'M'case 'N'case 'O'case 'P'case 'Q'case 'R'
419         case 'S'case 'T'case 'U'case 'V'case 'W'case 'X'
420         case 'Y'case 'Z':
421         case '_': { /* {L}({L}|{D})* */
422                 struct symtab *nl;
423
424                 /* Special hacks */
425                 for (;;) { /* get chars */
426                         ch = input();
ragge
1.14
427                         if (isalpha(ch) || isdigit(ch) || ch == '_') {
ragge
1.13
428                                 yytext[yyp++] = ch;
ragge
1.14
429                         } else {
430                                 unput(ch);
ragge
1.13
431                                 break;
ragge
1.14
432                         }
ragge
1.13
433                 }
434                 yytext[yyp] = 0/* need already string */
435
436                 switch (state) {
437                 case DEF:
438                         if (strcmp(yytext"__VA_ARGS__") == 0)
439                                 return VA_ARGS;
440                         break;
441                 case CONTR:
442 #define CC(s)   if (strcmp(yytext, s) == 0)
443                         CC("ifndef") {
444                                 contr = 0ifndefstmt();
ragge
1.18
445                                 BEGIN 0;
ragge
1.13
446                                 goto zagain;
447                         } else CC("ifdef") {
448                                 contr = 0ifdefstmt();
ragge
1.18
449                                 BEGIN 0;
ragge
1.13
450                                 goto zagain;
451                         } else CC("if") {
452                                 contr = 0storepb(); BEGIN IFR;
453                                 ifstmt(); BEGIN 0;
454                                 goto zagain;
455                         } else CC("include") {
456                                 contr = 0BEGIN 0include(); prtline();
457                                 goto zagain;
458                         } else CC("else") {
459                                 contr = 0elsestmt();
460                                 goto zagain;
461                         } else CC("endif") {
462                                 contr = 0endifstmt();
463                                 goto zagain;
464                         } else CC("error") {
465                                 contr = 0if (slowreturn IDENT;
466                                 cpperror(); BEGIN 0;
467                                 goto zagain;
468                         } else CC("define") {
469                                 contr = 0BEGIN DEFdefine(); BEGIN 0;
470                                 goto zagain;
471                         } else CC("undef") {
472                                 contr = 0if (slowreturn IDENTundefstmt();
473                                 goto zagain;
474                         } else CC("line") {
475                                 contr = 0storepb(); BEGIN 0line();
476                                 goto zagain;
477                         } else CC("pragma") {
478                                 contr = 0pragmastmt(); BEGIN 0;
479                                 goto zagain;
480                         } else CC("elif") {
481                                 contr = 0storepb(); BEGIN IFR;
482                                 elifstmt(); BEGIN 0;
483                                 goto zagain;
484                         }
485                         break;
486                 case  IFR:
487                         CC("defined") {
488                                 int pc;
489                                 gotdef = 1;
490                                 if ((p = c = yylex()) == '(')
491                                         c = yylex();
492                                 if (c != IDENT || (p != IDENT && p != '('))
493                                         error("syntax error");
494                                 if (p == '(' && yylex() != ')')
495                                         error("syntax error");
496                                 return NUMBER;
497                         } else {
498                                 yylval.node.op = NUMBER;
499                                 if (gotdef) {
500                                         yylval.node.nd_val
501                                             = lookup((usch *)yytextFIND) != 0;
502                                         gotdef = 0;
503                                         return IDENT;
504                                 }
505                                 yylval.node.nd_val = 0;
506                                 return NUMBER;
507                         }
508                 }
509
510                 /* end special hacks */
511
512                 if (slow)
513                         return IDENT;
514                 if (YYSTATE == CONTR) {
515                         if (flslvl == 0) {
516                                 /*error("undefined control");*/
517                                 while (input() != '\n')
518                                         ;
519                                 unput('\n');
520                                 BEGIN 0;
521                                 goto xx;
522                         } else {
523                                 BEGIN 0/* do nothing */
524                         }
525                 }
526                 if (flslvl) {
527                         ; /* do nothing */
528                 } else if (isdigit((int)yytext[0]) == 0 &&
529                     (nl = lookup((usch *)yytextFIND)) != 0) {
530                         usch *op = stringbuf;
531                         putstr(gotident(nl));
532                         stringbuf = op;
533                 } else
534                         putstr((usch *)yytext);
535                 xx:
ragge
1.14
536                 goto zagain;
ragge
1.13
537         }
538
539         default:
540         any:
541                 if (state == IFR)
542                         goto yyret;
543                 yytext[yyp] = 0;
544                 if (contr) {
545                         while (input() != '\n')
546                                 ;
547                         unput('\n');
548                         BEGIN 0;
549                         contr = 0;
550                         goto yy;
551                 }
552                 if (YYSTATE || slow)
553                         return yytext[0];
554                 if (yytext[0] == 6) { /* PRAGS */
555                         usch *obp = stringbuf;
556                         extern usch *prtprag(usch *);
557                         *stringbuf++ = yytext[0];
558                         do {
559                                 *stringbuf = input();
560                         } while (*stringbuf++ != 14);
561                         prtprag(obp);
562                         stringbuf = obp;
563                 } else {
564                         PRTOUT(yytext[0]);
565                 }
566                 yy:
567                 yyp = 0;
568                 break;
ragge
1.3
569
ragge
1.13
570         } /* endcase */
ragge
1.14
571         goto zagain;
ragge
1.6
572
ragge
1.13
573 yyret:
574         yytext[yyp] = 0;
575         return ch;
ragge
1.3
576 }
577
ragge
1.13
578 usch *yypyybuf[CPPBUF];
579
580 int yylex(void);
581 int yywrap(void);
ragge
1.3
582
ragge
1.2
583 static int
ragge
1.13
584 inpch(void)
ragge
1.2
585 {
ragge
1.6
586         int len;
ragge
1.3
587
ragge
1.11
588         if (ifiles->curptr < ifiles->maxread)
ragge
1.2
589                 return *ifiles->curptr++;
ragge
1.11
590
ragge
1.6
591         if ((len = read(ifiles->infilifiles->bufferCPPBUF)) < 0)
ragge
1.13
592                 error("read error on file %s"ifiles->orgfn);
ragge
1.6
593         if (len == 0)
ragge
1.3
594                 return -1;
595         ifiles->curptr = ifiles->buffer;
ragge
1.6
596         ifiles->maxread = ifiles->buffer + len;
ragge
1.13
597         return inpch();
ragge
1.2
598 }
ragge
1.1
599
600 static int
ragge
1.13
601 inch(void)
ragge
1.1
602 {
603         int c;
604
ragge
1.13
605 again:  switch (c = inpch()) {
ragge
1.1
606         case '\\'/* continued lines */
ragge
1.13
607 msdos:          if ((c = inpch()) == '\n') {
ragge
1.1
608                         ifiles->lineno++;
ragge
1.13
609                         putch('\n');
ragge
1.1
610                         goto again;
ragge
1.13
611                 } else if (c == '\r')
612                         goto msdos;
613                 unch(c);
ragge
1.1
614                 return '\\';
615         case '?'/* trigraphs */
ragge
1.13
616                 if ((c = inpch()) != '?') {
617                         unch(c);
ragge
1.1
618                         return '?';
619                 }
ragge
1.13
620                 switch (c = inpch()) {
ragge
1.1
621                 case '='c = '#'break;
622                 case '('c = '['break;
623                 case ')'c = ']'break;
624                 case '<'c = '{'break;
625                 case '>'c = '}'break;
626                 case '/'c = '\\'break;
627                 case '\''c = '^'break;
628                 case '!'c = '|'break;
629                 case '-'c = '~'break;
630                 default:
ragge
1.13
631                         unch(c);
632                         unch('?');
ragge
1.1
633                         return '?';
634                 }
ragge
1.13
635                 unch(c);
ragge
1.1
636                 goto again;
637         default:
638                 return c;
639         }
640 }
641
ragge
1.13
642 /*
643  * Let the command-line args be faked defines at beginning of file.
644  */
645 static void
646 prinit(struct initar *itstruct includ *ic)
ragge
1.1
647 {
ragge
1.13
648         char *a, *pre, *post;
ragge
1.1
649
ragge
1.13
650         if (it->next)
651                 prinit(it->nextic);
652         pre = post = NULL/* XXX gcc */
653         switch (it->type) {
654         case 'D':
655                 pre = "#define ";
656                 if ((a = strchr(it->str'=')) != NULL) {
657                         *a = ' ';
658                         post = "\n";
ragge
1.1
659                 } else
ragge
1.13
660                         post = " 1\n";
ragge
1.1
661                 break;
ragge
1.13
662         case 'U':
663                 pre = "#undef ";
664                 post = "\n";
ragge
1.1
665                 break;
ragge
1.13
666         case 'i':
667                 pre = "#include \"";
668                 post = "\"\n";
ragge
1.1
669                 break;
670         default:
ragge
1.13
671                 error("prinit");
ragge
1.1
672         }
ragge
1.13
673         strlcat((char *)ic->bufferpreCPPBUF+1);
674         strlcat((char *)ic->bufferit->strCPPBUF+1);
675         if (strlcat((char *)ic->bufferpostCPPBUF+1) >= CPPBUF+1)
676                 error("line exceeds buffer size");
677
678         ic->lineno--;
679         while (*ic->maxread)
680                 ic->maxread++;
ragge
1.1
681 }
682
ragge
1.4
683 /*
ragge
1.6
684  * A new file included.
685  * If ifiles == NULL, this is the first file and already opened (stdin).
ragge
1.13
686  * Return 0 on success, -1 if file to be included is not found.
ragge
1.4
687  */
688 int
ragge
1.13
689 pushfile(usch *file)
ragge
1.4
690 {
ragge
1.13
691         extern struct initar *initar;
ragge
1.6
692         struct includ ibuf;
693         struct includ *ic;
ragge
1.13
694         int cotrulvl;
ragge
1.6
695
696         ic = &ibuf;
ragge
1.13
697         ic->next = ifiles;
ragge
1.4
698
ragge
1.11
699         slow = 0;
ragge
1.6
700         if (file != NULL) {
ragge
1.13
701                 if ((ic->infil = open((char *)fileO_RDONLY)) < 0)
ragge
1.4
702                         return -1;
ragge
1.13
703                 ic->orgfn = ic->fname = file;
704                 if (++inclevel > MAX_INCLEVEL)
705                         error("Limit for nested includes exceeded");
ragge
1.6
706         } else {
707                 ic->infil = 0;
ragge
1.13
708                 ic->orgfn = ic->fname = (usch *)"<stdin>";
ragge
1.6
709         }
710         ic->buffer = ic->bbuf+NAMEMAX;
ragge
1.4
711         ic->curptr = ic->buffer;
712         ifiles = ic;
ragge
1.13
713         ic->lineno = 1;
ragge
1.6
714         ic->maxread = ic->curptr;
ragge
1.13
715         prtline();
716         if (initar) {
717                 *ic->maxread = 0;
718                 prinit(initaric);
719                 if (dMflag)
720                         write(ofdic->bufferstrlen((char *)ic->buffer));
721                 initar = NULL;
722         }
ragge
1.4
723
ragge
1.13
724         otrulvl = trulvl;
ragge
1.4
725
ragge
1.13
726         if ((c = yylex()) != 0)
727                 error("yylex returned %d"c);
728
ragge
1.15
729 wasnl = owasnl;
ragge
1.13
730         if (otrulvl != trulvl || flslvl)
ragge
1.6
731                 error("unterminated conditional");
ragge
1.4
732
ragge
1.13
733         ifiles = ic->next;
ragge
1.6
734         close(ic->infil);
ragge
1.13
735         inclevel--;
ragge
1.6
736         return 0;
ragge
1.4
737 }
ragge
1.1
738
739 /*
740  * Print current position to output file.
741  */
742 void
743 prtline()
744 {
ragge
1.13
745         usch *s, *os = stringbuf;
746
747         if (Mflag) {
748                 if (dMflag)
749                         return/* no output */
750                 if (ifiles->lineno == 1) {
751                         s = sheap("%s: %s\n"Mfileifiles->fname);
752                         write(ofdsstrlen((char *)s));
753                 }
754         } else if (!Pflag)
755                 putstr(sheap("# %d \"%s\"\n"ifiles->linenoifiles->fname));
756         stringbuf = os;
ragge
1.1
757 }
758
759 void
760 cunput(int c)
761 {
ragge
1.13
762 #ifdef CPP_DEBUG
763         extern int dflag;
764         if (dflag)printf(": '%c'(%d)"c > 31 ? c : ' 'c);
765 #endif
ragge
1.1
766         unput(c);
767 }
768
ragge
1.13
769 int yywrap(void) { return 1; }
770
771 static int
772 dig2num(int c)
773 {
774         if (c >= 'a')
775                 c = c - 'a' + 10;
776         else if (c >= 'A')
777                 c = c - 'A' + 10;
778         else
779                 c = c - '0';
780         return c;
781 }
782
783 /*
784  * Convert string numbers to unsigned long long and check overflow.
785  */
786 static void
787 cvtdig(int rad)
788 {
789         unsigned long long rv = 0;
790         unsigned long long rv2 = 0;
791         char *y = yytext;
792         int c;
793
794         c = *y++;
795         if (rad == 16)
796                 y++;
797         while (isxdigit(c)) {
798                 rv = rv * rad + dig2num(c);
799                 /* check overflow */
800                 if (rv / rad < rv2)
801                         error("Constant \"%s\" is out of range"yytext);
802                 rv2 = rv;
803                 c = *y++;
804         }
805         y--;
806         while (*y == 'l' || *y == 'L')
807                 y++;
808         yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER;
809         yylval.node.nd_uval = rv;
810         if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0)
811                 yylval.node.op = UNUMBER;
812         if (yylval.node.op == NUMBER && yylval.node.nd_val < 0)
813                 /* too large for signed */
814                 error("Constant \"%s\" is out of range"yytext);
815 }
816
817 static int
818 charcon(usch *p)
819 {
820         int valc;
821
822         p++; /* skip first ' */
823         val = 0;
824         if (*p++ == '\\') {
825                 switch (*p++) {
826                 case 'a'val = '\a'break;
827                 case 'b'val = '\b'break;
828                 case 'f'val = '\f'break;
829                 case 'n'val = '\n'break;
830                 case 'r'val = '\r'break;
831                 case 't'val = '\t'break;
832                 case 'v'val = '\v'break;
833                 case '\"'val = '\"'break;
834                 case '\''val = '\''break;
835                 case '\\'val = '\\'break;
836                 case 'x':
837                         while (isxdigit(c = *p)) {
838                                 val = val * 16 + dig2num(c);
839                                 p++;
840                         }
841                         break;
842                 case '0'case '1'case '2'case '3'case '4':
843                 case '5'case '6'case '7':
844                         p--;
845                         while (isdigit(c = *p)) {
846                                 val = val * 8 + (c - '0');
847                                 p++;
848                         }
849                         break;
850                 defaultval = p[-1];
851                 }
852
853         } else
854                 val = p[-1];
855         return val;
856 }
857
858 static void
859 chknl(int ignore)
860 {
861         int t;
862
863         slow = 1;
864         while ((t = yylex()) == WSPACE)
865                 ;
866         if (t != '\n') {
867                 if (ignore) {
868                         warning("newline expected, got \"%s\""yytext);
869                         /* ignore rest of line */
870                         while ((t = yylex()) && t != '\n')
871                                 ;
872                 }
873                 else
874                         error("newline expected, got \"%s\""yytext);
875         }
876         slow = 0;
877 }
878
879 static void
880 elsestmt(void)
881 {
882         if (flslvl) {
883                 if (elflvl > trulvl)
884                         ;
885                 else if (--flslvl!=0) {
886                         flslvl++;
887                 } else {
888                         trulvl++;
889                         prtline();
890                 }
891         } else if (trulvl) {
892                 flslvl++;
893                 trulvl--;
894         } else
895                 error("If-less else");
896         if (elslvl==trulvl+flslvl)
897                 error("Too many else");
898         elslvl=trulvl+flslvl;
899         chknl(1);
900 }
901
902 static void
903 ifdefstmt(void)          
904
905         int t;
906
907         if (flslvl) {
908                 /* just ignore the rest of the line */
909                 while (input() != '\n')
910                         ;
911                 unput('\n');
912                 flslvl++;
913                 return;
914         }
915         slow = 1;
916         do
917                 t = yylex();
918         while (t == WSPACE);
919         if (t != IDENT)
920                 error("bad ifdef");
921         slow = 0;
922         if (flslvl == 0 && lookup((usch *)yytextFIND) != 0)
923                 trulvl++;
924         else
925                 flslvl++;
926         chknl(0);
927 }
928
929 static void
930 ifndefstmt(void)          
931
932         int t;
933
934         slow = 1;
935         do
936                 t = yylex();
937         while (t == WSPACE);
938         if (t != IDENT)
939                 error("bad ifndef");
940         slow = 0;
941         if (flslvl == 0 && lookup((usch *)yytextFIND) == 0)
942                 trulvl++;
943         else
944                 flslvl++;
945         chknl(0);
946 }
947
948 static void
949 endifstmt(void)          
950 {
951         if (flslvl) {
952                 flslvl--;
953                 if (flslvl == 0)
954                         prtline();
955         } else if (trulvl)
956                 trulvl--;
957         else
958                 error("If-less endif");
959         if (flslvl == 0)
960                 elflvl = 0;
961         elslvl = 0;
962         chknl(1);
963 }
964
965 /*
966  * Note! Ugly!
967  * Walk over the string s and search for defined, and replace it with 
968  * spaces and a 1 or 0. 
969  */
970 static void
971 fixdefined(usch *s)
972 {
973         usch *bcoc;
974
975         for (; *ss++) {
976                 if (*s != 'd')
977                         continue;
978                 if (memcmp(s"defined"7))
979                         continue;
980                 /* Ok, got defined, can scratch it now */
981                 memset(s' '7);
982                 s += 7;
983 #define WSARG(x) (x == ' ' || x == '\t')
984                 if (*s != '(' && !WSARG(*s))
985                         continue;
986                 while (WSARG(*s))
987                         s++;
988                 if (*s == '(')
989                         s++;
990                 while (WSARG(*s))
991                         s++;
992 #define IDARG(x) ((x>= 'A' && x <= 'Z') || (x >= 'a' && x <= 'z') || (x == '_'))
993 #define NUMARG(x) (x >= '0' && x <= '9')
994                 if (!IDARG(*s))
995                         error("bad defined arg");
996                 bc = s;
997                 while (IDARG(*s) || NUMARG(*s))
998                         s++;
999                 oc = *s;
1000                 *s = 0;
1001                 *bc = (lookup(bcFIND) != 0) + '0';
1002                 memset(bc+1' 's-bc-1);
1003                 *s = oc;
1004         }
1005 }
1006
1007 /*
1008  * get the full line of identifiers after an #if, pushback a WARN and
1009  * the line and prepare for expmac() to expand.
1010  * This is done before switching state.  When expmac is finished,
1011  * pushback the expanded line, change state and call yyparse.
1012  */
1013 static void
1014 storepb(void)
1015 {
1016         usch *opb = stringbuf;
1017         int c;
1018
1019         while ((c = input()) != '\n') {
1020                 if (c == '/') {
1021                          if ((c = input()) == '*') {
1022                                 /* ignore comments here whatsoever */
1023                                 usch *g = stringbuf;
1024                                 getcmnt();
1025                                 stringbuf = g;
1026                                 continue;
1027                         } else if (c == '/') {
1028                                 while ((c = input()) && c != '\n')
1029                                         ;
1030                                 break;
1031                         }
1032                         unput(c);
1033                         c = '/';
1034                 }
1035                 savch(c);
1036         }
1037         cunput('\n');
1038         savch(0);
1039         fixdefined(opb); /* XXX can fail if #line? */
1040         cunput(1); /* WARN XXX */
1041         unpstr(opb);
1042         stringbuf = opb;
1043         slow = 1;
1044         expmac(NULL);
1045         slow = 0;
1046         /* line now expanded */
1047         while (stringbuf > opb)
1048                 cunput(*--stringbuf);
1049 }
1050
1051 static void
1052 ifstmt(void)
1053 {
1054         if (flslvl == 0) {
1055                 slow = 1;
1056                 if (yyparse())
1057                         ++trulvl;
1058                 else
1059                         ++flslvl;
1060                 slow = 0;
1061         } else
1062                 ++flslvl;
1063 }
1064
1065 static void
1066 elifstmt(void)
1067 {
1068         if (flslvl == 0)
1069                 elflvl = trulvl;
1070         if (flslvl) {
1071                 if (elflvl > trulvl)
1072                         ;
1073                 else if (--flslvl!=0)
1074   &nbs