1 %{ 2 /* Id: scan.l,v 1.6 2015/11/13 11:33:14 ragge Exp */ 3 /* $NetBSD: scan.l,v 1.1.1.3 2016/02/09 20:29:02 plunky Exp $ */ 4 5 /* 6 * Copyright (c) 2002 Anders Magnusson. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 %} 31 32 33 D [0-9] 34 L [a-zA-Z_] 35 H [a-fA-F0-9] 36 E [Ee][+-]?{D}+ 37 P [Pp][+-]?{D}+ 38 FS (f|F|l|L)?i? 39 IS (u|U|l|L)* 40 UL ({L}|\\u{H}{H}{H}{H}|\\U{H}{H}{H}{H}{H}{H}{H}{H}) 41 42 %{ 43 #include <stdlib.h> 44 #include <errno.h> 45 #include <string.h> 46 #include <stdarg.h> 47 #include <ctype.h> 48 49 #include "pass1.h" 50 #include "cgram.h" 51 52 static NODE *cvtdig(int radix); 53 static NODE *charcon(void); 54 static NODE *wcharcon(void); 55 static void control(int); 56 static void pragma(void); 57 int notype, parbal, inattr, parlvl, nodinit, inoso; 58 static int resw(TWORD, int); 59 static int namechk(void); 60 61 #define CPP_IDENT 2 62 #define CPP_LINE 3 63 #define CPP_HASH 4 64 65 #ifdef STABS 66 #define STABS_LINE(x) if (gflag && cftnsp) stabs_line(x) 67 #else 68 #define STABS_LINE(x) 69 #endif 70 #if defined(FLEX_SCANNER) && YY_FLEX_SUBMINOR_VERSION == 31 71 /* Hack to avoid unnecessary warnings */ 72 FILE *yyget_in (void); 73 FILE *yyget_out (void); 74 int yyget_leng (void); 75 char *yyget_text (void); 76 void yyset_in (FILE *); 77 void yyset_out (FILE *); 78 int yyget_debug (void); 79 void yyset_debug (int); 80 int yylex_destroy (void); 81 extern int yyget_lineno (void); 82 extern void yyset_lineno (int); 83 #endif 84 85 %} 86 87 %% 88 89 "__func__" { 90 if (cftnsp == NULL) 91 uerror("__func__ outside function"); 92 yylval.strp = cftnsp->sname; /* XXX - not C99 */ 93 return(C_STRING); 94 } 95 "asm" { return(C_ASM); } 96 "auto" { return resw(AUTO, C_CLASS); } 97 "_Bool" { return resw(BOOL, C_TYPE); } 98 "break" { return(C_BREAK); } 99 "case" { return(C_CASE); } 100 "char" { return resw(CHAR, C_TYPE); } 101 "class" { yylval.intval = CLNAME; notype=1; return(C_STRUCT); } 102 "_Complex" { return resw(COMPLEX, C_TYPE); } 103 "const" { return resw(CON, C_QUALIFIER); } 104 "const_cast" { yylval.intval = CONST_CAST; return(CXX_CASTS); } 105 "continue" { return(C_CONTINUE); } 106 "default" { return(C_DEFAULT); } 107 "delete" { return(CXX_DELETE); } 108 "do" { return(C_DO); } 109 "double" { return resw(DOUBLE, C_TYPE); } 110 "dynamic_cast" { yylval.intval = DYN_CAST; return(CXX_CASTS); } 111 "else" { return(C_ELSE); } 112 "enum" { notype=1; return(C_ENUM); } 113 "extern" { return resw(EXTERN, C_CLASS); } 114 "float" { return resw(FLOAT, C_TYPE); } 115 "for" { return(C_FOR); } 116 "goto" { notype=1; return(C_GOTO); } 117 "if" { return(C_IF); } 118 "_Imaginary" { return resw(IMAG, C_TYPE); } 119 "inline" { return(C_FUNSPEC); } 120 "int" { return resw(INT, C_TYPE); } 121 "long" { return resw(LONG, C_TYPE); } 122 "namespace" { return(CXX_NAMESPACE); } 123 "new" { notype = 0; return(CXX_NEW); } 124 "register" { return resw(REGISTER, C_CLASS); } 125 "reinterpret_cast" { yylval.intval = REINT_CAST; return(CXX_CASTS); } 126 "restrict" { ; /* just ignore */ } 127 "return" { return(C_RETURN); } 128 "short" { return resw(SHORT, C_TYPE); } 129 "signed" { return resw(SIGNED, C_TYPE); } 130 "sizeof" { return(C_SIZEOF); } 131 "static" { return resw(STATIC, C_CLASS); } 132 "static_cast" { yylval.intval = STATIC_CAST; return(CXX_CASTS); } 133 "struct" { yylval.intval = STNAME; notype=1; return(C_STRUCT); } 134 "switch" { return(C_SWITCH); } 135 "template" { return(CXX_TEMPLATE); } 136 "typedef" { return resw(TYPEDEF, C_CLASS); } 137 "typename" { return(CXX_TYPENAME); } 138 "union" { yylval.intval = UNAME; notype=1; return(C_STRUCT); } 139 "unsigned" { return resw(UNSIGNED, C_TYPE); } 140 "using" { return(CXX_USING); } 141 "void" { return resw(VOID, C_TYPE); } 142 "volatile" { return resw(VOL, C_QUALIFIER); } 143 "while" { return(C_WHILE); } 144 145 {UL}({UL}|{D})* { return namechk(); } 146 0[xX]{H}+{IS}? { yylval.nodep = cvtdig(16); return(C_ICON); } 147 0{D}+{IS}? { yylval.nodep = cvtdig(8); return(C_ICON); } 148 {D}+{IS}? { yylval.nodep = cvtdig(10); return(C_ICON); } 149 L'(\\.|[^\\'])*' { yylval.nodep = wcharcon(); return(C_ICON); } 150 '(\\.|[^\\'])*' { yylval.nodep = charcon(); return(C_ICON); } 151 152 {D}+{E}{FS}? { yylval.nodep = floatcon(yytext); return(C_FCON); } 153 {D}*"."{D}+({E})?{FS}? { yylval.nodep = floatcon(yytext); return(C_FCON); } 154 {D}+"."{D}*({E})?{FS}? { yylval.nodep = floatcon(yytext); return(C_FCON); } 155 0[xX]{H}*"."{H}+{P}{FS}? { yylval.nodep = fhexcon(yytext); return(C_FCON); } 156 0[xX]{H}+"."{P}{FS}? { yylval.nodep = fhexcon(yytext); return(C_FCON); } 157 0[xX]{H}+{P}{FS}? { yylval.nodep = fhexcon(yytext); return(C_FCON); } 158 159 L?\"(\\.|[^\\"])*\" { yylval.strp = yytext; return C_STRING; } 160 161 "..." { return(C_ELLIPSIS); } 162 ">>=" { yylval.intval = RSEQ; return(C_ASOP); } 163 "<<=" { yylval.intval = LSEQ; return(C_ASOP); } 164 "+=" { yylval.intval = PLUSEQ; return(C_ASOP); } 165 "-=" { yylval.intval = MINUSEQ; return(C_ASOP); } 166 "*=" { yylval.intval = MULEQ; return(C_ASOP); } 167 "/=" { yylval.intval = DIVEQ; return(C_ASOP); } 168 "%=" { yylval.intval = MODEQ; return(C_ASOP); } 169 "&=" { yylval.intval = ANDEQ; return(C_ASOP); } 170 "^=" { yylval.intval = EREQ; return(C_ASOP); } 171 "|=" { yylval.intval = OREQ; return(C_ASOP); } 172 ">>" { yylval.intval = RS; return(C_SHIFTOP); } 173 "<<" { yylval.intval = LS; return(C_SHIFTOP); } 174 "++" { yylval.intval = INCR; return(C_INCOP); } 175 "--" { yylval.intval = DECR; return(C_INCOP); } 176 "->" { yylval.intval = STREF; return(C_STROP); } 177 "&&" { yylval.intval = ANDAND; return(C_ANDAND); } 178 "||" { yylval.intval = OROR; return(C_OROR); } 179 "<=" { yylval.intval = LE; return(C_RELOP); } 180 ">=" { yylval.intval = GE; return(C_RELOP); } 181 "==" { yylval.intval = EQ; return(C_EQUOP); } 182 "!=" { yylval.intval = NE; return(C_EQUOP); } 183 "::" { return(CXX_DUALCC); } 184 ";" { notype = 0; return(';'); } 185 ("{"|"<%") { notype = 0; return('{'); } 186 ("}"|"%>") { if (rpole) notype = 1; return('}'); } 187 "," { if (parbal && !inoso) notype = 0; return(','); } 188 ":" { if (doing_init) nodinit--; return(':'); } 189 "=" { return('='); } 190 "(" { parbal++; notype = 0; return('('); } 191 ")" { parbal--; 192 inoso = 0; 193 if (parbal==0) { notype = 0; } 194 if (inattr && parlvl == parbal) 195 inattr = 0; 196 return(')'); } 197 ("["|"<:") { return('['); } 198 ("]"|":>") { return(']'); } 199 "." { yylval.intval = DOT; return(C_STROP); } 200 "&" { return('&'); } 201 "!" { yylval.intval = NOT; return(C_UNOP); } 202 "~" { yylval.intval = COMPL; return(C_UNOP); } 203 "-" { return('-'); } 204 "+" { return('+'); } 205 "*" { if (parbal && notype == 0) notype = 1; return('*'); } 206 "/" { yylval.intval = DIV; return(C_DIVOP); } 207 "%" { yylval.intval = MOD; return(C_DIVOP); } 208 "<" { yylval.intval = LT; return(C_RELOP); } 209 ">" { yylval.intval = GT; return(C_RELOP); } 210 "^" { return('^'); } 211 "|" { return('|'); } 212 "?" { if (doing_init) nodinit++; return('?'); } 213 ^#pragma[ \t].* { pragma(); } 214 ^#ident[ \t].* { control(CPP_IDENT); } 215 ^#line[ \t].* { control(CPP_LINE); } 216 ^#.* { control(CPP_HASH); } 217 218 [ \t\v\f] { } 219 "\n" { ++lineno; STABS_LINE(lineno); } 220 . { /* ignore bad characters */ } 221 222 %% 223 224 int lineno, issyshdr; 225 char *ftitle = "<stdin>"; 226 227 static int 228 namechk(void) 229 { 230 struct symtab *s; 231 int i; 232 233 yylval.strp = addname(yytext); 234 235 while ((i = input()) == ' ' || i == '\t') 236 ; 237 if (i == ':') { 238 if ((i = input()) == ':') 239 return CXX_MORENM; 240 unput(i); 241 if (doing_init && nodinit == 0) 242 return(GCC_DESIG); 243 i = ':'; 244 } 245 unput(i); 246 247 #ifdef GCC_COMPAT 248 if ((i = gcc_keyword(yylval.strp, &yylval.nodep)) > 0) 249 return i; 250 #endif 251 252 if (notype) 253 return(C_NAME); 254 s = lookup(yylval.strp, SNOCREAT); 255 return s && s->sclass == TYPEDEF ? notype=1, C_TYPENAME : C_NAME; 256 } 257 258 int 259 yywrap(void) 260 { 261 if (0) unput(0); /* quiet gcc */ 262 return(1); 263 } 264 265 int 266 resw(TWORD t, int rv) 267 { 268 if (inattr) { 269 yylval.strp = addname(yytext); 270 return C_NAME; 271 } 272 273 switch (rv) { 274 case C_CLASS: 275 yylval.nodep = block(CLASS, NIL, NIL, t, 0, 0); 276 return rv; 277 278 case C_QUALIFIER: 279 yylval.nodep = block(QUALIFIER, NIL, NIL, 0, 0, 0); 280 yylval.nodep->n_qual = t; 281 return rv; 282 283 case C_TYPE: 284 yylval.nodep = mkty(t, 0, 0); 285 notype=1; 286 return(rv); 287 288 default: 289 cerror("resw"); 290 } 291 return 0; 292 } 293 294 #ifndef SOFTFLOAT 295 296 static long double 297 typround(long double dc, char *e, TWORD *tw) 298 { 299 int im = 0; 300 301 *tw = DOUBLE; 302 for (; *e; e++) { 303 switch (*e) { 304 case 'f': 305 case 'F': 306 *tw = FLOAT; 307 dc = (float)dc; 308 break; 309 case 'l': 310 case 'L': 311 *tw = LDOUBLE; 312 break; 313 case 'i': 314 case 'I': 315 im = 1; 316 break; 317 } 318 } 319 if (*tw == DOUBLE) 320 dc = (double)dc; 321 #ifndef NO_COMPLEX 322 if (im) 323 *tw += (FIMAG-FLOAT); 324 #endif 325 return dc; 326 } 327 328 /* 329 * XXX floatcon() and fhexcon() should be in support libraries for 330 * the target floating point. 331 */ 332 static NODE * 333 f2(char *str) 334 { 335 TWORD tw; 336 NODE *p; 337 long double dc; 338 char *eptr; 339 340 #ifdef HAVE_STRTOLD 341 dc = strtold(str, &eptr); /* XXX - avoid strtod() */ 342 #else 343 dc = strtod(str, &eptr); /* XXX - avoid strtod() */ 344 #endif 345 dc = typround(dc, eptr, &tw); 346 p = block(FCON, NIL, NIL, tw, 0, 0); 347 p->n_dcon = tmpalloc(sizeof(union flt));; 348 ((union flt *)p->n_dcon)->fp = dc; 349 return p; 350 } 351 352 NODE * 353 floatcon(char *s) 354 { 355 return f2(s); 356 } 357 358 static int 359 h2n(int ch) 360 { 361 if (ch >= '0' && ch <= '9') 362 return ch - '0'; 363 if (ch >= 'a' && ch <= 'f') 364 return ch - 'a' + 10; 365 return ch - 'A' + 10; 366 367 } 368 369 NODE * 370 fhexcon(char *c) 371 { 372 TWORD tw; 373 char *ep; 374 long double d; 375 int i, ed; 376 NODE *p; 377 378 d = 0.0; 379 ed = 0; 380 c+= 2; /* skip 0x */ 381 #define FSET(n) { d *= 2; if (i & n) d += 1.0; } 382 for (; *c != '.' && *c != 'p' && *c != 'P'; c++) { 383 i = h2n(*c); 384 FSET(8); FSET(4); FSET(2); FSET(1); 385 } 386 if (*c != '.' && *c != 'p' && *c != 'P') 387 cerror("fhexcon"); 388 if (*c == '.') { 389 c++; 390 for (; *c != 'p' && *c != 'P'; c++) { 391 i = h2n(*c); 392 FSET(8); FSET(4); FSET(2); FSET(1); 393 ed -= 4; 394 } 395 } 396 if (*c != 'P' && *c != 'p') 397 cerror("fhexcon2"); 398 c++; 399 ed += strtol(c, &ep, 10); 400 401 /* avoid looping in vain. Idea from Fred J. Tydeman */ 402 if (ed > 32769) ed = 32769; 403 if (ed < -32769) ed = -32769; 404 405 while (ed > 0) 406 d *= 2, ed--; 407 while (ed < 0) 408 d /= 2, ed++; 409 d = typround(d, ep, &tw); 410 p = block(FCON, NIL, NIL, tw, 0, 0); 411 p->n_dcon = tmpalloc(sizeof(union flt));; 412 ((union flt *)p->n_dcon)->fp = d; 413 return p; 414 } 415 #endif 416 417 unsigned int 418 esccon(char **sptr) 419 { 420 char *wr = *sptr; 421 char *owr; 422 char c; 423 unsigned int val; 424 int wsz = 4, esccon_warn = 1; 425 426 switch (*wr++) { 427 case 'a': val = '\a'; break; 428 case 'b': val = '\b'; break; 429 case 'f': val = '\f'; break; 430 case 'n': val = '\n'; break; 431 case 'r': val = '\r'; break; 432 case 't': val = '\t'; break; 433 case 'v': val = '\v'; break; 434 case '\"': val = '\"'; break; 435 case 'x': val = strtoul(wr, &wr, 16); break; 436 /* ISO/IEC 9099:1999 (E) 6.4.3 */ 437 case 'U'|(char)0x80: 438 esccon_warn = 0; 439 /* FALLTHROUGH */ 440 case 'U': 441 wsz = 8; 442 /* FALLTHROUGH */ 443 case 'u': 444 owr = wr; 445 while (wr < (owr + wsz)) 446 if (*wr == '\0') 447 break; 448 else 449 ++wr; 450 if (wr != (owr + wsz)) { 451 /* incomplete */ 452 val = strtoul(owr, &wr, 16); 453 } else { 454 c = owr[wsz]; 455 owr[wsz] = '\0'; /* prevent it from reading too much */ 456 val = strtoul(owr, &wr, 16); 457 owr[wsz] = c; 458 } 459 if (wr != (owr + wsz)) 460 werror("incomplete universal character name"); 461 if (wsz == 4) 462 val &= 0xFFFF; 463 if (esccon_warn && ((val >= 0xD800 && val <= 0xDFFF) || 464 (val < 0xA0 && val != 0x24 && val != 0x40 && val != 0x60))) 465 werror("invalid universal character name %04X", val); 466 break; 467 case '0': case '1': case '2': case '3': case '4': 468 case '5': case '6': case '7': 469 val = wr[-1] - '0'; 470 if (*wr >= '0' && *wr <= '7') { 471 val = (val << 3) + (*wr++ - '0'); 472 if (*wr >= '0' && *wr <= '7') 473 val = (val << 3) + (*wr++ - '0'); 474 } 475 break; 476 default: val = wr[-1]; 477 } 478 *sptr = wr; 479 return val; 480 } 481 482 NODE * 483 cvtdig(int radix) 484 { 485 NODE *p; 486 TWORD otype, ntype; 487 unsigned long long v; 488 char *ch = yytext; 489 int n, numl, numu; 490 491 if (radix == 16) 492 ch += 2; /* Skip 0x */ 493 494 v = 0; 495 while ((*ch >= '0' && *ch <= '9') || (*ch >= 'a' && *ch <= 'f') || 496 (*ch >= 'A' && *ch <= 'F')) { 497 v *= radix; 498 n = *ch; 499 n = (n <= '9' ? n - '0' : (n > 'F' ? n - 'a' : n - 'A') + 10); 500 ch++; 501 v += n; 502 } 503 /* Parse trailing chars */ 504 ntype = INT; 505 numl = numu = 0; 506 for (n = 0; n < 3; n++) { 507 if (*ch == 0) 508 break; 509 if ((*ch == 'l' || *ch == 'L') && numl < 2) 510 ntype+=2, numl++; 511 else if ((*ch == 'u' || *ch == 'U') && numu < 1) 512 ntype = ENUNSIGN(ntype), numu++; 513 else 514 break; 515 ch++; 516 } 517 if (*ch) 518 uerror("constant has too many '%c'", *ch); 519 520 otype = ntype; 521 switch (ntype) { 522 case INT: 523 case LONG: 524 case LONGLONG: 525 if (radix == 10) { 526 if (otype == LONGLONG) 527 break; 528 if (v > MAX_LONG) { 529 ntype = LONGLONG; 530 if (otype == LONG) 531 break; 532 } else if (v > MAX_INT) 533 ntype = LONG; 534 } else { 535 if (v > MAX_LONGLONG) { 536 ntype = ULONGLONG; 537 if (otype == LONGLONG) 538 break; 539 } else if (v > MAX_ULONG) { 540 ntype = LONGLONG; 541 } else if (v > MAX_LONG) { 542 ntype = ULONG; 543 if (otype == LONG) 544 break; 545 } else if (v > MAX_UNSIGNED) { 546 ntype = LONG; 547 } else if (v > MAX_INT) 548 ntype = UNSIGNED; 549 } 550 break; 551 case UNSIGNED: 552 case ULONG: 553 if (v > MAX_ULONG) { 554 ntype = ULONGLONG; 555 if (otype == ULONG) 556 break; 557 } else if (v > MAX_UNSIGNED) 558 ntype = ULONG; 559 break; 560 } 561 562 ntype = ctype(ntype); 563 p = xbcon(v, NULL, ntype); 564 ASGLVAL(p->n_slval, v); 565 566 return p; 567 } 568 569 /* 570 * Convert a character constant to an integer. 571 */ 572 NODE * 573 charcon(void) 574 { 575 int lastcon = 0; 576 int val, i = 0; 577 char *pp = yytext; 578 579 pp++; /* skip ' */ 580 while (*pp != '\'') { 581 if (*pp++ == '\\') { 582 val = esccon(&pp); 583 } else 584 val = pp[-1]; 585 makecc(val, i); 586 i++; 587 } 588 589 if (i == 0) 590 uerror("empty character constant"); 591 else if (i > (SZINT/SZCHAR) || (i>1)) 592 werror("too many characters in character constant"); 593 return bcon(lastcon); 594 } 595 596 NODE * 597 wcharcon(void) 598 { 599 unsigned int lastcon = 0; 600 unsigned int val, i = 0; 601 char *pp = yytext; 602 603 pp++; /* skip L */ 604 pp++; /* skip ' */ 605 while (*pp != '\'') { 606 if (*pp++ == '\\') { 607 val = esccon(&pp); 608 } else 609 val = pp[-1]; 610 #if WCHAR_SIZE == 2 611 lastcon = (lastcon << 16) | (val & 0xFFFF); 612 #else 613 lastcon = val; 614 #endif 615 i++; 616 } 617 618 if (i == 0) 619 uerror("empty wide-character constant"); 620 else if (i > 1) 621 werror("too many characters in wide-character constant"); 622 return xbcon(lastcon, NULL, ctype(UNSIGNED)); 623 } 624 625 void 626 control(int t) 627 { 628 char *wr = yytext; 629 char *eptr; 630 int val; 631 632 wr++; /* Skip initial '#' */ 633 switch (t) { 634 case CPP_IDENT: 635 return; /* Just skip these for now. */ 636 637 case CPP_LINE: 638 wr += 4; 639 /* FALLTHROUGH */ 640 case CPP_HASH: 641 val = strtol(wr, &eptr, 10); 642 if (wr == eptr) /* Illegal string */ 643 goto bad; 644 wr = eptr; 645 lineno = val - 1; 646 while (*wr && *wr != '\"') 647 wr++; 648 if (*wr == 0) 649 return; 650 if (*wr++ != '\"') 651 goto bad; 652 eptr = wr; 653 while (*wr && *wr != '\"') 654 wr++; 655 if (*wr != '\"') 656 goto bad; 657 *wr = 0; 658 ftitle = addstring(eptr); 659 #ifdef STABS 660 if (gflag) 661 stabs_file(ftitle); 662 #endif 663 } 664 return; 665 bad: 666 werror("%s: illegal control", yytext); 667 } 668 669 int pragma_allpacked; 670 int pragma_packed, pragma_aligned; 671 char *pragma_renamed; 672 673 static int 674 pragmas_weak(char *str) 675 { 676 struct symtab *sp; 677 char *s1, *s2; 678 679 if ((s1 = pragtok(NULL)) == NULL) 680 return 1; 681 if ((s2 = pragtok(NULL)) == NULL) { 682 sp = lookup(addname(s1), SNORMAL); 683 #ifdef GCC_COMPAT 684 sp->sap = attr_add(sp->sap, gcc_attr_parse(bdty(NAME, "weak"))); 685 #else 686 sp->sap = 0; 687 #endif 688 } else if (*s2 == '=') { 689 if ((s2 = pragtok(NULL)) == NULL) 690 return 1; 691 sp = lookup(addname(s2), SNORMAL); 692 #ifdef GCC_COMPAT 693 sp->sap = attr_add(sp->sap, gcc_attr_parse(bdty(CALL, 694 bdty(NAME, "aliasweak"), bdty(STRING, s1, 0)))); 695 #else 696 sp->sap = NULL; 697 #endif 698 } else 699 return 1; 700 return 0; 701 } 702 703 char *pragstore; 704 705 /* trivial tokenizer for pragmas */ 706 #define ps pragstore 707 char * 708 pragtok(char *sin) 709 { 710 static char ss[2]; 711 char *rv; 712 713 if (sin) 714 ps = sin; 715 716 for (; isspace((int)*ps); ps++) 717 ; 718 if (*ps == 0) 719 return NULL; 720 for (rv = ps; isalpha((int)*ps) || isdigit((int)*ps) || *ps == '_'; ps++) 721 ; 722 ss[0] = *ps; 723 if (rv == ps) { 724 rv = ss, ps++; 725 } else { 726 *ps = 0; 727 rv = tmpstrdup(rv); 728 *ps = ss[0]; 729 } 730 return rv; 731 } 732 733 /* return 1 on error */ 734 int 735 eat(int ch) 736 { 737 char *s = pragtok(0); 738 return (s == 0 || *s != ch); 739 } 740 741 static int 742 pragmas_alpack(char *t) 743 { 744 char *s; 745 int ap; 746 747 ap = (s = pragtok(0)) ? atoi(s) : 1; 748 if (strcmp(t, "packed") == 0) 749 pragma_packed = ap; 750 else 751 pragma_aligned = ap; 752 return 0; 753 } 754 755 756 /* 757 * Packing control. 758 * still missing push/pop. 759 */ 760 static int 761 pragmas_pack(char *t) 762 { 763 char *s; 764 765 if (eat('(')) 766 return 1; 767 s = pragtok(0); 768 if (*s == ')') 769 return pragma_allpacked = 0; 770 771 if (*s < '0' || *s > '9') /* no number */ 772 return 1; 773 pragma_allpacked = atoi(s); 774 return eat(')'); 775 } 776 777 static int 778 pragmas_renamed(char *t) 779 { 780 char *f = pragtok(0); 781 782 if (f == 0) 783 return 1; 784 pragma_renamed = newstring(f, strlen(f)); 785 return 0; 786 } 787 788 static int 789 pragmas_stdc(char *t) 790 { 791 return 0; /* Just ignore */ 792 } 793 794 struct pragmas { 795 char *name; 796 int (*fun)(char *); 797 } pragmas[] = { 798 { "pack", pragmas_pack }, 799 { "packed", pragmas_alpack }, 800 { "aligned", pragmas_alpack }, 801 { "rename", pragmas_renamed }, 802 #ifdef GCC_COMPAT 803 { "GCC", pragmas_gcc }, 804 #endif 805 { "STDC", pragmas_stdc }, 806 { "weak", pragmas_weak }, 807 { "ident", NULL }, 808 { 0 }, 809 }; 810 811 /* 812 * got a full pragma line. Split it up here. 813 */ 814 static void 815 pragma(void) 816 { 817 struct pragmas *p; 818 char *t, *pt; 819 820 if ((t = pragtok(&yytext[7])) != NULL) { 821 pt = ps; 822 for (p = pragmas; p->name; p++) { 823 if (strcmp(t, p->name) == 0) { 824 if (p->fun && (*p->fun)(t)) 825 uerror("bad argument to #pragma"); 826 return; 827 } 828 } 829 ps = pt; 830 if (mypragma(t)) 831 return; 832 } 833 warner(Wunknown_pragmas, t, ps); 834 } 835 836 void 837 cunput(char c) 838 { 839 unput(c); 840 } 841