Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20090309202039

Diff

Diff from 1.14 to:

Annotations

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

Annotated File View

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