Quick Search:

Mode

Context

Displaying the whole file. None | Less | More | Full

Other Diffs

Ignore

Blank Lines Whitespace: Expand:

Diff

1.48
 
1.49
 
MAIN:ragge:20110226063207
 
token.c
_>11 /*      $Id$    */
 22 
 33 /*
 44  * Copyright (c) 2004,2009 Anders Magnusson. All rights reserved.
 55  *
 66  * Redistribution and use in source and binary forms, with or without
 77  * modification, are permitted provided that the following conditions
 88  * are met:
 99  * 1. Redistributions of source code must retain the above copyright
 1010  *    notice, this list of conditions and the following disclaimer.
 1111  * 2. Redistributions in binary form must reproduce the above copyright
 1212  *    notice, this list of conditions and the following disclaimer in the
 1313  *    documentation and/or other materials provided with the distribution.
 1414  *
 1515  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 1616  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 1717  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 1818  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 1919  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 2020  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 2121  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 2222  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 2323  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 2424  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 2525  */
 2626 
 2727 /*
 2828  * Tokenizer for the C preprocessor.
 2929  * There are three main routines:
 3030  *      - fastscan() loops over the input stream searching for magic
 3131  *              characters that may require actions.
 3232  *      - sloscan() tokenize the input stream and returns tokens.
 3333  *              It may recurse into itself during expansion.
 3434  *      - yylex() returns something from the input stream that
 3535  *              is suitable for yacc.
 3636  *
 3737  *      Other functions of common use:
 3838  *      - inpch() returns a raw character from the current input stream.
 3939  *      - inch() is like inpch but \\n and trigraphs are expanded.
 4040  *      - unch() pushes back a character to the input stream.
 4141  */
 4242 
 4343 #include "config.h"
 4444 
 4545 #include <stdlib.h>
 4646 #include <string.h>
 4747 #include <ctype.h>
 4848 #ifdef HAVE_UNISTD_H
 4949 #include <unistd.h>
 5050 #endif
 5151 #include <fcntl.h>
 5252 #include <errno.h>
 5353 
 5454 #include "compat.h"
 5555 #include "cpp.h"
 5656 #include "y.tab.h"
 5757 
 5858 static void cvtdig(int rad);
 5959 static int charcon(usch *);
 6060 static void elsestmt(void);
 6161 static void ifdefstmt(void);
 6262 static void ifndefstmt(void);
 6363 static void endifstmt(void);
 6464 static void ifstmt(void);
 6565 static void cpperror(void);
 6666 static void pragmastmt(void);
 6767 static void undefstmt(void);
 6868 static void cppwarning(void);
 6969 static void elifstmt(void);
 7070 static void badop(const char *);
 7171 static int chktg(void);
 7272 static void ppdir(void);
 7373 void  include(void);
 7474 void  include_next(void);
 7575 void  define(void);
 7676 static int inpch(void);
 7777 
 7878 extern int yyget_lineno (void);
 7979 extern void yyset_lineno (int);
 8080 
 8181 static int inch(void);
 8282 
 8383 int inif;
 8484 extern int dflag;
 8585 
 8686 #define PUTCH(ch) if (!flslvl) putch(ch)
 8787 /* protection against recursion in #include */
 8888 #define MAX_INCLEVEL    100
 8989 static int inclevel;
 9090 
 9191 /* get next character unaltered */
 9292 #define NXTCH() (ifiles->curptr < ifiles->maxread ? *ifiles->curptr++ : inpch())
 9393 
 9494 usch yytext[CPPBUF];
 9595 
 9696 char spechr[256] = {
 9797         0,      0,      0,      0,      C_SPECC_SPEC0,      0,
 9898         0,      C_WSNLC_SPEC|C_WSNL,  0,
 9999         0,      C_WSNL0,      0,
 100100         0,      0,      0,      0,      0,      0,      0,      0,
 101101         0,      0,      0,      0,      0,      0,      0,      0,
 102102 
 103103         C_WSNLC_2,    C_SPEC0,      0,      0,      C_2,    C_SPEC,
 104104         0,      0,      0,      C_2,    0,      C_2,    0,      C_SPEC|C_2,
 105105         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 106106         C_I,    C_I,    0,      0,      C_2,    C_2,    C_2,    C_SPEC,
 107107 
 108108         0,      C_I,    C_I,    C_I,    C_I,    C_I|C_EP, C_I,  C_I,
 109109         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 110110         C_I|C_EP, C_I,  C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 111111         C_I,    C_I,    C_I,    0,      C_I,    0,      0,      C_I,
 112112 
 113113         0,      C_I,    C_I,    C_I,    C_I,    C_I|C_EP, C_I,  C_I,
 114114         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 115115         C_I|C_EP, C_I,  C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 116116         C_I,    C_I,    C_I,    0,      C_2,    0,      0,      0,
 117117 
 118118 };
 119119 
 120120 /*
 121121  * No-replacement array.  If a macro is found and exists in this array
 122122  * then no replacement shall occur.  This is a stack.
 123123  */
 124124 struct symtab *norep[RECMAX];   /* Symbol table index table */
 125125 int norepptr = 1;                       /* Top of index table */
 126126 unsigned short bptr[RECMAX];    /* currently active noexpand macro stack */
 127127 int bidx;                       /* Top of bptr stack */
 128128 
 129129 static void
 130130 unch(int c)
 131131 {
 132132                 
 133133         --ifiles->curptr;
 134134         if (ifiles->curptr < ifiles->bbuf)
 135135                 error("pushback buffer full");
 136136         *ifiles->curptr = (usch)c;
 137137 }
 138138 
 139139 static int
 140140 eatcmnt(void)
 141141 {
 142142         int ch;
 143143 
 144144         if (Cflag) { PUTCH('/'); PUTCH('*'); }
 145145         for (;;) {
 146146                 ch = inch();
 147147                 if (ch == '\n') {
 148148                         ifiles->lineno++;
 149149                         PUTCH('\n');
 150150                 }
 151151                 if (ch == -1)
 152152                         return -1;
 153153                 if (ch == '*') {
 154154                         ch = inch();
 155155                         if (ch == '/') {
 156156                                 if (Cflag) {
 157157                                         PUTCH('*');
 158158                                         PUTCH('/');
 159159                                 } else
 160160                                         PUTCH(' ');
 161161                                 break;
 162162                         }
 163163                         unch(ch);
 164164                         ch = '*';
 165165                 }
 166166                 if (Cflag) PUTCH(ch);
 167167         }
 168168         return 0;
 169169 }
 170170 
 171171 /*
 172172  * Scan quickly the input file searching for:
 173173  *      - '#' directives
 174174  *      - keywords (if not flslvl)
 175175  *      - comments
 176176  *
 177177  *      Handle strings, numbers and trigraphs with care.
 178178  *      Only data from pp files are scanned here, never any rescans.
 179179  *      TODO: Only print out strings before calling other functions.
 180180  */
 181181 static void
 182182 fastscan(void)
 183183 {
 184184         struct symtab *nl;
 185185         int ch, i, ccnt, onemore;
<> 186+        usch *cp;
186187 
 187188         goto run;
 188189         for (;;) {
 189190                 ch = NXTCH();
 190191 xloop:          if (ch == -1)
 191192                         return;
 192193                 if (dflag>1)
 193194                         printf("fastscan ch %d (%c)\n", ch, ch > 31 ? ch : '@');
 194195                 if ((spechr[ch] & C_SPEC) == 0) {
 195196                         PUTCH(ch);
 196197                         continue;
 197198                 }
 198199                 switch (ch) {
 199200                 case EBLOCK:
 200201                 case WARN:
 201202                 case CONC:
 202203                         error("bad char passed");
 203204                         break;
 204205 
 205206                 case '/': /* Comments */
 206207                         if ((ch = inch()) == '/') {
 207208 cppcmt:                         if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
 208209                                 do {
 209210                                         if (Cflag) PUTCH(ch);
 210211                                         ch = inch();
 211212                                 } while (ch != -1 && ch != '\n');
 212213                                 goto xloop;
 213214                         } else if (ch == '*') {
 214215                                 if (eatcmnt())
 215216                                         return;
 216217                         } else {
 217218                                 PUTCH('/');
 218219                                 goto xloop;
 219220                         }
 220221                         break;
 221222 
 222223                 case '?'/* trigraphs */
 223224                         if ((ch = chktg()))
 224225                                 goto xloop;
 225226                         PUTCH('?');
 226227                         break;
 227228 
 228229                 case '\\':
 229230                         if ((ch = NXTCH()) == '\n') {
 230231                                 ifiles->lineno++;
 231232                                 continue;
 232233                         } else {
 233234                                 PUTCH('\\');
 234235                         }
 235236                         goto xloop;
 236237 
 237238                 case '\n': /* newlines, for pp directives */
 238239                         ifiles->lineno++;
 239240                         do {
 240241                                 PUTCH(ch);
 241242 run:                            ch = NXTCH();
 242243                                 if (ch == '/') {
 243244                                         ch = NXTCH();
 244245                                         if (ch == '/')
 245246                                                 goto cppcmt;
 246247                                         if (ch == '*') {
 247248                                                 if (eatcmnt())
 248249                                                         return;
 249250                                                 goto run;
 250251                                         }
 251252                                         unch(ch);
 252253                                         ch = '/';
 253254                                 }
 254255                         } while (ch == ' ' || ch == '\t');
 255256                         if (ch == '#') {
 256257                                 ppdir();
 257258                                 continue;
 258259                         } else if (ch == '%') {
 259260                                 ch = NXTCH();
 260261                                 if (ch == ':') {
 261262                                         ppdir();
 262263                                         continue;
 263264                                 } else {
 264265                                         unch(ch);
 265266                                         ch = '%';
 266267                                 }
 267268                         }
 268269                         goto xloop;
 269270 
 270271                 case '\"': /* strings */
 271272 str:                    PUTCH(ch);
 272273                         while ((ch = inch()) != '\"') {
 273274                                         PUTCH(ch);
 274275                                 if (ch == '\\') {
 275276                                         ch = inch();
 276277                                         PUTCH(ch);
 277278                                 }
 278279                                 if (ch < 0)
 279280                                         return;
 280281                         }
 281282                         PUTCH(ch);
 282283                         break;
 283284 
 284285                 case '.'/* for pp-number */
 285286                         PUTCH(ch);
 286287                         ch = NXTCH();
 287288                         if (ch < '0' || ch > '9')
 288289                                 goto xloop;
 289290                         /* FALLTHROUGH */
 290291                 case '0': case '1': case '2': case '3': case '4':
 291292                 case '5': case '6': case '7': case '8': case '9':
 292293                         do {
 293294                                 PUTCH(ch);
 294295 nxt:                            ch = NXTCH();
 295296                                 if (ch == '\\') {
 296297                                         ch = NXTCH();
 297298                                         if (ch == '\n') {
 298299                                                 goto nxt;
 299300                                         } else {
 300301                                                 unch(ch);
 301302                                                 ch = '\\';
 302303                                         }
 303304                                 }
 304305                                 if (spechr[ch] & C_EP) {
 305306                                         PUTCH(ch);
 306307                                         ch = NXTCH();
 307308                                         if (ch == '-' || ch == '+')
 308309                                                 continue;
 309310                                 }
 310311                         } while ((spechr[ch] & C_ID) || (ch == '.'));
 311312                         goto xloop;
 312313 
 313314                 case '\'': /* character literal */
 314315 con:                    PUTCH(ch);
 315316                         if (tflag)
 316317                                 continue; /* character constants ignored */
 317318                         while ((ch = NXTCH()) != '\'') {
 318319                                 PUTCH(ch);
 319320                                 if (ch == '\\') {
 320321                                         ch = NXTCH();
 321322                                         PUTCH(ch);
 322323                                 } else if (ch < 0)
 323324                                         return;
 324325                                 else if (ch == '\n')
 325326                                         goto xloop;
 326327                         }
 327328                         PUTCH(ch);
 328329                         break;
 329330 
 330331                 case 'L':
 331332                         ch = NXTCH();
 332333                         if (ch == '\"') {
 333334                                 PUTCH('L');
 334335                                 goto str;
 335336                         }
 336337                         if (ch == '\'') {
 337338                                 PUTCH('L');
 338339                                 goto con;
 339340                         }
 340341                         unch(ch);
 341342                         ch = 'L';
 342343                         /* FALLTHROUGH */
 343344                 default:
 344345                         if ((spechr[ch] & C_ID) == 0)
 345346                                 error("fastscan");
 346347                         if (flslvl) {
 347348                                 while (spechr[ch] & C_ID)
 348349                                         ch = NXTCH();
 349350                                 goto xloop;
 350351                         }
 351352                         onemore = i = ccnt = 0;
 352353                         do {
 353354                                 yytext[i++] = (usch)ch;
 354355                                 ch = NXTCH();
 355356                                 if (ch == '\\') {
 356357                                         ch = NXTCH();
 357358                                         if (ch != '\n') {
 358359                                                 unch('\n');
 359360                                                 ch = '\\';
 360361                                         } else {
 361362                                                 ifiles->lineno++;
 362363                                                 ch = NXTCH();
 363364                                         }
 364365                                 }
 365366                                 if (ch < 0)
 366367                                         return;
 367368                         } while (spechr[ch] & C_ID);
 368369 
 369370                         yytext[i] = 0;
 370371                         unch(ch);
 371372 
<> 373+                        cp = stringbuf;
372374                         if ((nl = lookup((usch *)yytext, FIND)) && kfind(nl)) {
 373375                                 putstr(stringbuf);
 374376                         } else
 375377                                 putstr((usch *)yytext);
<> 378+                        stringbuf = cp;
376379 
 377380                         break;
 378381                 }
 379382         }
 380383 }
 381384 
 382385 int
 383386 sloscan()
 384387 {
 385388         int ch;
 386389         int yyp;
 387390 
 388391 zagain:
 389392         yyp = 0;
 390393         ch = inch();
 391394         yytext[yyp++] = (usch)ch;
 392395         switch (ch) {
 393396         case -1:
 394397                 return 0;
 395398         case '\n':
 396399                 /* sloscan() never passes \n, that's up to fastscan() */
 397400                 unch(ch);
 398401                 goto yyret;
 399402 
 400403         case '\r': /* Ignore CR's */
 401404                 yyp = 0;
 402405                 break;
 403406 
 404407         case '0': case '1': case '2': case '3': case '4': case '5':
 405408         case '6': case '7': case '8': case '9':
 406409                 /* readin a "pp-number" */
 407410 ppnum:          for (;;) {
 408411                         ch = inch();
 409412                         if (spechr[ch] & C_EP) {
 410413                                 yytext[yyp++] = (usch)ch;
 411414                                 ch = inch();
 412415                                 if (ch == '-' || ch == '+') {
 413416                                         yytext[yyp++] = (usch)ch;
 414417                                 } else
 415418                                         unch(ch);
 416419                                 continue;
 417420                         }
 418421                         if ((spechr[ch] & C_ID) || ch == '.') {
 419422                                 yytext[yyp++] = (usch)ch;
 420423                                 continue;
 421424                         }
 422425                         break;
 423426                 }
 424427                 unch(ch);
 425428                 yytext[yyp] = 0;
 426429 
 427430                 return NUMBER;
 428431 
 429432         case '\'':
 430433 chlit:          
 431434                 for (;;) {
 432435                         if ((ch = inch()) == '\\') {
 433436                                 yytext[yyp++] = (usch)ch;
 434437                                 yytext[yyp++] = (usch)inch();
 435438                                 continue;
 436439                         } else if (ch == '\n') {
 437440                                 /* not a constant */
 438441                                 while (yyp > 1)
 439442                                         unch(yytext[--yyp]);
 440443                                 ch = '\'';
 441444                                 goto any;
 442445                         } else
 443446                                 yytext[yyp++] = (usch)ch;
 444447                         if (ch == '\'')
 445448                                 break;
 446449                 }
 447450                 yytext[yyp] = 0;
 448451 
 449452                 return (NUMBER);
 450453 
 451454         case ' ':
 452455         case '\t':
 453456                 while ((ch = inch()) == ' ' || ch == '\t')
 454457                         yytext[yyp++] = (usch)ch;
 455458                 unch(ch);
 456459                 yytext[yyp] = 0;
 457460                 return(WSPACE);
 458461 
 459462         case '/':
 460463                 if ((ch = inch()) == '/') {
 461464                         do {
 462465                                 yytext[yyp++] = (usch)ch;
 463466                                 ch = inch();
 464467                         } while (ch && ch != '\n');
 465468                         yytext[yyp] = 0;
 466469                         unch(ch);
 467470                         goto zagain;
 468471                 } else if (ch == '*') {
 469472                         int c, wrn;
 470473                         extern int readmac;
 471474 
 472475                         if (Cflag && !flslvl && readmac) {
 473476                                 unch(ch);
 474477                                 yytext[yyp] = 0;
 475478                                 return CMNT;
 476479                         }
 477480 
 478481                         wrn = 0;
 479482                 more:   while ((c = inch()) && c != '*') {
 480483                                 if (c == '\n')
 481484                                         putch(c), ifiles->lineno++;
 482485                                 else if (c == EBLOCK) {
 483486                                         (void)inch();
 484487                                         (void)inch();
 485488                                 } else if (c == 1) /* WARN */
 486489                                         wrn = 1;
 487490                         }
 488491                         if (c == 0)
 489492                                 return 0;
 490493                         if ((c = inch()) && c != '/') {
 491494                                 unch(c);
 492495                                 goto more;
 493496                         }
 494497                         if (c == 0)
 495498                                 return 0;
 496499                         if (!tflag && !Cflag && !flslvl)
 497500                                 unch(' ');
 498501                         if (wrn)
 499502                                 unch(1);
 500503                         goto zagain;
 501504                 }
 502505                 unch(ch);
 503506                 ch = '/';
 504507                 goto any;
 505508 
 506509         case '.':
 507510                 ch = inch();
 508511                 if (isdigit(ch)) {
 509512                         yytext[yyp++] = (usch)ch;
 510513                         goto ppnum;
 511514                 } else {
 512515                         unch(ch);
 513516                         ch = '.';
 514517                 }
 515518                 goto any;
 516519 
 517520         case '\"':
 518521                 if (tflag)
 519522                         goto any;
 520523         strng:
 521524                 for (;;) {
 522525                         if ((ch = inch()) == '\\') {
 523526                                 yytext[yyp++] = (usch)ch;
 524527                                 yytext[yyp++] = (usch)inch();
 525528                                 continue;
 526529                         } else
 527530                                 yytext[yyp++] = (usch)ch;
 528531                         if (ch == '\"')
 529532                                 break;
 530533                 }
 531534                 yytext[yyp] = 0;
 532535                 return(STRING);
 533536 
 534537         case 'L':
 535538                 if ((ch = inch()) == '\"' && !tflag) {
 536539                         yytext[yyp++] = (usch)ch;
 537540                         goto strng;
 538541                 } else if (ch == '\'' && !tflag) {
 539542                         yytext[yyp++] = (usch)ch;
 540543                         goto chlit;
 541544                 }
 542545                 unch(ch);
 543546                 /* FALLTHROUGH */
 544547 
 545548         /* Yetch, all identifiers */
 546549         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
 547550         case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
 548551         case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
 549552         case 's': case 't': case 'u': case 'v': case 'w': case 'x':
 550553         case 'y': case 'z':
 551554         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
 552555         case 'G': case 'H': case 'I': case 'J': case 'K':
 553556         case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
 554557         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
 555558         case 'Y': case 'Z':
 556559         case '_': /* {L}({L}|{D})* */
 557560 
 558561                 /* Special hacks */
 559562                 for (;;) { /* get chars */
 560563                         ch = inch();
 561564                         if (isalpha(ch) || isdigit(ch) || ch == '_') {
 562565                                 yytext[yyp++] = (usch)ch;
 563566                         } else {
 564567                                 unch(ch);
 565568                                 break;
 566569                         }
 567570                 }
 568571                 yytext[yyp] = 0; /* need already string */
 569572                 /* end special hacks */
 570573 
 571574                 return IDENT;
 572575         default:
 573576         any:
 574577                 yytext[yyp] = 0;
 575578                 return yytext[0];
 576579 
 577580         } /* endcase */
 578581         goto zagain;
 579582 
 580583 yyret:
 581584         yytext[yyp] = 0;
 582585         return ch;
 583586 }
 584587 
 585588 int
 586589 yylex()
 587590 {
 588591         static int ifdef, noex;
 589592         struct symtab *nl;
 590593         int ch, c2;
 591594 
 592595         while ((ch = sloscan()) == WSPACE)
 593596                 ;
 594597         if (ch < 128 && spechr[ch] & C_2)
 595598                 c2 = inpch();
 596599         else
 597600                 c2 = 0;
 598601 
 599602 #define C2(a,b,c) case a: if (c2 == b) return c; break
 600603         switch (ch) {
 601604         C2('=', '=', EQ);
 602605         C2('!', '=', NE);
 603606         C2('|', '|', OROR);
 604607         C2('&', '&', ANDAND);
 605608         case '<':
 606609                 if (c2 == '<') return LS;
 607610                 if (c2 == '=') return LE;
 608611                 break;
 609612         case '>':
 610613                 if (c2 == '>') return RS;
 611614                 if (c2 == '=') return GE;
 612615                 break;
 613616         case '+':
 614617         case '-':
 615618                 if (ch == c2)
 616619                         badop("");
 617620                 break;
 618621 
 619622         case '/':
 620623                 if (Cflag == 0 || c2 != '*')
 621624                         break;
 622625                 /* Found comment that need to be skipped */
 623626                 for (;;) {
 624627                         ch = inpch();
 625628                 c1:     if (ch != '*')
 626629                                 continue;
 627630                         if ((ch = inpch()) == '/')
 628631                                 break;
 629632                         goto c1;
 630633                 }
 631634                 return yylex();
 632635 
 633636         case NUMBER:
 634637                 if (yytext[0] == '\'') {
 635638                         yylval.node.op = NUMBER;
 636639                         yylval.node.nd_val = charcon((usch *)yytext);
 637640                 } else
 638641                         cvtdig(yytext[0] != '0' ? 10 :
 639642                             yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
 640643                 return NUMBER;
 641644 
 642645         case IDENT:
 643646                 if (strcmp((char *)yytext, "defined") == 0) {
 644647                         ifdef = 1;
 645648                         return DEFINED;
 646649                 }
 647650                 nl = lookup((usch *)yytext, FIND);
 648651                 if (ifdef) {
 649652                         yylval.node.nd_val = nl != NULL;
 650653                         ifdef = 0;
 651654                 } else if (nl && noex == 0) {
 652655                         usch *och = stringbuf;
 653656                         int i;
 654657 
 655658                         i = kfind(nl);
 656659                         unch(WARN);
 657660                         if (i)
 658661                                 unpstr(stringbuf);
 659662                         else
 660663                                 unpstr(nl->namep);
 661664                         stringbuf = och;
 662665                         noex = 1;
 663666                         return yylex();
 664667                 } else {
 665668                         yylval.node.nd_val = 0;
 666669                 }
 667670                 yylval.node.op = NUMBER;
 668671                 return NUMBER;
 669672         case WARN:
 670673                 noex = 0;
 671674                 return yylex();
 672675         default:
 673676                 return ch;
 674677         }
 675678         unch(c2);
 676679         return ch;
 677680 }
 678681 
 679682 usch *yyp, yybuf[CPPBUF];
 680683 
 681684 int yywrap(void);
 682685 
 683686 static int
 684687 inpch(void)
 685688 {
 686689         int len;
 687690 
 688691         if (ifiles->curptr < ifiles->maxread)
 689692                 return *ifiles->curptr++;
 690693 
 691694         if (ifiles->infil == -1)
 692695                 return -1;
 693696         if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0)
 694697                 error("read error on file %s", ifiles->orgfn);
 695698         if (len == 0)
 696699                 return -1;
 697700         ifiles->curptr = ifiles->buffer;
 698701         ifiles->maxread = ifiles->buffer + len;
 699702         return inpch();
 700703 }
 701704 
 702705 static int
 703706 inch(void)
 704707 {
 705708         int c;
 706709 
 707710 again:  switch (c = inpch()) {
 708711         case '\\': /* continued lines */
 709712 msdos:          if ((c = inpch()) == '\n') {
 710713                         ifiles->lineno++;
 711714                         goto again;
 712715                 } else if (c == '\r')
 713716                         goto msdos;
 714717                 unch(c);
 715718                 return '\\';
 716719         case '?': /* trigraphs */
 717720                 if ((c = chktg())) {
 718721                         unch(c);
 719722                         goto again;
 720723                 }
 721724                 return '?';
 722725         default:
 723726                 return c;
 724727         }
 725728 }
 726729 
 727730 /*
 728731  * Let the command-line args be faked defines at beginning of file.
 729732  */
 730733 static void
 731734 prinit(struct initar *it, struct includ *ic)
 732735 {
 733736         const char *pre, *post;
 734737         char *a;
 735738 
 736739         if (it->next)
 737740                 prinit(it->next, ic);
 738741         pre = post = NULL; /* XXX gcc */
 739742         switch (it->type) {
 740743         case 'D':
 741744                 pre = "#define ";
 742745                 if ((a = strchr(it->str, '=')) != NULL) {
 743746                         *a = ' ';
 744747                         post = "\n";
 745748                 } else
 746749                         post = " 1\n";
 747750                 break;
 748751         case 'U':
 749752                 pre = "#undef ";
 750753                 post = "\n";
 751754                 break;
 752755         case 'i':
 753756                 pre = "#include \"";
 754757                 post = "\"\n";
 755758                 break;
 756759         default:
 757760                 error("prinit");
 758761         }
 759762         strlcat((char *)ic->buffer, pre, CPPBUF+1);
 760763         strlcat((char *)ic->buffer, it->str, CPPBUF+1);
 761764         if (strlcat((char *)ic->buffer, post, CPPBUF+1) >= CPPBUF+1)
 762765                 error("line exceeds buffer size");
 763766 
 764767         ic->lineno--;
 765768         while (*ic->maxread)
 766769                 ic->maxread++;
 767770 }
 768771 
 769772 /*
 770773  * A new file included.
 771774  * If ifiles == NULL, this is the first file and already opened (stdin).
 772775  * Return 0 on success, -1 if file to be included is not found.
 773776  */
 774777 int
 775778 pushfile(const usch *file, const usch *fn, int idx, void *incs)
 776779 {
 777780         extern struct initar *initar;
 778781         struct includ ibuf;
 779782         struct includ *ic;
 780783         int otrulvl;
 781784 
 782785         ic = &ibuf;
 783786         ic->next = ifiles;
 784787 
 785788         if (file != NULL) {
 786789                 if ((ic->infil = open((const char *)file, O_RDONLY)) < 0)
 787790                         return -1;
 788791                 ic->orgfn = ic->fname = file;
 789792                 if (++inclevel > MAX_INCLEVEL)
 790793                         error("Limit for nested includes exceeded");
 791794         } else {
 792795                 ic->infil = 0;
 793796                 ic->orgfn = ic->fname = (const usch *)"<stdin>";
 794797         }
<> 798+#ifndef BUF_STACK
  799+        ic->bbuf = malloc(BBUFSZ);
  800+#endif
795801         ic->buffer = ic->bbuf+NAMEMAX;
 796802         ic->curptr = ic->buffer;
 797803         ifiles = ic;
 798804         ic->lineno = 1;
 799805         ic->maxread = ic->curptr;
 800806         ic->idx = idx;
 801807         ic->incs = incs;
 802808         ic->fn = fn;
 803809         prtline();
 804810         if (initar) {
 805811                 int oin = ic->infil;
 806812                 ic->infil = -1;
 807813                 *ic->maxread = 0;
 808814                 prinit(initar, ic);
 809815                 initar = NULL;
 810816                 if (dMflag)
 811817                         write(ofd, ic->buffer, strlen((char *)ic->buffer));
 812818                 fastscan();
 813819                 prtline();
 814820                 ic->infil = oin;
 815821         }
 816822 
 817823         otrulvl = trulvl;
 818824 
 819825         fastscan();
 820826 
 821827         if (otrulvl != trulvl || flslvl)
 822828                 error("unterminated conditional");
 823829 
<> 830+#ifndef BUF_STACK
  831+        free(ic->bbuf);
  832+#endif
<_824833         ifiles = ic->next;
 825834         close(ic->infil);
 826835         inclevel--;
 827836         return 0;
 828837 }
 829838 
 830839 /*
 831840  * Print current position to output file.
 832841  */
 833842 void
 834843 prtline()
 835844 {
 836845         usch *s, *os = stringbuf;
 837846 
 838847         if (Mflag) {
 839848                 if (dMflag)
 840849                         return; /* no output */
 841850                 if (ifiles->lineno == 1) {
 842851                         s = sheap("%s: %s\n", Mfile, ifiles->fname);
 843852                         write(ofd, s, strlen((char *)s));
 844853                 }
 845854         } else if (!Pflag)
 846855                 putstr(sheap("\n# %d \"%s\"\n", ifiles->lineno, ifiles->fname));
 847856         stringbuf = os;
 848857 }
 849858 
 850859 void
 851860 cunput(int c)
 852861 {
 853862 #ifdef CPP_DEBUG
 854863 //      extern int dflag;
 855864 //      if (dflag)printf(": '%c'(%d)\n", c > 31 ? c : ' ', c);
 856865 #endif
 857866 #if 0
 858867 if (c == 10) {
 859868         printf("c == 10!!!\n");
 860869 }
 861870 #endif
 862871         unch(c);
 863872 }
 864873 
 865874 int yywrap(void) { return 1; }
 866875 
 867876 static int
 868877 dig2num(int c)
 869878 {
 870879         if (c >= 'a')
 871880                 c = c - 'a' + 10;
 872881         else if (c >= 'A')
 873882                 c = c - 'A' + 10;
 874883         else
 875884                 c = c - '0';
 876885         return c;
 877886 }
 878887 
 879888 /*
 880889  * Convert string numbers to unsigned long long and check overflow.
 881890  */
 882891 static void
 883892 cvtdig(int rad)
 884893 {
 885894         unsigned long long rv = 0;
 886895         unsigned long long rv2 = 0;
 887896         usch *y = yytext;
 888897         int c;
 889898 
 890899         c = *y++;
 891900         if (rad == 16)
 892901                 y++;
 893902         while (isxdigit(c)) {
 894903                 rv = rv * rad + dig2num(c);
 895904                 /* check overflow */
 896905                 if (rv / rad < rv2)
 897906                         error("Constant \"%s\" is out of range", yytext);
 898907                 rv2 = rv;
 899908                 c = *y++;
 900909         }
 901910         y--;
 902911         while (*y == 'l' || *y == 'L')
 903912                 y++;
 904913         yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER;
 905914         yylval.node.nd_uval = rv;
 906915         if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0)
 907916                 yylval.node.op = UNUMBER;
 908917         if (yylval.node.op == NUMBER && yylval.node.nd_val < 0)
 909918                 /* too large for signed, see 6.4.4.1 */
 910919                 error("Constant \"%s\" is out of range", yytext);
 911920 }
 912921 
 913922 static int
 914923 charcon(usch *p)
 915924 {
 916925         int val, c;
 917926 
 918927         p++; /* skip first ' */
 919928         val = 0;
 920929         if (*p++ == '\\') {
 921930                 switch (*p++) {
 922931                 case 'a': val = '\a'; break;
 923932                 case 'b': val = '\b'; break;
 924933                 case 'f': val = '\f'; break;
 925934                 case 'n': val = '\n'; break;
 926935                 case 'r': val = '\r'; break;
 927936                 case 't': val = '\t'; break;
 928937                 case 'v': val = '\v'; break;
 929938                 case '\"': val = '\"'; break;
 930939                 case '\'': val = '\''; break;
 931940                 case '\\': val = '\\'; break;
 932941                 case 'x':
 933942                         while (isxdigit(c = *p)) {
 934943                                 val = val * 16 + dig2num(c);
 935944                                 p++;
 936945                         }
 937946                         break;
 938947                 case '0': case '1': case '2': case '3': case '4':
 939948                 case '5': case '6': case '7':
 940949                         p--;
 941950                         while (isdigit(c = *p)) {
 942951                                 val = val * 8 + (c - '0');
 943952                                 p++;
 944953                         }
 945954                         break;
 946955                 default: val = p[-1];
 947956                 }
 948957 
 949958         } else
 950959                 val = p[-1];
 951960         return val;
 952961 }
 953962 
 954963 static void
 955964 chknl(int ignore)
 956965 {
 957966         int t;
 958967 
 959968         while ((t = sloscan()) == WSPACE)
 960969                 ;
 961970         if (t != '\n') {
 962971                 if (ignore) {
 963972                         warning("newline expected, got \"%s\"", yytext);
 964973                         /* ignore rest of line */
 965974                         while ((t = sloscan()) && t != '\n')
 966975                                 ;
 967976                 }
 968977                 else
 969978                         error("newline expected, got \"%s\"", yytext);
 970979         }
 971980 }
 972981 
 973982 static void
 974983 elsestmt(void)
 975984 {
 976985         if (flslvl) {
 977986                 if (elflvl > trulvl)
 978987                         ;
 979988                 else if (--flslvl!=0) {
 980989                         flslvl++;
 981990                 } else {
 982991                         trulvl++;
 983992                         prtline();
 984993                 }
 985994         } else if (trulvl) {
 986995                 flslvl++;
 987996                 trulvl--;
 988997         } else
 989998                 error("If-less else");
 990999         if (elslvl==trulvl+flslvl)
 9911000                 error("Too many else");
 9921001         elslvl=trulvl+flslvl;
 9931002         chknl(1);
 9941003 }
 9951004 
 9961005 static void
 9971006 skpln(void)
 9981007 {
 9991008         /* just ignore the rest of the line */
 10001009         while (inch() != '\n')
 10011010                 ;
 10021011         unch('\n');
 10031012         flslvl++;
 10041013 }
 10051014 
 10061015 static void
 10071016 ifdefstmt(void)         
 10081017 {
 10091018         int t;
 10101019 
 10111020         if (flslvl) {
 10121021                 skpln();
 10131022                 return;
 10141023         }
 10151024         do
 10161025                 t = sloscan();
 10171026         while (t == WSPACE);
 10181027         if (t != IDENT)
 10191028                 error("bad ifdef");
 10201029         if (lookup((usch *)yytext, FIND) == 0) {
 10211030                 putch('\n');
 10221031                 flslvl++;
 10231032         } else
 10241033                 trulvl++;
 10251034         chknl(0);
 10261035 }
 10271036 
 10281037 static void
 10291038 ifndefstmt(void)         
 10301039 {
 10311040         int t;
 10321041 
 10331042         if (flslvl) {
 10341043                 skpln();
 10351044                 return;
 10361045         }
 10371046         do
 10381047                 t = sloscan();
 10391048         while (t == WSPACE);
 10401049         if (t != IDENT)
 10411050                 error("bad ifndef");
 10421051         if (lookup((usch *)yytext, FIND) != 0) {
 10431052                 putch('\n');
 10441053                 flslvl++;
 10451054         } else
 10461055                 trulvl++;
 10471056         chknl(0);
 10481057 }
 10491058 
 10501059 static void
 10511060 endifstmt(void)         
 10521061 {
 10531062         if (flslvl) {
 10541063                 flslvl--;
 10551064                 if (flslvl == 0) {
 10561065                         putch('\n');
 10571066                         prtline();
 10581067                 }
 10591068         } else if (trulvl)
 10601069                 trulvl--;
 10611070         else
 10621071                 error("If-less endif");
 10631072         if (flslvl == 0)
 10641073                 elflvl = 0;
 10651074         elslvl = 0;
 10661075         chknl(1);
 10671076 }
 10681077 
 10691078 static void
 10701079 ifstmt(void)
 10711080 {
 10721081         if (flslvl == 0) {
 10731082                 if (yyparse() == 0) {
 10741083                         putch('\n');
 10751084                         ++flslvl;
 10761085                 } else
 10771086                         ++trulvl;
 10781087         } else
 10791088                 ++flslvl;
 10801089 }
 10811090 
 10821091 static void
 10831092 elifstmt(void)
 10841093 {
 10851094         if (flslvl == 0)
 10861095                 elflvl = trulvl;
 10871096         if (flslvl) {
 10881097                 if (elflvl > trulvl)
 10891098                         ;
 10901099                 else if (--flslvl!=0)
 10911100                         ++flslvl;
 10921101                 else {
 10931102                         if (yyparse()) {
 10941103                                 ++trulvl;
 10951104                                 prtline();
 10961105                         } else {
 10971106                                 putch('\n');
 10981107                                 ++flslvl;
 10991108                         }
 11001109                 }
 11011110         } else if (trulvl) {
 11021111                 ++flslvl;
 11031112                 --trulvl;
 11041113         } else
 11051114                 error("If-less elif");
 11061115 }
 11071116 
 11081117 static usch *
 11091118 svinp(void)
 11101119 {
 11111120         int c;
 11121121         usch *cp = stringbuf;
 11131122 
 11141123         while ((c = inch()) && c != '\n')
 11151124                 savch(c);
 11161125         savch('\n');
 11171126         savch(0);
 11181127         return cp;
 11191128 }
 11201129 
 11211130 static void
 11221131 cpperror(void)
 11231132 {
 11241133         usch *cp;
 11251134         int c;
 11261135 
 11271136         if (flslvl)
 11281137                 return;
 11291138         c = sloscan();
 11301139         if (c != WSPACE && c != '\n')
 11311140                 error("bad error");
 11321141         cp = svinp();
 11331142         if (flslvl)
 11341143                 stringbuf = cp;
 11351144         else
 11361145                 error("%s", cp);
 11371146 }
 11381147 
 11391148 static void
 11401149 cppwarning(void)
 11411150 {
 11421151         usch *cp;
 11431152         int c;
 11441153 
 11451154         if (flslvl)
 11461155                 return;
 11471156         c = sloscan();
 11481157         if (c != WSPACE && c != '\n')
 11491158                 error("bad warning");
 11501159 
 11511160         /* svinp() add an unwanted \n */
 11521161         cp = stringbuf;
 11531162         while ((c = inch()) && c != '\n')
 11541163                 savch(c);
 11551164         savch(0);
 11561165 
 11571166         if (flslvl)
 11581167                 stringbuf = cp;
 11591168         else
 11601169                 warning("#warning %s", cp);
 11611170 
 11621171         unch('\n');
 11631172 }
 11641173 
 11651174 static void
 11661175 undefstmt(void)
 11671176 {
 11681177         struct symtab *np;
 11691178 
 11701179         if (sloscan() != WSPACE || sloscan() != IDENT)
 11711180                 error("bad undef");
 11721181         if (flslvl == 0 && (np = lookup((usch *)yytext, FIND)))
 11731182                 np->value = 0;
 11741183         chknl(0);
 11751184 }
 11761185 
 11771186 static void
 11781187 pragmastmt(void)
 11791188 {
 11801189         int c;
 11811190 
 11821191         if (sloscan() != WSPACE)
 11831192                 error("bad pragma");
 11841193         if (!flslvl)
 11851194                 putstr((const usch *)"\n#pragma ");
 11861195         do {
 11871196                 c = inch();
 11881197                 if (!flslvl)
 11891198                         putch(c);       /* Do arg expansion instead? */
 11901199         } while (c && c != '\n');
 11911200         if (c == '\n')
 11921201                 unch(c);
 11931202         prtline();
 11941203 }
 11951204 
 11961205 static void
 11971206 badop(const char *op)
 11981207 {
 11991208         error("invalid operator in preprocessor expression: %s", op);
 12001209 }
 12011210 
 12021211 int
 12031212 cinput()
 12041213 {
 12051214         return inch();
 12061215 }
 12071216 
 12081217 /*
 12091218  * Check for (and convert) trigraphs.
 12101219  */
 12111220 int
 12121221 chktg()
 12131222 {
 12141223         int c;
 12151224 
 12161225         if ((c = inpch()) != '?') {
 12171226                 unch(c);
 12181227                 return 0;
 12191228         }
 12201229         switch (c = inpch()) {
 12211230         case '=': c = '#'; break;
 12221231         case '(': c = '['; break;
 12231232         case ')': c = ']'; break;
 12241233         case '<': c = '{'; break;
 12251234         case '>': c = '}'; break;
 12261235         case '/': c = '\\'; break;
 12271236         case '\'': c = '^'; break;
 12281237         case '!': c = '|'; break;
 12291238         case '-': c = '~'; break;
 12301239         default:
 12311240                 unch(c);
 12321241                 unch('?');
 12331242                 c = 0;
 12341243         }
 12351244         return c;
 12361245 }
 12371246 
 12381247 static struct {
 12391248         const char *name;
 12401249         void (*fun)(void);
 12411250 } ppd[] = {
 12421251         { "ifndef", ifndefstmt },
 12431252         { "ifdef", ifdefstmt },
 12441253         { "if", ifstmt },
 12451254         { "include", include },
 12461255         { "else", elsestmt },
 12471256         { "endif", endifstmt },
 12481257         { "error", cpperror },
 12491258         { "warning", cppwarning },
 12501259         { "define", define },
 12511260         { "undef", undefstmt },
 12521261         { "line", line },
 12531262         { "pragma", pragmastmt },
 12541263         { "elif", elifstmt },
 12551264 #ifdef GCC_COMPAT
 12561265         { "include_next", include_next },
 12571266 #endif
 12581267 };
 12591268 
 12601269 /*
 12611270  * Handle a preprocessor directive.
 12621271  */
 12631272 void
 12641273 ppdir(void)
 12651274 {
 12661275         char bp[20];
 12671276         int ch, i;
 12681277 
 12691278         while ((ch = inch()) == ' ' || ch == '\t')
 12701279                 ;
 12711280         if (ch == '\n') { /* empty directive */
 12721281                 unch(ch);
 12731282                 return;
 12741283         }
 12751284         if (ch < 'a' || ch > 'z')
 12761285                 goto out; /* something else, ignore */
 12771286         i = 0;
 12781287         do {
 12791288                 bp[i++] = (usch)ch;
 12801289                 if (i == sizeof(bp)-1)
 12811290                         goto out; /* too long */
 12821291                 ch = inch();
 12831292         } while ((ch >= 'a' && ch <= 'z') || (ch == '_'));
 12841293         unch(ch);
 12851294         bp[i++] = 0;
 12861295 
 12871296         /* got keyword */
 12881297 #define SZ (int)(sizeof(ppd)/sizeof(ppd[0]))
 12891298         for (i = 0; i < SZ; i++)
 12901299                 if (bp[0] == ppd[i].name[0] && strcmp(bp, ppd[i].name) == 0)
 12911300                         break;
 12921301         if (i == SZ)
 12931302                 goto out;
 12941303 
 12951304         /* Found matching keyword */
 12961305         (*ppd[i].fun)();
 12971306         return;
 12981307 
 12991308 out:    while ((ch = inch()) != '\n' && ch != -1)
 13001309                 ;
 13011310         unch('\n');
 13021311 }
FishEye: Open Source License registered to PCC.
Your maintenance has expired. You can renew your license at http://www.atlassian.com/fisheye/renew
Atlassian FishEye, CVS analysis. (Version:1.6.3 Build:build-336 2008-11-04) - Administration - Page generated 2014-07-10 20:20 +0200