Quick Search:

Mode

Context

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

Other Diffs

Ignore

Blank Lines Whitespace: Expand:

Diff

1.92
 
1.93
 
MAIN:plunky:20121029172623
 
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 
 5353 #include "compat.h"
 5454 #include "cpp.h"
 5555 #include "cpy.h"
 5656 
 5757 static void cvtdig(int rad);
 5858 static int charcon(usch *);
 5959 static void elsestmt(void);
 6060 static void ifdefstmt(void);
 6161 static void ifndefstmt(void);
 6262 static void endifstmt(void);
 6363 static void ifstmt(void);
 6464 static void cpperror(void);
 6565 static void pragmastmt(void);
 6666 static void undefstmt(void);
 6767 static void cppwarning(void);
 6868 static void elifstmt(void);
 6969 static int chktg(void);
 7070 static int inpch(void);
 7171 static int inch(void);
 7272 
 7373 #define PUTCH(ch) if (!flslvl) putch(ch)
 7474 /* protection against recursion in #include */
 7575 #define MAX_INCLEVEL    100
 7676 static int inclevel;
 7777 
 7878 /* get next character unaltered */
 7979 #define NXTCH() (ifiles->curptr < ifiles->maxread ? *ifiles->curptr++ : inpch())
 8080 
 8181 usch yytext[CPPBUF];
 8282 
 8383 struct includ *ifiles;
 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 static void
 110110 unch(int c)
 111111 {
<> 112+        if (c == -1)
  113+                return;
<_112114                 
 113115         --ifiles->curptr;
 114116         if (ifiles->curptr < ifiles->bbuf)
 115117                 error("pushback buffer full");
 116118         *ifiles->curptr = (usch)c;
 117119 }
 118120 
 119121 static void
 120122 eatcmnt(void)
 121123 {
 122124         int ch;
 123125 
 124126         if (Cflag) { PUTCH('/'); PUTCH('*'); }
 125127         for (;;) {
 126128                 ch = inch();
 127129                 if (ch == '\n') {
 128130                         ifiles->lineno++;
 129131                         if (!Cflag) PUTCH('\n');
 130132                 }
 131133                 if (ch == -1)
 132134                         break;
 133135                 if (ch == '*') {
 134136                         ch = inch();
 135137                         if (ch == '/') {
 136138                                 if (Cflag) {
 137139                                         PUTCH('*');
 138140                                         PUTCH('/');
 139141                                 } else
 140142                                         PUTCH(' ');
 141143                                 break;
 142144                         }
 143145                         unch(ch);
 144146                         ch = '*';
 145147                 }
 146148                 if (Cflag) PUTCH(ch);
 147149         }
 148150 }
 149151 
 150152 /*
 151153  * Scan quickly the input file searching for:
 152154  *      - '#' directives
 153155  *      - keywords (if not flslvl)
 154156  *      - comments
 155157  *
 156158  *      Handle strings, numbers and trigraphs with care.
 157159  *      Only data from pp files are scanned here, never any rescans.
 158160  *      TODO: Only print out strings before calling other functions.
 159161  */
 160162 static void
 161163 fastscan(void)
 162164 {
 163165         struct symtab *nl;
 164166         int ch, i = 0;
 165167         int nnl = 0;
 166168         usch *cp;
 167169 
 168170         goto run;
 169171         for (;;) {
 170172                 ch = NXTCH();
 171173 xloop:          if (ch == -1)
 172174                         return;
 173175 #ifdef PCC_DEBUG
 174176                 if (dflag>1)
 175177                         printf("fastscan ch %d (%c)\n", ch, ch > 31 ? ch : '@');
 176178 #endif
 177179                 if ((spechr[ch] & C_SPEC) == 0) {
 178180                         PUTCH(ch);
 179181                         continue;
 180182                 }
 181183                 switch (ch) {
 182184                 case EBLOCK:
 183185                 case WARN:
 184186                 case CONC:
 185187                         error("bad char passed");
 186188                         break;
 187189 
 188190                 case '/': /* Comments */
 189191                         if ((ch = inch()) == '/') {
 190192 cppcmt:                         if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
 191193                                 do {
 192194                                         if (Cflag) PUTCH(ch);
 193195                                         ch = inch();
 194196                                 } while (ch != -1 && ch != '\n');
 195197                                 goto xloop;
 196198                         } else if (ch == '*') {
 197199                                 eatcmnt();
 198200                                 continue;
 199201                         } else {
 200202                                 PUTCH('/');
 201203                                 goto xloop;
 202204                         }
 203205                         break;
 204206 
 205207                 case '?'/* trigraphs */
 206208                         if ((ch = chktg()))
 207209                                 goto xloop;
 208210                         PUTCH('?');
 209211                         break;
 210212 
 211213                 case '\\':
 212214                         if ((ch = NXTCH()) == '\n') {
 213215                                 ifiles->lineno++;
 214216                                 continue;
 215217                         }
 216218                         PUTCH('\\');
 217219                         goto xloop;
 218220 
 219221                 case '\n': /* newlines, for pp directives */
 220222                         while (nnl > 0) { PUTCH('\n'); nnl--; ifiles->lineno++; }
 221223 run2:                   ifiles->lineno++;
 222224                         do {
 223225                                 PUTCH(ch);
 224226 run:                            ch = NXTCH();
 225227                                 if (ch == '/') {
 226228                                         ch = NXTCH();
 227229                                         if (ch == '/')
 228230                                                 goto cppcmt;
 229231                                         if (ch == '*') {
 230232                                                 eatcmnt();
 231233                                                 goto run;
 232234                                         }
 233235                                         unch(ch);
 234236                                         ch = '/';
 235237                                 }
 236238                         } while (ch == ' ' || ch == '\t');
 237239                         if (ch == '\\') {
 238240                                 ch = NXTCH();
 239241                                 if (ch == '\n')
 240242                                         goto run2;
 241243                                 unch(ch);
 242244                                 ch = '\\';
 243245                         }
 244246                         if (ch == '#') {
 245247                                 ppdir();
 246248                                 continue;
 247249                         } else if (ch == '%') {
 248250                                 ch = NXTCH();
 249251                                 if (ch == ':') {
 250252                                         ppdir();
 251253                                         continue;
 252254                                 }
 253255                                 unch(ch);
 254256                                 ch = '%';
 255257                         } else if (ch == '?') {
 256258                                 if ((ch = chktg()) == '#') {
 257259                                         ppdir();
 258260                                         continue;
 259261                                 } else if (ch == 0)
 260262                                         ch = '?';
 261263                         }
 262264                         goto xloop;
 263265 
 264266                 case '\"': /* strings */
 265267 str:                    PUTCH(ch);
 266268                         while ((ch = NXTCH()) != '\"') {
 267269                                 if (ch == '\n')
 268270                                         goto xloop;
 269271                                 if (ch == '\\') {
 270272                                         if ((ch = NXTCH()) != '\n') {
 271273                                                 PUTCH('\\');
 272274                                                 PUTCH(ch);
 273275                                         } else
 274276                                                 nnl++;
 275277                                         continue;
 276278                                 }
 277279                                 if (ch == -1)
 278280                                         return;
 279281                                 PUTCH(ch);
 280282                         }
 281283                         PUTCH(ch);
 282284                         break;
 283285 
 284286                 case '.'/* for pp-number */
 285287                         PUTCH(ch);
 286288                         ch = NXTCH();
 287289                         if (ch < '0' || ch > '9')
 288290                                 goto xloop;
 289291                         /* FALLTHROUGH */
 290292                 case '0': case '1': case '2': case '3': case '4':
 291293                 case '5': case '6': case '7': case '8': case '9':
 292294                         do {
 293295                                 PUTCH(ch);
 294296 nxt:                            ch = NXTCH();
 295297                                 if (ch == '\\') {
 296298                                         ch = NXTCH();
 297299                                         if (ch == '\n') {
 298300                                                 nnl++;
 299301                                                 goto nxt;
 300302                                         }
 301303                                         unch(ch);
 302304                                         ch = '\\';
 303305                                 }
 304306                                 if (spechr[ch] & C_EP) {
 305307                                         PUTCH(ch);
 306308                                         ch = NXTCH();
 307309                                         if (ch == '-' || ch == '+')
 308310                                                 continue;
 309311                                 }
 310312                         } while ((spechr[ch] & C_ID) || (ch == '.'));
 311313                         goto xloop;
 312314 
 313315                 case '\'': /* character literal */
 314316 con:                    PUTCH(ch);
 315317                         if (tflag)
 316318                                 continue; /* character constants ignored */
 317319                         while ((ch = NXTCH()) != '\'') {
 318320                                 if (ch == '\n')
 319321                                         goto xloop;
 320322                                 if (ch == '\\') {
 321323                                         if ((ch = NXTCH()) != '\n') {
 322324                                                 PUTCH('\\');
 323325                                                 PUTCH(ch);
 324326                                         } else
 325327                                                 nnl++;
 326328                                         continue;
 327329                                 }
 328330                                 if (ch == -1)
 329331                                         return;
 330332                                 PUTCH(ch);
 331333                         }
 332334                         PUTCH(ch);
 333335                         break;
 334336 
 335337                 case 'L':
 336338                         ch = NXTCH();
 337339                         if (ch == '\"') {
 338340                                 PUTCH('L');
 339341                                 goto str;
 340342                         }
 341343                         if (ch == '\'') {
 342344                                 PUTCH('L');
 343345                                 goto con;
 344346                         }
 345347                         unch(ch);
 346348                         ch = 'L';
 347349                         /* FALLTHROUGH */
 348350                 default:
 349351                         if ((spechr[ch] & C_ID) == 0)
 350352                                 error("fastscan");
 351353                         if (flslvl) {
 352354                                 while (spechr[ch] & C_ID)
 353355                                         ch = NXTCH();
 354356                                 goto xloop;
 355357                         }
 356358                         i = 0;
 357359                         do {
 358360                                 yytext[i++] = (usch)ch;
 359361                                 ch = NXTCH();
 360362                                 if (ch == '\\') {
 361363                                         ch = NXTCH();
 362364                                         if (ch != '\n') {
 363365                                                 unch(ch);
 364366                                                 ch = '\\';
 365367                                         } else {
 366368                                                 putch('\n');
 367369                                                 ifiles->lineno++;
 368370                                                 ch = NXTCH();
 369371                                         }
 370372                                 }
 371373                                 if (ch == -1)
 372374                                         return;
 373375                         } while (spechr[ch] & C_ID);
 374376 
 375377                         yytext[i] = 0;
 376378                         unch(ch);
 377379 
 378380                         cp = stringbuf;
 379381                         if ((nl = lookup(yytext, FIND)) && kfind(nl)) {
 380382                                 putstr(stringbuf);
 381383                         } else
 382384                                 putstr(yytext);
 383385                         stringbuf = cp;
 384386 
 385387                         break;
 386388                 }
 387389         }
 388390 }
 389391 
 390392 int
 391393 sloscan(void)
 392394 {
 393395         int ch;
 394396         int yyp;
 395397 
 396398 zagain:
 397399         yyp = 0;
 398400         ch = inch();
 399401         yytext[yyp++] = (usch)ch;
 400402         switch (ch) {
 401403         case -1:
 402404                 return 0;
 403405         case '\n':
 404406                 /* sloscan() never passes \n, that's up to fastscan() */
 405407                 unch(ch);
 406408                 goto yyret;
 407409 
 408410         case '\r': /* Ignore CR's */
 409411                 yyp = 0;
 410412                 break;
 411413 
 412414         case '0': case '1': case '2': case '3': case '4': case '5':
 413415         case '6': case '7': case '8': case '9':
 414416                 /* readin a "pp-number" */
 415417 ppnum:          for (;;) {
 416418                         ch = inch();
 417419                         if (spechr[ch] & C_EP) {
 418420                                 yytext[yyp++] = (usch)ch;
 419421                                 ch = inch();
 420422                                 if (ch == '-' || ch == '+') {
 421423                                         yytext[yyp++] = (usch)ch;
 422424                                 } else
 423425                                         unch(ch);
 424426                                 continue;
 425427                         }
 426428                         if ((spechr[ch] & C_ID) || ch == '.') {
 427429                                 yytext[yyp++] = (usch)ch;
 428430                                 continue;
 429431                         }
 430432                         break;
 431433                 }
 432434                 unch(ch);
 433435                 yytext[yyp] = 0;
 434436 
 435437                 return NUMBER;
 436438 
 437439         case '\'':
 438440 chlit:          
 439441                 for (;;) {
 440442                         if ((ch = inch()) == '\\') {
 441443                                 yytext[yyp++] = (usch)ch;
 442444                                 yytext[yyp++] = (usch)inch();
 443445                                 continue;
 444446                         } else if (ch == '\n') {
 445447                                 /* not a constant */
 446448                                 while (yyp > 1)
 447449                                         unch(yytext[--yyp]);
 448450                                 ch = '\'';
 449451                                 goto any;
 450452                         } else
 451453                                 yytext[yyp++] = (usch)ch;
 452454                         if (ch == '\'')
 453455                                 break;
 454456                 }
 455457                 yytext[yyp] = 0;
 456458 
 457459                 return NUMBER;
 458460 
 459461         case ' ':
 460462         case '\t':
 461463                 while ((ch = inch()) == ' ' || ch == '\t')
 462464                         yytext[yyp++] = (usch)ch;
 463465                 unch(ch);
 464466                 yytext[yyp] = 0;
 465467                 return WSPACE;
 466468 
 467469         case '/':
 468470                 if ((ch = inch()) == '/') {
 469471                         do {
 470472                                 yytext[yyp++] = (usch)ch;
 471473                                 ch = inch();
 472474                         } while (ch && ch != '\n');
 473475                         yytext[yyp] = 0;
 474476                         unch(ch);
 475477                         goto zagain;
 476478                 } else if (ch == '*') {
 477479                         int c, wrn;
 478480                         extern int readmac;
 479481 
 480482                         if (Cflag && !flslvl && readmac) {
 481483                                 unch(ch);
 482484                                 yytext[yyp] = 0;
 483485                                 return CMNT;
 484486                         }
 485487 
 486488                         wrn = 0;
 487489                 more:   while ((c = inch()) && c != '*') {
 488490                                 if (c == '\n')
 489491                                         putch(c), ifiles->lineno++;
 490492                                 else if (c == EBLOCK) {
 491493                                         (void)inch();
 492494                                         (void)inch();
 493495                                 } else if (c == 1) /* WARN */
 494496                                         wrn = 1;
 495497                         }
 496498                         if (c == 0)
 497499                                 return 0;
 498500                         if ((c = inch()) && c != '/') {
 499501                                 unch(c);
 500502                                 goto more;
 501503                         }
 502504                         if (c == 0)
 503505                                 return 0;
 504506                         if (!tflag && !Cflag && !flslvl)
 505507                                 unch(' ');
 506508                         if (wrn)
 507509                                 unch(1);
 508510                         goto zagain;
 509511                 }
 510512                 unch(ch);
 511513                 ch = '/';
 512514                 goto any;
 513515 
 514516         case '.':
 515517                 ch = inch();
 516518                 if (isdigit(ch)) {
 517519                         yytext[yyp++] = (usch)ch;
 518520                         goto ppnum;
 519521                 } else {
 520522                         unch(ch);
 521523                         ch = '.';
 522524                 }
 523525                 goto any;
 524526 
 525527         case '\"':
 526528                 if (tflag && defining)
 527529                         goto any;
 528530         strng:
 529531                 for (;;) {
 530532                         if ((ch = inch()) == '\\') {
 531533                                 yytext[yyp++] = (usch)ch;
 532534                                 yytext[yyp++] = (usch)inch();
 533535                                 continue;
 534536                         } else
 535537                                 yytext[yyp++] = (usch)ch;
 536538                         if (ch == '\"')
 537539                                 break;
 538540                 }
 539541                 yytext[yyp] = 0;
 540542                 return STRING;
 541543 
 542544         case 'L':
 543545                 if ((ch = inch()) == '\"' && !tflag) {
 544546                         yytext[yyp++] = (usch)ch;
 545547                         goto strng;
 546548                 } else if (ch == '\'' && !tflag) {
 547549                         yytext[yyp++] = (usch)ch;
 548550                         goto chlit;
 549551                 }
 550552                 unch(ch);
 551553                 /* FALLTHROUGH */
 552554 
 553555         /* Yetch, all identifiers */
 554556         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
 555557         case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
 556558         case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
 557559         case 's': case 't': case 'u': case 'v': case 'w': case 'x':
 558560         case 'y': case 'z':
 559561         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
 560562         case 'G': case 'H': case 'I': case 'J': case 'K':
 561563         case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
 562564         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
 563565         case 'Y': case 'Z':
 564566         case '_': /* {L}({L}|{D})* */
 565567 
 566568                 /* Special hacks */
 567569                 for (;;) { /* get chars */
 568570                         ch = inch();
 569571                         if (isalpha(ch) || isdigit(ch) || ch == '_') {
 570572                                 yytext[yyp++] = (usch)ch;
 571573                         } else {
 572574                                 if (ch != -1)
 573575                                         unch(ch);
 574576                                 break;
 575577                         }
 576578                 }
 577579                 yytext[yyp] = 0; /* need already string */
 578580                 /* end special hacks */
 579581 
 580582                 return IDENT;
 581583         default:
 582584         any:
 583585                 yytext[yyp] = 0;
 584586                 return yytext[0];
 585587 
 586588         } /* endcase */
 587589         goto zagain;
 588590 
 589591 yyret:
 590592         yytext[yyp] = 0;
 591593         return ch;
 592594 }
 593595 
 594596 int
 595597 yylex(void)
 596598 {
 597599         static int ifdef, noex;
 598600         struct symtab *nl;
 599601         int ch, c2;
 600602 
 601603         while ((ch = sloscan()) == WSPACE)
 602604                 ;
 603605         if (ch < 128 && spechr[ch] & C_2)
 604606                 c2 = inpch();
 605607         else
 606608                 c2 = 0;
 607609 
 608610 #define C2(a,b,c) case a: if (c2 == b) return c; break
 609611         switch (ch) {
 610612         C2('=', '=', EQ);
 611613         C2('!', '=', NE);
 612614         C2('|', '|', OROR);
 613615         C2('&', '&', ANDAND);
 614616         case '<':
 615617                 if (c2 == '<') return LS;
 616618                 if (c2 == '=') return LE;
 617619                 break;
 618620         case '>':
 619621                 if (c2 == '>') return RS;
 620622                 if (c2 == '=') return GE;
 621623                 break;
 622624         case '+':
 623625         case '-':
 624626                 if (ch == c2)
 625627                         error("invalid preprocessor operator %c%c", ch, c2);
 626628                 break;
 627629 
 628630         case '/':
 629631                 if (Cflag == 0 || c2 != '*')
 630632                         break;
 631633                 /* Found comment that need to be skipped */
 632634                 for (;;) {
 633635                         ch = inpch();
 634636                 c1:     if (ch != '*')
 635637                                 continue;
 636638                         if ((ch = inpch()) == '/')
 637639                                 break;
 638640                         goto c1;
 639641                 }
 640642                 return yylex();
 641643 
 642644         case NUMBER:
 643645                 if (yytext[0] == '\'') {
 644646                         yylval.node.op = NUMBER;
 645647                         yylval.node.nd_val = charcon(yytext);
 646648                 } else
 647649                         cvtdig(yytext[0] != '0' ? 10 :
 648650                             yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
 649651                 return NUMBER;
 650652 
 651653         case IDENT:
 652654                 if (strcmp((char *)yytext, "defined") == 0) {
 653655                         ifdef = 1;
 654656                         return DEFINED;
 655657                 }
 656658                 nl = lookup(yytext, FIND);
 657659                 if (ifdef) {
 658660                         yylval.node.nd_val = nl != NULL;
 659661                         ifdef = 0;
 660662                 } else if (nl && noex == 0) {
 661663                         usch *och = stringbuf;
 662664                         int i;
 663665 
 664666                         i = kfind(nl);
 665667                         unch(WARN);
 666668                         if (i)
 667669                                 unpstr(stringbuf);
 668670                         else
 669671                                 unpstr(nl->namep);
 670672                         stringbuf = och;
 671673                         noex = 1;
 672674                         return yylex();
 673675                 } else {
 674676                         yylval.node.nd_val = 0;
 675677                 }
 676678                 yylval.node.op = NUMBER;
 677679                 return NUMBER;
 678680         case WARN:
 679681                 noex = 0;
 680682                 /* FALLTHROUGH */
 681683         case PHOLD:
 682684                 return yylex();
 683685         default:
 684686                 return ch;
 685687         }
 686688         unch(c2);
 687689         return ch;
 688690 }
 689691 
 690692 static int
 691693 inpch(void)
 692694 {
 693695         int len;
 694696 
 695697         if (ifiles->curptr < ifiles->maxread)
 696698                 return *ifiles->curptr++;
 697699 
 698700         if (ifiles->infil == -1)
 699701                 return -1;
 700702         if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0)
 701703                 error("read error on file %s", ifiles->orgfn);
 702704         if (len == 0)
 703705                 return -1;
 704706         ifiles->buffer[len] = 0;
 705707         ifiles->curptr = ifiles->buffer;
 706708         ifiles->maxread = ifiles->buffer + len;
 707709         return inpch();
 708710 }
 709711 
 710712 static int
 711713 inch(void)
 712714 {
 713715         int c;
 714716 
 715717 again:  switch (c = inpch()) {
 716718         case '\\': /* continued lines */
 717719 msdos:          if ((c = inpch()) == '\n') {
 718720                         ifiles->lineno++;
 719721                         putch('\n');
 720722                         goto again;
 721723                 } else if (c == '\r')
 722724                         goto msdos;
 723725                 unch(c);
 724726                 return '\\';
 725727         case '?': /* trigraphs */
 726728                 if ((c = chktg())) {
 727729                         unch(c);
 728730                         goto again;
 729731                 }
 730732                 return '?';
 731733         default:
 732734                 return c;
 733735         }
 734736 }
 735737 
 736738 /*
 737739  * Let the command-line args be faked defines at beginning of file.
 738740  */
 739741 static void
 740742 prinit(struct initar *it, struct includ *ic)
 741743 {
 742744         const char *pre, *post;
 743745         char *a;
 744746 
 745747         if (it->next)
 746748                 prinit(it->next, ic);
 747749         pre = post = NULL; /* XXX gcc */
 748750         switch (it->type) {
 749751         case 'D':
 750752                 pre = "#define ";
 751753                 if ((a = strchr(it->str, '=')) != NULL) {
 752754                         *a = ' ';
 753755                         post = "\n";
 754756                 } else
 755757                         post = " 1\n";
 756758                 break;
 757759         case 'U':
 758760                 pre = "#undef ";
 759761                 post = "\n";
 760762                 break;
 761763         case 'i':
 762764                 pre = "#include \"";
 763765                 post = "\"\n";
 764766                 break;
 765767         default:
 766768                 error("prinit");
 767769         }
 768770         strlcat((char *)ic->buffer, pre, CPPBUF+1);
 769771         strlcat((char *)ic->buffer, it->str, CPPBUF+1);
 770772         if (strlcat((char *)ic->buffer, post, CPPBUF+1) >= CPPBUF+1)
 771773                 error("line exceeds buffer size");
 772774 
 773775         ic->lineno--;
 774776         while (*ic->maxread)
 775777                 ic->maxread++;
 776778 }
 777779 
 778780 /*
 779781  * A new file included.
 780782  * If ifiles == NULL, this is the first file and already opened (stdin).
 781783  * Return 0 on success, -1 if file to be included is not found.
 782784  */
 783785 int
 784786 pushfile(const usch *file, const usch *fn, int idx, void *incs)
 785787 {
 786788         extern struct initar *initar;
 787789         struct includ ibuf;
 788790         struct includ *ic;
 789791         int otrulvl;
 790792 
 791793         ic = &ibuf;
 792794         ic->next = ifiles;
 793795 
 794796         if (file != NULL) {
 795797                 if ((ic->infil = open((const char *)file, O_RDONLY)) < 0)
 796798                         return -1;
 797799                 ic->orgfn = ic->fname = file;
 798800                 if (++inclevel > MAX_INCLEVEL)
 799801                         error("Limit for nested includes exceeded");
 800802         } else {
 801803                 ic->infil = 0;
 802804                 ic->orgfn = ic->fname = (const usch *)"<stdin>";
 803805         }
 804806 #ifndef BUF_STACK
 805807         ic->bbuf = malloc(BBUFSZ);
 806808 #endif
 807809         ic->buffer = ic->bbuf+NAMEMAX;
 808810         ic->curptr = ic->buffer;
 809811         ifiles = ic;
 810812         ic->lineno = 1;
 811813         ic->maxread = ic->curptr;
 812814         ic->idx = idx;
 813815         ic->incs = incs;
 814816         ic->fn = fn;
 815817         prtline();
 816818         if (initar) {
 817819                 int oin = ic->infil;
 818820                 ic->infil = -1;
 819821                 *ic->maxread = 0;
 820822                 prinit(initar, ic);
 821823                 initar = NULL;
 822824                 if (dMflag)
 823825                         xwrite(ofd, ic->buffer, strlen((char *)ic->buffer));
 824826                 fastscan();
 825827                 prtline();
 826828                 ic->infil = oin;
 827829         }
 828830 
 829831         otrulvl = trulvl;
 830832 
 831833         fastscan();
 832834 
 833835         if (otrulvl != trulvl || flslvl)
 834836                 error("unterminated conditional");
 835837 
 836838 #ifndef BUF_STACK
 837839         free(ic->bbuf);
 838840 #endif
 839841         ifiles = ic->next;
 840842         close(ic->infil);
 841843         inclevel--;
 842844         return 0;
 843845 }
 844846 
 845847 /*
 846848  * Print current position to output file.
 847849  */
 848850 void
 849851 prtline(void)
 850852 {
 851853         usch *sb = stringbuf;
 852854 
 853855         if (Mflag) {
 854856                 if (dMflag)
 855857                         return; /* no output */
 856858                 if (ifiles->lineno == 1) {
 857859                         sheap("%s: %s\n", Mfile, ifiles->fname);
 858860                         if (MPflag &&
 859861                             strcmp((const char *)ifiles->fname, (char *)MPfile))
 860862                                 sheap("%s:\n", ifiles->fname);
 861863                         xwrite(ofd, sb, stringbuf - sb);
 862864                 }
 863865         } else if (!Pflag) {
 864866                 sheap("\n# %d \"%s\"", ifiles->lineno, ifiles->fname);
 865867                 if (ifiles->idx == SYSINC)
 866868                         sheap(" 3");
 867869                 sheap("\n");
 868870                 putstr(sb);
 869871         }
 870872         stringbuf = sb;
 871873 }
 872874 
 873875 void
 874876 cunput(int c)
 875877 {
 876878 #ifdef PCC_DEBUG
 877879 //      if (dflag)printf(": '%c'(%d)\n", c > 31 ? c : ' ', c);
 878880 #endif
 879881         unch(c);
 880882 }
 881883 
 882884 static int
 883885 dig2num(int c)
 884886 {
 885887         if (c >= 'a')
 886888                 c = c - 'a' + 10;
 887889         else if (c >= 'A')
 888890                 c = c - 'A' + 10;
 889891         else
 890892                 c = c - '0';
 891893         return c;
 892894 }
 893895 
 894896 /*
 895897  * Convert string numbers to unsigned long long and check overflow.
 896898  */
 897899 static void
 898900 cvtdig(int rad)
 899901 {
 900902         unsigned long long rv = 0;
 901903         unsigned long long rv2 = 0;
 902904         usch *y = yytext;
 903905         int c;
 904906 
 905907         c = *y++;
 906908         if (rad == 16)
 907909                 y++;
 908910         while (isxdigit(c)) {
 909911                 rv = rv * rad + dig2num(c);
 910912                 /* check overflow */
 911913                 if (rv / rad < rv2)
 912914                         error("Constant \"%s\" is out of range", yytext);
 913915                 rv2 = rv;
 914916                 c = *y++;
 915917         }
 916918         y--;
 917919         while (*y == 'l' || *y == 'L')
 918920                 y++;
 919921         yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER;
 920922         yylval.node.nd_uval = rv;
 921923         if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0)
 922924                 yylval.node.op = UNUMBER;
 923925         if (yylval.node.op == NUMBER && yylval.node.nd_val < 0)
 924926                 /* too large for signed, see 6.4.4.1 */
 925927                 error("Constant \"%s\" is out of range", yytext);
 926928 }
 927929 
 928930 static int
 929931 charcon(usch *p)
 930932 {
 931933         int val, c;
 932934 
 933935         p++; /* skip first ' */
 934936         val = 0;
 935937         if (*p++ == '\\') {
 936938                 switch (*p++) {
 937939                 case 'a': val = '\a'; break;
 938940                 case 'b': val = '\b'; break;
 939941                 case 'f': val = '\f'; break;
 940942                 case 'n': val = '\n'; break;
 941943                 case 'r': val = '\r'; break;
 942944                 case 't': val = '\t'; break;
 943945                 case 'v': val = '\v'; break;
 944946                 case '\"': val = '\"'; break;
 945947                 case '\'': val = '\''; break;
 946948                 case '\\': val = '\\'; break;
 947949                 case 'x':
 948950                         while (isxdigit(c = *p)) {
 949951                                 val = val * 16 + dig2num(c);
 950952                                 p++;
 951953                         }
 952954                         break;
 953955                 case '0': case '1': case '2': case '3': case '4':
 954956                 case '5': case '6': case '7':
 955957                         p--;
 956958                         while (isdigit(c = *p)) {
 957959                                 val = val * 8 + (c - '0');
 958960                                 p++;
 959961                         }
 960962                         break;
 961963                 default: val = p[-1];
 962964                 }
 963965 
 964966         } else
 965967                 val = p[-1];
 966968         return val;
 967969 }
 968970 
 969971 static void
 970972 chknl(int ignore)
 971973 {
 972974         int t;
 973975 
 974976         while ((t = sloscan()) == WSPACE)
 975977                 ;
 976978         if (t != '\n') {
 977979                 if (t && t != (usch)-1) {
 978980                         if (ignore) {
 979981                                 warning("newline expected, got \"%s\"", yytext);
 980982                                 /* ignore rest of line */
 981983                                 while ((t = sloscan()) && t != '\n')
 982984                                         ;
 983985                         }
 984986                         else
 985987                                 error("newline expected, got \"%s\"", yytext);
 986988                 } else {
 987989                         if (ignore)
 988990                                 warning("no newline at end of file");
 989991                         else
 990992                                 error("no newline at end of file");
 991993                 }
 992994         }
 993995 }
 994996 
 995997 static void
 996998 elsestmt(void)
 997999 {
 9981000         if (flslvl) {
 9991001                 if (elflvl > trulvl)
 10001002                         ;
 10011003                 else if (--flslvl!=0) {
 10021004                         flslvl++;
 10031005                 } else {
 10041006                         trulvl++;
 10051007                         prtline();
 10061008                 }
 10071009         } else if (trulvl) {
 10081010                 flslvl++;
 10091011                 trulvl--;
 10101012         } else
 10111013                 error("If-less else");
 10121014         if (elslvl==trulvl+flslvl)
 10131015                 error("Too many else");
 10141016         elslvl=trulvl+flslvl;
 10151017         chknl(1);
 10161018 }
 10171019 
 10181020 static void
 10191021 skpln(void)
 10201022 {
 10211023         /* just ignore the rest of the line */
 10221024         while (inch() != '\n')
 10231025                 ;
 10241026         unch('\n');
 10251027         flslvl++;
 10261028 }
 10271029 
 10281030 static void
 10291031 ifdefstmt(void)         
 10301032 {
 10311033         int t;
 10321034 
 10331035         if (flslvl) {
 10341036                 skpln();
 10351037                 return;
 10361038         }
 10371039         do
 10381040                 t = sloscan();
 10391041         while (t == WSPACE);
 10401042         if (t != IDENT)
 10411043                 error("bad #ifdef");
 10421044         if (lookup(yytext, FIND) == NULL) {
 10431045                 putch('\n');
 10441046                 flslvl++;
 10451047         } else
 10461048                 trulvl++;
 10471049         chknl(0);
 10481050 }
 10491051 
 10501052 static void
 10511053 ifndefstmt(void)         
 10521054 {
 10531055         int t;
 10541056 
 10551057         if (flslvl) {
 10561058                 skpln();
 10571059                 return;
 10581060         }
 10591061         do
 10601062                 t = sloscan();
 10611063         while (t == WSPACE);
 10621064         if (t != IDENT)
 10631065                 error("bad #ifndef");
 10641066         if (lookup(yytext, FIND) != NULL) {
 10651067                 putch('\n');
 10661068                 flslvl++;
 10671069         } else
 10681070                 trulvl++;
 10691071         chknl(0);
 10701072 }
 10711073 
 10721074 static void
 10731075 endifstmt(void)         
 10741076 {
 10751077         if (flslvl) {
 10761078                 flslvl--;
 10771079                 if (flslvl == 0) {
 10781080                         putch('\n');
 10791081                         prtline();
 10801082                 }
 10811083         } else if (trulvl)
 10821084                 trulvl--;
 10831085         else
 10841086                 error("If-less endif");
 10851087         if (flslvl == 0)
 10861088                 elflvl = 0;
 10871089         elslvl = 0;
 10881090         chknl(1);
 10891091 }
 10901092 
 10911093 static void
 10921094 ifstmt(void)
 10931095 {
 10941096         if (flslvl == 0) {
 10951097                 if (yyparse() == 0) {
 10961098                         putch('\n');
 10971099                         ++flslvl;
 10981100                 } else
 10991101                         ++trulvl;
 11001102         } else
 11011103                 ++flslvl;
 11021104 }
 11031105 
 11041106 static void
 11051107 elifstmt(void)
 11061108 {
 11071109         if (flslvl == 0)
 11081110                 elflvl = trulvl;
 11091111         if (flslvl) {
 11101112                 if (elflvl > trulvl)
 11111113                         ;
 11121114                 else if (--flslvl!=0)
 11131115                         ++flslvl;
 11141116                 else {
 11151117                         if (yyparse()) {
 11161118                                 ++trulvl;
 11171119                                 prtline();
 11181120                         } else {
 11191121                                 putch('\n');
 11201122                                 ++flslvl;
 11211123                         }
 11221124                 }
 11231125         } else if (trulvl) {
 11241126                 ++flslvl;
 11251127                 --trulvl;
 11261128         } else
 11271129                 error("If-less elif");
 11281130 }
 11291131 
 11301132 /* save line into stringbuf */
 11311133 static usch *
 11321134 savln(void)
 11331135 {
 11341136         int c;
 11351137         usch *cp = stringbuf;
 11361138 
 11371139         while ((c = inch()) != 0) {
 11381140                 if (c == '\n') {
 11391141                         unch(c);
 11401142                         break;
 11411143                 }
 11421144                 savch(c);
 11431145         }
 11441146         savch(0);
 11451147 
 11461148         return cp;
 11471149 }
 11481150 
 11491151 static void
 11501152 cpperror(void)
 11511153 {
 11521154         usch *cp;
 11531155         int c;
 11541156 
 11551157         if (flslvl)
 11561158                 return;
 11571159         c = sloscan();
 11581160         if (c != WSPACE && c != '\n')
 11591161                 error("bad #error");
 11601162         cp = savln();
 11611163         error("#error %s", cp);
 11621164 }
 11631165 
 11641166 static void
 11651167 cppwarning(void)
 11661168 {
 11671169         usch *cp;
 11681170         int c;
 11691171 
 11701172         if (flslvl)
 11711173                 return;
 11721174         c = sloscan();
 11731175         if (c != WSPACE && c != '\n')
 11741176                 error("bad #warning");
 11751177         cp = savln();
 11761178         warning("#warning %s", cp);
 11771179         stringbuf = cp;
 11781180 }
 11791181 
 11801182 static void
 11811183 undefstmt(void)
 11821184 {
 11831185         struct symtab *np;
 11841186 
 11851187         if (flslvl)
 11861188                 return;
 11871189         if (sloscan() != WSPACE || sloscan() != IDENT)
 11881190                 error("bad #undef");
 11891191         if ((np = lookup(yytext, FIND)) != NULL)
 11901192                 np->value = 0;
 11911193         chknl(0);
 11921194 }
 11931195 
 11941196 static void
 11951197 pragmastmt(void)
 11961198 {
 11971199         usch *sb;
 11981200 
 11991201         if (flslvl)
 12001202                 return;
 12011203         if (sloscan() != WSPACE)
 12021204                 error("bad #pragma");
 12031205         sb = stringbuf;
 12041206         savstr((const usch *)"#pragma ");
 12051207         savln();
 12061208         putstr(sb);
 12071209         stringbuf = sb;
 12081210 }
 12091211 
 12101212 int
 12111213 cinput(void)
 12121214 {
 12131215         return inch();
 12141216 }
 12151217 
 12161218 /*
 12171219  * Check for (and convert) trigraphs.
 12181220  */
 12191221 int
 12201222 chktg(void)
 12211223 {
 12221224         int c;
 12231225 
 12241226         if ((c = inpch()) != '?') {
 12251227                 unch(c);
 12261228                 return 0;
 12271229         }
 12281230         switch (c = inpch()) {
 12291231         case '=': c = '#'; break;
 12301232         case '(': c = '['; break;
 12311233         case ')': c = ']'; break;
 12321234         case '<': c = '{'; break;
 12331235         case '>': c = '}'; break;
 12341236         case '/': c = '\\'; break;
 12351237         case '\'': c = '^'; break;
 12361238         case '!': c = '|'; break;
 12371239         case '-': c = '~'; break;
 12381240         default:
 12391241                 unch(c);
 12401242                 unch('?');
 12411243                 c = 0;
 12421244         }
 12431245         return c;
 12441246 }
 12451247 
 12461248 static struct {
 12471249         const char *name;
 12481250         void (*fun)(void);
 12491251 } ppd[] = {
 12501252         { "ifndef", ifndefstmt },
 12511253         { "ifdef", ifdefstmt },
 12521254         { "if", ifstmt },
 12531255         { "include", include },
 12541256         { "else", elsestmt },
 12551257         { "endif", endifstmt },
 12561258         { "error", cpperror },
 12571259         { "warning", cppwarning },
 12581260         { "define", define },
 12591261         { "undef", undefstmt },
 12601262         { "line", line },
 12611263         { "pragma", pragmastmt },
 12621264         { "elif", elifstmt },
 12631265 #ifdef GCC_COMPAT
 12641266         { "include_next", include_next },
 12651267 #endif
 12661268 };
 12671269 
 12681270 /*
 12691271  * Handle a preprocessor directive.
 12701272  */
 12711273 void
 12721274 ppdir(void)
 12731275 {
 12741276         char bp[20];
 12751277         int ch, i;
 12761278 
 12771279         while ((ch = inch()) == ' ' || ch == '\t')
 12781280                 ;
 12791281         if (ch == '\n') { /* empty directive */
 12801282                 unch(ch);
 12811283                 return;
 12821284         }
 12831285         if (ch < 'a' || ch > 'z')
 12841286                 goto out; /* something else, ignore */
 12851287         i = 0;
 12861288         do {
 12871289                 bp[i++] = (usch)ch;
 12881290                 if (i == sizeof(bp)-1)
 12891291                         goto out; /* too long */
 12901292                 ch = inch();
 12911293         } while ((ch >= 'a' && ch <= 'z') || (ch == '_'));
 12921294         unch(ch);
 12931295         bp[i++] = 0;
 12941296 
 12951297         /* got keyword */
 12961298 #define SZ (int)(sizeof(ppd)/sizeof(ppd[0]))
 12971299         for (i = 0; i < SZ; i++)
 12981300                 if (bp[0] == ppd[i].name[0] && strcmp(bp, ppd[i].name) == 0)
 12991301                         break;
 13001302         if (i == SZ)
 13011303                 goto out;
 13021304 
 13031305         /* Found matching keyword */
 13041306         (*ppd[i].fun)();
 13051307         return;
 13061308 
 13071309 out:    while ((ch = inch()) != '\n' && ch != -1)
 13081310                 ;
 13091311         unch('\n');
 13101312 }
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-01 09:51 +0200