Quick Search:

Mode

Context

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

Other Diffs

Ignore

Blank Lines Whitespace: Expand:

Diff

1.74
 
1.75
 
MAIN:plunky:20121002092433
 
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 "cpy.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 int inpch(void);
<>73 -
 74 -extern int yyget_lineno (void);
 75 -extern void yyset_lineno (int);
 76 -
7773 static int inch(void);
 7874 
<>79 -int inif;
 80 -
8175 #define PUTCH(ch) if (!flslvl) putch(ch)
 8276 /* protection against recursion in #include */
 8377 #define MAX_INCLEVEL    100
 8478 static int inclevel;
 8579 
 8680 /* get next character unaltered */
 8781 #define NXTCH() (ifiles->curptr < ifiles->maxread ? *ifiles->curptr++ : inpch())
 8882 
 8983 usch yytext[CPPBUF];
 9084 
 9185 char spechr[256] = {
 9286         0,      0,      0,      0,      C_SPECC_SPEC0,      0,
 9387         0,      C_WSNLC_SPEC|C_WSNL,  0,
 9488         0,      C_WSNL0,      0,
 9589         0,      0,      0,      0,      0,      0,      0,      0,
 9690         0,      0,      0,      0,      0,      0,      0,      0,
 9791 
 9892         C_WSNLC_2,    C_SPEC0,      0,      0,      C_2,    C_SPEC,
 9993         0,      0,      0,      C_2,    0,      C_2,    0,      C_SPEC|C_2,
 10094         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 10195         C_I,    C_I,    0,      0,      C_2,    C_2,    C_2,    C_SPEC,
 10296 
 10397         0,      C_I,    C_I,    C_I,    C_I,    C_I|C_EP, C_I,  C_I,
 10498         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 10599         C_I|C_EP, C_I,  C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 106100         C_I,    C_I,    C_I,    0,      C_SPEC0,      0,      C_I,
 107101 
 108102         0,      C_I,    C_I,    C_I,    C_I,    C_I|C_EP, C_I,  C_I,
 109103         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 110104         C_I|C_EP, C_I,  C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 111105         C_I,    C_I,    C_I,    0,      C_2,    0,      0,      0,
 112106 
 113107 };
 114108 
 115109 /*
 116110  * No-replacement array.  If a macro is found and exists in this array
 117111  * then no replacement shall occur.  This is a stack.
 118112  */
 119113 struct symtab *norep[RECMAX];   /* Symbol table index table */
 120114 int norepptr = 1;                       /* Top of index table */
 121115 unsigned short bptr[RECMAX];    /* currently active noexpand macro stack */
 122116 int bidx;                       /* Top of bptr stack */
 123117 
 124118 static void
 125119 unch(int c)
 126120 {
 127121                 
 128122         --ifiles->curptr;
 129123         if (ifiles->curptr < ifiles->bbuf)
 130124                 error("pushback buffer full");
 131125         *ifiles->curptr = (usch)c;
 132126 }
 133127 
 134128 static int
 135129 eatcmnt(void)
 136130 {
 137131         int ch;
 138132 
 139133         if (Cflag) { PUTCH('/'); PUTCH('*'); }
 140134         for (;;) {
 141135                 ch = inch();
 142136                 if (ch == '\n') {
 143137                         ifiles->lineno++;
 144138                         PUTCH('\n');
 145139                 }
 146140                 if (ch == -1)
 147141                         return -1;
 148142                 if (ch == '*') {
 149143                         ch = inch();
 150144                         if (ch == '/') {
 151145                                 if (Cflag) {
 152146                                         PUTCH('*');
 153147                                         PUTCH('/');
 154148                                 } else
 155149                                         PUTCH(' ');
 156150                                 break;
 157151                         }
 158152                         unch(ch);
 159153                         ch = '*';
 160154                 }
 161155                 if (Cflag) PUTCH(ch);
 162156         }
 163157         return 0;
 164158 }
 165159 
 166160 /*
 167161  * Scan quickly the input file searching for:
 168162  *      - '#' directives
 169163  *      - keywords (if not flslvl)
 170164  *      - comments
 171165  *
 172166  *      Handle strings, numbers and trigraphs with care.
 173167  *      Only data from pp files are scanned here, never any rescans.
 174168  *      TODO: Only print out strings before calling other functions.
 175169  */
 176170 static void
 177171 fastscan(void)
 178172 {
 179173         struct symtab *nl;
 180174         int ch, i = 0;
 181175         int nnl = 0;
 182176         usch *cp;
 183177 
 184178         goto run;
 185179         for (;;) {
 186180                 ch = NXTCH();
 187181 xloop:          if (ch == -1)
 188182                         return;
 189183 #ifdef PCC_DEBUG
 190184                 if (dflag>1)
 191185                         printf("fastscan ch %d (%c)\n", ch, ch > 31 ? ch : '@');
 192186 #endif
 193187                 if ((spechr[ch] & C_SPEC) == 0) {
 194188                         PUTCH(ch);
 195189                         continue;
 196190                 }
 197191                 switch (ch) {
 198192                 case EBLOCK:
 199193                 case WARN:
 200194                 case CONC:
 201195                         error("bad char passed");
 202196                         break;
 203197 
 204198                 case '/': /* Comments */
 205199                         if ((ch = inch()) == '/') {
 206200 cppcmt:                         if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
 207201                                 do {
 208202                                         if (Cflag) PUTCH(ch);
 209203                                         ch = inch();
 210204                                 } while (ch != -1 && ch != '\n');
 211205                                 goto xloop;
 212206                         } else if (ch == '*') {
 213207                                 if (eatcmnt())
 214208                                         return;
 215209                         } else {
 216210                                 PUTCH('/');
 217211                                 goto xloop;
 218212                         }
 219213                         break;
 220214 
 221215                 case '?'/* trigraphs */
 222216                         if ((ch = chktg()))
 223217                                 goto xloop;
 224218                         PUTCH('?');
 225219                         break;
 226220 
 227221                 case '\\':
 228222                         if ((ch = NXTCH()) == '\n') {
 229223                                 ifiles->lineno++;
 230224                                 continue;
 231225                         } else {
 232226                                 PUTCH('\\');
 233227                         }
 234228                         goto xloop;
 235229 
 236230                 case '\n': /* newlines, for pp directives */
 237231                         while (nnl > 0) { PUTCH('\n'); nnl--; }
 238232 run2:                   ifiles->lineno++;
 239233                         do {
 240234                                 PUTCH(ch);
 241235 run:                            ch = NXTCH();
 242236                                 if (ch == '/') {
 243237                                         ch = NXTCH();
 244238                                         if (ch == '/')
 245239                                                 goto cppcmt;
 246240                                         if (ch == '*') {
 247241                                                 if (eatcmnt())
 248242                                                         return;
 249243                                                 goto run;
 250244                                         }
 251245                                         unch(ch);
 252246                                         ch = '/';
 253247                                 }
 254248                         } while (ch == ' ' || ch == '\t');
 255249                         if (ch == '\\') {
 256250                                 ch = NXTCH();
 257251                                 if (ch == '\n')
 258252                                         goto run2;
 259253                                 unch(ch);
 260254                                 ch = '\\';
 261255                         }
 262256                         if (ch == '#') {
 263257                                 ppdir();
 264258                                 continue;
 265259                         } else if (ch == '%') {
 266260                                 ch = NXTCH();
 267261                                 if (ch == ':') {
 268262                                         ppdir();
 269263                                         continue;
 270264                                 } else {
 271265                                         unch(ch);
 272266                                         ch = '%';
 273267                                 }
 274268                         } else if (ch == '?') {
 275269                                 if ((ch = chktg()) == '#') {
 276270                                         ppdir();
 277271                                         continue;
 278272                                 } else if (ch == 0)
 279273                                         ch = '?';
 280274                         }
 281275                         goto xloop;
 282276 
 283277                 case '\"': /* strings */
 284278 str:                    PUTCH(ch);
 285279                         while ((ch = NXTCH()) != '\"') {
 286280                                 if (ch == '\n')
 287281                                         goto xloop;
 288282                                 if (ch == '\\') {
 289283                                         if ((ch = NXTCH()) != '\n') {
 290284                                                 PUTCH('\\');
 291285                                                 PUTCH(ch);
 292286                                         } else
 293287                                                 nnl++;
 294288                                         continue;
 295289                                 }
 296290                                 if (ch < 0)
 297291                                         return;
 298292                                 PUTCH(ch);
 299293                         }
 300294                         PUTCH(ch);
 301295                         break;
 302296 
 303297                 case '.'/* for pp-number */
 304298                         PUTCH(ch);
 305299                         ch = NXTCH();
 306300                         if (ch < '0' || ch > '9')
 307301                                 goto xloop;
 308302                         /* FALLTHROUGH */
 309303                 case '0': case '1': case '2': case '3': case '4':
 310304                 case '5': case '6': case '7': case '8': case '9':
 311305                         do {
 312306                                 PUTCH(ch);
 313307 nxt:                            ch = NXTCH();
 314308                                 if (ch == '\\') {
 315309                                         ch = NXTCH();
 316310                                         if (ch == '\n') {
 317311                                                 goto nxt;
 318312                                         } else {
 319313                                                 unch(ch);
 320314                                                 ch = '\\';
 321315                                         }
 322316                                 }
 323317                                 if (spechr[ch] & C_EP) {
 324318                                         PUTCH(ch);
 325319                                         ch = NXTCH();
 326320                                         if (ch == '-' || ch == '+')
 327321                                                 continue;
 328322                                 }
 329323                         } while ((spechr[ch] & C_ID) || (ch == '.'));
 330324                         goto xloop;
 331325 
 332326                 case '\'': /* character literal */
 333327 con:                    PUTCH(ch);
 334328                         if (tflag)
 335329                                 continue; /* character constants ignored */
 336330                         while ((ch = NXTCH()) != '\'') {
 337331                                 if (ch == '\n')
 338332                                         goto xloop;
 339333                                 if (ch == '\\') {
 340334                                         if ((ch = NXTCH()) != '\n') {
 341335                                                 PUTCH('\\');
 342336                                                 PUTCH(ch);
 343337                                         } else
 344338                                                 nnl++;
 345339                                         continue;
 346340                                 }
 347341                                 if (ch < 0)
 348342                                         return;
 349343                                 PUTCH(ch);
 350344                         }
 351345                         PUTCH(ch);
 352346                         break;
 353347 
 354348                 case 'L':
 355349                         ch = NXTCH();
 356350                         if (ch == '\"') {
 357351                                 PUTCH('L');
 358352                                 goto str;
 359353                         }
 360354                         if (ch == '\'') {
 361355                                 PUTCH('L');
 362356                                 goto con;
 363357                         }
 364358                         unch(ch);
 365359                         ch = 'L';
 366360                         /* FALLTHROUGH */
 367361                 default:
 368362                         if ((spechr[ch] & C_ID) == 0)
 369363                                 error("fastscan");
 370364                         if (flslvl) {
 371365                                 while (spechr[ch] & C_ID)
 372366                                         ch = NXTCH();
 373367                                 goto xloop;
 374368                         }
 375369                         i = 0;
 376370                         do {
 377371                                 yytext[i++] = (usch)ch;
 378372                                 ch = NXTCH();
 379373                                 if (ch == '\\') {
 380374                                         ch = NXTCH();
 381375                                         if (ch != '\n') {
 382376                                                 unch(ch);
 383377                                                 ch = '\\';
 384378                                         } else {
 385379                                                 putch('\n');
 386380                                                 ifiles->lineno++;
 387381                                                 ch = NXTCH();
 388382                                         }
 389383                                 }
 390384                                 if (ch < 0)
 391385                                         return;
 392386                         } while (spechr[ch] & C_ID);
 393387 
 394388                         yytext[i] = 0;
 395389                         unch(ch);
 396390 
 397391                         cp = stringbuf;
 398392                         if ((nl = lookup(yytext, FIND)) && kfind(nl)) {
 399393                                 putstr(stringbuf);
 400394                         } else
 401395                                 putstr(yytext);
 402396                         stringbuf = cp;
 403397 
 404398                         break;
 405399                 }
 406400         }
 407401 }
 408402 
 409403 int
 410404 sloscan(void)
 411405 {
 412406         int ch;
 413407         int yyp;
 414408 
 415409 zagain:
 416410         yyp = 0;
 417411         ch = inch();
 418412         yytext[yyp++] = (usch)ch;
 419413         switch (ch) {
 420414         case -1:
 421415                 return 0;
 422416         case '\n':
 423417                 /* sloscan() never passes \n, that's up to fastscan() */
 424418                 unch(ch);
 425419                 goto yyret;
 426420 
 427421         case '\r': /* Ignore CR's */
 428422                 yyp = 0;
 429423                 break;
 430424 
 431425         case '0': case '1': case '2': case '3': case '4': case '5':
 432426         case '6': case '7': case '8': case '9':
 433427                 /* readin a "pp-number" */
 434428 ppnum:          for (;;) {
 435429                         ch = inch();
 436430                         if (spechr[ch] & C_EP) {
 437431                                 yytext[yyp++] = (usch)ch;
 438432                                 ch = inch();
 439433                                 if (ch == '-' || ch == '+') {
 440434                                         yytext[yyp++] = (usch)ch;
 441435                                 } else
 442436                                         unch(ch);
 443437                                 continue;
 444438                         }
 445439                         if ((spechr[ch] & C_ID) || ch == '.') {
 446440                                 yytext[yyp++] = (usch)ch;
 447441                                 continue;
 448442                         }
 449443                         break;
 450444                 }
 451445                 unch(ch);
 452446                 yytext[yyp] = 0;
 453447 
 454448                 return NUMBER;
 455449 
 456450         case '\'':
 457451 chlit:          
 458452                 for (;;) {
 459453                         if ((ch = inch()) == '\\') {
 460454                                 yytext[yyp++] = (usch)ch;
 461455                                 yytext[yyp++] = (usch)inch();
 462456                                 continue;
 463457                         } else if (ch == '\n') {
 464458                                 /* not a constant */
 465459                                 while (yyp > 1)
 466460                                         unch(yytext[--yyp]);
 467461                                 ch = '\'';
 468462                                 goto any;
 469463                         } else
 470464                                 yytext[yyp++] = (usch)ch;
 471465                         if (ch == '\'')
 472466                                 break;
 473467                 }
 474468                 yytext[yyp] = 0;
 475469 
 476470                 return NUMBER;
 477471 
 478472         case ' ':
 479473         case '\t':
 480474                 while ((ch = inch()) == ' ' || ch == '\t')
 481475                         yytext[yyp++] = (usch)ch;
 482476                 unch(ch);
 483477                 yytext[yyp] = 0;
 484478                 return WSPACE;
 485479 
 486480         case '/':
 487481                 if ((ch = inch()) == '/') {
 488482                         do {
 489483                                 yytext[yyp++] = (usch)ch;
 490484                                 ch = inch();
 491485                         } while (ch && ch != '\n');
 492486                         yytext[yyp] = 0;
 493487                         unch(ch);
 494488                         goto zagain;
 495489                 } else if (ch == '*') {
 496490                         int c, wrn;
 497491                         extern int readmac;
 498492 
 499493                         if (Cflag && !flslvl && readmac) {
 500494                                 unch(ch);
 501495                                 yytext[yyp] = 0;
 502496                                 return CMNT;
 503497                         }
 504498 
 505499                         wrn = 0;
 506500                 more:   while ((c = inch()) && c != '*') {
 507501                                 if (c == '\n')
 508502                                         putch(c), ifiles->lineno++;
 509503                                 else if (c == EBLOCK) {
 510504                                         (void)inch();
 511505                                         (void)inch();
 512506                                 } else if (c == 1) /* WARN */
 513507                                         wrn = 1;
 514508                         }
 515509                         if (c == 0)
 516510                                 return 0;
 517511                         if ((c = inch()) && c != '/') {
 518512                                 unch(c);
 519513                                 goto more;
 520514                         }
 521515                         if (c == 0)
 522516                                 return 0;
 523517                         if (!tflag && !Cflag && !flslvl)
 524518                                 unch(' ');
 525519                         if (wrn)
 526520                                 unch(1);
 527521                         goto zagain;
 528522                 }
 529523                 unch(ch);
 530524                 ch = '/';
 531525                 goto any;
 532526 
 533527         case '.':
 534528                 ch = inch();
 535529                 if (isdigit(ch)) {
 536530                         yytext[yyp++] = (usch)ch;
 537531                         goto ppnum;
 538532                 } else {
 539533                         unch(ch);
 540534                         ch = '.';
 541535                 }
 542536                 goto any;
 543537 
 544538         case '\"':
 545539                 if (tflag && defining)
 546540                         goto any;
 547541         strng:
 548542                 for (;;) {
 549543                         if ((ch = inch()) == '\\') {
 550544                                 yytext[yyp++] = (usch)ch;
 551545                                 yytext[yyp++] = (usch)inch();
 552546                                 continue;
 553547                         } else
 554548                                 yytext[yyp++] = (usch)ch;
 555549                         if (ch == '\"')
 556550                                 break;
 557551                 }
 558552                 yytext[yyp] = 0;
 559553                 return STRING;
 560554 
 561555         case 'L':
 562556                 if ((ch = inch()) == '\"' && !tflag) {
 563557                         yytext[yyp++] = (usch)ch;
 564558                         goto strng;
 565559                 } else if (ch == '\'' && !tflag) {
 566560                         yytext[yyp++] = (usch)ch;
 567561                         goto chlit;
 568562                 }
 569563                 unch(ch);
 570564                 /* FALLTHROUGH */
 571565 
 572566         /* Yetch, all identifiers */
 573567         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
 574568         case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
 575569         case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
 576570         case 's': case 't': case 'u': case 'v': case 'w': case 'x':
 577571         case 'y': case 'z':
 578572         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
 579573         case 'G': case 'H': case 'I': case 'J': case 'K':
 580574         case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
 581575         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
 582576         case 'Y': case 'Z':
 583577         case '_': /* {L}({L}|{D})* */
 584578 
 585579                 /* Special hacks */
 586580                 for (;;) { /* get chars */
 587581                         ch = inch();
 588582                         if (isalpha(ch) || isdigit(ch) || ch == '_') {
 589583                                 yytext[yyp++] = (usch)ch;
 590584                         } else {
 591585                                 if (ch != -1)
 592586                                         unch(ch);
 593587                                 break;
 594588                         }
 595589                 }
 596590                 yytext[yyp] = 0; /* need already string */
 597591                 /* end special hacks */
 598592 
 599593                 return IDENT;
 600594         default:
 601595         any:
 602596                 yytext[yyp] = 0;
 603597                 return yytext[0];
 604598 
 605599         } /* endcase */
 606600         goto zagain;
 607601 
 608602 yyret:
 609603         yytext[yyp] = 0;
 610604         return ch;
 611605 }
 612606 
 613607 int
 614608 yylex(void)
 615609 {
 616610         static int ifdef, noex;
 617611         struct symtab *nl;
 618612         int ch, c2;
 619613 
 620614         while ((ch = sloscan()) == WSPACE)
 621615                 ;
 622616         if (ch < 128 && spechr[ch] & C_2)
 623617                 c2 = inpch();
 624618         else
 625619                 c2 = 0;
 626620 
 627621 #define C2(a,b,c) case a: if (c2 == b) return c; break
 628622         switch (ch) {
 629623         C2('=', '=', EQ);
 630624         C2('!', '=', NE);
 631625         C2('|', '|', OROR);
 632626         C2('&', '&', ANDAND);
 633627         case '<':
 634628                 if (c2 == '<') return LS;
 635629                 if (c2 == '=') return LE;
 636630                 break;
 637631         case '>':
 638632                 if (c2 == '>') return RS;
 639633                 if (c2 == '=') return GE;
 640634                 break;
 641635         case '+':
 642636         case '-':
 643637                 if (ch == c2)
 644638                         badop("");
 645639                 break;
 646640 
 647641         case '/':
 648642                 if (Cflag == 0 || c2 != '*')
 649643                         break;
 650644                 /* Found comment that need to be skipped */
 651645                 for (;;) {
 652646                         ch = inpch();
 653647                 c1:     if (ch != '*')
 654648                                 continue;
 655649                         if ((ch = inpch()) == '/')
 656650                                 break;
 657651                         goto c1;
 658652                 }
 659653                 return yylex();
 660654 
 661655         case NUMBER:
 662656                 if (yytext[0] == '\'') {
 663657                         yylval.node.op = NUMBER;
 664658                         yylval.node.nd_val = charcon(yytext);
 665659                 } else
 666660                         cvtdig(yytext[0] != '0' ? 10 :
 667661                             yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
 668662                 return NUMBER;
 669663 
 670664         case IDENT:
 671665                 if (strcmp((char *)yytext, "defined") == 0) {
 672666                         ifdef = 1;
 673667                         return DEFINED;
 674668                 }
 675669                 nl = lookup(yytext, FIND);
 676670                 if (ifdef) {
 677671                         yylval.node.nd_val = nl != NULL;
 678672                         ifdef = 0;
 679673                 } else if (nl && noex == 0) {
 680674                         usch *och = stringbuf;
 681675                         int i;
 682676 
 683677                         i = kfind(nl);
 684678                         unch(WARN);
 685679                         if (i)
 686680                                 unpstr(stringbuf);
 687681                         else
 688682                                 unpstr(nl->namep);
 689683                         stringbuf = och;
 690684                         noex = 1;
 691685                         return yylex();
 692686                 } else {
 693687                         yylval.node.nd_val = 0;
 694688                 }
 695689                 yylval.node.op = NUMBER;
 696690                 return NUMBER;
 697691         case WARN:
 698692                 noex = 0;
 699693                 /* FALLTHROUGH */
 700694         case PHOLD:
 701695                 return yylex();
 702696         default:
 703697                 return ch;
 704698         }
 705699         unch(c2);
 706700         return ch;
 707701 }
 708702 
<>709 -usch *yyp, yybuf[CPPBUF];
 710 -
 711 -int yywrap(void);
 712 -
713703 static int
 714704 inpch(void)
 715705 {
 716706         int len;
 717707 
 718708         if (ifiles->curptr < ifiles->maxread)
 719709                 return *ifiles->curptr++;
 720710 
 721711         if (ifiles->infil == -1)
 722712                 return -1;
 723713         if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0)
 724714                 error("read error on file %s", ifiles->orgfn);
 725715         if (len == 0)
 726716                 return -1;
 727717         ifiles->buffer[len] = 0;
 728718         ifiles->curptr = ifiles->buffer;
 729719         ifiles->maxread = ifiles->buffer + len;
 730720         return inpch();
 731721 }
 732722 
 733723 static int
 734724 inch(void)
 735725 {
 736726         int c;
 737727 
 738728 again:  switch (c = inpch()) {
 739729         case '\\': /* continued lines */
 740730 msdos:          if ((c = inpch()) == '\n') {
 741731                         ifiles->lineno++;
 742732                         putch('\n');
 743733                         goto again;
 744734                 } else if (c == '\r')
 745735                         goto msdos;
 746736                 unch(c);
 747737                 return '\\';
 748738         case '?': /* trigraphs */
 749739                 if ((c = chktg())) {
 750740                         unch(c);
 751741                         goto again;
 752742                 }
 753743                 return '?';
 754744         default:
 755745                 return c;
 756746         }
 757747 }
 758748 
 759749 /*
 760750  * Let the command-line args be faked defines at beginning of file.
 761751  */
 762752 static void
 763753 prinit(struct initar *it, struct includ *ic)
 764754 {
 765755         const char *pre, *post;
 766756         char *a;
 767757 
 768758         if (it->next)
 769759                 prinit(it->next, ic);
 770760         pre = post = NULL; /* XXX gcc */
 771761         switch (it->type) {
 772762         case 'D':
 773763                 pre = "#define ";
 774764                 if ((a = strchr(it->str, '=')) != NULL) {
 775765                         *a = ' ';
 776766                         post = "\n";
 777767                 } else
 778768                         post = " 1\n";
 779769                 break;
 780770         case 'U':
 781771                 pre = "#undef ";
 782772                 post = "\n";
 783773                 break;
 784774         case 'i':
 785775                 pre = "#include \"";
 786776                 post = "\"\n";
 787777                 break;
 788778         default:
 789779                 error("prinit");
 790780         }
 791781         strlcat((char *)ic->buffer, pre, CPPBUF+1);
 792782         strlcat((char *)ic->buffer, it->str, CPPBUF+1);
 793783         if (strlcat((char *)ic->buffer, post, CPPBUF+1) >= CPPBUF+1)
 794784                 error("line exceeds buffer size");
 795785 
 796786         ic->lineno--;
 797787         while (*ic->maxread)
 798788                 ic->maxread++;
 799789 }
 800790 
 801791 /*
 802792  * A new file included.
 803793  * If ifiles == NULL, this is the first file and already opened (stdin).
 804794  * Return 0 on success, -1 if file to be included is not found.
 805795  */
 806796 int
 807797 pushfile(const usch *file, const usch *fn, int idx, void *incs)
 808798 {
 809799         extern struct initar *initar;
 810800         struct includ ibuf;
 811801         struct includ *ic;
 812802         int otrulvl, i;
 813803 
 814804         ic = &ibuf;
 815805         ic->next = ifiles;
 816806 
 817807         if (file != NULL) {
 818808                 if ((ic->infil = open((const char *)file, O_RDONLY)) < 0)
 819809                         return -1;
 820810                 ic->orgfn = ic->fname = file;
 821811                 if (++inclevel > MAX_INCLEVEL)
 822812                         error("Limit for nested includes exceeded");
 823813         } else {
 824814                 ic->infil = 0;
 825815                 ic->orgfn = ic->fname = (const usch *)"<stdin>";
 826816         }
 827817 #ifndef BUF_STACK
 828818         ic->bbuf = malloc(BBUFSZ);
 829819 #endif
 830820         ic->buffer = ic->bbuf+NAMEMAX;
 831821         ic->curptr = ic->buffer;
 832822         ifiles = ic;
 833823         ic->lineno = 1;
 834824         ic->maxread = ic->curptr;
 835825         ic->idx = idx;
 836826         ic->incs = incs;
 837827         ic->fn = fn;
 838828         prtline();
 839829         if (initar) {
 840830                 int oin = ic->infil;
 841831                 ic->infil = -1;
 842832                 *ic->maxread = 0;
 843833                 prinit(initar, ic);
 844834                 initar = NULL;
 845835                 if (dMflag)
 846836                         i = write(ofd, ic->buffer, strlen((char *)ic->buffer));
 847837                 fastscan();
 848838                 prtline();
 849839                 ic->infil = oin;
 850840         }
 851841 
 852842         otrulvl = trulvl;
 853843 
 854844         fastscan();
 855845 
 856846         if (otrulvl != trulvl || flslvl)
 857847                 error("unterminated conditional");
 858848 
 859849 #ifndef BUF_STACK
 860850         free(ic->bbuf);
 861851 #endif
 862852         ifiles = ic->next;
 863853         close(ic->infil);
 864854         inclevel--;
 865855         return 0;
 866856 }
 867857 
 868858 /*
 869859  * Print current position to output file.
 870860  */
 871861 void
 872862 prtline(void)
 873863 {
 874864         usch *s, *os = stringbuf;
 875865         int i;
 876866 
 877867         if (Mflag) {
 878868                 if (dMflag)
 879869                         return; /* no output */
 880870                 if (ifiles->lineno == 1) {
 881871                         s = sheap("%s: %s\n", Mfile, ifiles->fname);
 882872                         i = write(ofd, s, strlen((char *)s));
 883873                         if (MPflag &&
 884874                             strcmp((const char *)ifiles->fname, (char *)MPfile)) {
 885875                                 s = sheap("%s:\n", ifiles->fname);
 886876                                 i = write(ofd, s, strlen((char *)s));
 887877                         }
 888878                 }
 889879         } else if (!Pflag) {
 890880                 putstr(sheap("\n# %d \"%s\"", ifiles->lineno, ifiles->fname));
 891881                 if (ifiles->idx == SYSINC)
 892882                         putstr(sheap(" 3"));
 893883                 putstr(sheap("\n"));
 894884         }
 895885         stringbuf = os;
 896886 }
 897887 
 898888 void
 899889 cunput(int c)
 900890 {
 901891 #ifdef PCC_DEBUG
 902892 //      extern int dflag;
 903893 //      if (dflag)printf(": '%c'(%d)\n", c > 31 ? c : ' ', c);
 904894 #endif
 905895 #if 0
 906896 if (c == 10) {
 907897         printf("c == 10!!!\n");
 908898 }
 909899 #endif
 910900         unch(c);
 911901 }
 912902 
<>913 -int yywrap(void) { return 1; }
 914 -
<_915903 static int
 916904 dig2num(int c)
 917905 {
 918906         if (c >= 'a')
 919907                 c = c - 'a' + 10;
 920908         else if (c >= 'A')
 921909                 c = c - 'A' + 10;
 922910         else
 923911                 c = c - '0';
 924912         return c;
 925913 }
 926914 
 927915 /*
 928916  * Convert string numbers to unsigned long long and check overflow.
 929917  */
 930918 static void
 931919 cvtdig(int rad)
 932920 {
 933921         unsigned long long rv = 0;
 934922         unsigned long long rv2 = 0;
 935923         usch *y = yytext;
 936924         int c;
 937925 
 938926         c = *y++;
 939927         if (rad == 16)
 940928                 y++;
 941929         while (isxdigit(c)) {
 942930                 rv = rv * rad + dig2num(c);
 943931                 /* check overflow */
 944932                 if (rv / rad < rv2)
 945933                         error("Constant \"%s\" is out of range", yytext);
 946934                 rv2 = rv;
 947935                 c = *y++;
 948936         }
 949937         y--;
 950938         while (*y == 'l' || *y == 'L')
 951939                 y++;
 952940         yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER;
 953941         yylval.node.nd_uval = rv;
 954942         if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0)
 955943                 yylval.node.op = UNUMBER;
 956944         if (yylval.node.op == NUMBER && yylval.node.nd_val < 0)
 957945                 /* too large for signed, see 6.4.4.1 */
 958946                 error("Constant \"%s\" is out of range", yytext);
 959947 }
 960948 
 961949 static int
 962950 charcon(usch *p)
 963951 {
 964952         int val, c;
 965953 
 966954         p++; /* skip first ' */
 967955         val = 0;
 968956         if (*p++ == '\\') {
 969957                 switch (*p++) {
 970958                 case 'a': val = '\a'; break;
 971959                 case 'b': val = '\b'; break;
 972960                 case 'f': val = '\f'; break;
 973961                 case 'n': val = '\n'; break;
 974962                 case 'r': val = '\r'; break;
 975963                 case 't': val = '\t'; break;
 976964                 case 'v': val = '\v'; break;
 977965                 case '\"': val = '\"'; break;
 978966                 case '\'': val = '\''; break;
 979967                 case '\\': val = '\\'; break;
 980968                 case 'x':
 981969                         while (isxdigit(c = *p)) {
 982970                                 val = val * 16 + dig2num(c);
 983971                                 p++;
 984972                         }
 985973                         break;
 986974                 case '0': case '1': case '2': case '3': case '4':
 987975                 case '5': case '6': case '7':
 988976                         p--;
 989977                         while (isdigit(c = *p)) {
 990978                                 val = val * 8 + (c - '0');
 991979                                 p++;
 992980                         }
 993981                         break;
 994982                 default: val = p[-1];
 995983                 }
 996984 
 997985         } else
 998986                 val = p[-1];
 999987         return val;
 1000988 }
 1001989 
 1002990 static void
 1003991 chknl(int ignore)
 1004992 {
 1005993         int t;
 1006994 
 1007995         while ((t = sloscan()) == WSPACE)
 1008996                 ;
 1009997         if (t != '\n') {
 1010998                 if (t && t != (usch)-1) {
 1011999                         if (ignore) {
 10121000                                 warning("newline expected, got \"%s\"", yytext);
 10131001                                 /* ignore rest of line */
 10141002                                 while ((t = sloscan()) && t != '\n')
 10151003                                         ;
 10161004                         }
 10171005                         else
 10181006                                 error("newline expected, got \"%s\"", yytext);
 10191007                 } else {
 10201008                         if (ignore)
 10211009                                 warning("no newline at end of file");
 10221010                         else
 10231011                                 error("no newline at end of file");
 10241012                 }
 10251013         }
 10261014 }
 10271015 
 10281016 static void
 10291017 elsestmt(void)
 10301018 {
 10311019         if (flslvl) {
 10321020                 if (elflvl > trulvl)
 10331021                         ;
 10341022                 else if (--flslvl!=0) {
 10351023                         flslvl++;
 10361024                 } else {
 10371025                         trulvl++;
 10381026                         prtline();
 10391027                 }
 10401028         } else if (trulvl) {
 10411029                 flslvl++;
 10421030                 trulvl--;
 10431031         } else
 10441032                 error("If-less else");
 10451033         if (elslvl==trulvl+flslvl)
 10461034                 error("Too many else");
 10471035         elslvl=trulvl+flslvl;
 10481036         chknl(1);
 10491037 }
 10501038 
 10511039 static void
 10521040 skpln(void)
 10531041 {
 10541042         /* just ignore the rest of the line */
 10551043         while (inch() != '\n')
 10561044                 ;
 10571045         unch('\n');
 10581046         flslvl++;
 10591047 }
 10601048 
 10611049 static void
 10621050 ifdefstmt(void)         
 10631051 {
 10641052         int t;
 10651053 
 10661054         if (flslvl) {
 10671055                 skpln();
 10681056                 return;
 10691057         }
 10701058         do
 10711059                 t = sloscan();
 10721060         while (t == WSPACE);
 10731061         if (t != IDENT)
 10741062                 error("bad ifdef");
 10751063         if (lookup(yytext, FIND) == 0) {
 10761064                 putch('\n');
 10771065                 flslvl++;
 10781066         } else
 10791067                 trulvl++;
 10801068         chknl(0);
 10811069 }
 10821070 
 10831071 static void
 10841072 ifndefstmt(void)         
 10851073 {
 10861074         int t;
 10871075 
 10881076         if (flslvl) {
 10891077                 skpln();
 10901078                 return;
 10911079         }
 10921080         do
 10931081                 t = sloscan();
 10941082         while (t == WSPACE);
 10951083         if (t != IDENT)
 10961084                 error("bad ifndef");
 10971085         if (lookup(yytext, FIND) != 0) {
 10981086                 putch('\n');
 10991087                 flslvl++;
 11001088         } else
 11011089                 trulvl++;
 11021090         chknl(0);
 11031091 }
 11041092 
 11051093 static void
 11061094 endifstmt(void)         
 11071095 {
 11081096         if (flslvl) {
 11091097                 flslvl--;
 11101098                 if (flslvl == 0) {
 11111099                         putch('\n');
 11121100                         prtline();
 11131101                 }
 11141102         } else if (trulvl)
 11151103                 trulvl--;
 11161104         else
 11171105                 error("If-less endif");
 11181106         if (flslvl == 0)
 11191107                 elflvl = 0;
 11201108         elslvl = 0;
 11211109         chknl(1);
 11221110 }
 11231111 
 11241112 static void
 11251113 ifstmt(void)
 11261114 {
 11271115         if (flslvl == 0) {
 11281116                 if (yyparse() == 0) {
 11291117                         putch('\n');
 11301118                         ++flslvl;
 11311119                 } else
 11321120                         ++trulvl;
 11331121         } else
 11341122                 ++flslvl;
 11351123 }
 11361124 
 11371125 static void
 11381126 elifstmt(void)
 11391127 {
 11401128         if (flslvl == 0)
 11411129                 elflvl = trulvl;
 11421130         if (flslvl) {
 11431131                 if (elflvl > trulvl)
 11441132                         ;
 11451133                 else if (--flslvl!=0)
 11461134                         ++flslvl;
 11471135                 else {
 11481136                         if (yyparse()) {
 11491137                                 ++trulvl;
 11501138                                 prtline();
 11511139                         } else {
 11521140                                 putch('\n');
 11531141                                 ++flslvl;
 11541142                         }
 11551143                 }
 11561144         } else if (trulvl) {
 11571145                 ++flslvl;
 11581146                 --trulvl;
 11591147         } else
 11601148                 error("If-less elif");
 11611149 }
 11621150 
 11631151 static usch *
 11641152 svinp(void)
 11651153 {
 11661154         int c;
 11671155         usch *cp = stringbuf;
 11681156 
 11691157         while ((c = inch()) && c != '\n')
 11701158                 savch(c);
 11711159         savch('\n');
 11721160         savch(0);
 11731161         return cp;
 11741162 }
 11751163 
 11761164 static void
 11771165 cpperror(void)
 11781166 {
 11791167         usch *cp;
 11801168         int c;
 11811169 
 11821170         if (flslvl)
 11831171                 return;
 11841172         c = sloscan();
 11851173         if (c != WSPACE && c != '\n')
 11861174                 error("bad error");
 11871175         cp = svinp();
 11881176         if (flslvl)
 11891177                 stringbuf = cp;
 11901178         else
 11911179                 error("%s", cp);
 11921180 }
 11931181 
 11941182 static void
 11951183 cppwarning(void)
 11961184 {
 11971185         usch *cp;
 11981186         int c;
 11991187 
 12001188         if (flslvl)
 12011189                 return;
 12021190         c = sloscan();
 12031191         if (c != WSPACE && c != '\n')
 12041192                 error("bad warning");
 12051193 
 12061194         /* svinp() add an unwanted \n */
 12071195         cp = stringbuf;
 12081196         while ((c = inch()) && c != '\n')
 12091197                 savch(c);
 12101198         savch(0);
 12111199 
 12121200         if (flslvl)
 12131201                 stringbuf = cp;
 12141202         else
 12151203                 warning("#warning %s", cp);
 12161204 
 12171205         unch('\n');
 12181206 }
 12191207 
 12201208 static void
 12211209 undefstmt(void)
 12221210 {
 12231211         struct symtab *np;
 12241212 
 12251213         if (flslvl)
 12261214                 return;
 12271215         if (sloscan() != WSPACE || sloscan() != IDENT)
 12281216                 error("bad undef");
 12291217         if (flslvl == 0 && (np = lookup(yytext, FIND)))
 12301218                 np->value = 0;
 12311219         chknl(0);
 12321220 }
 12331221 
 12341222 static void
 12351223 pragmastmt(void)
 12361224 {
 12371225         int c;
 12381226         usch *sb = stringbuf;
 12391227 
 12401228         if (sloscan() != WSPACE)
 12411229                 error("bad pragma");
 12421230         savstr((const usch *)"\n#pragma ");
 12431231         do {
 12441232                 savch(c = inch());
 12451233         } while (c && c != '\n');
 12461234         if (c == '\n')
 12471235                 unch(c);
 12481236         savch(0);
 12491237         if (!flslvl)
 12501238                 putstr(sb);
 12511239         stringbuf = sb;
 12521240         prtline();
 12531241 }
 12541242 
 12551243 static void
 12561244 badop(const char *op)
 12571245 {
 12581246         error("invalid operator in preprocessor expression: %s", op);
 12591247 }
 12601248 
 12611249 int
 12621250 cinput(void)
 12631251 {
 12641252         return inch();
 12651253 }
 12661254 
 12671255 /*
 12681256  * Check for (and convert) trigraphs.
 12691257  */
 12701258 int
 12711259 chktg(void)
 12721260 {
 12731261         int c;
 12741262 
 12751263         if ((c = inpch()) != '?') {
 12761264                 unch(c);
 12771265                 return 0;
 12781266         }
 12791267         switch (c = inpch()) {
 12801268         case '=': c = '#'; break;
 12811269         case '(': c = '['; break;
 12821270         case ')': c = ']'; break;
 12831271         case '<': c = '{'; break;
 12841272         case '>': c = '}'; break;
 12851273         case '/': c = '\\'; break;
 12861274         case '\'': c = '^'; break;
 12871275         case '!': c = '|'; break;
 12881276         case '-': c = '~'; break;
 12891277         default:
 12901278                 unch(c);
 12911279                 unch('?');
 12921280                 c = 0;
 12931281         }
 12941282         return c;
 12951283 }
 12961284 
 12971285 static struct {
 12981286         const char *name;
 12991287         void (*fun)(void);
 13001288 } ppd[] = {
 13011289         { "ifndef", ifndefstmt },
 13021290         { "ifdef", ifdefstmt },
 13031291         { "if", ifstmt },
 13041292         { "include", include },
 13051293         { "else", elsestmt },
 13061294         { "endif", endifstmt },
 13071295         { "error", cpperror },
 13081296         { "warning", cppwarning },
 13091297         { "define", define },
 13101298         { "undef", undefstmt },
 13111299         { "line", line },
 13121300         { "pragma", pragmastmt },
 13131301         { "elif", elifstmt },
 13141302 #ifdef GCC_COMPAT
 13151303         { "include_next", include_next },
 13161304 #endif
 13171305 };
 13181306 
 13191307 /*
 13201308  * Handle a preprocessor directive.
 13211309  */
 13221310 void
 13231311 ppdir(void)
 13241312 {
 13251313         char bp[20];
 13261314         int ch, i;
 13271315 
 13281316         while ((ch = inch()) == ' ' || ch == '\t')
 13291317                 ;
 13301318         if (ch == '\n') { /* empty directive */
 13311319                 unch(ch);
 13321320                 return;
 13331321         }
 13341322         if (ch < 'a' || ch > 'z')
 13351323                 goto out; /* something else, ignore */
 13361324         i = 0;
 13371325         do {
 13381326                 bp[i++] = (usch)ch;
 13391327                 if (i == sizeof(bp)-1)
 13401328                         goto out; /* too long */
 13411329                 ch = inch();
 13421330         } while ((ch >= 'a' && ch <= 'z') || (ch == '_'));
 13431331         unch(ch);
 13441332         bp[i++] = 0;
 13451333 
 13461334         /* got keyword */
 13471335 #define SZ (int)(sizeof(ppd)/sizeof(ppd[0]))
 13481336         for (i = 0; i < SZ; i++)
 13491337                 if (bp[0] == ppd[i].name[0] && strcmp(bp, ppd[i].name) == 0)
 13501338                         break;
 13511339         if (i == SZ)
 13521340                 goto out;
 13531341 
 13541342         /* Found matching keyword */
 13551343         (*ppd[i].fun)();
 13561344         return;
 13571345 
 13581346 out:    while ((ch = inch()) != '\n' && ch != -1)
 13591347                 ;
 13601348         unch('\n');
 13611349 }
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-25 05:21 +0100