Quick Search:

Mode

Context

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

Other Diffs

Ignore

Blank Lines Whitespace: Expand:

Diff

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