Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20061007133832

Diff

Diff from 1.3 to:

Annotations

Annotate by Age | Author | Mixed | None
/fisheye/browse/pcc/pcc/cc/cpp/scanner.l

Annotated File View

ragge
1.1
1 %{
ragge
1.3
2 /*      $Id: scanner.l,v 1.3 2006/10/07 13:38:34 ragge Exp $    */
ragge
1.1
3
4 /*
5  * Copyright (c) 2004 Anders Magnusson. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <ctype.h>
33 #include <unistd.h>
34 #include <fcntl.h>
35
36 #include "cpp.h"
37 #include "y.tab.h"
38 %}
39
40 %{
41 static long long cvtdig(int rad);
ragge
1.2
42 static int charcon(void);
ragge
1.1
43 static void elsestmt(void);
44 static void ifdefstmt(void);
45 static void ifndefstmt(void);
46 static void endifstmt(void);
47 static void ifstmt(void);
48 static void cpperror(void);
49 static void pragmastmt(void);
50 static void undefstmt(void);
51 static void cpperror(void);
52 static void elifstmt(void);
53 void  include(void);
54 void  define(void);
55
ragge
1.2
56 #define ACK     6       /* not legal input char */
ragge
1.1
57
58 static int inch(void);
59
ragge
1.2
60 static int scale, inmac;
ragge
1.1
61
62 #ifdef FLEX_SCANNER /* should be set by autoconf instead */
63 static int
64 yyinput(char *b, int m)
65 {
66         int c, i;
67
68         for (i = 0; i < m; i++) {
69                 if ((c = inch()) < 0)
70                         break;
71                 *b++ = c;
72                 if (c == '\n') {
73                         i++;
74                         break;
75                 }
76         }
77         return i;
78 }
79 #undef YY_INPUT
80 #define YY_INPUT(b,r,m) (r = yyinput(b, m))
ragge
1.2
81 #define fprintf(x, ...) error(__VA_ARGS__)
82 #define ECHO putstr(yytext)
ragge
1.3
83 #undef fileno
ragge
1.2
84 #define fileno(x) 0
85
86 #if YY_FLEX_SUBMINOR_VERSION >= 31
87 /* Hack to avoid unneccessary warnings */
88 FILE *yyget_in  (void);
89 FILE *yyget_out  (void);
90 int yyget_leng  (void);
91 char *yyget_text  (void);
92 void yyset_in (FILE *  in_str );
93 void yyset_out (FILE *  out_str );
94 int yyget_debug  (void);
95 void yyset_debug (int  bdebug );
96 int yylex_destroy  (void);
97 #endif
ragge
1.1
98 #else   /* Assume lex here */
99 #undef input
100 #undef unput
101 #define input() inch()
102 #define unput(ch) unch(ch)
103 #endif
104 #define PRTOUT(x) if (YYSTATE || slow) return x; if (!flslvl) putstr(yytext);
105 %}
106
107 D       [0-9]
108 L       [a-zA-Z_]
109 H       [a-fA-F0-9]
110 E       [Ee][+-]?{D}+
111 FS      (f|F|l|L)
112 IS      (u|U|l|L)*
113 WS      [\t ]
114
115 %s IFR CONTR DEF
116
117 %%
118
119 "\n"                    {       int os = YYSTATE;
120                                 BEGIN 0;
121                                 ifiles->lineno++;
122                                 if (flslvl == 0) {
ragge
1.2
123                                         if (ifiles->lineno == 1)
ragge
1.1
124                                                 prtline();
125                                         else
126                                                 putch('\n');
127                                 }
128                                 if (os != 0 || slow)
129                                         return '\n';
130                         }
131
132 <IFR>"=="               { return EQ; }
133 <IFR>"!="               { return NE; }
134 <IFR>"<="               { return LE; }
135 <IFR>"<<"               { return LS; }
136 <IFR>">>"               { return RS; }
137 <IFR>">="               { return GE; }
138 <IFR>"||"               { return OROR; }
139 <IFR>"&&"               { return ANDAND; }
ragge
1.2
140 <IFR>"defined"          {       int p, c;
141                                 inmac++;
142                                 if ((p = c = yylex()) == '(')
143                                         c = yylex();
144                                 if (c != IDENT || (p != IDENT && p != '('))
145                                         error("syntax error");
146                                 if (p == '(' && yylex() != ')')
147                                         error("syntax error");
148                                 inmac--;
149                                 return IDENT;
150                         }
151
ragge
1.1
152 <IFR>{WS}+              { ; }
ragge
1.2
153 <IFR>{L}({L}|{D})*      {
154                                 struct symtab *nl;
155                                 /*
156                                  * Tricky: expand everything once, push it
157                                  * back on the input and then do not expand
158                                  * it again.
159                                  */
160                                 if (inmac == 0) {
161                                         if ((nl = lookup(yytext, FIND))) {
162                                                 usch *rv, *sp = stringbuf;
163                                                 rv = gotident(nl);
164                                                 cunput(ACK);
165                                                 unpstr(rv);
166                                                 stringbuf = sp;
167                                                 inmac = 1;
168                                         } else {
169                                                 yylval.nl = 0;
170                                                 return IDENT;
171                                         }
172                                 } else {
173                                         yylval.nl = lookup(yytext, FIND);
174                                         return IDENT;
175                                 }
176                         }
ragge
1.1
177
ragge
1.2
178 0[xX]{H}+{IS}?          {       scale = 16;
ragge
1.1
179                         num:    if (YYSTATE)
180                                         yylval.val = cvtdig(scale);
181                                 PRTOUT(NUMBER);
182                         }
183 0{D}+{IS}?              { scale = 8; goto num; }
184 {D}+{IS}?               { scale = 10; goto num; }
185 L?'(\\.|[^\\'])+'       {       if (YYSTATE)
186                                         yylval.val = charcon();
ragge
1.2
187                                 PRTOUT(NUMBER);
ragge
1.1
188                         }
189
ragge
1.2
190 <IFR>"\006"             { inmac = 0; /* end of pushbacked macro */ }
ragge
1.1
191 <IFR>.                  { return yytext[0]; }
192
193 {D}+{E}{FS}?            { PRTOUT(FPOINT); }
194 {D}*"."{D}+({E})?{FS}?  { PRTOUT(FPOINT); }
195 {D}+"."{D}*({E})?{FS}?  { PRTOUT(FPOINT); }
196
197 ^{WS}*#{WS}*            { BEGIN CONTR; }
198 {WS}+                   { PRTOUT(WSPACE); }
199
200 <CONTR>"ifndef"         { ifndefstmt(); }
201 <CONTR>"ifdef"          { ifdefstmt(); }
ragge
1.2
202 <CONTR>"if"{WS}+        { BEGIN IFR; ifstmt(); BEGIN 0; }
203 <CONTR>"include"        { BEGIN 0; include(); prtline(); }
ragge
1.1
204 <CONTR>"else"           { elsestmt(); }
205 <CONTR>"endif"          { endifstmt(); }
ragge
1.2
206 <CONTR>"error"          { cpperror(); BEGIN 0; }
207 <CONTR>"define"         { BEGIN DEF; define(); BEGIN 0; }
ragge
1.1
208 <CONTR>"undef"          { undefstmt(); }
ragge
1.2
209 <CONTR>"line"           { BEGIN 0; line(); }
ragge
1.1
210 <CONTR>"pragma"         { pragmastmt(); }
ragge
1.2
211 <CONTR>"elif"{WS}+      { BEGIN IFR; elifstmt(); BEGIN 0; }
ragge
1.1
212
213
214
215 "//".*$                 { /* if (tflag) yyless(..) */
216                                 if (Cflag)
217                                         putstr(yytext);
ragge
1.2
218                                 else if (!flslvl)
ragge
1.1
219                                         putch(' ');
220                         }
221 "/*"                    {       int c;
222                                 if (Cflag)
223                                         putstr(yytext);
224                         more:   while ((c = input()) && c != '*') {
225                                         if (c == '\n')
226                                                 putch(c), ifiles->lineno++;
227                                         else if (Cflag)
228                                                 putch(c);
229                                 }
230                                 if (c == 0)
231                                         return 0;
232                                 if (Cflag)
233                                         putch(c);
234                                 if ((c = input()) && c != '/') {
235                                         if (Cflag)
236                                                 putch('*');
237                                         unput(c);
238                                         goto more;
239                                 }
240                                 if (Cflag)
241                                         putch(c);
242                                 if (c == 0)
243                                         return 0;
ragge
1.2
244                                 if (!tflag && !Cflag && !flslvl)
ragge
1.1
245                                         unput(' ');
246                         }
247
248 <DEF>"##"               { return CONCAT; }
249 <DEF>"#"                { return MKSTR; }
250 <DEF>"..."              { return ELLIPS; }
ragge
1.2
251 <DEF>"__VA_ARGS__"      { return VA_ARGS; }
ragge
1.1
252
253 L?\"(\\.|[^\\"])*\"     { PRTOUT(STRING); }
254 {L}({L}|{D})*           {
255                                 struct symtab *nl;
256                                 if (slow)
257                                         return IDENT;
258                                 if (flslvl)
259                                         ; /* do nothing */
260                                 else if ((nl = lookup(yytext, FIND)) != 0) {
ragge
1.2
261                                         usch *op = stringbuf;
262                                         putstr(gotident(nl));
263                                         stringbuf = op;
ragge
1.1
264                                 } else
265                                         putstr(yytext);
266                         }
267
ragge
1.2
268 .                       { PRTOUT(yytext[0]); }
ragge
1.1
269
270 %%
271
272 usch *yyp, yybuf[CPPBUF];
273
274 int yylex(void);
275 int yywrap(void);
276
277 static int
278 inpch(void)
279 {
280         int len;
281
282         if (ifiles->curptr < ifiles->maxread)
283                 return *ifiles->curptr++;
284
285         if (ifiles->infil < 0) {
286                 ifiles = ifiles->next;
287                 return inpch();
288         }
289         if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0)
290                 error("read error on file %s", ifiles->fname);
291         if (len == 0)
292                 return -1;
293         ifiles->curptr = ifiles->buffer;
294         ifiles->maxread = ifiles->buffer + len;
295         return inpch();
296 }
297
298 #define unch(c) *--ifiles->curptr = c
299
300 static int
301 inch(void)
302 {
303         int c;
304
305 again:  switch (c = inpch()) {
306         case '\\': /* continued lines */
307                 if ((c = inpch()) == '\n') {
308                         ifiles->lineno++;
ragge
1.2
309                         putch('\n');
ragge
1.1
310                         goto again;
311                 }
312                 unch(c);
313                 return '\\';
314         case '?': /* trigraphs */
315                 if ((c = inpch()) != '?') {
316                         unch(c);
317                         return '?';
318                 }
319                 switch (c = inpch()) {
320                 case '=': c = '#'; break;
321                 case '(': c = '['; break;
322                 case ')': c = ']'; break;
323                 case '<': c = '{'; break;
324                 case '>': c = '}'; break;
325                 case '/': c = '\\'; break;
326                 case '\'': c = '^'; break;
327                 case '!': c = '|'; break;
328                 case '-': c = '~'; break;
329                 default:
330                         unch(c);
331                         unch('?');
332                         return '?';
333                 }
334                 unch(c);
335                 goto again;
336         default:
337                 return c;
338         }
339 }
340
341 /*
342  * A new file included.
343  * If ifiles == NULL, this is the first file and already opened (stdin).
344  * Return 0 on success, -1 on failure to open file.
345  */
346 int
347 pushfile(char *file)
348 {
349         struct includ ibuf;
350         struct includ *old;
351         struct includ *ic;
ragge
1.2
352         int c, otrulvl;
ragge
1.1
353
354         ic = &ibuf;
355         old = ifiles;
356
357         slow = 0;
358         if (file != NULL) {
359                 if ((ic->infil = open(file, O_RDONLY)) < 0)
360                         return -1;
361                 ic->fname = file;
362         } else {
363                 ic->infil = 0;
364                 ic->fname = "<stdin>";
365         }
366         ic->buffer = ic->bbuf+NAMEMAX;
367         ic->curptr = ic->buffer;
368         ifiles = ic;
369         ic->lineno = 1;
370         ic->maxread = ic->curptr;
371         prtline();
372
ragge
1.2
373         otrulvl = trulvl;
374
ragge
1.1
375         if ((c = yylex()) != 0)
376                 error("yylex returned %d", c);
377
ragge
1.2
378         if (otrulvl != trulvl || flslvl)
ragge
1.1
379                 error("unterminated conditional");
380
381         ifiles = old;
382         close(ic->infil);
383         return 0;
384 }
385
386 /*
387  * Print current position to output file.
388  */
389 void
390 prtline()
391 {
ragge
1.2
392         usch *os = stringbuf;
393
394         putstr(sheap("# %d \"%s\"\n", ifiles->lineno, ifiles->fname));
395         stringbuf = os;
ragge
1.1
396 }
397
398 void
399 cunput(int c)
400 {
ragge
1.2
401 #ifdef CPP_DEBUG
402         extern int dflag;
403         if (dflag)printf(": '%c'(%d)", c, c);
404 #endif
ragge
1.1
405         unput(c);
406 }
407
ragge
1.2
408 int yywrap(void) { return 1; }
ragge
1.1
409
ragge
1.2
410 static int
411 dig2num(int c)
ragge
1.1
412 {
ragge
1.2
413         if (c >= 'a')
414                 c = c - 'a' + 10;
415         else if (c >= 'A')
416                 c = c - 'A' + 10;
417         else
418                 c = c - '0';
419         return c;
ragge
1.1
420 }
421
422 static long long
423 cvtdig(int rad)
424 {
425         long long rv = 0;
426         char *y = yytext;
427         int c;
428
429         c = *y++;
430         while (isxdigit(c)) {
ragge
1.2
431                 rv = rv * rad + dig2num(c);
ragge
1.1
432                 c = *y++;
433         }
434         return rv;
435 }
436
ragge
1.2
437 static int
ragge
1.1
438 charcon(void)
439 {
ragge
1.2
440         usch *p = (usch *)yytext;
441         int val, c;
442
443         if (*p == 'L')
444                 p++;
445         p++; /* first ' */
446         val = 0;
447         if (*p++ == '\\') {
448                 switch (*p++) {
449                 case 'a': val = '\a'; break;
450                 case 'b': val = '\b'; break;
451                 case 'f': val = '\f'; break;
452                 case 'n': val = '\n'; break;
453                 case 'r': val = '\r'; break;
454                 case 't': val = '\t'; break;
455                 case 'v': val = '\v'; break;
456                 case '\"': val = '\"'; break;
457                 case '\'': val = '\''; break;
458                 case '\\': val = '\\'; break;
459                 case 'x':
460                         while (isxdigit(c = *p)) {
461                                 val = val * 16 + dig2num(c);
462                                 p++;
463                         }
464                         break;
465                 case '0': case '1': case '2': case '3': case '4':
466                 case '5': case '6': case '7':
467                         p--;
468                         while (isdigit(c = *p)) {
469                                 val = val * 8 + (c - '0');
470                                 p++;
471                         }
472                         break;
473                 default: val = p[-1];
474                 }
475
476         } else
477                 val = p[-1];
478         return val;
ragge
1.1
479 }
480
481 static void
482 chknl(void)
483 {
484         int t;
485
ragge
1.2
486         while ((t = yylex()) == WSPACE)
487                 ;
ragge
1.1
488         if (t != '\n')
489                 error("newline expected");
490 }
491
492 static void
493 elsestmt(void)
494 {
495         if (flslvl) {
496                 if (elflvl > trulvl)
497                         ;
498                 else if (--flslvl!=0) {
499                         flslvl++;
500                 } else {
501                         trulvl++;
502                         prtline();
503                 }
504         } else if (trulvl) {
505                 flslvl++;
506                 trulvl--;
507         } else
508                 error("If-less else");
509         if (elslvl==trulvl+flslvl)
510                 error("Too many else");
511         elslvl=trulvl+flslvl;
512         chknl();
513 }
514
515 static void
ragge
1.2
516 ifdefstmt(void)          
ragge
1.1
517
ragge
1.2
518         slow = 1;
ragge
1.1
519         if (yylex() != WSPACE || yylex() != IDENT)
520                 error("bad ifdef");
ragge
1.2
521         slow = 0;
ragge
1.1
522         if (flslvl == 0 && lookup(yytext, FIND) != 0)
523                 trulvl++;
524         else
525                 flslvl++;
526         chknl();
527 }
528
529 static void
ragge
1.2
530 ifndefstmt(void)          
ragge
1.1
531
ragge
1.2
532         slow = 1;
ragge
1.1
533         if (yylex() != WSPACE || yylex() != IDENT)
534                 error("bad ifndef");
ragge
1.2
535         slow = 0;
ragge
1.1
536         if (flslvl == 0 && lookup(yytext, FIND) == 0)
537                 trulvl++;
538         else
539                 flslvl++;
540         chknl();
541 }
542
543 static void
ragge
1.2
544 endifstmt(void)          
ragge
1.1
545 {
546         if (flslvl) {
547                 flslvl--;
548                 if (flslvl == 0)
549                         prtline();
550         } else if (trulvl)
551                 trulvl--;
552         else
553                 error("If-less endif");
554         if (flslvl == 0)
555                 elflvl = 0;
556         elslvl = 0;
557         chknl();
558 }
559
560 static void
561 ifstmt(void)
562 {
563         if (flslvl == 0) {
ragge
1.2
564                 slow = 1;
ragge
1.1
565                 if (yyparse())
566                         ++trulvl;
567                 else
568                         ++flslvl;
ragge
1.2
569                 slow = 0;
ragge
1.1
570         } else
571                 ++flslvl;
572 }
573
574 static void
575 elifstmt(void)
576 {
577         if (flslvl == 0)
578                 elflvl = trulvl;
579         if (flslvl) {
580                 if (elflvl > trulvl)
581                         ;
582                 else if (--flslvl!=0)
583                         ++flslvl;
584                 else {
ragge
1.2
585                         slow = 1;
ragge
1.1
586                         if (yyparse()) {
587                                 ++trulvl;
588                                 prtline();
589                         } else
590                                 ++flslvl;
ragge
1.2
591                         slow = 0;
ragge
1.1
592                 }
593         } else if (trulvl) {
594                 ++flslvl;
595                 --trulvl;
596         } else
597                 error("If-less elif");
598 }
599
600 static usch *
601 svinp(void)
602 {
603         int c;
604         usch *cp = stringbuf;
605
606         while ((c = input()) && c != '\n')
607                 savch(c);
608         savstr("\n");
609         BEGIN 0;
610         return cp;
611 }
612
613 static void
614 cpperror(void)
615 {
616         usch *cp;
ragge
1.2
617         int c;
ragge
1.1
618
ragge
1.2
619         if (flslvl)
620                 return;
621         c = yylex();
622         if (c != WSPACE && c != '\n')
ragge
1.1
623                 error("bad error");
624         cp = svinp();
625         if (flslvl)
626                 stringbuf = cp;
627         else
628                 error("error: %s", cp);
629 }
630
631 static void
632 undefstmt(void)
633 {
634         struct symtab *np;
635
636         slow = 1;
637         if (yylex() != WSPACE || yylex() != IDENT)
638                 error("bad undef");
639         if (flslvl == 0 && (np = lookup(yytext, FIND)))
640                 np->value = 0;
641         slow = 0;
642         chknl();
643 }
644
645 static void
646 pragmastmt(void)
647 {
648         if (yylex() != WSPACE)
649                 error("bad pragma");
650         /* macexpand() */
651         chknl();
652 }
FishEye: Open Source License registered to PCC.
Atlassian FishEye, CVS analysis. (Version:1.6.3 Build:build-336 2008-11-04) - Administration - Page generated 2014-12-20 18:56 +0100