Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:gmcgarry:20090414232246

Diff

Diff from 1.16 to:

Annotations

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

Annotated File View

gmcgarry
1.16
1 /*      $Id: token.c,v 1.16 2009/04/14 23:22:46 gmcgarry 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);
216                 } else if (yytext[0] == '0' && isdigit(yytext[1])) {
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();
445                                 goto zagain;
446                         } else CC("ifdef") {
447                                 contr = 0ifdefstmt();
448                                 goto zagain;
449                         } else CC("if") {
450                                 contr = 0storepb(); BEGIN IFR;
451                                 ifstmt(); BEGIN 0;
452                                 goto zagain;
453                         } else CC("include") {
454                                 contr = 0BEGIN 0include(); prtline();
455                                 goto zagain;
456                         } else CC("else") {
457                                 contr = 0elsestmt();
458                                 goto zagain;
459                         } else CC("endif") {
460                                 contr = 0endifstmt();
461                                 goto zagain;
462                         } else CC("error") {
463                                 contr = 0if (slowreturn IDENT;
464                                 cpperror(); BEGIN 0;
465                                 goto zagain;
466                         } else CC("define") {
467                                 contr = 0BEGIN DEFdefine(); BEGIN 0;
468                                 goto zagain;
469                         } else CC("undef") {
470                                 contr = 0if (slowreturn IDENTundefstmt();
471                                 goto zagain;
472                         } else CC("line") {
473                                 contr = 0storepb(); BEGIN 0line();
474                                 goto zagain;
475                         } else CC("pragma") {
476                                 contr = 0pragmastmt(); BEGIN 0;
477                                 goto zagain;
478                         } else CC("elif") {
479                                 contr = 0storepb(); BEGIN IFR;
480                                 elifstmt(); BEGIN 0;
481                                 goto zagain;
482                         }
483                         break;
484                 case  IFR:
485                         CC("defined") {
486                                 int pc;
487                                 gotdef = 1;
488                                 if ((p = c = yylex()) == '(')
489                                         c = yylex();
490                                 if (c != IDENT || (p != IDENT && p != '('))
491                                         error("syntax error");
492                                 if (p == '(' && yylex() != ')')
493                                         error("syntax error");
494                                 return NUMBER;
495                         } else {
496                                 yylval.node.op = NUMBER;
497                                 if (gotdef) {
498                                         yylval.node.nd_val
499                                             = lookup((usch *)yytextFIND) != 0;
500                                         gotdef = 0;
501                                         return IDENT;
502                                 }
503                                 yylval.node.nd_val = 0;
504                                 return NUMBER;
505                         }
506                 }
507
508                 /* end special hacks */
509
510                 if (slow)
511                         return IDENT;
512                 if (YYSTATE == CONTR) {
513                         if (flslvl == 0) {
514                                 /*error("undefined control");*/
515                                 while (input() != '\n')
516                                         ;
517                                 unput('\n');
518                                 BEGIN 0;
519                                 goto xx;
520                         } else {
521                                 BEGIN 0/* do nothing */
522                         }
523                 }
524                 if (flslvl) {
525                         ; /* do nothing */
526                 } else if (isdigit((int)yytext[0]) == 0 &&
527                     (nl = lookup((usch *)yytextFIND)) != 0) {
528                         usch *op = stringbuf;
529                         putstr(gotident(nl));
530                         stringbuf = op;
531                 } else
532                         putstr((usch *)yytext);
533                 xx:
ragge
1.14
534                 goto zagain;
ragge
1.13
535         }
536
537         default:
538         any:
539                 if (state == IFR)
540                         goto yyret;
541                 yytext[yyp] = 0;
542                 if (contr) {
543                         while (input() != '\n')
544                                 ;
545                         unput('\n');
546                         BEGIN 0;
547                         contr = 0;
548                         goto yy;
549                 }
550                 if (YYSTATE || slow)
551                         return yytext[0];
552                 if (yytext[0] == 6) { /* PRAGS */
553                         usch *obp = stringbuf;
554                         extern usch *prtprag(usch *);
555                         *stringbuf++ = yytext[0];
556                         do {
557                                 *stringbuf = input();
558                         } while (*stringbuf++ != 14);
559                         prtprag(obp);
560                         stringbuf = obp;
561                 } else {
562                         PRTOUT(yytext[0]);
563                 }
564                 yy:
565                 yyp = 0;
566                 break;
ragge
1.3
567
ragge
1.13
568         } /* endcase */
ragge
1.14
569         goto zagain;
ragge
1.6
570
ragge
1.13
571 yyret:
572         yytext[yyp] = 0;
573         return ch;
ragge
1.3
574 }
575
ragge
1.13
576 usch *yypyybuf[CPPBUF];
577
578 int yylex(void);
579 int yywrap(void);
ragge
1.3
580
ragge
1.2
581 static int
ragge
1.13
582 inpch(void)
ragge
1.2
583 {
ragge
1.6
584         int len;
ragge
1.3
585
ragge
1.11
586         if (ifiles->curptr < ifiles->maxread)
ragge
1.2
587                 return *ifiles->curptr++;
ragge
1.11
588
ragge
1.6
589         if ((len = read(ifiles->infilifiles->bufferCPPBUF)) < 0)
ragge
1.13
590                 error("read error on file %s"ifiles->orgfn);
ragge
1.6
591         if (len == 0)
ragge
1.3
592                 return -1;
593         ifiles->curptr = ifiles->buffer;
ragge
1.6
594         ifiles->maxread = ifiles->buffer + len;
ragge
1.13
595         return inpch();
ragge
1.2
596 }
ragge
1.1
597
598 static int
ragge
1.13
599 inch(void)
ragge
1.1
600 {
601         int c;
602
ragge
1.13
603 again:  switch (c = inpch()) {
ragge
1.1
604         case '\\'/* continued lines */
ragge
1.13
605 msdos:          if ((c = inpch()) == '\n') {
ragge
1.1
606                         ifiles->lineno++;
ragge
1.13
607                         putch('\n');
ragge
1.1
608                         goto again;
ragge
1.13
609                 } else if (c == '\r')
610                         goto msdos;
611                 unch(c);
ragge
1.1
612                 return '\\';
613         case '?'/* trigraphs */
ragge
1.13
614                 if ((c = inpch()) != '?') {
615                         unch(c);
ragge
1.1
616                         return '?';
617                 }
ragge
1.13
618                 switch (c = inpch()) {
ragge
1.1
619                 case '='c = '#'break;
620                 case '('c = '['break;
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                 default:
ragge
1.13
629                         unch(c);
630                         unch('?');
ragge
1.1
631                         return '?';
632                 }
ragge
1.13
633                 unch(c);
ragge
1.1
634                 goto again;
635         default:
636                 return c;
637         }
638 }
639
ragge
1.13
640 /*
641  * Let the command-line args be faked defines at beginning of file.
642  */
643 static void
644 prinit(struct initar *itstruct includ *ic)
ragge
1.1
645 {
ragge
1.13
646         char *a, *pre, *post;
ragge
1.1
647
ragge
1.13
648         if (it->next)
649                 prinit(it->nextic);
650         pre = post = NULL/* XXX gcc */
651         switch (it->type) {
652         case 'D':
653                 pre = "#define ";
654                 if ((a = strchr(it->str'=')) != NULL) {
655                         *a = ' ';
656                         post = "\n";
ragge
1.1
657                 } else
ragge
1.13
658                         post = " 1\n";
ragge
1.1
659                 break;
ragge
1.13
660         case 'U':
661                 pre = "#undef ";
662                 post = "\n";
ragge
1.1
663                 break;
ragge
1.13
664         case 'i':
665                 pre = "#include \"";
666                 post = "\"\n";
ragge
1.1
667                 break;
668         default:
ragge
1.13
669                 error("prinit");
ragge
1.1
670         }
ragge
1.13
671         strlcat((char *)ic->bufferpreCPPBUF+1);
672         strlcat((char *)ic->bufferit->strCPPBUF+1);
673         if (strlcat((char *)ic->bufferpostCPPBUF+1) >= CPPBUF+1)
674                 error("line exceeds buffer size");
675
676         ic->lineno--;
677         while (*ic->maxread)
678                 ic->maxread++;
ragge
1.1
679 }
680
ragge
1.4
681 /*
ragge
1.6
682  * A new file included.
683  * If ifiles == NULL, this is the first file and already opened (stdin).
ragge
1.13
684  * Return 0 on success, -1 if file to be included is not found.
ragge
1.4
685  */
686 int
ragge
1.13
687 pushfile(usch *file)
ragge
1.4
688 {
ragge
1.13
689         extern struct initar *initar;
ragge
1.6
690         struct includ ibuf;
691         struct includ *ic;
ragge
1.13
692         int cotrulvl;
ragge
1.6
693
694         ic = &ibuf;
ragge
1.13
695         ic->next = ifiles;
ragge
1.4
696
ragge
1.11
697         slow = 0;
ragge
1.6
698         if (file != NULL) {
ragge
1.13
699                 if ((ic->infil = open((char *)fileO_RDONLY)) < 0)
ragge
1.4
700                         return -1;
ragge
1.13
701                 ic->orgfn = ic->fname = file;
702                 if (++inclevel > MAX_INCLEVEL)
703                         error("Limit for nested includes exceeded");
ragge
1.6
704         } else {
705                 ic->infil = 0;
ragge
1.13
706                 ic->orgfn = ic->fname = (usch *)"<stdin>";
ragge
1.6
707         }
708         ic->buffer = ic->bbuf+NAMEMAX;
ragge
1.4
709         ic->curptr = ic->buffer;
710         ifiles = ic;
ragge
1.13
711         ic->lineno = 1;
ragge
1.6
712         ic->maxread = ic->curptr;
ragge
1.13
713         prtline();
714         if (initar) {
715                 *ic->maxread = 0;
716                 prinit(initaric);
717                 if (dMflag)
718                         write(ofdic->bufferstrlen((char *)ic->buffer));
719                 initar = NULL;
720         }
ragge
1.4
721
ragge
1.13
722         otrulvl = trulvl;
ragge
1.4
723
ragge
1.13
724         if ((c = yylex()) != 0)
725                 error("yylex returned %d"c);
726
ragge
1.15
727 wasnl = owasnl;
ragge
1.13
728         if (otrulvl != trulvl || flslvl)
ragge
1.6
729                 error("unterminated conditional");
ragge
1.4
730
ragge
1.13
731         ifiles = ic->next;
ragge
1.6
732         close(ic->infil);
ragge
1.13
733         inclevel--;
ragge
1.6
734         return 0;
ragge
1.4
735 }
ragge
1.1
736
737 /*
738  * Print current position to output file.
739  */
740 void
741 prtline()
742 {
ragge
1.13
743         usch *s, *os = stringbuf;
744
745         if (Mflag) {
746                 if (dMflag)
747                         return/* no output */
748                 if (ifiles->lineno == 1) {
749                         s = sheap("%s: %s\n"Mfileifiles->fname);
750                         write(ofdsstrlen((char *)s));
751                 }
752         } else if (!Pflag)
753                 putstr(sheap("# %d \"%s\"\n"ifiles->linenoifiles->fname));
754         stringbuf = os;
ragge
1.1
755 }
756
757 void
758 cunput(int c)
759 {
ragge
1.13
760 #ifdef CPP_DEBUG
761         extern int dflag;
762         if (dflag)printf(": '%c'(%d)"c > 31 ? c : ' 'c);
763 #endif
ragge
1.1
764         unput(c);
765 }
766
ragge
1.13
767 int yywrap(void) { return 1; }
768
769 static int
770 dig2num(int c)
771 {
772         if (c >= 'a')
773                 c = c - 'a' + 10;
774         else if (c >= 'A')
775                 c = c - 'A' + 10;
776         else
777                 c = c - '0';
778         return c;
779 }
780
781 /*
782  * Convert string numbers to unsigned long long and check overflow.
783  */
784 static void
785 cvtdig(int rad)
786 {
787         unsigned long long rv = 0;
788         unsigned long long rv2 = 0;
789         char *y = yytext;
790         int c;
791
792         c = *y++;
793         if (rad == 16)
794                 y++;
795         while (isxdigit(c)) {
796                 rv = rv * rad + dig2num(c);
797                 /* check overflow */
798                 if (rv / rad < rv2)
799                         error("Constant \"%s\" is out of range"yytext);
800                 rv2 = rv;
801                 c = *y++;
802         }
803         y--;
804         while (*y == 'l' || *y == 'L')
805                 y++;
806         yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER;
807         yylval.node.nd_uval = rv;
808         if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0)
809                 yylval.node.op = UNUMBER;
810         if (yylval.node.op == NUMBER && yylval.node.nd_val < 0)
811                 /* too large for signed */
812                 error("Constant \"%s\" is out of range"yytext);
813 }
814
815 static int
816 charcon(usch *p)
817 {
818         int valc;
819
820         p++; /* skip first ' */
821         val = 0;
822         if (*p++ == '\\') {
823                 switch (*p++) {
824                 case 'a'val = '\a'break;
825                 case 'b'val = '\b'break;
826                 case 'f'val = '\f'break;
827                 case 'n'val = '\n'break;
828                 case 'r'val = '\r'break;
829                 case 't'val = '\t'break;
830                 case 'v'val = '\v'break;
831                 case '\"'val = '\"'break;
832                 case '\''val = '\''break;
833                 case '\\'val = '\\'break;
834                 case 'x':
835                         while (isxdigit(c = *p)) {
836                                 val = val * 16 + dig2num(c);
837                                 p++;
838                         }
839                         break;
840                 case '0'case '1'case '2'case '3'case '4':
841                 case '5'case '6'case '7':
842                         p--;
843                         while (isdigit(c = *p)) {
844                                 val = val * 8 + (c - '0');
845                                 p++;
846                         }
847                         break;
848                 defaultval = p[-1];
849                 }
850
851         } else
852                 val = p[-1];
853         return val;
854 }
855
856 static void
857 chknl(int ignore)
858 {
859         int t;
860
861         slow = 1;
862         while ((t = yylex()) == WSPACE)
863                 ;
864         if (t != '\n') {
865                 if (ignore) {
866                         warning("newline expected, got \"%s\""yytext);
867                         /* ignore rest of line */
868                         while ((t = yylex()) && t != '\n')
869                                 ;
870                 }
871                 else
872                         error("newline expected, got \"%s\""yytext);
873         }
874         slow = 0;
875 }
876
877 static void
878 elsestmt(void)
879 {
880         if (flslvl) {
881                 if (elflvl > trulvl)
882                         ;
883                 else if (--flslvl!=0) {
884                         flslvl++;
885                 } else {
886                         trulvl++;
887                         prtline();
888                 }
889         } else if (trulvl) {
890                 flslvl++;
891                 trulvl--;
892         } else
893                 error("If-less else");
894         if (elslvl==trulvl+flslvl)
895                 error("Too many else");
896         elslvl=trulvl+flslvl;
897         chknl(1);
898 }
899
900 static void
901 ifdefstmt(void)          
902
903         int t;
904
905         if (flslvl) {
906                 /* just ignore the rest of the line */
907                 while (input() != '\n')
908                         ;
909                 unput('\n');
910                 yylex();
911                 flslvl++;
912                 return;
913         }
914         slow = 1;
915         do
916                 t = yylex();
917         while (t == WSPACE);
918         if (t != IDENT)
919                 error("bad ifdef");
920         slow = 0;
921         if (flslvl == 0 && lookup((usch *)yytextFIND) != 0)
922                 trulvl++;
923         else
924                 flslvl++;
925         chknl(0);
926 }
927
928 static void
929 ifndefstmt(void)          
930
931         int t;
932
933         slow = 1;
934         do
935                 t = yylex();
936         while (t == WSPACE);
937         if (t != IDENT)
938                 error("bad ifndef");
939         slow = 0;
940         if (flslvl == 0 && lookup((usch *)yytextFIND) == 0)
941                 trulvl++;
942         else
943                 flslvl++;
944         chknl(0);
945 }
946
947 static void
948 endifstmt(void)          
949 {
950         if (flslvl) {
951                 flslvl--;
952                 if (flslvl == 0)
953                         prtline();
954         } else if (trulvl)
955                 trulvl--;
956         else
957                 error("If-less endif");
958         if (flslvl == 0)
959                 elflvl = 0;
960         elslvl = 0;
961         chknl(1);
962 }
963
964 /*
965  * Note! Ugly!
966  * Walk over the string s and search for defined, and replace it with 
967  * spaces and a 1 or 0. 
968  */
969 static void
970 fixdefined(usch *s)
971 {
972         usch *bcoc;
973
974         for (; *ss++) {
975                 if (*s != 'd')
976                         continue;
977                 if (memcmp(s"defined"7))
978                         continue;
979                 /* Ok, got defined, can scratch it now */
980                 memset(s' '7);
981                 s += 7;
982 #define WSARG(x) (x == ' ' || x == '\t')
983                 if (*s != '(' && !WSARG(*s))
984                         continue;
985                 while (WSARG(*s))
986                         s++;
987                 if (*s == '(')
988                         s++;
989                 while (WSARG(*s))
990                         s++;
991 #define IDARG(x) ((x>= 'A' && x <= 'Z') || (x >= 'a' && x <= 'z') || (x == '_'))
992 #define NUMARG(x) (x >= '0' && x <= '9')
993                 if (!IDARG(*s))
994                         error("bad defined arg");
995                 bc = s;
996                 while (IDARG(*s) || NUMARG(*s))
997                         s++;
998                 oc = *s;
999                 *s = 0;
1000                 *bc = (lookup(bcFIND) != 0) + '0';
1001                 memset(bc+1' 's-bc-1);
1002                 *s = oc;
1003         }
1004 }
1005
1006 /*
1007  * get the full line of identifiers after an #if, pushback a WARN and
1008  * the line and prepare for expmac() to expand.
1009  * This is done before switching state.  When expmac is finished,
1010  * pushback the expanded line, change state and call yyparse.
1011  */
1012 static void
1013 storepb(void)
1014 {
1015         usch *opb = stringbuf;
1016         int c;
1017
1018         while ((c = input()) != '\n') {
1019                 if (c == '/') {
1020                          if ((c = input()) == '*') {
1021                                 /* ignore comments here whatsoever */
1022                                 usch *g = stringbuf;
1023                                 getcmnt();
1024                                 stringbuf = g;
1025                                 continue;
1026                         } else if (c == '/') {
1027                                 while ((c = input()) && c != '\n')
1028                                         ;
1029                                 break;
1030                         }
1031                         unput(c);
1032                         c = '/';
1033                 }
1034                 savch(c);
1035         }
1036         cunput('\n');
1037         savch(0);
1038         fixdefined(opb); /* XXX can fail if #line? */
1039         cunput(1); /* WARN XXX */
1040         unpstr(opb);
1041         stringbuf = opb;
1042         slow = 1;
1043         expmac(NULL);
1044         slow = 0;
1045         /* line now expanded */
1046         while (stringbuf > opb)
1047                 cunput(*--stringbuf);
1048 }
1049
1050 static void
1051 ifstmt(void)
1052 {
1053         if (flslvl == 0) {
1054                 slow = 1;
1055                 if (yyparse())
1056                         ++trulvl;
1057                 else
1058                         ++flslvl;
1059                 slow = 0;
1060         } else
1061                 ++flslvl;
1062 }
1063
1064 static void
1065 elifstmt(void)
1066 {
1067         if (flslvl == 0)
1068                 elflvl = trulvl;
1069         if (flslvl) {
1070                 if (elflvl > trulvl)
1071                         ;
1072                 else if (--flslvl!=0)
1073                         ++flslvl;
1074                 else {
1075                         slow = 1;
1076                         if (yyparse()) {
1077                                 ++trulvl;
1078                                 prtline();
1079         &