Quick Search:

Mode

Context

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

Other Diffs

Ignore

Blank Lines Whitespace: Expand:

Diff

1.59
 
1.60
 
MAIN:plunky:20110605084350
 
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;
<>84 -extern int dflag;
8584 
 8685 #define PUTCH(ch) if (!flslvl) putch(ch)
 8786 /* protection against recursion in #include */
 8887 #define MAX_INCLEVEL    100
 8988 static int inclevel;
 9089 
 9190 /* get next character unaltered */
 9291 #define NXTCH() (ifiles->curptr < ifiles->maxread ? *ifiles->curptr++ : inpch())
 9392 
 9493 usch yytext[CPPBUF];
 9594 
 9695 char spechr[256] = {
 9796         0,      0,      0,      0,      C_SPECC_SPEC0,      0,
 9897         0,      C_WSNLC_SPEC|C_WSNL,  0,
 9998         0,      C_WSNL0,      0,
 10099         0,      0,      0,      0,      0,      0,      0,      0,
 101100         0,      0,      0,      0,      0,      0,      0,      0,
 102101 
 103102         C_WSNLC_2,    C_SPEC0,      0,      0,      C_2,    C_SPEC,
 104103         0,      0,      0,      C_2,    0,      C_2,    0,      C_SPEC|C_2,
 105104         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 106105         C_I,    C_I,    0,      0,      C_2,    C_2,    C_2,    C_SPEC,
 107106 
 108107         0,      C_I,    C_I,    C_I,    C_I,    C_I|C_EP, C_I,  C_I,
 109108         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 110109         C_I|C_EP, C_I,  C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 111110         C_I,    C_I,    C_I,    0,      C_SPEC0,      0,      C_I,
 112111 
 113112         0,      C_I,    C_I,    C_I,    C_I,    C_I|C_EP, C_I,  C_I,
 114113         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 115114         C_I|C_EP, C_I,  C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 116115         C_I,    C_I,    C_I,    0,      C_2,    0,      0,      0,
 117116 
 118117 };
 119118 
 120119 /*
 121120  * No-replacement array.  If a macro is found and exists in this array
 122121  * then no replacement shall occur.  This is a stack.
 123122  */
 124123 struct symtab *norep[RECMAX];   /* Symbol table index table */
 125124 int norepptr = 1;                       /* Top of index table */
 126125 unsigned short bptr[RECMAX];    /* currently active noexpand macro stack */
 127126 int bidx;                       /* Top of bptr stack */
 128127 
 129128 static void
 130129 unch(int c)
 131130 {
 132131                 
 133132         --ifiles->curptr;
 134133         if (ifiles->curptr < ifiles->bbuf)
 135134                 error("pushback buffer full");
 136135         *ifiles->curptr = (usch)c;
 137136 }
 138137 
 139138 static int
 140139 eatcmnt(void)
 141140 {
 142141         int ch;
 143142 
 144143         if (Cflag) { PUTCH('/'); PUTCH('*'); }
 145144         for (;;) {
 146145                 ch = inch();
 147146                 if (ch == '\n') {
 148147                         ifiles->lineno++;
 149148                         PUTCH('\n');
 150149                 }
 151150                 if (ch == -1)
 152151                         return -1;
 153152                 if (ch == '*') {
 154153                         ch = inch();
 155154                         if (ch == '/') {
 156155                                 if (Cflag) {
 157156                                         PUTCH('*');
 158157                                         PUTCH('/');
 159158                                 } else
 160159                                         PUTCH(' ');
 161160                                 break;
 162161                         }
 163162                         unch(ch);
 164163                         ch = '*';
 165164                 }
 166165                 if (Cflag) PUTCH(ch);
 167166         }
 168167         return 0;
 169168 }
 170169 
 171170 /*
 172171  * Scan quickly the input file searching for:
 173172  *      - '#' directives
 174173  *      - keywords (if not flslvl)
 175174  *      - comments
 176175  *
 177176  *      Handle strings, numbers and trigraphs with care.
 178177  *      Only data from pp files are scanned here, never any rescans.
 179178  *      TODO: Only print out strings before calling other functions.
 180179  */
 181180 static void
 182181 fastscan(void)
 183182 {
 184183         struct symtab *nl;
 185184         int ch, i = 0;
 186185         int nnl = 0;
 187186         usch *cp;
 188187 
 189188         goto run;
 190189         for (;;) {
 191190                 ch = NXTCH();
 192191 xloop:          if (ch == -1)
 193192                         return;
<> 193+#ifdef PCC_DEBUG
194194                 if (dflag>1)
 195195                         printf("fastscan ch %d (%c)\n", ch, ch > 31 ? ch : '@');
<> 196+#endif
<_196197                 if ((spechr[ch] & C_SPEC) == 0) {
 197198                         PUTCH(ch);
 198199                         continue;
 199200                 }
 200201                 switch (ch) {
 201202                 case EBLOCK:
 202203                 case WARN:
 203204                 case CONC:
 204205                         error("bad char passed");
 205206                         break;
 206207 
 207208                 case '/': /* Comments */
 208209                         if ((ch = inch()) == '/') {
 209210 cppcmt:                         if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
 210211                                 do {
 211212                                         if (Cflag) PUTCH(ch);
 212213                                         ch = inch();
 213214                                 } while (ch != -1 && ch != '\n');
 214215                                 goto xloop;
 215216                         } else if (ch == '*') {
 216217                                 if (eatcmnt())
 217218                                         return;
 218219                         } else {
 219220                                 PUTCH('/');
 220221                                 goto xloop;
 221222                         }
 222223                         break;
 223224 
 224225                 case '?'/* trigraphs */
 225226                         if ((ch = chktg()))
 226227                                 goto xloop;
 227228                         PUTCH('?');
 228229                         break;
 229230 
 230231                 case '\\':
 231232                         if ((ch = NXTCH()) == '\n') {
 232233                                 ifiles->lineno++;
 233234                                 continue;
 234235                         } else {
 235236                                 PUTCH('\\');
 236237                         }
 237238                         goto xloop;
 238239 
 239240                 case '\n': /* newlines, for pp directives */
 240241                         while (nnl > 0) { PUTCH('\n'); nnl--; }
 241242 run2:                   ifiles->lineno++;
 242243                         do {
 243244                                 PUTCH(ch);
 244245 run:                            ch = NXTCH();
 245246                                 if (ch == '/') {
 246247                                         ch = NXTCH();
 247248                                         if (ch == '/')
 248249                                                 goto cppcmt;
 249250                                         if (ch == '*') {
 250251                                                 if (eatcmnt())
 251252                                                         return;
 252253                                                 goto run;
 253254                                         }
 254255                                         unch(ch);
 255256                                         ch = '/';
 256257                                 }
 257258                         } while (ch == ' ' || ch == '\t');
 258259                         if (ch == '\\') {
 259260                                 ch = NXTCH();
 260261                                 if (ch == '\n')
 261262                                         goto run2;
 262263                                 unch(ch);
 263264                                 ch = '\\';
 264265                         }
 265266                         if (ch == '#') {
 266267                                 ppdir();
 267268                                 continue;
 268269                         } else if (ch == '%') {
 269270                                 ch = NXTCH();
 270271                                 if (ch == ':') {
 271272                                         ppdir();
 272273                                         continue;
 273274                                 } else {
 274275                                         unch(ch);
 275276                                         ch = '%';
 276277                                 }
 277278                         } else if (ch == '?') {
 278279                                 if ((ch = chktg()) == '#') {
 279280                                         ppdir();
 280281                                         continue;
 281282                                 } else if (ch == 0)
 282283                                         ch = '?';
 283284                         }
 284285                         goto xloop;
 285286 
 286287                 case '\"': /* strings */
 287288 str:                    PUTCH(ch);
 288289                         while ((ch = NXTCH()) != '\"') {
 289290                                 if (ch == '\n')
 290291                                         goto xloop;
 291292                                 if (ch == '\\') {
 292293                                         if ((ch = NXTCH()) != '\n') {
 293294                                                 PUTCH('\\');
 294295                                                 PUTCH(ch);
 295296                                         } else
 296297                                                 nnl++;
 297298                                         continue;
 298299                                 }
 299300                                 if (ch < 0)
 300301                                         return;
 301302                                 PUTCH(ch);
 302303                         }
 303304                         PUTCH(ch);
 304305                         break;
 305306 
 306307                 case '.'/* for pp-number */
 307308                         PUTCH(ch);
 308309                         ch = NXTCH();
 309310                         if (ch < '0' || ch > '9')
 310311                                 goto xloop;
 311312                         /* FALLTHROUGH */
 312313                 case '0': case '1': case '2': case '3': case '4':
 313314                 case '5': case '6': case '7': case '8': case '9':
 314315                         do {
 315316                                 PUTCH(ch);
 316317 nxt:                            ch = NXTCH();
 317318                                 if (ch == '\\') {
 318319                                         ch = NXTCH();
 319320                                         if (ch == '\n') {
 320321                                                 goto nxt;
 321322                                         } else {
 322323                                                 unch(ch);
 323324                                                 ch = '\\';
 324325                                         }
 325326                                 }
 326327                                 if (spechr[ch] & C_EP) {
 327328                                         PUTCH(ch);
 328329                                         ch = NXTCH();
 329330                                         if (ch == '-' || ch == '+')
 330331                                                 continue;
 331332                                 }
 332333                         } while ((spechr[ch] & C_ID) || (ch == '.'));
 333334                         goto xloop;
 334335 
 335336                 case '\'': /* character literal */
 336337 con:                    PUTCH(ch);
 337338                         if (tflag)
 338339                                 continue; /* character constants ignored */
 339340                         while ((ch = NXTCH()) != '\'') {
 340341                                 if (ch == '\n')
 341342                                         goto xloop;
 342343                                 if (ch == '\\') {
 343344                                         if ((ch = NXTCH()) != '\n') {
 344345                                                 PUTCH('\\');
 345346                                                 PUTCH(ch);
 346347                                         } else
 347348                                                 nnl++;
 348349                                         continue;
 349350                                 }
 350351                                 if (ch < 0)
 351352                                         return;
 352353                                 PUTCH(ch);
 353354                         }
 354355                         PUTCH(ch);
 355356                         break;
 356357 
 357358                 case 'L':
 358359                         ch = NXTCH();
 359360                         if (ch == '\"') {
 360361                                 PUTCH('L');
 361362                                 goto str;
 362363                         }
 363364                         if (ch == '\'') {
 364365                                 PUTCH('L');
 365366                                 goto con;
 366367                         }
 367368                         unch(ch);
 368369                         ch = 'L';
 369370                         /* FALLTHROUGH */
 370371                 default:
 371372                         if ((spechr[ch] & C_ID) == 0)
 372373                                 error("fastscan");
 373374                         if (flslvl) {
 374375                                 while (spechr[ch] & C_ID)
 375376                                         ch = NXTCH();
 376377                                 goto xloop;
 377378                         }
 378379                         i = 0;
 379380                         do {
 380381                                 yytext[i++] = (usch)ch;
 381382                                 ch = NXTCH();
 382383                                 if (ch == '\\') {
 383384                                         ch = NXTCH();
 384385                                         if (ch != '\n') {
 385386                                                 unch(ch);
 386387                                                 ch = '\\';
 387388                                         } else {
 388389                                                 putch('\n');
 389390                                                 ifiles->lineno++;
 390391                                                 ch = NXTCH();
 391392                                         }
 392393                                 }
 393394                                 if (ch < 0)
 394395                                         return;
 395396                         } while (spechr[ch] & C_ID);
 396397 
 397398                         yytext[i] = 0;
 398399                         unch(ch);
 399400 
 400401                         cp = stringbuf;
 401402                         if ((nl = lookup((usch *)yytext, FIND)) && kfind(nl)) {
 402403                                 putstr(stringbuf);
 403404                         } else
 404405                                 putstr((usch *)yytext);
 405406                         stringbuf = cp;
 406407 
 407408                         break;
 408409                 }
 409410         }
 410411 }
 411412 
 412413 int
 413414 sloscan()
 414415 {
 415416         int ch;
 416417         int yyp;
 417418 
 418419 zagain:
 419420         yyp = 0;
 420421         ch = inch();
 421422         yytext[yyp++] = (usch)ch;
 422423         switch (ch) {
 423424         case -1:
 424425                 return 0;
 425426         case '\n':
 426427                 /* sloscan() never passes \n, that's up to fastscan() */
 427428                 unch(ch);
 428429                 goto yyret;
 429430 
 430431         case '\r': /* Ignore CR's */
 431432                 yyp = 0;
 432433                 break;
 433434 
 434435         case '0': case '1': case '2': case '3': case '4': case '5':
 435436         case '6': case '7': case '8': case '9':
 436437                 /* readin a "pp-number" */
 437438 ppnum:          for (;;) {
 438439                         ch = inch();
 439440                         if (spechr[ch] & C_EP) {
 440441                                 yytext[yyp++] = (usch)ch;
 441442                                 ch = inch();
 442443                                 if (ch == '-' || ch == '+') {
 443444                                         yytext[yyp++] = (usch)ch;
 444445                                 } else
 445446                                         unch(ch);
 446447                                 continue;
 447448                         }
 448449                         if ((spechr[ch] & C_ID) || ch == '.') {
 449450                                 yytext[yyp++] = (usch)ch;
 450451                                 continue;
 451452                         }
 452453                         break;
 453454                 }
 454455                 unch(ch);
 455456                 yytext[yyp] = 0;
 456457 
 457458                 return NUMBER;
 458459 
 459460         case '\'':
 460461 chlit:          
 461462                 for (;;) {
 462463                         if ((ch = inch()) == '\\') {
 463464                                 yytext[yyp++] = (usch)ch;
 464465                                 yytext[yyp++] = (usch)inch();
 465466                                 continue;
 466467                         } else if (ch == '\n') {
 467468                                 /* not a constant */
 468469                                 while (yyp > 1)
 469470                                         unch(yytext[--yyp]);
 470471                                 ch = '\'';
 471472                                 goto any;
 472473                         } else
 473474                                 yytext[yyp++] = (usch)ch;
 474475                         if (ch == '\'')
 475476                                 break;
 476477                 }
 477478                 yytext[yyp] = 0;
 478479 
 479480                 return (NUMBER);
 480481 
 481482         case ' ':
 482483         case '\t':
 483484                 while ((ch = inch()) == ' ' || ch == '\t')
 484485                         yytext[yyp++] = (usch)ch;
 485486                 unch(ch);
 486487                 yytext[yyp] = 0;
 487488                 return(WSPACE);
 488489 
 489490         case '/':
 490491                 if ((ch = inch()) == '/') {
 491492                         do {
 492493                                 yytext[yyp++] = (usch)ch;
 493494                                 ch = inch();
 494495                         } while (ch && ch != '\n');
 495496                         yytext[yyp] = 0;
 496497                         unch(ch);
 497498                         goto zagain;
 498499                 } else if (ch == '*') {
 499500                         int c, wrn;
 500501                         extern int readmac;
 501502 
 502503                         if (Cflag && !flslvl && readmac) {
 503504                                 unch(ch);
 504505                                 yytext[yyp] = 0;
 505506                                 return CMNT;
 506507                         }
 507508 
 508509                         wrn = 0;
 509510                 more:   while ((c = inch()) && c != '*') {
 510511                                 if (c == '\n')
 511512                                         putch(c), ifiles->lineno++;
 512513                                 else if (c == EBLOCK) {
 513514                                         (void)inch();
 514515                                         (void)inch();
 515516                                 } else if (c == 1) /* WARN */
 516517                                         wrn = 1;
 517518                         }
 518519                         if (c == 0)
 519520                                 return 0;
 520521                         if ((c = inch()) && c != '/') {
 521522                                 unch(c);
 522523                                 goto more;
 523524                         }
 524525                         if (c == 0)
 525526                                 return 0;
 526527                         if (!tflag && !Cflag && !flslvl)
 527528                                 unch(' ');
 528529                         if (wrn)
 529530                                 unch(1);
 530531                         goto zagain;
 531532                 }
 532533                 unch(ch);
 533534                 ch = '/';
 534535                 goto any;
 535536 
 536537         case '.':
 537538                 ch = inch();
 538539                 if (isdigit(ch)) {
 539540                         yytext[yyp++] = (usch)ch;
 540541                         goto ppnum;
 541542                 } else {
 542543                         unch(ch);
 543544                         ch = '.';
 544545                 }
 545546                 goto any;
 546547 
 547548         case '\"':
 548549                 if (tflag)
 549550                         goto any;
 550551         strng:
 551552                 for (;;) {
 552553                         if ((ch = inch()) == '\\') {
 553554                                 yytext[yyp++] = (usch)ch;
 554555                                 yytext[yyp++] = (usch)inch();
 555556                                 continue;
 556557                         } else
 557558                                 yytext[yyp++] = (usch)ch;
 558559                         if (ch == '\"')
 559560                                 break;
 560561                 }
 561562                 yytext[yyp] = 0;
 562563                 return(STRING);
 563564 
 564565         case 'L':
 565566                 if ((ch = inch()) == '\"' && !tflag) {
 566567                         yytext[yyp++] = (usch)ch;
 567568                         goto strng;
 568569                 } else if (ch == '\'' && !tflag) {
 569570                         yytext[yyp++] = (usch)ch;
 570571                         goto chlit;
 571572                 }
 572573                 unch(ch);
 573574                 /* FALLTHROUGH */
 574575 
 575576         /* Yetch, all identifiers */
 576577         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
 577578         case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
 578579         case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
 579580         case 's': case 't': case 'u': case 'v': case 'w': case 'x':
 580581         case 'y': case 'z':
 581582         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
 582583         case 'G': case 'H': case 'I': case 'J': case 'K':
 583584         case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
 584585         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
 585586         case 'Y': case 'Z':
 586587         case '_': /* {L}({L}|{D})* */
 587588 
 588589                 /* Special hacks */
 589590                 for (;;) { /* get chars */
 590591                         ch = inch();
 591592                         if (isalpha(ch) || isdigit(ch) || ch == '_') {
 592593                                 yytext[yyp++] = (usch)ch;
 593594                         } else {
 594595                                 if (ch != -1)
 595596                                         unch(ch);
 596597                                 break;
 597598                         }
 598599                 }
 599600                 yytext[yyp] = 0; /* need already string */
 600601                 /* end special hacks */
 601602 
 602603                 return IDENT;
 603604         default:
 604605         any:
 605606                 yytext[yyp] = 0;
 606607                 return yytext[0];
 607608 
 608609         } /* endcase */
 609610         goto zagain;
 610611 
 611612 yyret:
 612613         yytext[yyp] = 0;
 613614         return ch;
 614615 }
 615616 
 616617 int
 617618 yylex()
 618619 {
 619620         static int ifdef, noex;
 620621         struct symtab *nl;
 621622         int ch, c2;
 622623 
 623624         while ((ch = sloscan()) == WSPACE)
 624625                 ;
 625626         if (ch < 128 && spechr[ch] & C_2)
 626627                 c2 = inpch();
 627628         else
 628629                 c2 = 0;
 629630 
 630631 #define C2(a,b,c) case a: if (c2 == b) return c; break
 631632         switch (ch) {
 632633         C2('=', '=', EQ);
 633634         C2('!', '=', NE);
 634635         C2('|', '|', OROR);
 635636         C2('&', '&', ANDAND);
 636637         case '<':
 637638                 if (c2 == '<') return LS;
 638639                 if (c2 == '=') return LE;
 639640                 break;
 640641         case '>':
 641642                 if (c2 == '>') return RS;
 642643                 if (c2 == '=') return GE;
 643644                 break;
 644645         case '+':
 645646         case '-':
 646647                 if (ch == c2)
 647648                         badop("");
 648649                 break;
 649650 
 650651         case '/':
 651652                 if (Cflag == 0 || c2 != '*')
 652653                         break;
 653654                 /* Found comment that need to be skipped */
 654655                 for (;;) {
 655656                         ch = inpch();
 656657                 c1:     if (ch != '*')
 657658                                 continue;
 658659                         if ((ch = inpch()) == '/')
 659660                                 break;
 660661                         goto c1;
 661662                 }
 662663                 return yylex();
 663664 
 664665         case NUMBER:
 665666                 if (yytext[0] == '\'') {
 666667                         yylval.node.op = NUMBER;
 667668                         yylval.node.nd_val = charcon((usch *)yytext);
 668669                 } else
 669670                         cvtdig(yytext[0] != '0' ? 10 :
 670671                             yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
 671672                 return NUMBER;
 672673 
 673674         case IDENT:
 674675                 if (strcmp((char *)yytext, "defined") == 0) {
 675676                         ifdef = 1;
 676677                         return DEFINED;
 677678                 }
 678679                 nl = lookup((usch *)yytext, FIND);
 679680                 if (ifdef) {
 680681                         yylval.node.nd_val = nl != NULL;
 681682                         ifdef = 0;
 682683                 } else if (nl && noex == 0) {
 683684                         usch *och = stringbuf;
 684685                         int i;
 685686 
 686687                         i = kfind(nl);
 687688                         unch(WARN);
 688689                         if (i)
 689690                                 unpstr(stringbuf);
 690691                         else
 691692                                 unpstr(nl->namep);
 692693                         stringbuf = och;
 693694                         noex = 1;
 694695                         return yylex();
 695696                 } else {
 696697                         yylval.node.nd_val = 0;
 697698                 }
 698699                 yylval.node.op = NUMBER;
 699700                 return NUMBER;
 700701         case WARN:
 701702                 noex = 0;
 702703                 return yylex();
 703704         default:
 704705                 return ch;
 705706         }
 706707         unch(c2);
 707708         return ch;
 708709 }
 709710 
 710711 usch *yyp, yybuf[CPPBUF];
 711712 
 712713 int yywrap(void);
 713714 
 714715 static int
 715716 inpch(void)
 716717 {
 717718         int len;
 718719 
 719720         if (ifiles->curptr < ifiles->maxread)
 720721                 return *ifiles->curptr++;
 721722 
 722723         if (ifiles->infil == -1)
 723724                 return -1;
 724725         if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0)
 725726                 error("read error on file %s", ifiles->orgfn);
 726727         if (len == 0)
 727728                 return -1;
 728729         ifiles->curptr = ifiles->buffer;
 729730         ifiles->maxread = ifiles->buffer + len;
 730731         return inpch();
 731732 }
 732733 
 733734 static int
 734735 inch(void)
 735736 {
 736737         int c;
 737738 
 738739 again:  switch (c = inpch()) {
 739740         case '\\': /* continued lines */
 740741 msdos:          if ((c = inpch()) == '\n') {
 741742                         ifiles->lineno++;
 742743                         goto again;
 743744                 } else if (c == '\r')
 744745                         goto msdos;
 745746                 unch(c);
 746747                 return '\\';
 747748         case '?': /* trigraphs */
 748749                 if ((c = chktg())) {
 749750                         unch(c);
 750751                         goto again;
 751752                 }
 752753                 return '?';
 753754         default:
 754755                 return c;
 755756         }
 756757 }
 757758 
 758759 /*
 759760  * Let the command-line args be faked defines at beginning of file.
 760761  */
 761762 static void
 762763 prinit(struct initar *it, struct includ *ic)
 763764 {
 764765         const char *pre, *post;
 765766         char *a;
 766767 
 767768         if (it->next)
 768769                 prinit(it->next, ic);
 769770         pre = post = NULL; /* XXX gcc */
 770771         switch (it->type) {
 771772         case 'D':
 772773                 pre = "#define ";
 773774                 if ((a = strchr(it->str, '=')) != NULL) {
 774775                         *a = ' ';
 775776                         post = "\n";
 776777                 } else
 777778                         post = " 1\n";
 778779                 break;
 779780         case 'U':
 780781                 pre = "#undef ";
 781782                 post = "\n";
 782783                 break;
 783784         case 'i':
 784785                 pre = "#include \"";
 785786                 post = "\"\n";
 786787                 break;
 787788         default:
 788789                 error("prinit");
 789790         }
 790791         strlcat((char *)ic->buffer, pre, CPPBUF+1);
 791792         strlcat((char *)ic->buffer, it->str, CPPBUF+1);
 792793         if (strlcat((char *)ic->buffer, post, CPPBUF+1) >= CPPBUF+1)
 793794                 error("line exceeds buffer size");
 794795 
 795796         ic->lineno--;
 796797         while (*ic->maxread)
 797798                 ic->maxread++;
 798799 }
 799800 
 800801 /*
 801802  * A new file included.
 802803  * If ifiles == NULL, this is the first file and already opened (stdin).
 803804  * Return 0 on success, -1 if file to be included is not found.
 804805  */
 805806 int
 806807 pushfile(const usch *file, const usch *fn, int idx, void *incs)
 807808 {
 808809         extern struct initar *initar;
 809810         struct includ ibuf;
 810811         struct includ *ic;
 811812         int otrulvl;
 812813 
 813814         ic = &ibuf;
 814815         ic->next = ifiles;
 815816 
 816817         if (file != NULL) {
 817818                 if ((ic->infil = open((const char *)file, O_RDONLY)) < 0)
 818819                         return -1;
 819820                 ic->orgfn = ic->fname = file;
 820821                 if (++inclevel > MAX_INCLEVEL)
 821822                         error("Limit for nested includes exceeded");
 822823         } else {
 823824                 ic->infil = 0;
 824825                 ic->orgfn = ic->fname = (const usch *)"<stdin>";
 825826         }
 826827 #ifndef BUF_STACK
 827828         ic->bbuf = malloc(BBUFSZ);
 828829 #endif
 829830         ic->buffer = ic->bbuf+NAMEMAX;
 830831         ic->curptr = ic->buffer;
 831832         ifiles = ic;
 832833         ic->lineno = 1;
 833834         ic->maxread = ic->curptr;
 834835         ic->idx = idx;
 835836         ic->incs = incs;
 836837         ic->fn = fn;
 837838         prtline();
 838839         if (initar) {
 839840                 int oin = ic->infil;
 840841                 ic->infil = -1;
 841842                 *ic->maxread = 0;
 842843                 prinit(initar, ic);
 843844                 initar = NULL;
 844845                 if (dMflag)
 845846                         write(ofd, ic->buffer, strlen((char *)ic->buffer));
 846847                 fastscan();
 847848                 prtline();
 848849                 ic->infil = oin;
 849850         }
 850851 
 851852         otrulvl = trulvl;
 852853 
 853854         fastscan();
 854855 
 855856         if (otrulvl != trulvl || flslvl)
 856857                 error("unterminated conditional");
 857858 
 858859 #ifndef BUF_STACK
 859860         free(ic->bbuf);
 860861 #endif
 861862         ifiles = ic->next;
 862863         close(ic->infil);
 863864         inclevel--;
 864865         return 0;
 865866 }
 866867 
 867868 /*
 868869  * Print current position to output file.
 869870  */
 870871 void
 871872 prtline()
 872873 {
 873874         usch *s, *os = stringbuf;
 874875 
 875876         if (Mflag) {
 876877                 if (dMflag)
 877878                         return; /* no output */
 878879                 if (ifiles->lineno == 1) {
 879880                         s = sheap("%s: %s\n", Mfile, ifiles->fname);
 880881                         write(ofd, s, strlen((char *)s));
 881882                 }
 882883         } else if (!Pflag)
 883884                 putstr(sheap("\n# %d \"%s\"\n", ifiles->lineno, ifiles->fname));
 884885         stringbuf = os;
 885886 }
 886887 
 887888 void
 888889 cunput(int c)
 889890 {
 890891 #ifdef PCC_DEBUG
 891892 //      extern int dflag;
 892893 //      if (dflag)printf(": '%c'(%d)\n", c > 31 ? c : ' ', c);
 893894 #endif
 894895 #if 0
 895896 if (c == 10) {
 896897         printf("c == 10!!!\n");
 897898 }
 898899 #endif
 899900         unch(c);
 900901 }
 901902 
 902903 int yywrap(void) { return 1; }
 903904 
 904905 static int
 905906 dig2num(int c)
 906907 {
 907908         if (c >= 'a')
 908909                 c = c - 'a' + 10;
 909910         else if (c >= 'A')
 910911                 c = c - 'A' + 10;
 911912         else
 912913                 c = c - '0';
 913914         return c;
 914915 }
 915916 
 916917 /*
 917918  * Convert string numbers to unsigned long long and check overflow.
 918919  */
 919920 static void
 920921 cvtdig(int rad)
 921922 {
 922923         unsigned long long rv = 0;
 923924         unsigned long long rv2 = 0;
 924925         usch *y = yytext;
 925926         int c;
 926927 
 927928         c = *y++;
 928929         if (rad == 16)
 929930                 y++;
 930931         while (isxdigit(c)) {
 931932                 rv = rv * rad + dig2num(c);
 932933                 /* check overflow */
 933934                 if (rv / rad < rv2)
 934935                         error("Constant \"%s\" is out of range", yytext);
 935936                 rv2 = rv;
 936937                 c = *y++;
 937938         }
 938939         y--;
 939940         while (*y == 'l' || *y == 'L')
 940941                 y++;
 941942         yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER;
 942943         yylval.node.nd_uval = rv;
 943944         if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0)
 944945                 yylval.node.op = UNUMBER;
 945946         if (yylval.node.op == NUMBER && yylval.node.nd_val < 0)
 946947                 /* too large for signed, see 6.4.4.1 */
 947948                 error("Constant \"%s\" is out of range", yytext);
 948949 }
 949950 
 950951 static int
 951952 charcon(usch *p)
 952953 {
 953954         int val, c;
 954955 
 955956         p++; /* skip first ' */
 956957         val = 0;
 957958         if (*p++ == '\\') {
 958959                 switch (*p++) {
 959960                 case 'a': val = '\a'; break;
 960961                 case 'b': val = '\b'; break;
 961962                 case 'f': val = '\f'; break;
 962963                 case 'n': val = '\n'; break;
 963964                 case 'r': val = '\r'; break;
 964965                 case 't': val = '\t'; break;
 965966                 case 'v': val = '\v'; break;
 966967                 case '\"': val = '\"'; break;
 967968                 case '\'': val = '\''; break;
 968969                 case '\\': val = '\\'; break;
 969970                 case 'x':
 970971                         while (isxdigit(c = *p)) {
 971972                                 val = val * 16 + dig2num(c);
 972973                                 p++;
 973974                         }
 974975                         break;
 975976                 case '0': case '1': case '2': case '3': case '4':
 976977                 case '5': case '6': case '7':
 977978                         p--;
 978979                         while (isdigit(c = *p)) {
 979980                                 val = val * 8 + (c - '0');
 980981                                 p++;
 981982                         }
 982983                         break;
 983984                 default: val = p[-1];
 984985                 }
 985986 
 986987         } else
 987988                 val = p[-1];
 988989         return val;
 989990 }
 990991 
 991992 static void
 992993 chknl(int ignore)
 993994 {
 994995         int t;
 995996 
 996997         while ((t = sloscan()) == WSPACE)
 997998                 ;
 998999         if (t != '\n') {
 9991000                 if (ignore) {
 10001001                         warning("newline expected, got \"%s\"", yytext);
 10011002                         /* ignore rest of line */
 10021003                         while ((t = sloscan()) && t != '\n')
 10031004                                 ;
 10041005                 }
 10051006                 else
 10061007                         error("newline expected, got \"%s\"", yytext);
 10071008         }
 10081009 }
 10091010 
 10101011 static void
 10111012 elsestmt(void)
 10121013 {
 10131014         if (flslvl) {
 10141015                 if (elflvl > trulvl)
 10151016                         ;
 10161017                 else if (--flslvl!=0) {
 10171018                         flslvl++;
 10181019                 } else {
 10191020                         trulvl++;
 10201021                         prtline();
 10211022                 }
 10221023         } else if (trulvl) {
 10231024                 flslvl++;
 10241025                 trulvl--;
 10251026         } else
 10261027                 error("If-less else");
 10271028         if (elslvl==trulvl+flslvl)
 10281029                 error("Too many else");
 10291030         elslvl=trulvl+flslvl;
 10301031         chknl(1);
 10311032 }
 10321033 
 10331034 static void
 10341035 skpln(void)
 10351036 {
 10361037         /* just ignore the rest of the line */
 10371038         while (inch() != '\n')
 10381039                 ;
 10391040         unch('\n');
 10401041         flslvl++;
 10411042 }
 10421043 
 10431044 static void
 10441045 ifdefstmt(void)         
 10451046 {
 10461047         int t;
 10471048 
 10481049         if (flslvl) {
 10491050                 skpln();
 10501051                 return;
 10511052         }
 10521053         do
 10531054                 t = sloscan();
 10541055         while (t == WSPACE);
 10551056         if (t != IDENT)
 10561057                 error("bad ifdef");
 10571058         if (lookup((usch *)yytext, FIND) == 0) {
 10581059                 putch('\n');
 10591060                 flslvl++;
 10601061         } else
 10611062                 trulvl++;
 10621063         chknl(0);
 10631064 }
 10641065 
 10651066 static void
 10661067 ifndefstmt(void)         
 10671068 {
 10681069         int t;
 10691070 
 10701071         if (flslvl) {
 10711072                 skpln();
 10721073                 return;
 10731074         }
 10741075         do
 10751076                 t = sloscan();
 10761077         while (t == WSPACE);
 10771078         if (t != IDENT)
 10781079                 error("bad ifndef");
 10791080         if (lookup((usch *)yytext, FIND) != 0) {
 10801081                 putch('\n');
 10811082                 flslvl++;
 10821083         } else
 10831084                 trulvl++;
 10841085         chknl(0);
 10851086 }
 10861087 
 10871088 static void
 10881089 endifstmt(void)         
 10891090 {
 10901091         if (flslvl) {
 10911092                 flslvl--;
 10921093                 if (flslvl == 0) {
 10931094                         putch('\n');
 10941095                         prtline();
 10951096                 }
 10961097         } else if (trulvl)
 10971098                 trulvl--;
 10981099         else
 10991100                 error("If-less endif");
 11001101         if (flslvl == 0)
 11011102                 elflvl = 0;
 11021103         elslvl = 0;
 11031104         chknl(1);
 11041105 }
 11051106 
 11061107 static void
 11071108 ifstmt(void)
 11081109 {
 11091110         if (flslvl == 0) {
 11101111                 if (yyparse() == 0) {
 11111112                         putch('\n');
 11121113                         ++flslvl;
 11131114                 } else
 11141115                         ++trulvl;
 11151116         } else
 11161117                 ++flslvl;
 11171118 }
 11181119 
 11191120 static void
 11201121 elifstmt(void)
 11211122 {
 11221123         if (flslvl == 0)
 11231124                 elflvl = trulvl;
 11241125         if (flslvl) {
 11251126                 if (elflvl > trulvl)
 11261127                         ;
 11271128                 else if (--flslvl!=0)
 11281129                         ++flslvl;
 11291130                 else {
 11301131                         if (yyparse()) {
 11311132                                 ++trulvl;
 11321133                                 prtline();
 11331134                         } else {
 11341135                                 putch('\n');
 11351136                                 ++flslvl;
 11361137                         }
 11371138                 }
 11381139         } else if (trulvl) {
 11391140                 ++flslvl;
 11401141                 --trulvl;
 11411142         } else
 11421143                 error("If-less elif");
 11431144 }
 11441145 
 11451146 static usch *
 11461147 svinp(void)
 11471148 {
 11481149         int c;
 11491150         usch *cp = stringbuf;
 11501151 
 11511152         while ((c = inch()) && c != '\n')
 11521153                 savch(c);
 11531154         savch('\n');
 11541155         savch(0);
 11551156         return cp;
 11561157 }
 11571158 
 11581159 static void
 11591160 cpperror(void)
 11601161 {
 11611162         usch *cp;
 11621163         int c;
 11631164 
 11641165         if (flslvl)
 11651166                 return;
 11661167         c = sloscan();
 11671168         if (c != WSPACE && c != '\n')
 11681169                 error("bad error");
 11691170         cp = svinp();
 11701171         if (flslvl)
 11711172                 stringbuf = cp;
 11721173         else
 11731174                 error("%s", cp);
 11741175 }
 11751176 
 11761177 static void
 11771178 cppwarning(void)
 11781179 {
 11791180         usch *cp;
 11801181         int c;
 11811182 
 11821183         if (flslvl)
 11831184                 return;
 11841185         c = sloscan();
 11851186         if (c != WSPACE && c != '\n')
 11861187                 error("bad warning");
 11871188 
 11881189         /* svinp() add an unwanted \n */
 11891190         cp = stringbuf;
 11901191         while ((c = inch()) && c != '\n')
 11911192                 savch(c);
 11921193         savch(0);
 11931194 
 11941195         if (flslvl)
 11951196                 stringbuf = cp;
 11961197         else
 11971198                 warning("#warning %s", cp);
 11981199 
 11991200         unch('\n');
 12001201 }
 12011202 
 12021203 static void
 12031204 undefstmt(void)
 12041205 {
 12051206         struct symtab *np;
 12061207 
 12071208         if (flslvl)
 12081209                 return;
 12091210         if (sloscan() != WSPACE || sloscan() != IDENT)
 12101211                 error("bad undef");
 12111212         if (flslvl == 0 && (np = lookup((usch *)yytext, FIND)))
 12121213                 np->value = 0;
 12131214         chknl(0);
 12141215 }
 12151216 
 12161217 static void
 12171218 pragmastmt(void)
 12181219 {
 12191220         int c;
 12201221 
 12211222         if (sloscan() != WSPACE)
 12221223                 error("bad pragma");
 12231224         if (!flslvl)
 12241225                 putstr((const usch *)"\n#pragma ");
 12251226         do {
 12261227                 c = inch();
 12271228                 if (!flslvl)
 12281229                         putch(c);       /* Do arg expansion instead? */
 12291230         } while (c && c != '\n');
 12301231         if (c == '\n')
 12311232                 unch(c);
 12321233         prtline();
 12331234 }
 12341235 
 12351236 static void
 12361237 badop(const char *op)
 12371238 {
 12381239         error("invalid operator in preprocessor expression: %s", op);
 12391240 }
 12401241 
 12411242 int
 12421243 cinput()
 12431244 {
 12441245         return inch();
 12451246 }
 12461247 
 12471248 /*
 12481249  * Check for (and convert) trigraphs.
 12491250  */
 12501251 int
 12511252 chktg()
 12521253 {
 12531254         int c;
 12541255 
 12551256         if ((c = inpch()) != '?') {
 12561257                 unch(c);
 12571258                 return 0;
 12581259         }
 12591260         switch (c = inpch()) {
 12601261         case '=': c = '#'; break;
 12611262         case '(': c = '['; break;
 12621263         case ')': c = ']'; break;
 12631264         case '<': c = '{'; break;
 12641265         case '>': c = '}'; break;
 12651266         case '/': c = '\\'; break;
 12661267         case '\'': c = '^'; break;
 12671268         case '!': c = '|'; break;
 12681269         case '-': c = '~'; break;
 12691270         default:
 12701271                 unch(c);
 12711272                 unch('?');
 12721273                 c = 0;
 12731274         }
 12741275         return c;
 12751276 }
 12761277 
 12771278 static struct {
 12781279         const char *name;
 12791280         void (*fun)(void);
 12801281 } ppd[] = {
 12811282         { "ifndef", ifndefstmt },
 12821283         { "ifdef", ifdefstmt },
 12831284         { "if", ifstmt },
 12841285         { "include", include },
 12851286         { "else", elsestmt },
 12861287         { "endif", endifstmt },
 12871288         { "error", cpperror },
 12881289         { "warning", cppwarning },
 12891290         { "define", define },
 12901291         { "undef", undefstmt },
 12911292         { "line", line },
 12921293         { "pragma", pragmastmt },
 12931294         { "elif", elifstmt },
 12941295 #ifdef GCC_COMPAT
 12951296         { "include_next", include_next },
 12961297 #endif
 12971298 };
 12981299 
 12991300 /*
 13001301  * Handle a preprocessor directive.
 13011302  */
 13021303 void
 13031304 ppdir(void)
 13041305 {
 13051306         char bp[20];
 13061307         int ch, i;
 13071308 
 13081309         while ((ch = inch()) == ' ' || ch == '\t')
 13091310                 ;
 13101311         if (ch == '\n') { /* empty directive */
 13111312                 unch(ch);
 13121313                 return;
 13131314         }
 13141315         if (ch < 'a' || ch > 'z')
 13151316                 goto out; /* something else, ignore */
 13161317         i = 0;
 13171318         do {
 13181319                 bp[i++] = (usch)ch;
 13191320                 if (i == sizeof(bp)-1)
 13201321                         goto out; /* too long */
 13211322                 ch = inch();
 13221323         } while ((ch >= 'a' && ch <= 'z') || (ch == '_'));
 13231324         unch(ch);
 13241325         bp[i++] = 0;
 13251326 
 13261327         /* got keyword */
 13271328 #define SZ (int)(sizeof(ppd)/sizeof(ppd[0]))
 13281329         for (i = 0; i < SZ; i++)
 13291330                 if (bp[0] == ppd[i].name[0] && strcmp(bp, ppd[i].name) == 0)
 13301331                         break;
 13311332         if (i == SZ)
 13321333                 goto out;
 13331334 
 13341335         /* Found matching keyword */
 13351336         (*ppd[i].fun)();
 13361337         return;
 13371338 
 13381339 out:    while ((ch = inch()) != '\n' && ch != -1)
 13391340                 ;
 13401341         unch('\n');
 13411342 }
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-09-03 09:04 +0200