Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20090312201943

Diff

Diff from 1.15 to:

Annotations

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

Annotated File View

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