Quick Search:

Mode

Context

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

Other Diffs

Ignore

Blank Lines Whitespace: Expand:

Diff

1.61
 
1.62
 
MAIN:ragge:20110715105259
 
token.c
_>11 /*      $Id$    */
 22 
 33 /*
 44  * Copyright (c) 2004,2009 Anders Magnusson. All rights reserved.
 55  *
 66  * Redistribution and use in source and binary forms, with or without
 77  * modification, are permitted provided that the following conditions
 88  * are met:
 99  * 1. Redistributions of source code must retain the above copyright
 1010  *    notice, this list of conditions and the following disclaimer.
 1111  * 2. Redistributions in binary form must reproduce the above copyright
 1212  *    notice, this list of conditions and the following disclaimer in the
 1313  *    documentation and/or other materials provided with the distribution.
 1414  *
 1515  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 1616  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 1717  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 1818  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 1919  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 2020  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 2121  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 2222  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 2323  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 2424  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 2525  */
 2626 
 2727 /*
 2828  * Tokenizer for the C preprocessor.
 2929  * There are three main routines:
 3030  *      - fastscan() loops over the input stream searching for magic
 3131  *              characters that may require actions.
 3232  *      - sloscan() tokenize the input stream and returns tokens.
 3333  *              It may recurse into itself during expansion.
 3434  *      - yylex() returns something from the input stream that
 3535  *              is suitable for yacc.
 3636  *
 3737  *      Other functions of common use:
 3838  *      - inpch() returns a raw character from the current input stream.
 3939  *      - inch() is like inpch but \\n and trigraphs are expanded.
 4040  *      - unch() pushes back a character to the input stream.
 4141  */
 4242 
 4343 #include "config.h"
 4444 
 4545 #include <stdlib.h>
 4646 #include <string.h>
 4747 #include <ctype.h>
 4848 #ifdef HAVE_UNISTD_H
 4949 #include <unistd.h>
 5050 #endif
 5151 #include <fcntl.h>
 5252 #include <errno.h>
 5353 
 5454 #include "compat.h"
 5555 #include "cpp.h"
 5656 #include "y.tab.h"
 5757 
 5858 static void cvtdig(int rad);
 5959 static int charcon(usch *);
 6060 static void elsestmt(void);
 6161 static void ifdefstmt(void);
 6262 static void ifndefstmt(void);
 6363 static void endifstmt(void);
 6464 static void ifstmt(void);
 6565 static void cpperror(void);
 6666 static void pragmastmt(void);
 6767 static void undefstmt(void);
 6868 static void cppwarning(void);
 6969 static void elifstmt(void);
 7070 static void badop(const char *);
 7171 static int chktg(void);
 7272 static void ppdir(void);
 7373 void  include(void);
 7474 void  include_next(void);
 7575 void  define(void);
 7676 static int inpch(void);
 7777 
 7878 extern int yyget_lineno (void);
 7979 extern void yyset_lineno (int);
 8080 
 8181 static int inch(void);
 8282 
 8383 int inif;
 8484 
 8585 #define PUTCH(ch) if (!flslvl) putch(ch)
 8686 /* protection against recursion in #include */
 8787 #define MAX_INCLEVEL    100
 8888 static int inclevel;
 8989 
 9090 /* get next character unaltered */
 9191 #define NXTCH() (ifiles->curptr < ifiles->maxread ? *ifiles->curptr++ : inpch())
 9292 
 9393 usch yytext[CPPBUF];
 9494 
 9595 char spechr[256] = {
 9696         0,      0,      0,      0,      C_SPECC_SPEC0,      0,
 9797         0,      C_WSNLC_SPEC|C_WSNL,  0,
 9898         0,      C_WSNL0,      0,
 9999         0,      0,      0,      0,      0,      0,      0,      0,
 100100         0,      0,      0,      0,      0,      0,      0,      0,
 101101 
 102102         C_WSNLC_2,    C_SPEC0,      0,      0,      C_2,    C_SPEC,
 103103         0,      0,      0,      C_2,    0,      C_2,    0,      C_SPEC|C_2,
 104104         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 105105         C_I,    C_I,    0,      0,      C_2,    C_2,    C_2,    C_SPEC,
 106106 
 107107         0,      C_I,    C_I,    C_I,    C_I,    C_I|C_EP, C_I,  C_I,
 108108         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 109109         C_I|C_EP, C_I,  C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 110110         C_I,    C_I,    C_I,    0,      C_SPEC0,      0,      C_I,
 111111 
 112112         0,      C_I,    C_I,    C_I,    C_I,    C_I|C_EP, C_I,  C_I,
 113113         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 114114         C_I|C_EP, C_I,  C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 115115         C_I,    C_I,    C_I,    0,      C_2,    0,      0,      0,
 116116 
 117117 };
 118118 
 119119 /*
 120120  * No-replacement array.  If a macro is found and exists in this array
 121121  * then no replacement shall occur.  This is a stack.
 122122  */
 123123 struct symtab *norep[RECMAX];   /* Symbol table index table */
 124124 int norepptr = 1;                       /* Top of index table */
 125125 unsigned short bptr[RECMAX];    /* currently active noexpand macro stack */
 126126 int bidx;                       /* Top of bptr stack */
 127127 
 128128 static void
 129129 unch(int c)
 130130 {
 131131                 
 132132         --ifiles->curptr;
 133133         if (ifiles->curptr < ifiles->bbuf)
 134134                 error("pushback buffer full");
 135135         *ifiles->curptr = (usch)c;
 136136 }
 137137 
 138138 static int
 139139 eatcmnt(void)
 140140 {
 141141         int ch;
 142142 
 143143         if (Cflag) { PUTCH('/'); PUTCH('*'); }
 144144         for (;;) {
 145145                 ch = inch();
 146146                 if (ch == '\n') {
 147147                         ifiles->lineno++;
 148148                         PUTCH('\n');
 149149                 }
 150150                 if (ch == -1)
 151151                         return -1;
 152152                 if (ch == '*') {
 153153                         ch = inch();
 154154                         if (ch == '/') {
 155155                                 if (Cflag) {
 156156                                         PUTCH('*');
 157157                                         PUTCH('/');
 158158                                 } else
 159159                                         PUTCH(' ');
 160160                                 break;
 161161                         }
 162162                         unch(ch);
 163163                         ch = '*';
 164164                 }
 165165                 if (Cflag) PUTCH(ch);
 166166         }
 167167         return 0;
 168168 }
 169169 
 170170 /*
 171171  * Scan quickly the input file searching for:
 172172  *      - '#' directives
 173173  *      - keywords (if not flslvl)
 174174  *      - comments
 175175  *
 176176  *      Handle strings, numbers and trigraphs with care.
 177177  *      Only data from pp files are scanned here, never any rescans.
 178178  *      TODO: Only print out strings before calling other functions.
 179179  */
 180180 static void
 181181 fastscan(void)
 182182 {
 183183         struct symtab *nl;
 184184         int ch, i = 0;
 185185         int nnl = 0;
 186186         usch *cp;
 187187 
 188188         goto run;
 189189         for (;;) {
 190190                 ch = NXTCH();
 191191 xloop:          if (ch == -1)
 192192                         return;
 193193 #ifdef PCC_DEBUG
 194194                 if (dflag>1)
 195195                         printf("fastscan ch %d (%c)\n", ch, ch > 31 ? ch : '@');
 196196 #endif
 197197                 if ((spechr[ch] & C_SPEC) == 0) {
 198198                         PUTCH(ch);
 199199                         continue;
 200200                 }
 201201                 switch (ch) {
 202202                 case EBLOCK:
 203203                 case WARN:
 204204                 case CONC:
 205205                         error("bad char passed");
 206206                         break;
 207207 
 208208                 case '/': /* Comments */
 209209                         if ((ch = inch()) == '/') {
 210210 cppcmt:                         if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
 211211                                 do {
 212212                                         if (Cflag) PUTCH(ch);
 213213                                         ch = inch();
 214214                                 } while (ch != -1 && ch != '\n');
 215215                                 goto xloop;
 216216                         } else if (ch == '*') {
 217217                                 if (eatcmnt())
 218218                                         return;
 219219                         } else {
 220220                                 PUTCH('/');
 221221                                 goto xloop;
 222222                         }
 223223                         break;
 224224 
 225225                 case '?'/* trigraphs */
 226226                         if ((ch = chktg()))
 227227                                 goto xloop;
 228228                         PUTCH('?');
 229229                         break;
 230230 
 231231                 case '\\':
 232232                         if ((ch = NXTCH()) == '\n') {
 233233                                 ifiles->lineno++;
 234234                                 continue;
 235235                         } else {
 236236                                 PUTCH('\\');
 237237                         }
 238238                         goto xloop;
 239239 
 240240                 case '\n': /* newlines, for pp directives */
 241241                         while (nnl > 0) { PUTCH('\n'); nnl--; }
 242242 run2:                   ifiles->lineno++;
 243243                         do {
 244244                                 PUTCH(ch);
 245245 run:                            ch = NXTCH();
 246246                                 if (ch == '/') {
 247247                                         ch = NXTCH();
 248248                                         if (ch == '/')
 249249                                                 goto cppcmt;
 250250                                         if (ch == '*') {
 251251                                                 if (eatcmnt())
 252252                                                         return;
 253253                                                 goto run;
 254254                                         }
 255255                                         unch(ch);
 256256                                         ch = '/';
 257257                                 }
 258258                         } while (ch == ' ' || ch == '\t');
 259259                         if (ch == '\\') {
 260260                                 ch = NXTCH();
 261261                                 if (ch == '\n')
 262262                                         goto run2;
 263263                                 unch(ch);
 264264                                 ch = '\\';
 265265                         }
 266266                         if (ch == '#') {
 267267                                 ppdir();
 268268                                 continue;
 269269                         } else if (ch == '%') {
 270270                                 ch = NXTCH();
 271271                                 if (ch == ':') {
 272272                                         ppdir();
 273273                                         continue;
 274274                                 } else {
 275275                                         unch(ch);
 276276                                         ch = '%';
 277277                                 }
 278278                         } else if (ch == '?') {
 279279                                 if ((ch = chktg()) == '#') {
 280280                                         ppdir();
 281281                                         continue;
 282282                                 } else if (ch == 0)
 283283                                         ch = '?';
 284284                         }
 285285                         goto xloop;
 286286 
 287287                 case '\"': /* strings */
 288288 str:                    PUTCH(ch);
 289289                         while ((ch = NXTCH()) != '\"') {
 290290                                 if (ch == '\n')
 291291                                         goto xloop;
 292292                                 if (ch == '\\') {
 293293                                         if ((ch = NXTCH()) != '\n') {
 294294                                                 PUTCH('\\');
 295295                                                 PUTCH(ch);
 296296                                         } else
 297297                                                 nnl++;
 298298                                         continue;
 299299                                 }
 300300                                 if (ch < 0)
 301301                                         return;
 302302                                 PUTCH(ch);
 303303                         }
 304304                         PUTCH(ch);
 305305                         break;
 306306 
 307307                 case '.'/* for pp-number */
 308308                         PUTCH(ch);
 309309                         ch = NXTCH();
 310310                         if (ch < '0' || ch > '9')
 311311                                 goto xloop;
 312312                         /* FALLTHROUGH */
 313313                 case '0': case '1': case '2': case '3': case '4':
 314314                 case '5': case '6': case '7': case '8': case '9':
 315315                         do {
 316316                                 PUTCH(ch);
 317317 nxt:                            ch = NXTCH();
 318318                                 if (ch == '\\') {
 319319                                         ch = NXTCH();
 320320                                         if (ch == '\n') {
 321321                                                 goto nxt;
 322322                                         } else {
 323323                                                 unch(ch);
 324324                                                 ch = '\\';
 325325                                         }
 326326                                 }
 327327                                 if (spechr[ch] & C_EP) {
 328328                                         PUTCH(ch);
 329329                                         ch = NXTCH();
 330330                                         if (ch == '-' || ch == '+')
 331331                                                 continue;
 332332                                 }
 333333                         } while ((spechr[ch] & C_ID) || (ch == '.'));
 334334                         goto xloop;
 335335 
 336336                 case '\'': /* character literal */
 337337 con:                    PUTCH(ch);
 338338                         if (tflag)
 339339                                 continue; /* character constants ignored */
 340340                         while ((ch = NXTCH()) != '\'') {
 341341                                 if (ch == '\n')
 342342                                         goto xloop;
 343343                                 if (ch == '\\') {
 344344                                         if ((ch = NXTCH()) != '\n') {
 345345                                                 PUTCH('\\');
 346346                                                 PUTCH(ch);
 347347                                         } else
 348348                                                 nnl++;
 349349                                         continue;
 350350                                 }
 351351                                 if (ch < 0)
 352352                                         return;
 353353                                 PUTCH(ch);
 354354                         }
 355355                         PUTCH(ch);
 356356                         break;
 357357 
 358358                 case 'L':
 359359                         ch = NXTCH();
 360360                         if (ch == '\"') {
 361361                                 PUTCH('L');
 362362                                 goto str;
 363363                         }
 364364                         if (ch == '\'') {
 365365                                 PUTCH('L');
 366366                                 goto con;
 367367                         }
 368368                         unch(ch);
 369369                         ch = 'L';
 370370                         /* FALLTHROUGH */
 371371                 default:
 372372                         if ((spechr[ch] & C_ID) == 0)
 373373                                 error("fastscan");
 374374                         if (flslvl) {
 375375                                 while (spechr[ch] & C_ID)
 376376                                         ch = NXTCH();
 377377                                 goto xloop;
 378378                         }
 379379                         i = 0;
 380380                         do {
 381381                                 yytext[i++] = (usch)ch;
 382382                                 ch = NXTCH();
 383383                                 if (ch == '\\') {
 384384                                         ch = NXTCH();
 385385                                         if (ch != '\n') {
 386386                                                 unch(ch);
 387387                                                 ch = '\\';
 388388                                         } else {
 389389                                                 putch('\n');
 390390                                                 ifiles->lineno++;
 391391                                                 ch = NXTCH();
 392392                                         }
 393393                                 }
 394394                                 if (ch < 0)
 395395                                         return;
 396396                         } while (spechr[ch] & C_ID);
 397397 
 398398                         yytext[i] = 0;
 399399                         unch(ch);
 400400 
 401401                         cp = stringbuf;
 402402                         if ((nl = lookup((usch *)yytext, FIND)) && kfind(nl)) {
 403403                                 putstr(stringbuf);
 404404                         } else
 405405                                 putstr((usch *)yytext);
 406406                         stringbuf = cp;
 407407 
 408408                         break;
 409409                 }
 410410         }
 411411 }
 412412 
 413413 int
 414414 sloscan()
 415415 {
 416416         int ch;
 417417         int yyp;
 418418 
 419419 zagain:
 420420         yyp = 0;
 421421         ch = inch();
 422422         yytext[yyp++] = (usch)ch;
 423423         switch (ch) {
 424424         case -1:
 425425                 return 0;
 426426         case '\n':
 427427                 /* sloscan() never passes \n, that's up to fastscan() */
 428428                 unch(ch);
 429429                 goto yyret;
 430430 
 431431         case '\r': /* Ignore CR's */
 432432                 yyp = 0;
 433433                 break;
 434434 
 435435         case '0': case '1': case '2': case '3': case '4': case '5':
 436436         case '6': case '7': case '8': case '9':
 437437                 /* readin a "pp-number" */
 438438 ppnum:          for (;;) {
 439439                         ch = inch();
 440440                         if (spechr[ch] & C_EP) {
 441441                                 yytext[yyp++] = (usch)ch;
 442442                                 ch = inch();
 443443                                 if (ch == '-' || ch == '+') {
 444444                                         yytext[yyp++] = (usch)ch;
 445445                                 } else
 446446                                         unch(ch);
 447447                                 continue;
 448448                         }
 449449                         if ((spechr[ch] & C_ID) || ch == '.') {
 450450                                 yytext[yyp++] = (usch)ch;
 451451                                 continue;
 452452                         }
 453453                         break;
 454454                 }
 455455                 unch(ch);
 456456                 yytext[yyp] = 0;
 457457 
 458458                 return NUMBER;
 459459 
 460460         case '\'':
 461461 chlit:          
 462462                 for (;;) {
 463463                         if ((ch = inch()) == '\\') {
 464464                                 yytext[yyp++] = (usch)ch;
 465465                                 yytext[yyp++] = (usch)inch();
 466466                                 continue;
 467467                         } else if (ch == '\n') {
 468468                                 /* not a constant */
 469469                                 while (yyp > 1)
 470470                                         unch(yytext[--yyp]);
 471471                                 ch = '\'';
 472472                                 goto any;
 473473                         } else
 474474                                 yytext[yyp++] = (usch)ch;
 475475                         if (ch == '\'')
 476476                                 break;
 477477                 }
 478478                 yytext[yyp] = 0;
 479479 
 480480                 return (NUMBER);
 481481 
 482482         case ' ':
 483483         case '\t':
 484484                 while ((ch = inch()) == ' ' || ch == '\t')
 485485                         yytext[yyp++] = (usch)ch;
 486486                 unch(ch);
 487487                 yytext[yyp] = 0;
 488488                 return(WSPACE);
 489489 
 490490         case '/':
 491491                 if ((ch = inch()) == '/') {
 492492                         do {
 493493                                 yytext[yyp++] = (usch)ch;
 494494                                 ch = inch();
 495495                         } while (ch && ch != '\n');
 496496                         yytext[yyp] = 0;
 497497                         unch(ch);
 498498                         goto zagain;
 499499                 } else if (ch == '*') {
 500500                         int c, wrn;
 501501                         extern int readmac;
 502502 
 503503                         if (Cflag && !flslvl && readmac) {
 504504                                 unch(ch);
 505505                                 yytext[yyp] = 0;
 506506                                 return CMNT;
 507507                         }
 508508 
 509509                         wrn = 0;
 510510                 more:   while ((c = inch()) && c != '*') {
 511511                                 if (c == '\n')
 512512                                         putch(c), ifiles->lineno++;
 513513                                 else if (c == EBLOCK) {
 514514                                         (void)inch();
 515515                                         (void)inch();
 516516                                 } else if (c == 1) /* WARN */
 517517                                         wrn = 1;
 518518                         }
 519519                         if (c == 0)
 520520                                 return 0;
 521521                         if ((c = inch()) && c != '/') {
 522522                                 unch(c);
 523523                                 goto more;
 524524                         }
 525525                         if (c == 0)
 526526                                 return 0;
 527527                         if (!tflag && !Cflag && !flslvl)
 528528                                 unch(' ');
 529529                         if (wrn)
 530530                                 unch(1);
 531531                         goto zagain;
 532532                 }
 533533                 unch(ch);
 534534                 ch = '/';
 535535                 goto any;
 536536 
 537537         case '.':
 538538                 ch = inch();
 539539                 if (isdigit(ch)) {
 540540                         yytext[yyp++] = (usch)ch;
 541541                         goto ppnum;
 542542                 } else {
 543543                         unch(ch);
 544544                         ch = '.';
 545545                 }
 546546                 goto any;
 547547 
 548548         case '\"':
<>549 -                if (tflag)
  549+                if (tflag && defining)
<_550550                         goto any;
 551551         strng:
 552552                 for (;;) {
 553553                         if ((ch = inch()) == '\\') {
 554554                                 yytext[yyp++] = (usch)ch;
 555555                                 yytext[yyp++] = (usch)inch();
 556556                                 continue;
 557557                         } else
 558558                                 yytext[yyp++] = (usch)ch;
 559559                         if (ch == '\"')
 560560                                 break;
 561561                 }
 562562                 yytext[yyp] = 0;
 563563                 return(STRING);
 564564 
 565565         case 'L':
 566566                 if ((ch = inch()) == '\"' && !tflag) {
 567567                         yytext[yyp++] = (usch)ch;
 568568                         goto strng;
 569569                 } else if (ch == '\'' && !tflag) {
 570570                         yytext[yyp++] = (usch)ch;
 571571                         goto chlit;
 572572                 }
 573573                 unch(ch);
 574574                 /* FALLTHROUGH */
 575575 
 576576         /* Yetch, all identifiers */
 577577         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
 578578         case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
 579579         case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
 580580         case 's': case 't': case 'u': case 'v': case 'w': case 'x':
 581581         case 'y': case 'z':
 582582         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
 583583         case 'G': case 'H': case 'I': case 'J': case 'K':
 584584         case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
 585585         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
 586586         case 'Y': case 'Z':
 587587         case '_': /* {L}({L}|{D})* */
 588588 
 589589                 /* Special hacks */
 590590                 for (;;) { /* get chars */
 591591                         ch = inch();
 592592                         if (isalpha(ch) || isdigit(ch) || ch == '_') {
 593593                                 yytext[yyp++] = (usch)ch;
 594594                         } else {
 595595                                 if (ch != -1)
 596596                                         unch(ch);
 597597                                 break;
 598598                         }
 599599                 }
 600600                 yytext[yyp] = 0; /* need already string */
 601601                 /* end special hacks */
 602602 
 603603                 return IDENT;
 604604         default:
 605605         any:
 606606                 yytext[yyp] = 0;
 607607                 return yytext[0];
 608608 
 609609         } /* endcase */
 610610         goto zagain;
 611611 
 612612 yyret:
 613613         yytext[yyp] = 0;
 614614         return ch;
 615615 }
 616616 
 617617 int
 618618 yylex()
 619619 {
 620620         static int ifdef, noex;
 621621         struct symtab *nl;
 622622         int ch, c2;
 623623 
 624624         while ((ch = sloscan()) == WSPACE)
 625625                 ;
 626626         if (ch < 128 && spechr[ch] & C_2)
 627627                 c2 = inpch();
 628628         else
 629629                 c2 = 0;
 630630 
 631631 #define C2(a,b,c) case a: if (c2 == b) return c; break
 632632         switch (ch) {
 633633         C2('=', '=', EQ);
 634634         C2('!', '=', NE);
 635635         C2('|', '|', OROR);
 636636         C2('&', '&', ANDAND);
 637637         case '<':
 638638                 if (c2 == '<') return LS;
 639639                 if (c2 == '=') return LE;
 640640                 break;
 641641         case '>':
 642642                 if (c2 == '>') return RS;
 643643                 if (c2 == '=') return GE;
 644644                 break;
 645645         case '+':
 646646         case '-':
 647647                 if (ch == c2)
 648648                         badop("");
 649649                 break;
 650650 
 651651         case '/':
 652652                 if (Cflag == 0 || c2 != '*')
 653653                         break;
 654654                 /* Found comment that need to be skipped */
 655655                 for (;;) {
 656656                         ch = inpch();
 657657                 c1:     if (ch != '*')
 658658                                 continue;
 659659                         if ((ch = inpch()) == '/')
 660660                                 break;
 661661                         goto c1;
 662662                 }
 663663                 return yylex();
 664664 
 665665         case NUMBER:
 666666                 if (yytext[0] == '\'') {
 667667                         yylval.node.op = NUMBER;
 668668                         yylval.node.nd_val = charcon((usch *)yytext);
 669669                 } else
 670670                         cvtdig(yytext[0] != '0' ? 10 :
 671671                             yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
 672672                 return NUMBER;
 673673 
 674674         case IDENT:
 675675                 if (strcmp((char *)yytext, "defined") == 0) {
 676676                         ifdef = 1;
 677677                         return DEFINED;
 678678                 }
 679679                 nl = lookup((usch *)yytext, FIND);
 680680                 if (ifdef) {
 681681                         yylval.node.nd_val = nl != NULL;
 682682                         ifdef = 0;
 683683                 } else if (nl && noex == 0) {
 684684                         usch *och = stringbuf;
 685685                         int i;
 686686 
 687687                         i = kfind(nl);
 688688                         unch(WARN);
 689689                         if (i)
 690690                                 unpstr(stringbuf);
 691691                         else
 692692                                 unpstr(nl->namep);
 693693                         stringbuf = och;
 694694                         noex = 1;
 695695                         return yylex();
 696696                 } else {
 697697                         yylval.node.nd_val = 0;
 698698                 }
 699699                 yylval.node.op = NUMBER;
 700700                 return NUMBER;
 701701         case WARN:
 702702                 noex = 0;
 703703                 return yylex();
 704704         default:
 705705                 return ch;
 706706         }
 707707         unch(c2);
 708708         return ch;
 709709 }
 710710 
 711711 usch *yyp, yybuf[CPPBUF];
 712712 
 713713 int yywrap(void);
 714714 
 715715 static int
 716716 inpch(void)
 717717 {
 718718         int len;
 719719 
 720720         if (ifiles->curptr < ifiles->maxread)
 721721                 return *ifiles->curptr++;
 722722 
 723723         if (ifiles->infil == -1)
 724724                 return -1;
 725725         if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0)
 726726                 error("read error on file %s", ifiles->orgfn);
 727727         if (len == 0)
 728728                 return -1;
 729729         ifiles->curptr = ifiles->buffer;
 730730         ifiles->maxread = ifiles->buffer + len;
 731731         return inpch();
 732732 }
 733733 
 734734 static int
 735735 inch(void)
 736736 {
 737737         int c;
 738738 
 739739 again:  switch (c = inpch()) {
 740740         case '\\': /* continued lines */
 741741 msdos:          if ((c = inpch()) == '\n') {
 742742                         ifiles->lineno++;
 743743                         goto again;
 744744                 } else if (c == '\r')
 745745                         goto msdos;
 746746                 unch(c);
 747747                 return '\\';
 748748         case '?': /* trigraphs */
 749749                 if ((c = chktg())) {
 750750                         unch(c);
 751751                         goto again;
 752752                 }
 753753                 return '?';
 754754         default:
 755755                 return c;
 756756         }
 757757 }
 758758 
 759759 /*
 760760  * Let the command-line args be faked defines at beginning of file.
 761761  */
 762762 static void
 763763 prinit(struct initar *it, struct includ *ic)
 764764 {
 765765         const char *pre, *post;
 766766         char *a;
 767767 
 768768         if (it->next)
 769769                 prinit(it->next, ic);
 770770         pre = post = NULL; /* XXX gcc */
 771771         switch (it->type) {
 772772         case 'D':
 773773                 pre = "#define ";
 774774                 if ((a = strchr(it->str, '=')) != NULL) {
 775775                         *a = ' ';
 776776                         post = "\n";
 777777                 } else
 778778                         post = " 1\n";
 779779                 break;
 780780         case 'U':
 781781                 pre = "#undef ";
 782782                 post = "\n";
 783783                 break;
 784784         case 'i':
 785785                 pre = "#include \"";
 786786                 post = "\"\n";
 787787                 break;
 788788         default:
 789789                 error("prinit");
 790790         }
 791791         strlcat((char *)ic->buffer, pre, CPPBUF+1);
 792792         strlcat((char *)ic->buffer, it->str, CPPBUF+1);
 793793         if (strlcat((char *)ic->buffer, post, CPPBUF+1) >= CPPBUF+1)
 794794                 error("line exceeds buffer size");
 795795 
 796796         ic->lineno--;
 797797         while (*ic->maxread)
 798798                 ic->maxread++;
 799799 }
 800800 
 801801 /*
 802802  * A new file included.
 803803  * If ifiles == NULL, this is the first file and already opened (stdin).
 804804  * Return 0 on success, -1 if file to be included is not found.
 805805  */
 806806 int
 807807 pushfile(const usch *file, const usch *fn, int idx, void *incs)
 808808 {
 809809         extern struct initar *initar;
 810810         struct includ ibuf;
 811811         struct includ *ic;
 812812         int otrulvl;
 813813 
 814814         ic = &ibuf;
 815815         ic->next = ifiles;
 816816 
 817817         if (file != NULL) {
 818818                 if ((ic->infil = open((const char *)file, O_RDONLY)) < 0)
 819819                         return -1;
 820820                 ic->orgfn = ic->fname = file;
 821821                 if (++inclevel > MAX_INCLEVEL)
 822822                         error("Limit for nested includes exceeded");
 823823         } else {
 824824                 ic->infil = 0;
 825825                 ic->orgfn = ic->fname = (const usch *)"<stdin>";
 826826         }
 827827 #ifndef BUF_STACK
 828828         ic->bbuf = malloc(BBUFSZ);
 829829 #endif
 830830         ic->buffer = ic->bbuf+NAMEMAX;
 831831         ic->curptr = ic->buffer;
 832832         ifiles = ic;
 833833         ic->lineno = 1;
 834834         ic->maxread = ic->curptr;
 835835         ic->idx = idx;
 836836         ic->incs = incs;
 837837         ic->fn = fn;
 838838         prtline();
 839839         if (initar) {
 840840                 int oin = ic->infil;
 841841                 ic->infil = -1;
 842842                 *ic->maxread = 0;
 843843                 prinit(initar, ic);
 844844                 initar = NULL;
 845845                 if (dMflag)
 846846                         write(ofd, ic->buffer, strlen((char *)ic->buffer));
 847847                 fastscan();
 848848                 prtline();
 849849                 ic->infil = oin;
 850850         }
 851851 
 852852         otrulvl = trulvl;
 853853 
 854854         fastscan();
 855855 
 856856         if (otrulvl != trulvl || flslvl)
 857857                 error("unterminated conditional");
 858858 
 859859 #ifndef BUF_STACK
 860860         free(ic->bbuf);
 861861 #endif
 862862         ifiles = ic->next;
 863863         close(ic->infil);
 864864         inclevel--;
 865865         return 0;
 866866 }
 867867 
 868868 /*
 869869  * Print current position to output file.
 870870  */
 871871 void
 872872 prtline()
 873873 {
 874874         usch *s, *os = stringbuf;
 875875 
 876876         if (Mflag) {
 877877                 if (dMflag)
 878878                         return; /* no output */
 879879                 if (ifiles->lineno == 1) {
 880880                         s = sheap("%s: %s\n", Mfile, ifiles->fname);
 881881                         write(ofd, s, strlen((char *)s));
 882882                 }
 883883         } else if (!Pflag)
 884884                 putstr(sheap("\n# %d \"%s\"\n", ifiles->lineno, ifiles->fname));
 885885         stringbuf = os;
 886886 }
 887887 
 888888 void
 889889 cunput(int c)
 890890 {
 891891 #ifdef PCC_DEBUG
 892892 //      extern int dflag;
 893893 //      if (dflag)printf(": '%c'(%d)\n", c > 31 ? c : ' ', c);
 894894 #endif
 895895 #if 0
 896896 if (c == 10) {
 897897         printf("c == 10!!!\n");
 898898 }
 899899 #endif
 900900         unch(c);
 901901 }
 902902 
 903903 int yywrap(void) { return 1; }
 904904 
 905905 static int
 906906 dig2num(int c)
 907907 {
 908908         if (c >= 'a')
 909909                 c = c - 'a' + 10;
 910910         else if (c >= 'A')
 911911                 c = c - 'A' + 10;
 912912         else
 913913                 c = c - '0';
 914914         return c;
 915915 }
 916916 
 917917 /*
 918918  * Convert string numbers to unsigned long long and check overflow.
 919919  */
 920920 static void
 921921 cvtdig(int rad)
 922922 {
 923923         unsigned long long rv = 0;
 924924         unsigned long long rv2 = 0;
 925925         usch *y = yytext;
 926926         int c;
 927927 
 928928         c = *y++;
 929929         if (rad == 16)
 930930                 y++;
 931931         while (isxdigit(c)) {
 932932                 rv = rv * rad + dig2num(c);
 933933                 /* check overflow */
 934934                 if (rv / rad < rv2)
 935935                         error("Constant \"%s\" is out of range", yytext);
 936936                 rv2 = rv;
 937937                 c = *y++;
 938938         }
 939939         y--;
 940940         while (*y == 'l' || *y == 'L')
 941941                 y++;
 942942         yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER;
 943943         yylval.node.nd_uval = rv;
 944944         if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0)
 945945                 yylval.node.op = UNUMBER;
 946946         if (yylval.node.op == NUMBER && yylval.node.nd_val < 0)
 947947                 /* too large for signed, see 6.4.4.1 */
 948948                 error("Constant \"%s\" is out of range", yytext);
 949949 }
 950950 
 951951 static int
 952952 charcon(usch *p)
 953953 {
 954954         int val, c;
 955955 
 956956         p++; /* skip first ' */
 957957         val = 0;
 958958         if (*p++ == '\\') {
 959959                 switch (*p++) {
 960960                 case 'a': val = '\a'; break;
 961961                 case 'b': val = '\b'; break;
 962962                 case 'f': val = '\f'; break;
 963963                 case 'n': val = '\n'; break;
 964964                 case 'r': val = '\r'; break;
 965965                 case 't': val = '\t'; break;
 966966                 case 'v': val = '\v'; break;
 967967                 case '\"': val = '\"'; break;
 968968                 case '\'': val = '\''; break;
 969969                 case '\\': val = '\\'; break;
 970970                 case 'x':
 971971                         while (isxdigit(c = *p)) {
 972972                                 val = val * 16 + dig2num(c);
 973973                                 p++;
 974974                         }
 975975                         break;
 976976                 case '0': case '1': case '2': case '3': case '4':
 977977                 case '5': case '6': case '7':
 978978                         p--;
 979979                         while (isdigit(c = *p)) {
 980980                                 val = val * 8 + (c - '0');
 981981                                 p++;
 982982                         }
 983983                         break;
 984984                 default: val = p[-1];
 985985                 }
 986986 
 987987         } else
 988988                 val = p[-1];
 989989         return val;
 990990 }
 991991 
 992992 static void
 993993 chknl(int ignore)
 994994 {
 995995         int t;
 996996 
 997997         while ((t = sloscan()) == WSPACE)
 998998                 ;
 999999         if (t != '\n') {
 10001000                 if (t && t != (usch)-1) {
 10011001                         if (ignore) {
 10021002                                 warning("newline expected, got \"%s\"", yytext);
 10031003                                 /* ignore rest of line */
 10041004                                 while ((t = sloscan()) && t != '\n')
 10051005                                         ;
 10061006                         }
 10071007                         else
 10081008                                 error("newline expected, got \"%s\"", yytext);
 10091009                 } else {
 10101010                         if (ignore)
 10111011                                 warning("no newline at end of file");
 10121012                         else
 10131013                                 error("no newline at end of file");
 10141014                 }
 10151015         }
 10161016 }
 10171017 
 10181018 static void
 10191019 elsestmt(void)
 10201020 {
 10211021         if (flslvl) {
 10221022                 if (elflvl > trulvl)
 10231023                         ;
 10241024                 else if (--flslvl!=0) {
 10251025                         flslvl++;
 10261026                 } else {
 10271027                         trulvl++;
 10281028                         prtline();
 10291029                 }
 10301030         } else if (trulvl) {
 10311031                 flslvl++;
 10321032                 trulvl--;
 10331033         } else
 10341034                 error("If-less else");
 10351035         if (elslvl==trulvl+flslvl)
 10361036                 error("Too many else");
 10371037         elslvl=trulvl+flslvl;
 10381038         chknl(1);
 10391039 }
 10401040 
 10411041 static void
 10421042 skpln(void)
 10431043 {
 10441044         /* just ignore the rest of the line */
 10451045         while (inch() != '\n')
 10461046                 ;
 10471047         unch('\n');
 10481048         flslvl++;
 10491049 }
 10501050 
 10511051 static void
 10521052 ifdefstmt(void)         
 10531053 {
 10541054         int t;
 10551055 
 10561056         if (flslvl) {
 10571057                 skpln();
 10581058                 return;
 10591059         }
 10601060         do
 10611061                 t = sloscan();
 10621062         while (t == WSPACE);
 10631063         if (t != IDENT)
 10641064                 error("bad ifdef");
 10651065         if (lookup((usch *)yytext, FIND) == 0) {
 10661066                 putch('\n');
 10671067                 flslvl++;
 10681068         } else
 10691069                 trulvl++;
 10701070         chknl(0);
 10711071 }
 10721072 
 10731073 static void
 10741074 ifndefstmt(void)         
 10751075 {
 10761076         int t;
 10771077 
 10781078         if (flslvl) {
 10791079                 skpln();
 10801080                 return;
 10811081         }
 10821082         do
 10831083                 t = sloscan();
 10841084         while (t == WSPACE);
 10851085         if (t != IDENT)
 10861086                 error("bad ifndef");
 10871087         if (lookup((usch *)yytext, FIND) != 0) {
 10881088                 putch('\n');
 10891089                 flslvl++;
 10901090         } else
 10911091                 trulvl++;
 10921092         chknl(0);
 10931093 }
 10941094 
 10951095 static void
 10961096 endifstmt(void)         
 10971097 {
 10981098         if (flslvl) {
 10991099                 flslvl--;
 11001100                 if (flslvl == 0) {
 11011101                         putch('\n');
 11021102                         prtline();
 11031103                 }
 11041104         } else if (trulvl)
 11051105                 trulvl--;
 11061106         else
 11071107                 error("If-less endif");
 11081108         if (flslvl == 0)
 11091109                 elflvl = 0;
 11101110         elslvl = 0;
 11111111         chknl(1);
 11121112 }
 11131113 
 11141114 static void
 11151115 ifstmt(void)
 11161116 {
 11171117         if (flslvl == 0) {
 11181118                 if (yyparse() == 0) {
 11191119                         putch('\n');
 11201120                         ++flslvl;
 11211121                 } else
 11221122                         ++trulvl;
 11231123         } else
 11241124                 ++flslvl;
 11251125 }
 11261126 
 11271127 static void
 11281128 elifstmt(void)
 11291129 {
 11301130         if (flslvl == 0)
 11311131                 elflvl = trulvl;
 11321132         if (flslvl) {
 11331133                 if (elflvl > trulvl)
 11341134                         ;
 11351135                 else if (--flslvl!=0)
 11361136                         ++flslvl;
 11371137                 else {
 11381138                         if (yyparse()) {
 11391139                                 ++trulvl;
 11401140                                 prtline();
 11411141                         } else {
 11421142                                 putch('\n');
 11431143                                 ++flslvl;
 11441144                         }
 11451145                 }
 11461146         } else if (trulvl) {
 11471147                 ++flslvl;
 11481148                 --trulvl;
 11491149         } else
 11501150                 error("If-less elif");
 11511151 }
 11521152 
 11531153 static usch *
 11541154 svinp(void)
 11551155 {
 11561156         int c;
 11571157         usch *cp = stringbuf;
 11581158 
 11591159         while ((c = inch()) && c != '\n')
 11601160                 savch(c);
 11611161         savch('\n');
 11621162         savch(0);
 11631163         return cp;
 11641164 }
 11651165 
 11661166 static void
 11671167 cpperror(void)
 11681168 {
 11691169         usch *cp;
 11701170         int c;
 11711171 
 11721172         if (flslvl)
 11731173                 return;
 11741174         c = sloscan();
 11751175         if (c != WSPACE && c != '\n')
 11761176                 error("bad error");
 11771177         cp = svinp();
 11781178         if (flslvl)
 11791179                 stringbuf = cp;
 11801180         else
 11811181                 error("%s", cp);
 11821182 }
 11831183 
 11841184 static void
 11851185 cppwarning(void)
 11861186 {
 11871187         usch *cp;
 11881188         int c;
 11891189 
 11901190         if (flslvl)
 11911191                 return;
 11921192         c = sloscan();
 11931193         if (c != WSPACE && c != '\n')
 11941194                 error("bad warning");
 11951195 
 11961196         /* svinp() add an unwanted \n */
 11971197         cp = stringbuf;
 11981198         while ((c = inch()) && c != '\n')
 11991199                 savch(c);
 12001200         savch(0);
 12011201 
 12021202         if (flslvl)
 12031203                 stringbuf = cp;
 12041204         else
 12051205                 warning("#warning %s", cp);
 12061206 
 12071207         unch('\n');
 12081208 }
 12091209 
 12101210 static void
 12111211 undefstmt(void)
 12121212 {
 12131213         struct symtab *np;
 12141214 
 12151215         if (flslvl)
 12161216                 return;
 12171217         if (sloscan() != WSPACE || sloscan() != IDENT)
 12181218                 error("bad undef");
 12191219         if (flslvl == 0 && (np = lookup((usch *)yytext, FIND)))
 12201220                 np->value = 0;
 12211221         chknl(0);
 12221222 }
 12231223 
 12241224 static void
 12251225 pragmastmt(void)
 12261226 {
 12271227         int c;
 12281228 
 12291229         if (sloscan() != WSPACE)
 12301230                 error("bad pragma");
 12311231         if (!flslvl)
 12321232                 putstr((const usch *)"\n#pragma ");
 12331233         do {
 12341234                 c = inch();
 12351235                 if (!flslvl)
 12361236                         putch(c);       /* Do arg expansion instead? */
 12371237         } while (c && c != '\n');
 12381238         if (c == '\n')
 12391239                 unch(c);
 12401240         prtline();
 12411241 }
 12421242 
 12431243 static void
 12441244 badop(const char *op)
 12451245 {
 12461246         error("invalid operator in preprocessor expression: %s", op);
 12471247 }
 12481248 
 12491249 int
 12501250 cinput()
 12511251 {
 12521252         return inch();
 12531253 }
 12541254 
 12551255 /*
 12561256  * Check for (and convert) trigraphs.
 12571257  */
 12581258 int
 12591259 chktg()
 12601260 {
 12611261         int c;
 12621262 
 12631263         if ((c = inpch()) != '?') {
 12641264                 unch(c);
 12651265                 return 0;
 12661266         }
 12671267         switch (c = inpch()) {
 12681268         case '=': c = '#'; break;
 12691269         case '(': c = '['; break;
 12701270         case ')': c = ']'; break;
 12711271         case '<': c = '{'; break;
 12721272         case '>': c = '}'; break;
 12731273         case '/': c = '\\'; break;
 12741274         case '\'': c = '^'; break;
 12751275         case '!': c = '|'; break;
 12761276         case '-': c = '~'; break;
 12771277         default:
 12781278                 unch(c);
 12791279                 unch('?');
 12801280                 c = 0;
 12811281         }
 12821282         return c;
 12831283 }
 12841284 
 12851285 static struct {
 12861286         const char *name;
 12871287         void (*fun)(void);
 12881288 } ppd[] = {
 12891289         { "ifndef", ifndefstmt },
 12901290         { "ifdef", ifdefstmt },
 12911291         { "if", ifstmt },
 12921292         { "include", include },
 12931293         { "else", elsestmt },
 12941294         { "endif", endifstmt },
 12951295         { "error", cpperror },
 12961296         { "warning", cppwarning },
 12971297         { "define", define },
 12981298         { "undef", undefstmt },
 12991299         { "line", line },
 13001300         { "pragma", pragmastmt },
 13011301         { "elif", elifstmt },
 13021302 #ifdef GCC_COMPAT
 13031303         { "include_next", include_next },
 13041304 #endif
 13051305 };
 13061306 
 13071307 /*
 13081308  * Handle a preprocessor directive.
 13091309  */
 13101310 void
 13111311 ppdir(void)
 13121312 {
 13131313         char bp[20];
 13141314         int ch, i;
 13151315 
 13161316         while ((ch = inch()) == ' ' || ch == '\t')
 13171317                 ;
 13181318         if (ch == '\n') { /* empty directive */
 13191319                 unch(ch);
 13201320                 return;
 13211321         }
 13221322         if (ch < 'a' || ch > 'z')
 13231323                 goto out; /* something else, ignore */
 13241324         i = 0;
 13251325         do {
 13261326                 bp[i++] = (usch)ch;
 13271327                 if (i == sizeof(bp)-1)
 13281328                         goto out; /* too long */
 13291329                 ch = inch();
 13301330         } while ((ch >= 'a' && ch <= 'z') || (ch == '_'));
 13311331         unch(ch);
 13321332         bp[i++] = 0;
 13331333 
 13341334         /* got keyword */
 13351335 #define SZ (int)(sizeof(ppd)/sizeof(ppd[0]))
 13361336         for (i = 0; i < SZ; i++)
 13371337                 if (bp[0] == ppd[i].name[0] && strcmp(bp, ppd[i].name) == 0)
 13381338                         break;
 13391339         if (i == SZ)
 13401340                 goto out;
 13411341 
 13421342         /* Found matching keyword */
 13431343         (*ppd[i].fun)();
 13441344         return;
 13451345 
 13461346 out:    while ((ch = inch()) != '\n' && ch != -1)
 13471347                 ;
 13481348         unch('\n');
 13491349 }
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-08-28 01:00 +0200