Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20090308102151

Diff

Diff from 1.13 to:

Annotations

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

Annotated File View

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