2 /* $Id: scan.l,v 1.102 2011/02/16 18:50:42 ragge Exp $ */
5 * Copyright (c) 2002 Anders Magnusson. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
39 UL ({L}|\\u{H}{H}{H}{H}|\\U{H}{H}{H}{H}{H}{H}{H}{H})
51 static NODE *cvtdig(int radix);
52 static NODE *charcon(void);
53 static NODE *wcharcon(void);
54 static void control(int);
55 static void pragma(void);
56 int notype, parbal, inattr, parlvl;
57 static int resw(TWORD, int);
64 #define STABS_LINE(x) if (gflag && cftnsp) stabs_line(x)
68 #if defined(FLEX_SCANNER) && YY_FLEX_SUBMINOR_VERSION == 31
69 /* Hack to avoid unnecessary warnings */
70 FILE *yyget_in (void);
71 FILE *yyget_out (void);
72 int yyget_leng (void);
73 char *yyget_text (void);
74 void yyset_in (FILE *);
75 void yyset_out (FILE *);
76 int yyget_debug (void);
77 void yyset_debug (int);
78 int yylex_destroy (void);
79 extern int yyget_lineno (void);
80 extern void yyset_lineno (int);
89 uerror("__func__ outside function");
90 yylval.strp = cftnsp->sname; /* XXX - not C99 */
93 "asm" { return(C_ASM); }
94 "auto" { return resw(AUTO, C_CLASS); }
95 "_Bool" { return resw(BOOL, C_TYPE); }
96 "break" { return(C_BREAK); }
97 "case" { return(C_CASE); }
98 "char" { return resw(CHAR, C_TYPE); }
99 "_Complex" { return resw(COMPLEX, C_TYPE); }
100 "const" { return resw(CON, C_QUALIFIER); }
101 "continue" { return(C_CONTINUE); }
102 "default" { return(C_DEFAULT); }
103 "do" { return(C_DO); }
104 "double" { return resw(DOUBLE, C_TYPE); }
105 "else" { return(C_ELSE); }
106 "enum" { notype=1; return(C_ENUM); }
107 "extern" { return resw(EXTERN, C_CLASS); }
108 "float" { return resw(FLOAT, C_TYPE); }
109 "for" { return(C_FOR); }
110 "goto" { notype=1; return(C_GOTO); }
111 "if" { return(C_IF); }
112 "_Imaginary" { return resw(IMAG, C_TYPE); }
113 "inline" { return(C_FUNSPEC); }
114 "int" { return resw(INT, C_TYPE); }
115 "long" { return resw(LONG, C_TYPE); }
116 "register" { return resw(REGISTER, C_CLASS); }
117 "restrict" { ; /* just ignore */ }
118 "return" { return(C_RETURN); }
119 "short" { return resw(SHORT, C_TYPE); }
120 "signed" { return resw(SIGNED, C_TYPE); }
121 "sizeof" { return(C_SIZEOF); }
122 "static" { return resw(STATIC, C_CLASS); }
123 "struct" { yylval.intval = STNAME; notype=1; return(C_STRUCT); }
124 "switch" { return(C_SWITCH); }
125 "typedef" { return resw(TYPEDEF, C_CLASS); }
126 "union" { yylval.intval = UNAME; notype=1; return(C_STRUCT); }
127 "unsigned" { return resw(UNSIGNED, C_TYPE); }
128 "void" { return resw(VOID, C_TYPE); }
129 "volatile" { return resw(VOL, C_QUALIFIER); }
130 "while" { return(C_WHILE); }
132 {UL}({UL}|{D})* { struct symtab *s;
135 yylval.strp = addname(yytext);
137 if ((i = gcc_keyword(yylval.strp, &yylval.nodep)) > 0)
143 s = lookup(yylval.strp, SNOCREAT);
144 return s && s->sclass == TYPEDEF ?
145 notype=1, C_TYPENAME : C_NAME;
149 0[xX]{H}+{IS}? { yylval.nodep = cvtdig(16); return(C_ICON); }
150 0{D}+{IS}? { yylval.nodep = cvtdig(8); return(C_ICON); }
151 {D}+{IS}? { yylval.nodep = cvtdig(10); return(C_ICON); }
152 L'(\\.|[^\\'])+' { yylval.nodep = wcharcon(); return(C_ICON); }
153 '(\\.|[^\\'])+' { yylval.nodep = charcon(); return(C_ICON); }
155 {D}+{E}{FS}? { yylval.nodep = floatcon(yytext); return(C_FCON); }
156 {D}*"."{D}+({E})?{FS}? { yylval.nodep = floatcon(yytext); return(C_FCON); }
157 {D}+"."{D}*({E})?{FS}? { yylval.nodep = floatcon(yytext); return(C_FCON); }
158 0[xX]{H}*"."{H}+{P}{FS}? { yylval.nodep = fhexcon(yytext); return(C_FCON); }
159 0[xX]{H}+"."{P}{FS}? { yylval.nodep = fhexcon(yytext); return(C_FCON); }
160 0[xX]{H}+{P}{FS}? { yylval.nodep = fhexcon(yytext); return(C_FCON); }
162 L?\"(\\.|[^\\"])*\" { yylval.strp = yytext; return C_STRING; }
164 "..." { return(C_ELLIPSIS); }
165 ">>=" { yylval.intval = RSEQ; return(C_ASOP); }
166 "<<=" { yylval.intval = LSEQ; return(C_ASOP); }
167 "+=" { yylval.intval = PLUSEQ; return(C_ASOP); }
168 "-=" { yylval.intval = MINUSEQ; return(C_ASOP); }
169 "*=" { yylval.intval = MULEQ; return(C_ASOP); }
170 "/=" { yylval.intval = DIVEQ; return(C_ASOP); }
171 "%=" { yylval.intval = MODEQ; return(C_ASOP); }
172 "&=" { yylval.intval = ANDEQ; return(C_ASOP); }
173 "^=" { yylval.intval = EREQ; return(C_ASOP); }
174 "|=" { yylval.intval = OREQ; return(C_ASOP); }
175 ">>" { yylval.intval = RS; return(C_SHIFTOP); }
176 "<<" { yylval.intval = LS; return(C_SHIFTOP); }
177 "++" { yylval.intval = INCR; return(C_INCOP); }
178 "--" { yylval.intval = DECR; return(C_INCOP); }
179 "->" { yylval.intval = STREF; return(C_STROP); }
180 "&&" { yylval.intval = ANDAND; return(C_ANDAND); }
181 "||" { yylval.intval = OROR; return(C_OROR); }
182 "<=" { yylval.intval = LE; return(C_RELOP); }
183 ">=" { yylval.intval = GE; return(C_RELOP); }
184 "==" { yylval.intval = EQ; return(C_EQUOP); }
185 "!=" { yylval.intval = NE; return(C_EQUOP); }
186 ";" { notype = 0; return(';'); }
187 ("{"|"<%") { notype = 0; return('{'); }
188 ("}"|"%>") { if (rpole) notype = 1; return('}'); }
189 "," { if (parbal) notype = 0; return(','); }
192 "(" { parbal++; notype = 0; return('('); }
194 if (parbal==0) { notype = 0; }
195 if (inattr && parlvl == parbal)
198 ("["|"<:") { return('['); }
199 ("]"|":>") { return(']'); }
200 "." { yylval.intval = DOT; return(C_STROP); }
202 "!" { yylval.intval = NOT; return(C_UNOP); }
203 "~" { yylval.intval = COMPL; return(C_UNOP); }
206 "*" { if (parbal && notype == 0) notype = 1; return('*'); }
207 "/" { yylval.intval = DIV; return(C_DIVOP); }
208 "%" { yylval.intval = MOD; return(C_DIVOP); }
209 "<" { yylval.intval = LT; return(C_RELOP); }
210 ">" { yylval.intval = GT; return(C_RELOP); }
214 ^#pragma[ \t].* { pragma(); }
215 ^#ident[ \t].* { control(CPP_IDENT); }
216 ^#line[ \t].* { control(CPP_LINE); }
217 ^#.* { control(CPP_HASH); }
220 "\n" { ++lineno; STABS_LINE(lineno); }
221 . { /* ignore bad characters */ }
226 char *ftitle = "<stdin>";
231 if (0) unput(0); /* quiet gcc */
236 resw(TWORD t, int rv)
239 yylval.strp = addname(yytext);
245 yylval.nodep = block(CLASS, NIL, NIL, t, 0, 0);
249 yylval.nodep = block(QUALIFIER, NIL, NIL, 0, 0, 0);
250 yylval.nodep->n_qual = t;
254 yylval.nodep = mkty(t, 0, MKAP(t));
267 typround(long double dc, char *e, TWORD *tw)
293 *tw += (FIMAG-FLOAT);
299 * XXX floatcon() and fhexcon() should be in support libraries for
300 * the target floating point.
311 dc = strtold(str, &eptr); /* XXX - avoid strtod() */
313 dc = strtod(str, &eptr); /* XXX - avoid strtod() */
315 dc = typround(dc, eptr, &tw);
316 p = block(FCON, NIL, NIL, tw, 0, MKAP(tw));
330 if (ch >= '0' && ch <= '9')
332 if (ch >= 'a' && ch <= 'f')
333 return ch - 'a' + 10;
334 return ch - 'A' + 10;
350 #define FSET(n) { d *= 2; if (i & n) d += 1.0; }
351 for (; *c != '.' && *c != 'p' && *c != 'P'; c++) {
353 FSET(8); FSET(4); FSET(2); FSET(1);
355 if (*c != '.' && *c != 'p' && *c != 'P')
359 for (; *c != 'p' && *c != 'P'; c++) {
361 FSET(8); FSET(4); FSET(2); FSET(1);
365 if (*c != 'P' && *c != 'p')
368 ed += strtol(c, &ep, 10);
370 /* avoid looping in vain. Idea from Fred J. Tydeman */
371 if (ed > 32769) ed = 32769;
372 if (ed < -32769) ed = -32769;
378 d = typround(d, ep, &tw);
379 p = block(FCON, NIL, NIL, tw, 0, MKAP(tw));
392 int wsz = 4, esccon_warn = 1;
395 case 'a': val = '\a'; break;
396 case 'b': val = '\b'; break;
397 case 'f': val = '\f'; break;
398 case 'n': val = '\n'; break;
399 case 'r': val = '\r'; break;
400 case 't': val = '\t'; break;
401 case 'v': val = '\v'; break;
402 case '\"': val = '\"'; break;
403 case 'x': val = strtoul(wr, &wr, 16); break;
404 /* ISO/IEC 9099:1999 (E) 6.4.3 */
413 while (wr < (owr + wsz))
418 if (wr != (owr + wsz)) {
420 val = strtoul(owr, &wr, 16);
423 owr[wsz] = '\0'; /* prevent it from reading too much */
424 val = strtoul(owr, &wr, 16);
427 if (wr != (owr + wsz))
428 werror("incomplete universal character name");
431 if (esccon_warn && ((val >= 0xD800 && val <= 0xDFFF) ||
432 (val < 0xA0 && val != 0x24 && val != 0x40 && val != 0x60)))
433 werror("invalid universal character name %04X", val);
435 case '0': case '1': case '2': case '3': case '4':
436 case '5': case '6': case '7':
438 if (*wr >= '0' && *wr <= '7') {
439 val = (val << 3) + (*wr++ - '0');
440 if (*wr >= '0' && *wr <= '7')
441 val = (val << 3) + (*wr++ - '0');
444 default: val = wr[-1];
455 unsigned long long v;
460 ch += 2; /* Skip 0x */
463 while ((*ch >= '0' && *ch <= '9') || (*ch >= 'a' && *ch <= 'f') ||
464 (*ch >= 'A' && *ch <= 'F')) {
467 n = (n <= '9' ? n - '0' : (n > 'F' ? n - 'a' : n - 'A') + 10);
471 /* Parse trailing chars */
474 for (n = 0; n < 3; n++) {
477 if ((*ch == 'l' || *ch == 'L') && numl < 2)
479 else if ((*ch == 'u' || *ch == 'U') && numu < 1)
480 ntype = ENUNSIGN(ntype), numu++;
486 uerror("constant has too many '%c'", *ch);
489 /* v contains a number. Get type correct */
490 if (v > MAX_LONGLONG && radix != 10)
492 else if (v > MAX_ULONG)
494 else if (v > MAX_LONG && radix != 10)
496 else if (v > MAX_UNSIGNED)
498 else if (v > MAX_INT && radix != 10)
501 ntype = ctype(ntype);
502 p = xbcon(v, NULL, ntype);
503 ASGLVAL(p->n_slval, v);
509 * Convert a character constant to an integer.
521 while (*pp != '\'') {
531 uerror("empty character constant");
532 if (i > (SZINT/SZCHAR) || (i>1))
533 werror("too many characters in character constant");
534 return bcon(lastcon);
540 unsigned int lastcon = 0;
541 unsigned int val, i = 0;
547 while (*pp != '\'') {
553 lastcon = (lastcon << 16) | (val & 0xFFFF);
561 uerror("empty wide character constant");
563 werror("too many characters in wide character constant");
564 return xbcon(lastcon, NULL, ctype(UNSIGNED));
574 wr++; /* Skip initial '#' */
577 return; /* Just skip these for now. */
583 val = strtol(wr, &eptr, 10);
584 if (wr == eptr) /* Illegal string */
588 while (*wr && *wr != '\"')
595 while (*wr && *wr != '\"')
600 ftitle = addstring(eptr);
608 werror("%s: illegal control", yytext);
611 int pragma_allpacked;
612 int pragma_packed, pragma_aligned;
613 char *pragma_renamed;
616 pragmas_weak(char *str)
621 if ((s1 = pragtok(NULL)) == NULL)
623 if ((s2 = pragtok(NULL)) == NULL) {
624 sp = lookup(addname(s1), SNORMAL);
625 sp->sap = attr_add(sp->sap, gcc_attr_parse(bdty(NAME, "weak")));
626 } else if (*s2 == '=') {
627 if ((s2 = pragtok(NULL)) == NULL)
629 sp = lookup(addname(s2), SNORMAL);
630 sp->sap = attr_add(sp->sap, gcc_attr_parse(bdty(CALL,
631 bdty(NAME, "aliasweak"), bdty(STRING, s1, 0))));
639 /* trivial tokenizer for pragmas */
650 for (; isspace((int)*ps); ps++)
654 for (rv = ps; isalpha((int)*ps) || isdigit((int)*ps) || *ps == '_'; ps++)
667 /* return 1 on error */
671 char *s = pragtok(0);
672 return (s == 0 || *s != ch);
676 pragmas_alpack(char *t)
681 ap = (s = pragtok(0)) ? atoi(s) : 1;
682 if (strcmp(t, "packed") == 0)
692 * still missing push/pop.
695 pragmas_pack(char *t)
703 return pragma_allpacked = 0;
705 if (*s < '0' || *s > '9') /* no number */
707 pragma_allpacked = atoi(s);
712 pragmas_renamed(char *t)
714 char *f = pragtok(0);
718 pragma_renamed = newstring(f, strlen(f));
723 pragmas_stdc(char *t)
725 return 0; /* Just ignore */
732 { "pack", pragmas_pack },
733 { "packed", pragmas_alpack },
734 { "aligned", pragmas_alpack },
735 { "rename", pragmas_renamed },
737 { "GCC", pragmas_gcc },
739 { "STDC", pragmas_stdc },
740 { "weak", pragmas_weak },
745 * got a full pragma line. Split it up here.
753 if ((t = pragtok(&yytext[7])) != NULL) {
755 for (p = pragmas; p->name; p++) {
756 if (strcmp(t, p->name) == 0) {
757 if (p->fun && (*p->fun)(t))
758 uerror("bad argument to #pragma");
766 warner(Wunknown_pragmas, t, ps);