Quick Search:

Mode

Context

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

Other Diffs

Ignore

Blank Lines Whitespace: Expand:

Diff

1.75
 
1.76
 
MAIN:plunky:20121002093732
 
token.c
_>11 /*      $Id$    */
 22 
 33 /*
 44  * Copyright (c) 2004,2009 Anders Magnusson. All rights reserved.
 55  *
 66  * Redistribution and use in source and binary forms, with or without
 77  * modification, are permitted provided that the following conditions
 88  * are met:
 99  * 1. Redistributions of source code must retain the above copyright
 1010  *    notice, this list of conditions and the following disclaimer.
 1111  * 2. Redistributions in binary form must reproduce the above copyright
 1212  *    notice, this list of conditions and the following disclaimer in the
 1313  *    documentation and/or other materials provided with the distribution.
 1414  *
 1515  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 1616  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 1717  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 1818  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 1919  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 2020  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 2121  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 2222  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 2323  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 2424  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 2525  */
 2626 
 2727 /*
 2828  * Tokenizer for the C preprocessor.
 2929  * There are three main routines:
 3030  *      - fastscan() loops over the input stream searching for magic
 3131  *              characters that may require actions.
 3232  *      - sloscan() tokenize the input stream and returns tokens.
 3333  *              It may recurse into itself during expansion.
 3434  *      - yylex() returns something from the input stream that
 3535  *              is suitable for yacc.
 3636  *
 3737  *      Other functions of common use:
 3838  *      - inpch() returns a raw character from the current input stream.
 3939  *      - inch() is like inpch but \\n and trigraphs are expanded.
 4040  *      - unch() pushes back a character to the input stream.
 4141  */
 4242 
 4343 #include "config.h"
 4444 
 4545 #include <stdlib.h>
 4646 #include <string.h>
 4747 #include <ctype.h>
 4848 #ifdef HAVE_UNISTD_H
 4949 #include <unistd.h>
 5050 #endif
 5151 #include <fcntl.h>
 5252 #include <errno.h>
 5353 
 5454 #include "compat.h"
 5555 #include "cpp.h"
 5656 #include "cpy.h"
 5757 
 5858 static void cvtdig(int rad);
 5959 static int charcon(usch *);
 6060 static void elsestmt(void);
 6161 static void ifdefstmt(void);
 6262 static void ifndefstmt(void);
 6363 static void endifstmt(void);
 6464 static void ifstmt(void);
 6565 static void cpperror(void);
 6666 static void pragmastmt(void);
 6767 static void undefstmt(void);
 6868 static void cppwarning(void);
 6969 static void elifstmt(void);
 7070 static void badop(const char *);
 7171 static int chktg(void);
 7272 static int inpch(void);
 7373 static int inch(void);
 7474 
 7575 #define PUTCH(ch) if (!flslvl) putch(ch)
 7676 /* protection against recursion in #include */
 7777 #define MAX_INCLEVEL    100
 7878 static int inclevel;
 7979 
 8080 /* get next character unaltered */
 8181 #define NXTCH() (ifiles->curptr < ifiles->maxread ? *ifiles->curptr++ : inpch())
 8282 
 8383 usch yytext[CPPBUF];
 8484 
 8585 char spechr[256] = {
 8686         0,      0,      0,      0,      C_SPECC_SPEC0,      0,
 8787         0,      C_WSNLC_SPEC|C_WSNL,  0,
 8888         0,      C_WSNL0,      0,
 8989         0,      0,      0,      0,      0,      0,      0,      0,
 9090         0,      0,      0,      0,      0,      0,      0,      0,
 9191 
 9292         C_WSNLC_2,    C_SPEC0,      0,      0,      C_2,    C_SPEC,
 9393         0,      0,      0,      C_2,    0,      C_2,    0,      C_SPEC|C_2,
 9494         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 9595         C_I,    C_I,    0,      0,      C_2,    C_2,    C_2,    C_SPEC,
 9696 
 9797         0,      C_I,    C_I,    C_I,    C_I,    C_I|C_EP, C_I,  C_I,
 9898         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 9999         C_I|C_EP, C_I,  C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 100100         C_I,    C_I,    C_I,    0,      C_SPEC0,      0,      C_I,
 101101 
 102102         0,      C_I,    C_I,    C_I,    C_I,    C_I|C_EP, C_I,  C_I,
 103103         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 104104         C_I|C_EP, C_I,  C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 105105         C_I,    C_I,    C_I,    0,      C_2,    0,      0,      0,
 106106 
 107107 };
 108108 
 109109 /*
 110110  * No-replacement array.  If a macro is found and exists in this array
 111111  * then no replacement shall occur.  This is a stack.
 112112  */
 113113 struct symtab *norep[RECMAX];   /* Symbol table index table */
 114114 int norepptr = 1;                       /* Top of index table */
 115115 unsigned short bptr[RECMAX];    /* currently active noexpand macro stack */
 116116 int bidx;                       /* Top of bptr stack */
 117117 
 118118 static void
 119119 unch(int c)
 120120 {
 121121                 
 122122         --ifiles->curptr;
 123123         if (ifiles->curptr < ifiles->bbuf)
 124124                 error("pushback buffer full");
 125125         *ifiles->curptr = (usch)c;
 126126 }
 127127 
 128128 static int
 129129 eatcmnt(void)
 130130 {
 131131         int ch;
 132132 
 133133         if (Cflag) { PUTCH('/'); PUTCH('*'); }
 134134         for (;;) {
 135135                 ch = inch();
 136136                 if (ch == '\n') {
 137137                         ifiles->lineno++;
 138138                         PUTCH('\n');
 139139                 }
 140140                 if (ch == -1)
 141141                         return -1;
 142142                 if (ch == '*') {
 143143                         ch = inch();
 144144                         if (ch == '/') {
 145145                                 if (Cflag) {
 146146                                         PUTCH('*');
 147147                                         PUTCH('/');
 148148                                 } else
 149149                                         PUTCH(' ');
 150150                                 break;
 151151                         }
 152152                         unch(ch);
 153153                         ch = '*';
 154154                 }
 155155                 if (Cflag) PUTCH(ch);
 156156         }
 157157         return 0;
 158158 }
 159159 
 160160 /*
 161161  * Scan quickly the input file searching for:
 162162  *      - '#' directives
 163163  *      - keywords (if not flslvl)
 164164  *      - comments
 165165  *
 166166  *      Handle strings, numbers and trigraphs with care.
 167167  *      Only data from pp files are scanned here, never any rescans.
 168168  *      TODO: Only print out strings before calling other functions.
 169169  */
 170170 static void
 171171 fastscan(void)
 172172 {
 173173         struct symtab *nl;
 174174         int ch, i = 0;
 175175         int nnl = 0;
 176176         usch *cp;
 177177 
 178178         goto run;
 179179         for (;;) {
 180180                 ch = NXTCH();
 181181 xloop:          if (ch == -1)
 182182                         return;
 183183 #ifdef PCC_DEBUG
 184184                 if (dflag>1)
 185185                         printf("fastscan ch %d (%c)\n", ch, ch > 31 ? ch : '@');
 186186 #endif
 187187                 if ((spechr[ch] & C_SPEC) == 0) {
 188188                         PUTCH(ch);
 189189                         continue;
 190190                 }
 191191                 switch (ch) {
 192192                 case EBLOCK:
 193193                 case WARN:
 194194                 case CONC:
 195195                         error("bad char passed");
 196196                         break;
 197197 
 198198                 case '/': /* Comments */
 199199                         if ((ch = inch()) == '/') {
 200200 cppcmt:                         if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
 201201                                 do {
 202202                                         if (Cflag) PUTCH(ch);
 203203                                         ch = inch();
 204204                                 } while (ch != -1 && ch != '\n');
 205205                                 goto xloop;
 206206                         } else if (ch == '*') {
 207207                                 if (eatcmnt())
 208208                                         return;
 209209                         } else {
 210210                                 PUTCH('/');
 211211                                 goto xloop;
 212212                         }
 213213                         break;
 214214 
 215215                 case '?'/* trigraphs */
 216216                         if ((ch = chktg()))
 217217                                 goto xloop;
 218218                         PUTCH('?');
 219219                         break;
 220220 
 221221                 case '\\':
 222222                         if ((ch = NXTCH()) == '\n') {
 223223                                 ifiles->lineno++;
 224224                                 continue;
 225225                         } else {
 226226                                 PUTCH('\\');
 227227                         }
 228228                         goto xloop;
 229229 
 230230                 case '\n': /* newlines, for pp directives */
 231231                         while (nnl > 0) { PUTCH('\n'); nnl--; }
 232232 run2:                   ifiles->lineno++;
 233233                         do {
 234234                                 PUTCH(ch);
 235235 run:                            ch = NXTCH();
 236236                                 if (ch == '/') {
 237237                                         ch = NXTCH();
 238238                                         if (ch == '/')
 239239                                                 goto cppcmt;
 240240                                         if (ch == '*') {
 241241                                                 if (eatcmnt())
 242242                                                         return;
 243243                                                 goto run;
 244244                                         }
 245245                                         unch(ch);
 246246                                         ch = '/';
 247247                                 }
 248248                         } while (ch == ' ' || ch == '\t');
 249249                         if (ch == '\\') {
 250250                                 ch = NXTCH();
 251251                                 if (ch == '\n')
 252252                                         goto run2;
 253253                                 unch(ch);
 254254                                 ch = '\\';
 255255                         }
 256256                         if (ch == '#') {
 257257                                 ppdir();
 258258                                 continue;
 259259                         } else if (ch == '%') {
 260260                                 ch = NXTCH();
 261261                                 if (ch == ':') {
 262262                                         ppdir();
 263263                                         continue;
 264264                                 } else {
 265265                                         unch(ch);
 266266                                         ch = '%';
 267267                                 }
 268268                         } else if (ch == '?') {
 269269                                 if ((ch = chktg()) == '#') {
 270270                                         ppdir();
 271271                                         continue;
 272272                                 } else if (ch == 0)
 273273                                         ch = '?';
 274274                         }
 275275                         goto xloop;
 276276 
 277277                 case '\"': /* strings */
 278278 str:                    PUTCH(ch);
 279279                         while ((ch = NXTCH()) != '\"') {
 280280                                 if (ch == '\n')
 281281                                         goto xloop;
 282282                                 if (ch == '\\') {
 283283                                         if ((ch = NXTCH()) != '\n') {
 284284                                                 PUTCH('\\');
 285285                                                 PUTCH(ch);
 286286                                         } else
 287287                                                 nnl++;
 288288                                         continue;
 289289                                 }
 290290                                 if (ch < 0)
 291291                                         return;
 292292                                 PUTCH(ch);
 293293                         }
 294294                         PUTCH(ch);
 295295                         break;
 296296 
 297297                 case '.'/* for pp-number */
 298298                         PUTCH(ch);
 299299                         ch = NXTCH();
 300300                         if (ch < '0' || ch > '9')
 301301                                 goto xloop;
 302302                         /* FALLTHROUGH */
 303303                 case '0': case '1': case '2': case '3': case '4':
 304304                 case '5': case '6': case '7': case '8': case '9':
 305305                         do {
 306306                                 PUTCH(ch);
 307307 nxt:                            ch = NXTCH();
 308308                                 if (ch == '\\') {
 309309                                         ch = NXTCH();
 310310                                         if (ch == '\n') {
 311311                                                 goto nxt;
 312312                                         } else {
 313313                                                 unch(ch);
 314314                                                 ch = '\\';
 315315                                         }
 316316                                 }
 317317                                 if (spechr[ch] & C_EP) {
 318318                                         PUTCH(ch);
 319319                                         ch = NXTCH();
 320320                                         if (ch == '-' || ch == '+')
 321321                                                 continue;
 322322                                 }
 323323                         } while ((spechr[ch] & C_ID) || (ch == '.'));
 324324                         goto xloop;
 325325 
 326326                 case '\'': /* character literal */
 327327 con:                    PUTCH(ch);
 328328                         if (tflag)
 329329                                 continue; /* character constants ignored */
 330330                         while ((ch = NXTCH()) != '\'') {
 331331                                 if (ch == '\n')
 332332                                         goto xloop;
 333333                                 if (ch == '\\') {
 334334                                         if ((ch = NXTCH()) != '\n') {
 335335                                                 PUTCH('\\');
 336336                                                 PUTCH(ch);
 337337                                         } else
 338338                                                 nnl++;
 339339                                         continue;
 340340                                 }
 341341                                 if (ch < 0)
 342342                                         return;
 343343                                 PUTCH(ch);
 344344                         }
 345345                         PUTCH(ch);
 346346                         break;
 347347 
 348348                 case 'L':
 349349                         ch = NXTCH();
 350350                         if (ch == '\"') {
 351351                                 PUTCH('L');
 352352                                 goto str;
 353353                         }
 354354                         if (ch == '\'') {
 355355                                 PUTCH('L');
 356356                                 goto con;
 357357                         }
 358358                         unch(ch);
 359359                         ch = 'L';
 360360                         /* FALLTHROUGH */
 361361                 default:
 362362                         if ((spechr[ch] & C_ID) == 0)
 363363                                 error("fastscan");
 364364                         if (flslvl) {
 365365                                 while (spechr[ch] & C_ID)
 366366                                         ch = NXTCH();
 367367                                 goto xloop;
 368368                         }
 369369                         i = 0;
 370370                         do {
 371371                                 yytext[i++] = (usch)ch;
 372372                                 ch = NXTCH();
 373373                                 if (ch == '\\') {
 374374                                         ch = NXTCH();
 375375                                         if (ch != '\n') {
 376376                                                 unch(ch);
 377377                                                 ch = '\\';
 378378                                         } else {
 379379                                                 putch('\n');
 380380                                                 ifiles->lineno++;
 381381                                                 ch = NXTCH();
 382382                                         }
 383383                                 }
 384384                                 if (ch < 0)
 385385                                         return;
 386386                         } while (spechr[ch] & C_ID);
 387387 
 388388                         yytext[i] = 0;
 389389                         unch(ch);
 390390 
 391391                         cp = stringbuf;
 392392                         if ((nl = lookup(yytext, FIND)) && kfind(nl)) {
 393393                                 putstr(stringbuf);
 394394                         } else
 395395                                 putstr(yytext);
 396396                         stringbuf = cp;
 397397 
 398398                         break;
 399399                 }
 400400         }
 401401 }
 402402 
 403403 int
 404404 sloscan(void)
 405405 {
 406406         int ch;
 407407         int yyp;
 408408 
 409409 zagain:
 410410         yyp = 0;
 411411         ch = inch();
 412412         yytext[yyp++] = (usch)ch;
 413413         switch (ch) {
 414414         case -1:
 415415                 return 0;
 416416         case '\n':
 417417                 /* sloscan() never passes \n, that's up to fastscan() */
 418418                 unch(ch);
 419419                 goto yyret;
 420420 
 421421         case '\r': /* Ignore CR's */
 422422                 yyp = 0;
 423423                 break;
 424424 
 425425         case '0': case '1': case '2': case '3': case '4': case '5':
 426426         case '6': case '7': case '8': case '9':
 427427                 /* readin a "pp-number" */
 428428 ppnum:          for (;;) {
 429429                         ch = inch();
 430430                         if (spechr[ch] & C_EP) {
 431431                                 yytext[yyp++] = (usch)ch;
 432432                                 ch = inch();
 433433                                 if (ch == '-' || ch == '+') {
 434434                                         yytext[yyp++] = (usch)ch;
 435435                                 } else
 436436                                         unch(ch);
 437437                                 continue;
 438438                         }
 439439                         if ((spechr[ch] & C_ID) || ch == '.') {
 440440                                 yytext[yyp++] = (usch)ch;
 441441                                 continue;
 442442                         }
 443443                         break;
 444444                 }
 445445                 unch(ch);
 446446                 yytext[yyp] = 0;
 447447 
 448448                 return NUMBER;
 449449 
 450450         case '\'':
 451451 chlit:          
 452452                 for (;;) {
 453453                         if ((ch = inch()) == '\\') {
 454454                                 yytext[yyp++] = (usch)ch;
 455455                                 yytext[yyp++] = (usch)inch();
 456456                                 continue;
 457457                         } else if (ch == '\n') {
 458458                                 /* not a constant */
 459459                                 while (yyp > 1)
 460460                                         unch(yytext[--yyp]);
 461461                                 ch = '\'';
 462462                                 goto any;
 463463                         } else
 464464                                 yytext[yyp++] = (usch)ch;
 465465                         if (ch == '\'')
 466466                                 break;
 467467                 }
 468468                 yytext[yyp] = 0;
 469469 
 470470                 return NUMBER;
 471471 
 472472         case ' ':
 473473         case '\t':
 474474                 while ((ch = inch()) == ' ' || ch == '\t')
 475475                         yytext[yyp++] = (usch)ch;
 476476                 unch(ch);
 477477                 yytext[yyp] = 0;
 478478                 return WSPACE;
 479479 
 480480         case '/':
 481481                 if ((ch = inch()) == '/') {
 482482                         do {
 483483                                 yytext[yyp++] = (usch)ch;
 484484                                 ch = inch();
 485485                         } while (ch && ch != '\n');
 486486                         yytext[yyp] = 0;
 487487                         unch(ch);
 488488                         goto zagain;
 489489                 } else if (ch == '*') {
 490490                         int c, wrn;
 491491                         extern int readmac;
 492492 
 493493                         if (Cflag && !flslvl && readmac) {
 494494                                 unch(ch);
 495495                                 yytext[yyp] = 0;
 496496                                 return CMNT;
 497497                         }
 498498 
 499499                         wrn = 0;
 500500                 more:   while ((c = inch()) && c != '*') {
 501501                                 if (c == '\n')
 502502                                         putch(c), ifiles->lineno++;
 503503                                 else if (c == EBLOCK) {
 504504                                         (void)inch();
 505505                                         (void)inch();
 506506                                 } else if (c == 1) /* WARN */
 507507                                         wrn = 1;
 508508                         }
 509509                         if (c == 0)
 510510                                 return 0;
 511511                         if ((c = inch()) && c != '/') {
 512512                                 unch(c);
 513513                                 goto more;
 514514                         }
 515515                         if (c == 0)
 516516                                 return 0;
 517517                         if (!tflag && !Cflag && !flslvl)
 518518                                 unch(' ');
 519519                         if (wrn)
 520520                                 unch(1);
 521521                         goto zagain;
 522522                 }
 523523                 unch(ch);
 524524                 ch = '/';
 525525                 goto any;
 526526 
 527527         case '.':
 528528                 ch = inch();
 529529                 if (isdigit(ch)) {
 530530                         yytext[yyp++] = (usch)ch;
 531531                         goto ppnum;
 532532                 } else {
 533533                         unch(ch);
 534534                         ch = '.';
 535535                 }
 536536                 goto any;
 537537 
 538538         case '\"':
 539539                 if (tflag && defining)
 540540                         goto any;
 541541         strng:
 542542                 for (;;) {
 543543                         if ((ch = inch()) == '\\') {
 544544                                 yytext[yyp++] = (usch)ch;
 545545                                 yytext[yyp++] = (usch)inch();
 546546                                 continue;
 547547                         } else
 548548                                 yytext[yyp++] = (usch)ch;
 549549                         if (ch == '\"')
 550550                                 break;
 551551                 }
 552552                 yytext[yyp] = 0;
 553553                 return STRING;
 554554 
 555555         case 'L':
 556556                 if ((ch = inch()) == '\"' && !tflag) {
 557557                         yytext[yyp++] = (usch)ch;
 558558                         goto strng;
 559559                 } else if (ch == '\'' && !tflag) {
 560560                         yytext[yyp++] = (usch)ch;
 561561                         goto chlit;
 562562                 }
 563563                 unch(ch);
 564564                 /* FALLTHROUGH */
 565565 
 566566         /* Yetch, all identifiers */
 567567         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
 568568         case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
 569569         case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
 570570         case 's': case 't': case 'u': case 'v': case 'w': case 'x':
 571571         case 'y': case 'z':
 572572         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
 573573         case 'G': case 'H': case 'I': case 'J': case 'K':
 574574         case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
 575575         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
 576576         case 'Y': case 'Z':
 577577         case '_': /* {L}({L}|{D})* */
 578578 
 579579                 /* Special hacks */
 580580                 for (;;) { /* get chars */
 581581                         ch = inch();
 582582                         if (isalpha(ch) || isdigit(ch) || ch == '_') {
 583583                                 yytext[yyp++] = (usch)ch;
 584584                         } else {
 585585                                 if (ch != -1)
 586586                                         unch(ch);
 587587                                 break;
 588588                         }
 589589                 }
 590590                 yytext[yyp] = 0; /* need already string */
 591591                 /* end special hacks */
 592592 
 593593                 return IDENT;
 594594         default:
 595595         any:
 596596                 yytext[yyp] = 0;
 597597                 return yytext[0];
 598598 
 599599         } /* endcase */
 600600         goto zagain;
 601601 
 602602 yyret:
 603603         yytext[yyp] = 0;
 604604         return ch;
 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 #define C2(a,b,c) case a: if (c2 == b) return c; break
 622622         switch (ch) {
 623623         C2('=', '=', EQ);
 624624         C2('!', '=', NE);
 625625         C2('|', '|', OROR);
 626626         C2('&', '&', ANDAND);
 627627         case '<':
 628628                 if (c2 == '<') return LS;
 629629                 if (c2 == '=') return LE;
 630630                 break;
 631631         case '>':
 632632                 if (c2 == '>') return RS;
 633633                 if (c2 == '=') return GE;
 634634                 break;
 635635         case '+':
 636636         case '-':
 637637                 if (ch == c2)
 638638                         badop("");
 639639                 break;
 640640 
 641641         case '/':
 642642                 if (Cflag == 0 || c2 != '*')
 643643                         break;
 644644                 /* Found comment that need to be skipped */
 645645                 for (;;) {
 646646                         ch = inpch();
 647647                 c1:     if (ch != '*')
 648648                                 continue;
 649649                         if ((ch = inpch()) == '/')
 650650                                 break;
 651651                         goto c1;
 652652                 }
 653653                 return yylex();
 654654 
 655655         case NUMBER:
 656656                 if (yytext[0] == '\'') {
 657657                         yylval.node.op = NUMBER;
 658658                         yylval.node.nd_val = charcon(yytext);
 659659                 } else
 660660                         cvtdig(yytext[0] != '0' ? 10 :
 661661                             yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
 662662                 return NUMBER;
 663663 
 664664         case IDENT:
 665665                 if (strcmp((char *)yytext, "defined") == 0) {
 666666                         ifdef = 1;
 667667                         return DEFINED;
 668668                 }
 669669                 nl = lookup(yytext, FIND);
 670670                 if (ifdef) {
 671671                         yylval.node.nd_val = nl != NULL;
 672672                         ifdef = 0;
 673673                 } else if (nl && noex == 0) {
 674674                         usch *och = stringbuf;
 675675                         int i;
 676676 
 677677                         i = kfind(nl);
 678678                         unch(WARN);
 679679                         if (i)
 680680                                 unpstr(stringbuf);
 681681                         else
 682682                                 unpstr(nl->namep);
 683683                         stringbuf = och;
 684684                         noex = 1;
 685685                         return yylex();
 686686                 } else {
 687687                         yylval.node.nd_val = 0;
 688688                 }
 689689                 yylval.node.op = NUMBER;
 690690                 return NUMBER;
 691691         case WARN:
 692692                 noex = 0;
 693693                 /* FALLTHROUGH */
 694694         case PHOLD:
 695695                 return yylex();
 696696         default:
 697697                 return ch;
 698698         }
 699699         unch(c2);
 700700         return ch;
 701701 }
 702702 
 703703 static int
 704704 inpch(void)
 705705 {
 706706         int len;
 707707 
 708708         if (ifiles->curptr < ifiles->maxread)
 709709                 return *ifiles->curptr++;
 710710 
 711711         if (ifiles->infil == -1)
 712712                 return -1;
 713713         if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0)
 714714                 error("read error on file %s", ifiles->orgfn);
 715715         if (len == 0)
 716716                 return -1;
 717717         ifiles->buffer[len] = 0;
 718718         ifiles->curptr = ifiles->buffer;
 719719         ifiles->maxread = ifiles->buffer + len;
 720720         return inpch();
 721721 }
 722722 
 723723 static int
 724724 inch(void)
 725725 {
 726726         int c;
 727727 
 728728 again:  switch (c = inpch()) {
 729729         case '\\': /* continued lines */
 730730 msdos:          if ((c = inpch()) == '\n') {
 731731                         ifiles->lineno++;
 732732                         putch('\n');
 733733                         goto again;
 734734                 } else if (c == '\r')
 735735                         goto msdos;
 736736                 unch(c);
 737737                 return '\\';
 738738         case '?': /* trigraphs */
 739739                 if ((c = chktg())) {
 740740                         unch(c);
 741741                         goto again;
 742742                 }
 743743                 return '?';
 744744         default:
 745745                 return c;
 746746         }
 747747 }
 748748 
 749749 /*
 750750  * Let the command-line args be faked defines at beginning of file.
 751751  */
 752752 static void
 753753 prinit(struct initar *it, struct includ *ic)
 754754 {
 755755         const char *pre, *post;
 756756         char *a;
 757757 
 758758         if (it->next)
 759759                 prinit(it->next, ic);
 760760         pre = post = NULL; /* XXX gcc */
 761761         switch (it->type) {
 762762         case 'D':
 763763                 pre = "#define ";
 764764                 if ((a = strchr(it->str, '=')) != NULL) {
 765765                         *a = ' ';
 766766                         post = "\n";
 767767                 } else
 768768                         post = " 1\n";
 769769                 break;
 770770         case 'U':
 771771                 pre = "#undef ";
 772772                 post = "\n";
 773773                 break;
 774774         case 'i':
 775775                 pre = "#include \"";
 776776                 post = "\"\n";
 777777                 break;
 778778         default:
 779779                 error("prinit");
 780780         }
 781781         strlcat((char *)ic->buffer, pre, CPPBUF+1);
 782782         strlcat((char *)ic->buffer, it->str, CPPBUF+1);
 783783         if (strlcat((char *)ic->buffer, post, CPPBUF+1) >= CPPBUF+1)
 784784                 error("line exceeds buffer size");
 785785 
 786786         ic->lineno--;
 787787         while (*ic->maxread)
 788788                 ic->maxread++;
 789789 }
 790790 
 791791 /*
 792792  * A new file included.
 793793  * If ifiles == NULL, this is the first file and already opened (stdin).
 794794  * Return 0 on success, -1 if file to be included is not found.
 795795  */
 796796 int
 797797 pushfile(const usch *file, const usch *fn, int idx, void *incs)
 798798 {
 799799         extern struct initar *initar;
 800800         struct includ ibuf;
 801801         struct includ *ic;
 802802         int otrulvl, i;
 803803 
 804804         ic = &ibuf;
 805805         ic->next = ifiles;
 806806 
 807807         if (file != NULL) {
 808808                 if ((ic->infil = open((const char *)file, O_RDONLY)) < 0)
 809809                         return -1;
 810810                 ic->orgfn = ic->fname = file;
 811811                 if (++inclevel > MAX_INCLEVEL)
 812812                         error("Limit for nested includes exceeded");
 813813         } else {
 814814                 ic->infil = 0;
 815815                 ic->orgfn = ic->fname = (const usch *)"<stdin>";
 816816         }
 817817 #ifndef BUF_STACK
 818818         ic->bbuf = malloc(BBUFSZ);
 819819 #endif
 820820         ic->buffer = ic->bbuf+NAMEMAX;
 821821         ic->curptr = ic->buffer;
 822822         ifiles = ic;
 823823         ic->lineno = 1;
 824824         ic->maxread = ic->curptr;
 825825         ic->idx = idx;
 826826         ic->incs = incs;
 827827         ic->fn = fn;
 828828         prtline();
 829829         if (initar) {
 830830                 int oin = ic->infil;
 831831                 ic->infil = -1;
 832832                 *ic->maxread = 0;
 833833                 prinit(initar, ic);
 834834                 initar = NULL;
 835835                 if (dMflag)
 836836                         i = write(ofd, ic->buffer, strlen((char *)ic->buffer));
 837837                 fastscan();
 838838                 prtline();
 839839                 ic->infil = oin;
 840840         }
 841841 
 842842         otrulvl = trulvl;
 843843 
 844844         fastscan();
 845845 
 846846         if (otrulvl != trulvl || flslvl)
 847847                 error("unterminated conditional");
 848848 
 849849 #ifndef BUF_STACK
 850850         free(ic->bbuf);
 851851 #endif
 852852         ifiles = ic->next;
 853853         close(ic->infil);
 854854         inclevel--;
 855855         return 0;
 856856 }
 857857 
 858858 /*
 859859  * Print current position to output file.
 860860  */
 861861 void
 862862 prtline(void)
 863863 {
 864864         usch *s, *os = stringbuf;
 865865         int i;
 866866 
 867867         if (Mflag) {
 868868                 if (dMflag)
 869869                         return; /* no output */
 870870                 if (ifiles->lineno == 1) {
 871871                         s = sheap("%s: %s\n", Mfile, ifiles->fname);
 872872                         i = write(ofd, s, strlen((char *)s));
 873873                         if (MPflag &&
 874874                             strcmp((const char *)ifiles->fname, (char *)MPfile)) {
 875875                                 s = sheap("%s:\n", ifiles->fname);
 876876                                 i = write(ofd, s, strlen((char *)s));
 877877                         }
 878878                 }
 879879         } else if (!Pflag) {
 880880                 putstr(sheap("\n# %d \"%s\"", ifiles->lineno, ifiles->fname));
 881881                 if (ifiles->idx == SYSINC)
 882882                         putstr(sheap(" 3"));
 883883                 putstr(sheap("\n"));
 884884         }
 885885         stringbuf = os;
 886886 }
 887887 
 888888 void
 889889 cunput(int c)
 890890 {
 891891 #ifdef PCC_DEBUG
<>892 -//      extern int dflag;
893892 //      if (dflag)printf(": '%c'(%d)\n", c > 31 ? c : ' ', c);
 894893 #endif
<>895 -#if 0
 896 -if (c == 10) {
 897 -        printf("c == 10!!!\n");
 898 -}
 899 -#endif
<_900894         unch(c);
 901895 }
 902896 
 903897 static int
 904898 dig2num(int c)
 905899 {
 906900         if (c >= 'a')
 907901                 c = c - 'a' + 10;
 908902         else if (c >= 'A')
 909903                 c = c - 'A' + 10;
 910904         else
 911905                 c = c - '0';
 912906         return c;
 913907 }
 914908 
 915909 /*
 916910  * Convert string numbers to unsigned long long and check overflow.
 917911  */
 918912 static void
 919913 cvtdig(int rad)
 920914 {
 921915         unsigned long long rv = 0;
 922916         unsigned long long rv2 = 0;
 923917         usch *y = yytext;
 924918         int c;
 925919 
 926920         c = *y++;
 927921         if (rad == 16)
 928922                 y++;
 929923         while (isxdigit(c)) {
 930924                 rv = rv * rad + dig2num(c);
 931925                 /* check overflow */
 932926                 if (rv / rad < rv2)
 933927                         error("Constant \"%s\" is out of range", yytext);
 934928                 rv2 = rv;
 935929                 c = *y++;
 936930         }
 937931         y--;
 938932         while (*y == 'l' || *y == 'L')
 939933                 y++;
 940934         yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER;
 941935         yylval.node.nd_uval = rv;
 942936         if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0)
 943937                 yylval.node.op = UNUMBER;
 944938         if (yylval.node.op == NUMBER && yylval.node.nd_val < 0)
 945939                 /* too large for signed, see 6.4.4.1 */
 946940                 error("Constant \"%s\" is out of range", yytext);
 947941 }
 948942 
 949943 static int
 950944 charcon(usch *p)
 951945 {
 952946         int val, c;
 953947 
 954948         p++; /* skip first ' */
 955949         val = 0;
 956950         if (*p++ == '\\') {
 957951                 switch (*p++) {
 958952                 case 'a': val = '\a'; break;
 959953                 case 'b': val = '\b'; break;
 960954                 case 'f': val = '\f'; break;
 961955                 case 'n': val = '\n'; break;
 962956                 case 'r': val = '\r'; break;
 963957                 case 't': val = '\t'; break;
 964958                 case 'v': val = '\v'; break;
 965959                 case '\"': val = '\"'; break;
 966960                 case '\'': val = '\''; break;
 967961                 case '\\': val = '\\'; break;
 968962                 case 'x':
 969963                         while (isxdigit(c = *p)) {
 970964                                 val = val * 16 + dig2num(c);
 971965                                 p++;
 972966                         }
 973967                         break;
 974968                 case '0': case '1': case '2': case '3': case '4':
 975969                 case '5': case '6': case '7':
 976970                         p--;
 977971                         while (isdigit(c = *p)) {
 978972                                 val = val * 8 + (c - '0');
 979973                                 p++;
 980974                         }
 981975                         break;
 982976                 default: val = p[-1];
 983977                 }
 984978 
 985979         } else
 986980                 val = p[-1];
 987981         return val;
 988982 }
 989983 
 990984 static void
 991985 chknl(int ignore)
 992986 {
 993987         int t;
 994988 
 995989         while ((t = sloscan()) == WSPACE)
 996990                 ;
 997991         if (t != '\n') {
 998992                 if (t && t != (usch)-1) {
 999993                         if (ignore) {
 1000994                                 warning("newline expected, got \"%s\"", yytext);
 1001995                                 /* ignore rest of line */
 1002996                                 while ((t = sloscan()) && t != '\n')
 1003997                                         ;
 1004998                         }
 1005999                         else
 10061000                                 error("newline expected, got \"%s\"", yytext);
 10071001                 } else {
 10081002                         if (ignore)
 10091003                                 warning("no newline at end of file");
 10101004                         else
 10111005                                 error("no newline at end of file");
 10121006                 }
 10131007         }
 10141008 }
 10151009 
 10161010 static void
 10171011 elsestmt(void)
 10181012 {
 10191013         if (flslvl) {
 10201014                 if (elflvl > trulvl)
 10211015                         ;
 10221016                 else if (--flslvl!=0) {
 10231017                         flslvl++;
 10241018                 } else {
 10251019                         trulvl++;
 10261020                         prtline();
 10271021                 }
 10281022         } else if (trulvl) {
 10291023                 flslvl++;
 10301024                 trulvl--;
 10311025         } else
 10321026                 error("If-less else");
 10331027         if (elslvl==trulvl+flslvl)
 10341028                 error("Too many else");
 10351029         elslvl=trulvl+flslvl;
 10361030         chknl(1);
 10371031 }
 10381032 
 10391033 static void
 10401034 skpln(void)
 10411035 {
 10421036         /* just ignore the rest of the line */
 10431037         while (inch() != '\n')
 10441038                 ;
 10451039         unch('\n');
 10461040         flslvl++;
 10471041 }
 10481042 
 10491043 static void
 10501044 ifdefstmt(void)         
 10511045 {
 10521046         int t;
 10531047 
 10541048         if (flslvl) {
 10551049                 skpln();
 10561050                 return;
 10571051         }
 10581052         do
 10591053                 t = sloscan();
 10601054         while (t == WSPACE);
 10611055         if (t != IDENT)
 10621056                 error("bad ifdef");
 10631057         if (lookup(yytext, FIND) == 0) {
 10641058                 putch('\n');
 10651059                 flslvl++;
 10661060         } else
 10671061                 trulvl++;
 10681062         chknl(0);
 10691063 }
 10701064 
 10711065 static void
 10721066 ifndefstmt(void)         
 10731067 {
 10741068         int t;
 10751069 
 10761070         if (flslvl) {
 10771071                 skpln();
 10781072                 return;
 10791073         }
 10801074         do
 10811075                 t = sloscan();
 10821076         while (t == WSPACE);
 10831077         if (t != IDENT)
 10841078                 error("bad ifndef");
 10851079         if (lookup(yytext, FIND) != 0) {
 10861080                 putch('\n');
 10871081                 flslvl++;
 10881082         } else
 10891083                 trulvl++;
 10901084         chknl(0);
 10911085 }
 10921086 
 10931087 static void
 10941088 endifstmt(void)         
 10951089 {
 10961090         if (flslvl) {
 10971091                 flslvl--;
 10981092                 if (flslvl == 0) {
 10991093                         putch('\n');
 11001094                         prtline();
 11011095                 }
 11021096         } else if (trulvl)
 11031097                 trulvl--;
 11041098         else
 11051099                 error("If-less endif");
 11061100         if (flslvl == 0)
 11071101                 elflvl = 0;
 11081102         elslvl = 0;
 11091103         chknl(1);
 11101104 }
 11111105 
 11121106 static void
 11131107 ifstmt(void)
 11141108 {
 11151109         if (flslvl == 0) {
 11161110                 if (yyparse() == 0) {
 11171111                         putch('\n');
 11181112                         ++flslvl;
 11191113                 } else
 11201114                         ++trulvl;
 11211115         } else
 11221116                 ++flslvl;
 11231117 }
 11241118 
 11251119 static void
 11261120 elifstmt(void)
 11271121 {
 11281122         if (flslvl == 0)
 11291123                 elflvl = trulvl;
 11301124         if (flslvl) {
 11311125                 if (elflvl > trulvl)
 11321126                         ;
 11331127                 else if (--flslvl!=0)
 11341128                         ++flslvl;
 11351129                 else {
 11361130                         if (yyparse()) {
 11371131                                 ++trulvl;
 11381132                                 prtline();
 11391133                         } else {
 11401134                                 putch('\n');
 11411135                                 ++flslvl;
 11421136                         }
 11431137                 }
 11441138         } else if (trulvl) {
 11451139                 ++flslvl;
 11461140                 --trulvl;
 11471141         } else
 11481142                 error("If-less elif");
 11491143 }
 11501144 
 11511145 static usch *
 11521146 svinp(void)
 11531147 {
 11541148         int c;
 11551149         usch *cp = stringbuf;
 11561150 
 11571151         while ((c = inch()) && c != '\n')
 11581152                 savch(c);
 11591153         savch('\n');
 11601154         savch(0);
 11611155         return cp;
 11621156 }
 11631157 
 11641158 static void
 11651159 cpperror(void)
 11661160 {
 11671161         usch *cp;
 11681162         int c;
 11691163 
 11701164         if (flslvl)
 11711165                 return;
 11721166         c = sloscan();
 11731167         if (c != WSPACE && c != '\n')
 11741168                 error("bad error");
 11751169         cp = svinp();
 11761170         if (flslvl)
 11771171                 stringbuf = cp;
 11781172         else
 11791173                 error("%s", cp);
 11801174 }
 11811175 
 11821176 static void
 11831177 cppwarning(void)
 11841178 {
 11851179         usch *cp;
 11861180         int c;
 11871181 
 11881182         if (flslvl)
 11891183                 return;
 11901184         c = sloscan();
 11911185         if (c != WSPACE && c != '\n')
 11921186                 error("bad warning");
 11931187 
 11941188         /* svinp() add an unwanted \n */
 11951189         cp = stringbuf;
 11961190         while ((c = inch()) && c != '\n')
 11971191                 savch(c);
 11981192         savch(0);
 11991193 
 12001194         if (flslvl)
 12011195                 stringbuf = cp;
 12021196         else
 12031197                 warning("#warning %s", cp);
 12041198 
 12051199         unch('\n');
 12061200 }
 12071201 
 12081202 static void
 12091203 undefstmt(void)
 12101204 {
 12111205         struct symtab *np;
 12121206 
 12131207         if (flslvl)
 12141208                 return;
 12151209         if (sloscan() != WSPACE || sloscan() != IDENT)
 12161210                 error("bad undef");
 12171211         if (flslvl == 0 && (np = lookup(yytext, FIND)))
 12181212                 np->value = 0;
 12191213         chknl(0);
 12201214 }
 12211215 
 12221216 static void
 12231217 pragmastmt(void)
 12241218 {
 12251219         int c;
 12261220         usch *sb = stringbuf;
 12271221 
 12281222         if (sloscan() != WSPACE)
 12291223                 error("bad pragma");
 12301224         savstr((const usch *)"\n#pragma ");
 12311225         do {
 12321226                 savch(c = inch());
 12331227         } while (c && c != '\n');
 12341228         if (c == '\n')
 12351229                 unch(c);
 12361230         savch(0);
 12371231         if (!flslvl)
 12381232                 putstr(sb);
 12391233         stringbuf = sb;
 12401234         prtline();
 12411235 }
 12421236 
 12431237 static void
 12441238 badop(const char *op)
 12451239 {
 12461240         error("invalid operator in preprocessor expression: %s", op);
 12471241 }
 12481242 
 12491243 int
 12501244 cinput(void)
 12511245 {
 12521246         return inch();
 12531247 }
 12541248 
 12551249 /*
 12561250  * Check for (and convert) trigraphs.
 12571251  */
 12581252 int
 12591253 chktg(void)
 12601254 {
 12611255         int c;
 12621256 
 12631257         if ((c = inpch()) != '?') {
 12641258                 unch(c);
 12651259                 return 0;
 12661260         }
 12671261         switch (c = inpch()) {
 12681262         case '=': c = '#'; break;
 12691263         case '(': c = '['; break;
 12701264         case ')': c = ']'; break;
 12711265         case '<': c = '{'; break;
 12721266         case '>': c = '}'; break;
 12731267         case '/': c = '\\'; break;
 12741268         case '\'': c = '^'; break;
 12751269         case '!': c = '|'; break;
 12761270         case '-': c = '~'; break;
 12771271         default:
 12781272                 unch(c);
 12791273                 unch('?');
 12801274                 c = 0;
 12811275         }
 12821276         return c;
 12831277 }
 12841278 
 12851279 static struct {
 12861280         const char *name;
 12871281         void (*fun)(void);
 12881282 } ppd[] = {
 12891283         { "ifndef", ifndefstmt },
 12901284         { "ifdef", ifdefstmt },
 12911285         { "if", ifstmt },
 12921286         { "include", include },
 12931287         { "else", elsestmt },
 12941288         { "endif", endifstmt },
 12951289         { "error", cpperror },
 12961290         { "warning", cppwarning },
 12971291         { "define", define },
 12981292         { "undef", undefstmt },
 12991293         { "line", line },
 13001294         { "pragma", pragmastmt },
 13011295         { "elif", elifstmt },
 13021296 #ifdef GCC_COMPAT
 13031297         { "include_next", include_next },
 13041298 #endif
 13051299 };
 13061300 
 13071301 /*
 13081302  * Handle a preprocessor directive.
 13091303  */
 13101304 void
 13111305 ppdir(void)
 13121306 {
 13131307         char bp[20];
 13141308         int ch, i;
 13151309 
 13161310         while ((ch = inch()) == ' ' || ch == '\t')
 13171311                 ;
 13181312         if (ch == '\n') { /* empty directive */
 13191313                 unch(ch);
 13201314                 return;
 13211315         }
 13221316         if (ch < 'a' || ch > 'z')
 13231317                 goto out; /* something else, ignore */
 13241318         i = 0;
 13251319         do {
 13261320                 bp[i++] = (usch)ch;
 13271321                 if (i == sizeof(bp)-1)
 13281322                         goto out; /* too long */
 13291323                 ch = inch();
 13301324         } while ((ch >= 'a' && ch <= 'z') || (ch == '_'));
 13311325         unch(ch);
 13321326         bp[i++] = 0;
 13331327 
 13341328         /* got keyword */
 13351329 #define SZ (int)(sizeof(ppd)/sizeof(ppd[0]))
 13361330         for (i = 0; i < SZ; i++)
 13371331                 if (bp[0] == ppd[i].name[0] && strcmp(bp, ppd[i].name) == 0)
 13381332                         break;
 13391333         if (i == SZ)
 13401334                 goto out;
 13411335 
 13421336         /* Found matching keyword */
 13431337         (*ppd[i].fun)();
 13441338         return;
 13451339 
 13461340 out:    while ((ch = inch()) != '\n' && ch != -1)
 13471341                 ;
 13481342         unch('\n');
 13491343 }
FishEye: Open Source License registered to PCC.
Atlassian FishEye, CVS analysis. (Version:1.6.3 Build:build-336 2008-11-04) - Administration - Page generated 2014-12-21 03:39 +0100