Quick Search:

Mode

Context

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

Other Diffs

Ignore

Blank Lines Whitespace: Expand:

Diff

1.93
 
1.94
 
MAIN:plunky:20121029174801
 
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 {
 112112         if (c == -1)
 113113                 return;
 114114                 
 115115         --ifiles->curptr;
 116116         if (ifiles->curptr < ifiles->bbuf)
 117117                 error("pushback buffer full");
 118118         *ifiles->curptr = (usch)c;
 119119 }
 120120 
 121121 static void
 122122 eatcmnt(void)
 123123 {
 124124         int ch;
 125125 
 126126         if (Cflag) { PUTCH('/'); PUTCH('*'); }
 127127         for (;;) {
 128128                 ch = inch();
 129129                 if (ch == '\n') {
 130130                         ifiles->lineno++;
 131131                         if (!Cflag) PUTCH('\n');
 132132                 }
 133133                 if (ch == -1)
 134134                         break;
 135135                 if (ch == '*') {
 136136                         ch = inch();
 137137                         if (ch == '/') {
 138138                                 if (Cflag) {
 139139                                         PUTCH('*');
 140140                                         PUTCH('/');
 141141                                 } else
 142142                                         PUTCH(' ');
 143143                                 break;
 144144                         }
 145145                         unch(ch);
 146146                         ch = '*';
 147147                 }
 148148                 if (Cflag) PUTCH(ch);
 149149         }
 150150 }
 151151 
 152152 /*
 153153  * Scan quickly the input file searching for:
 154154  *      - '#' directives
 155155  *      - keywords (if not flslvl)
 156156  *      - comments
 157157  *
 158158  *      Handle strings, numbers and trigraphs with care.
 159159  *      Only data from pp files are scanned here, never any rescans.
 160160  *      TODO: Only print out strings before calling other functions.
 161161  */
 162162 static void
 163163 fastscan(void)
 164164 {
 165165         struct symtab *nl;
 166166         int ch, i = 0;
 167167         int nnl = 0;
 168168         usch *cp;
 169169 
 170170         goto run;
 171171         for (;;) {
 172172                 ch = NXTCH();
 173173 xloop:          if (ch == -1)
 174174                         return;
 175175 #ifdef PCC_DEBUG
 176176                 if (dflag>1)
 177177                         printf("fastscan ch %d (%c)\n", ch, ch > 31 ? ch : '@');
 178178 #endif
 179179                 if ((spechr[ch] & C_SPEC) == 0) {
 180180                         PUTCH(ch);
 181181                         continue;
 182182                 }
 183183                 switch (ch) {
 184184                 case EBLOCK:
 185185                 case WARN:
 186186                 case CONC:
 187187                         error("bad char passed");
 188188                         break;
 189189 
 190190                 case '/': /* Comments */
 191191                         if ((ch = inch()) == '/') {
 192192 cppcmt:                         if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
 193193                                 do {
 194194                                         if (Cflag) PUTCH(ch);
 195195                                         ch = inch();
 196196                                 } while (ch != -1 && ch != '\n');
 197197                                 goto xloop;
 198198                         } else if (ch == '*') {
 199199                                 eatcmnt();
 200200                                 continue;
 201201                         } else {
 202202                                 PUTCH('/');
 203203                                 goto xloop;
 204204                         }
 205205                         break;
 206206 
 207207                 case '?'/* trigraphs */
 208208                         if ((ch = chktg()))
 209209                                 goto xloop;
 210210                         PUTCH('?');
 211211                         break;
 212212 
 213213                 case '\\':
 214214                         if ((ch = NXTCH()) == '\n') {
 215215                                 ifiles->lineno++;
 216216                                 continue;
 217217                         }
 218218                         PUTCH('\\');
 219219                         goto xloop;
 220220 
 221221                 case '\n': /* newlines, for pp directives */
 222222                         while (nnl > 0) { PUTCH('\n'); nnl--; ifiles->lineno++; }
 223223 run2:                   ifiles->lineno++;
 224224                         do {
 225225                                 PUTCH(ch);
 226226 run:                            ch = NXTCH();
 227227                                 if (ch == '/') {
 228228                                         ch = NXTCH();
 229229                                         if (ch == '/')
 230230                                                 goto cppcmt;
 231231                                         if (ch == '*') {
 232232                                                 eatcmnt();
 233233                                                 goto run;
 234234                                         }
 235235                                         unch(ch);
 236236                                         ch = '/';
 237237                                 }
 238238                         } while (ch == ' ' || ch == '\t');
 239239                         if (ch == '\\') {
 240240                                 ch = NXTCH();
 241241                                 if (ch == '\n')
 242242                                         goto run2;
 243243                                 unch(ch);
 244244                                 ch = '\\';
 245245                         }
 246246                         if (ch == '#') {
 247247                                 ppdir();
 248248                                 continue;
 249249                         } else if (ch == '%') {
 250250                                 ch = NXTCH();
 251251                                 if (ch == ':') {
 252252                                         ppdir();
 253253                                         continue;
 254254                                 }
 255255                                 unch(ch);
 256256                                 ch = '%';
 257257                         } else if (ch == '?') {
 258258                                 if ((ch = chktg()) == '#') {
 259259                                         ppdir();
 260260                                         continue;
 261261                                 } else if (ch == 0)
 262262                                         ch = '?';
 263263                         }
 264264                         goto xloop;
 265265 
 266266                 case '\"': /* strings */
 267267 str:                    PUTCH(ch);
 268268                         while ((ch = NXTCH()) != '\"') {
 269269                                 if (ch == '\n')
 270270                                         goto xloop;
 271271                                 if (ch == '\\') {
 272272                                         if ((ch = NXTCH()) != '\n') {
 273273                                                 PUTCH('\\');
 274274                                                 PUTCH(ch);
 275275                                         } else
 276276                                                 nnl++;
 277277                                         continue;
 278278                                 }
 279279                                 if (ch == -1)
 280280                                         return;
 281281                                 PUTCH(ch);
 282282                         }
 283283                         PUTCH(ch);
 284284                         break;
 285285 
 286286                 case '.'/* for pp-number */
 287287                         PUTCH(ch);
 288288                         ch = NXTCH();
 289289                         if (ch < '0' || ch > '9')
 290290                                 goto xloop;
 291291                         /* FALLTHROUGH */
 292292                 case '0': case '1': case '2': case '3': case '4':
 293293                 case '5': case '6': case '7': case '8': case '9':
 294294                         do {
 295295                                 PUTCH(ch);
 296296 nxt:                            ch = NXTCH();
 297297                                 if (ch == '\\') {
 298298                                         ch = NXTCH();
 299299                                         if (ch == '\n') {
 300300                                                 nnl++;
 301301                                                 goto nxt;
 302302                                         }
 303303                                         unch(ch);
 304304                                         ch = '\\';
 305305                                 }
<> 306+                                if (ch == -1)
  307+                                        return;
306308                                 if (spechr[ch] & C_EP) {
 307309                                         PUTCH(ch);
 308310                                         ch = NXTCH();
 309311                                         if (ch == '-' || ch == '+')
 310312                                                 continue;
<> 313+                                        if (ch == -1)
  314+                                                return;
311315                                 }
 312316                         } while ((spechr[ch] & C_ID) || (ch == '.'));
 313317                         goto xloop;
 314318 
 315319                 case '\'': /* character literal */
 316320 con:                    PUTCH(ch);
 317321                         if (tflag)
 318322                                 continue; /* character constants ignored */
 319323                         while ((ch = NXTCH()) != '\'') {
 320324                                 if (ch == '\n')
 321325                                         goto xloop;
 322326                                 if (ch == '\\') {
 323327                                         if ((ch = NXTCH()) != '\n') {
 324328                                                 PUTCH('\\');
 325329                                                 PUTCH(ch);
 326330                                         } else
 327331                                                 nnl++;
 328332                                         continue;
 329333                                 }
 330334                                 if (ch == -1)
 331335                                         return;
 332336                                 PUTCH(ch);
 333337                         }
 334338                         PUTCH(ch);
 335339                         break;
 336340 
 337341                 case 'L':
 338342                         ch = NXTCH();
 339343                         if (ch == '\"') {
 340344                                 PUTCH('L');
 341345                                 goto str;
 342346                         }
 343347                         if (ch == '\'') {
 344348                                 PUTCH('L');
 345349                                 goto con;
 346350                         }
 347351                         unch(ch);
 348352                         ch = 'L';
 349353                         /* FALLTHROUGH */
 350354                 default:
 351355                         if ((spechr[ch] & C_ID) == 0)
 352356                                 error("fastscan");
 353357                         if (flslvl) {
<>354 -                                while (spechr[ch] & C_ID)
  358+                                while (ch != -1 && spechr[ch] & C_ID)
355359                                         ch = NXTCH();
 356360                                 goto xloop;
 357361                         }
 358362                         i = 0;
 359363                         do {
 360364                                 yytext[i++] = (usch)ch;
 361365                                 ch = NXTCH();
 362366                                 if (ch == '\\') {
 363367                                         ch = NXTCH();
 364368                                         if (ch != '\n') {
 365369                                                 unch(ch);
 366370                                                 ch = '\\';
 367371                                         } else {
 368372                                                 putch('\n');
 369373                                                 ifiles->lineno++;
 370374                                                 ch = NXTCH();
 371375                                         }
 372376                                 }
 373377                                 if (ch == -1)
 374378                                         return;
 375379                         } while (spechr[ch] & C_ID);
 376380 
 377381                         yytext[i] = 0;
 378382                         unch(ch);
 379383 
 380384                         cp = stringbuf;
 381385                         if ((nl = lookup(yytext, FIND)) && kfind(nl)) {
 382386                                 putstr(stringbuf);
 383387                         } else
 384388                                 putstr(yytext);
 385389                         stringbuf = cp;
 386390 
 387391                         break;
 388392                 }
 389393         }
 390394 }
 391395 
 392396 int
 393397 sloscan(void)
 394398 {
 395399         int ch;
 396400         int yyp;
 397401 
 398402 zagain:
 399403         yyp = 0;
 400404         ch = inch();
 401405         yytext[yyp++] = (usch)ch;
 402406         switch (ch) {
 403407         case -1:
 404408                 return 0;
 405409         case '\n':
 406410                 /* sloscan() never passes \n, that's up to fastscan() */
 407411                 unch(ch);
<>408 -                goto yyret;
  412+                yytext[yyp] = 0;
  413+                return ch;
409414 
 410415         case '\r': /* Ignore CR's */
 411416                 yyp = 0;
 412417                 break;
 413418 
 414419         case '0': case '1': case '2': case '3': case '4': case '5':
 415420         case '6': case '7': case '8': case '9':
 416421                 /* readin a "pp-number" */
 417422 ppnum:          for (;;) {
 418423                         ch = inch();
<> 424+                        if (ch == -1)
  425+                                break;
419426                         if (spechr[ch] & C_EP) {
 420427                                 yytext[yyp++] = (usch)ch;
 421428                                 ch = inch();
 422429                                 if (ch == '-' || ch == '+') {
 423430                                         yytext[yyp++] = (usch)ch;
 424431                                 } else
 425432                                         unch(ch);
 426433                                 continue;
 427434                         }
 428435                         if ((spechr[ch] & C_ID) || ch == '.') {
 429436                                 yytext[yyp++] = (usch)ch;
 430437                                 continue;
 431438                         }
 432439                         break;
 433440                 }
 434441                 unch(ch);
 435442                 yytext[yyp] = 0;
 436443 
 437444                 return NUMBER;
 438445 
 439446         case '\'':
 440447 chlit:          
 441448                 for (;;) {
 442449                         if ((ch = inch()) == '\\') {
 443450                                 yytext[yyp++] = (usch)ch;
 444451                                 yytext[yyp++] = (usch)inch();
 445452                                 continue;
<>446 -                        } else if (ch == '\n') {
  453+                        } else if (ch == -1 || ch == '\n') {
447454                                 /* not a constant */
 448455                                 while (yyp > 1)
 449456                                         unch(yytext[--yyp]);
 450457                                 ch = '\'';
 451458                                 goto any;
 452459                         } else
 453460                                 yytext[yyp++] = (usch)ch;
 454461                         if (ch == '\'')
 455462                                 break;
 456463                 }
 457464                 yytext[yyp] = 0;
 458465 
 459466                 return NUMBER;
 460467 
 461468         case ' ':
 462469         case '\t':
 463470                 while ((ch = inch()) == ' ' || ch == '\t')
 464471                         yytext[yyp++] = (usch)ch;
 465472                 unch(ch);
 466473                 yytext[yyp] = 0;
 467474                 return WSPACE;
 468475 
 469476         case '/':
 470477                 if ((ch = inch()) == '/') {
 471478                         do {
 472479                                 yytext[yyp++] = (usch)ch;
 473480                                 ch = inch();
<>474 -                        } while (ch && ch != '\n');
  481+                        } while (ch != -1 && ch != '\n');
475482                         yytext[yyp] = 0;
 476483                         unch(ch);
 477484                         goto zagain;
 478485                 } else if (ch == '*') {
 479486                         int c, wrn;
 480487                         extern int readmac;
 481488 
 482489                         if (Cflag && !flslvl && readmac) {
 483490                                 unch(ch);
 484491                                 yytext[yyp] = 0;
 485492                                 return CMNT;
 486493                         }
 487494 
 488495                         wrn = 0;
<>489 -                more:   while ((c = inch()) && c != '*') {
  496+                more:   while ((c = inch()) != '*') {
  497+                                if (c == -1)
  498+                                        return 0;       
490499                                 if (c == '\n')
 491500                                         putch(c), ifiles->lineno++;
 492501                                 else if (c == EBLOCK) {
 493502                                         (void)inch();
 494503                                         (void)inch();
 495504                                 } else if (c == 1) /* WARN */
 496505                                         wrn = 1;
 497506                         }
<>498 -                        if (c == 0)
  507+                        if ((c = inch()) == -1)
499508                                 return 0;
<>500 -                        if ((c = inch()) && c != '/') {
  509+                        if (c != '/') {
501510                                 unch(c);
 502511                                 goto more;
 503512                         }
<>504 -                        if (c == 0)
 505 -                                return 0;
506513                         if (!tflag && !Cflag && !flslvl)
 507514                                 unch(' ');
 508515                         if (wrn)
 509516                                 unch(1);
 510517                         goto zagain;
 511518                 }
 512519                 unch(ch);
 513520                 ch = '/';
 514521                 goto any;
 515522 
 516523         case '.':
<>517 -                ch = inch();
  524+                if ((ch = inch()) == -1)
  525+                        return 0;
518526                 if (isdigit(ch)) {
 519527                         yytext[yyp++] = (usch)ch;
 520528                         goto ppnum;
 521529                 } else {
 522530                         unch(ch);
 523531                         ch = '.';
 524532                 }
 525533                 goto any;
 526534 
 527535         case '\"':
 528536                 if (tflag && defining)
 529537                         goto any;
 530538         strng:
 531539                 for (;;) {
 532540                         if ((ch = inch()) == '\\') {
 533541                                 yytext[yyp++] = (usch)ch;
 534542                                 yytext[yyp++] = (usch)inch();
 535543                                 continue;
<> 544+                        } else if (ch == -1) {
  545+                                break;
536546                         } else
 537547                                 yytext[yyp++] = (usch)ch;
 538548                         if (ch == '\"')
 539549                                 break;
 540550                 }
 541551                 yytext[yyp] = 0;
 542552                 return STRING;
 543553 
 544554         case 'L':
 545555                 if ((ch = inch()) == '\"' && !tflag) {
 546556                         yytext[yyp++] = (usch)ch;
 547557                         goto strng;
 548558                 } else if (ch == '\'' && !tflag) {
 549559                         yytext[yyp++] = (usch)ch;
 550560                         goto chlit;
 551561                 }
 552562                 unch(ch);
 553563                 /* FALLTHROUGH */
 554564 
 555565         /* Yetch, all identifiers */
 556566         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
 557567         case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
 558568         case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
 559569         case 's': case 't': case 'u': case 'v': case 'w': case 'x':
 560570         case 'y': case 'z':
 561571         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
 562572         case 'G': case 'H': case 'I': case 'J': case 'K':
 563573         case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
 564574         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
 565575         case 'Y': case 'Z':
 566576         case '_': /* {L}({L}|{D})* */
 567577 
 568578                 /* Special hacks */
 569579                 for (;;) { /* get chars */
<>570 -                        ch = inch();
  580+                        if ((ch = inch()) == -1)
  581+                                break;
571582                         if (isalpha(ch) || isdigit(ch) || ch == '_') {
 572583                                 yytext[yyp++] = (usch)ch;
 573584                         } else {
<>574 -                                if (ch != -1)
 575 -                                        unch(ch);
  585+                                unch(ch);
576586                                 break;
 577587                         }
 578588                 }
 579589                 yytext[yyp] = 0; /* need already string */
 580590                 /* end special hacks */
 581591 
 582592                 return IDENT;
 583593         default:
 584594         any:
 585595                 yytext[yyp] = 0;
 586596                 return yytext[0];
 587597 
 588598         } /* endcase */
 589599         goto zagain;
<>590 -
 591 -yyret:
 592 -        yytext[yyp] = 0;
 593 -        return ch;
594600 }
 595601 
 596602 int
 597603 yylex(void)
 598604 {
 599605         static int ifdef, noex;
 600606         struct symtab *nl;
 601607         int ch, c2;
 602608 
 603609         while ((ch = sloscan()) == WSPACE)
 604610                 ;
 605611         if (ch < 128 && spechr[ch] & C_2)
 606612                 c2 = inpch();
 607613         else
 608614                 c2 = 0;
 609615 
 610616 #define C2(a,b,c) case a: if (c2 == b) return c; break
 611617         switch (ch) {
 612618         C2('=', '=', EQ);
 613619         C2('!', '=', NE);
 614620         C2('|', '|', OROR);
 615621         C2('&', '&', ANDAND);
 616622         case '<':
 617623                 if (c2 == '<') return LS;
 618624                 if (c2 == '=') return LE;
 619625                 break;
 620626         case '>':
 621627                 if (c2 == '>') return RS;
 622628                 if (c2 == '=') return GE;
 623629                 break;
 624630         case '+':
 625631         case '-':
 626632                 if (ch == c2)
 627633                         error("invalid preprocessor operator %c%c", ch, c2);
 628634                 break;
 629635 
 630636         case '/':
 631637                 if (Cflag == 0 || c2 != '*')
 632638                         break;
 633639                 /* Found comment that need to be skipped */
 634640                 for (;;) {
 635641                         ch = inpch();
 636642                 c1:     if (ch != '*')
 637643                                 continue;
 638644                         if ((ch = inpch()) == '/')
 639645                                 break;
 640646                         goto c1;
 641647                 }
 642648                 return yylex();
 643649 
 644650         case NUMBER:
 645651                 if (yytext[0] == '\'') {
 646652                         yylval.node.op = NUMBER;
 647653                         yylval.node.nd_val = charcon(yytext);
 648654                 } else
 649655                         cvtdig(yytext[0] != '0' ? 10 :
 650656                             yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
 651657                 return NUMBER;
 652658 
 653659         case IDENT:
 654660                 if (strcmp((char *)yytext, "defined") == 0) {
 655661                         ifdef = 1;
 656662                         return DEFINED;
 657663                 }
 658664                 nl = lookup(yytext, FIND);
 659665                 if (ifdef) {
 660666                         yylval.node.nd_val = nl != NULL;
 661667                         ifdef = 0;
 662668                 } else if (nl && noex == 0) {
 663669                         usch *och = stringbuf;
 664670                         int i;
 665671 
 666672                         i = kfind(nl);
 667673                         unch(WARN);
 668674                         if (i)
 669675                                 unpstr(stringbuf);
 670676                         else
 671677                                 unpstr(nl->namep);
 672678                         stringbuf = och;
 673679                         noex = 1;
 674680                         return yylex();
 675681                 } else {
 676682                         yylval.node.nd_val = 0;
 677683                 }
 678684                 yylval.node.op = NUMBER;
 679685                 return NUMBER;
 680686         case WARN:
 681687                 noex = 0;
 682688                 /* FALLTHROUGH */
 683689         case PHOLD:
 684690                 return yylex();
 685691         default:
 686692                 return ch;
 687693         }
 688694         unch(c2);
 689695         return ch;
 690696 }
 691697 
 692698 static int
 693699 inpch(void)
 694700 {
 695701         int len;
 696702 
 697703         if (ifiles->curptr < ifiles->maxread)
 698704                 return *ifiles->curptr++;
 699705 
 700706         if (ifiles->infil == -1)
 701707                 return -1;
 702708         if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0)
 703709                 error("read error on file %s", ifiles->orgfn);
 704710         if (len == 0)
 705711                 return -1;
 706712         ifiles->buffer[len] = 0;
 707713         ifiles->curptr = ifiles->buffer;
 708714         ifiles->maxread = ifiles->buffer + len;
 709715         return inpch();
 710716 }
 711717 
 712718 static int
 713719 inch(void)
 714720 {
 715721         int c;
 716722 
 717723 again:  switch (c = inpch()) {
 718724         case '\\': /* continued lines */
 719725 msdos:          if ((c = inpch()) == '\n') {
 720726                         ifiles->lineno++;
 721727                         putch('\n');
 722728                         goto again;
 723729                 } else if (c == '\r')
 724730                         goto msdos;
 725731                 unch(c);
 726732                 return '\\';
 727733         case '?': /* trigraphs */
 728734                 if ((c = chktg())) {
 729735                         unch(c);
 730736                         goto again;
 731737                 }
 732738                 return '?';
 733739         default:
 734740                 return c;
 735741         }
 736742 }
 737743 
 738744 /*
 739745  * Let the command-line args be faked defines at beginning of file.
 740746  */
 741747 static void
 742748 prinit(struct initar *it, struct includ *ic)
 743749 {
 744750         const char *pre, *post;
 745751         char *a;
 746752 
 747753         if (it->next)
 748754                 prinit(it->next, ic);
 749755         pre = post = NULL; /* XXX gcc */
 750756         switch (it->type) {
 751757         case 'D':
 752758                 pre = "#define ";
 753759                 if ((a = strchr(it->str, '=')) != NULL) {
 754760                         *a = ' ';
 755761                         post = "\n";
 756762                 } else
 757763                         post = " 1\n";
 758764                 break;
 759765         case 'U':
 760766                 pre = "#undef ";
 761767                 post = "\n";
 762768                 break;
 763769         case 'i':
 764770                 pre = "#include \"";
 765771                 post = "\"\n";
 766772                 break;
 767773         default:
 768774                 error("prinit");
 769775         }
 770776         strlcat((char *)ic->buffer, pre, CPPBUF+1);
 771777         strlcat((char *)ic->buffer, it->str, CPPBUF+1);
 772778         if (strlcat((char *)ic->buffer, post, CPPBUF+1) >= CPPBUF+1)
 773779                 error("line exceeds buffer size");
 774780 
 775781         ic->lineno--;
 776782         while (*ic->maxread)
 777783                 ic->maxread++;
 778784 }
 779785 
 780786 /*
 781787  * A new file included.
 782788  * If ifiles == NULL, this is the first file and already opened (stdin).
 783789  * Return 0 on success, -1 if file to be included is not found.
 784790  */
 785791 int
 786792 pushfile(const usch *file, const usch *fn, int idx, void *incs)
 787793 {
 788794         extern struct initar *initar;
 789795         struct includ ibuf;
 790796         struct includ *ic;
 791797         int otrulvl;
 792798 
 793799         ic = &ibuf;
 794800         ic->next = ifiles;
 795801 
 796802         if (file != NULL) {
 797803                 if ((ic->infil = open((const char *)file, O_RDONLY)) < 0)
 798804                         return -1;
 799805                 ic->orgfn = ic->fname = file;
 800806                 if (++inclevel > MAX_INCLEVEL)
 801807                         error("Limit for nested includes exceeded");
 802808         } else {
 803809                 ic->infil = 0;
 804810                 ic->orgfn = ic->fname = (const usch *)"<stdin>";
 805811         }
 806812 #ifndef BUF_STACK
 807813         ic->bbuf = malloc(BBUFSZ);
 808814 #endif
 809815         ic->buffer = ic->bbuf+NAMEMAX;
 810816         ic->curptr = ic->buffer;
 811817         ifiles = ic;
 812818         ic->lineno = 1;
 813819         ic->maxread = ic->curptr;
 814820         ic->idx = idx;
 815821         ic->incs = incs;
 816822         ic->fn = fn;
 817823         prtline();
 818824         if (initar) {
 819825                 int oin = ic->infil;
 820826                 ic->infil = -1;
 821827                 *ic->maxread = 0;
 822828                 prinit(initar, ic);
 823829                 initar = NULL;
 824830                 if (dMflag)
 825831                         xwrite(ofd, ic->buffer, strlen((char *)ic->buffer));
 826832                 fastscan();
 827833                 prtline();
 828834                 ic->infil = oin;
 829835         }
 830836 
 831837         otrulvl = trulvl;
 832838 
 833839         fastscan();
 834840 
 835841         if (otrulvl != trulvl || flslvl)
 836842                 error("unterminated conditional");
 837843 
 838844 #ifndef BUF_STACK
 839845         free(ic->bbuf);
 840846 #endif
 841847         ifiles = ic->next;
 842848         close(ic->infil);
 843849         inclevel--;
 844850         return 0;
 845851 }
 846852 
 847853 /*
 848854  * Print current position to output file.
 849855  */
 850856 void
 851857 prtline(void)
 852858 {
 853859         usch *sb = stringbuf;
 854860 
 855861         if (Mflag) {
 856862                 if (dMflag)
 857863                         return; /* no output */
 858864                 if (ifiles->lineno == 1) {
 859865                         sheap("%s: %s\n", Mfile, ifiles->fname);
 860866                         if (MPflag &&
 861867                             strcmp((const char *)ifiles->fname, (char *)MPfile))
 862868                                 sheap("%s:\n", ifiles->fname);
 863869                         xwrite(ofd, sb, stringbuf - sb);
 864870                 }
 865871         } else if (!Pflag) {
 866872                 sheap("\n# %d \"%s\"", ifiles->lineno, ifiles->fname);
 867873                 if (ifiles->idx == SYSINC)
 868874                         sheap(" 3");
 869875                 sheap("\n");
 870876                 putstr(sb);
 871877         }
 872878         stringbuf = sb;
 873879 }
 874880 
 875881 void
 876882 cunput(int c)
 877883 {
 878884 #ifdef PCC_DEBUG
 879885 //      if (dflag)printf(": '%c'(%d)\n", c > 31 ? c : ' ', c);
 880886 #endif
 881887         unch(c);
 882888 }
 883889 
 884890 static int
 885891 dig2num(int c)
 886892 {
 887893         if (c >= 'a')
 888894                 c = c - 'a' + 10;
 889895         else if (c >= 'A')
 890896                 c = c - 'A' + 10;
 891897         else
 892898                 c = c - '0';
 893899         return c;
 894900 }
 895901 
 896902 /*
 897903  * Convert string numbers to unsigned long long and check overflow.
 898904  */
 899905 static void
 900906 cvtdig(int rad)
 901907 {
 902908         unsigned long long rv = 0;
 903909         unsigned long long rv2 = 0;
 904910         usch *y = yytext;
 905911         int c;
 906912 
 907913         c = *y++;
 908914         if (rad == 16)
 909915                 y++;
 910916         while (isxdigit(c)) {
 911917                 rv = rv * rad + dig2num(c);
 912918                 /* check overflow */
 913919                 if (rv / rad < rv2)
 914920                         error("Constant \"%s\" is out of range", yytext);
 915921                 rv2 = rv;
 916922                 c = *y++;
 917923         }
 918924         y--;
 919925         while (*y == 'l' || *y == 'L')
 920926                 y++;
 921927         yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER;
 922928         yylval.node.nd_uval = rv;
 923929         if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0)
 924930                 yylval.node.op = UNUMBER;
 925931         if (yylval.node.op == NUMBER && yylval.node.nd_val < 0)
 926932                 /* too large for signed, see 6.4.4.1 */
 927933                 error("Constant \"%s\" is out of range", yytext);
 928934 }
 929935 
 930936 static int
 931937 charcon(usch *p)
 932938 {
 933939         int val, c;
 934940 
 935941         p++; /* skip first ' */
 936942         val = 0;
 937943         if (*p++ == '\\') {
 938944                 switch (*p++) {
 939945                 case 'a': val = '\a'; break;
 940946                 case 'b': val = '\b'; break;
 941947                 case 'f': val = '\f'; break;
 942948                 case 'n': val = '\n'; break;
 943949                 case 'r': val = '\r'; break;
 944950                 case 't': val = '\t'; break;
 945951                 case 'v': val = '\v'; break;
 946952                 case '\"': val = '\"'; break;
 947953                 case '\'': val = '\''; break;
 948954                 case '\\': val = '\\'; break;
 949955                 case 'x':
 950956                         while (isxdigit(c = *p)) {
 951957                                 val = val * 16 + dig2num(c);
 952958                                 p++;
 953959                         }
 954960                         break;
 955961                 case '0': case '1': case '2': case '3': case '4':
 956962                 case '5': case '6': case '7':
 957963                         p--;
 958964                         while (isdigit(c = *p)) {
 959965                                 val = val * 8 + (c - '0');
 960966                                 p++;
 961967                         }
 962968                         break;
 963969                 default: val = p[-1];
 964970                 }
 965971 
 966972         } else
 967973                 val = p[-1];
 968974         return val;
 969975 }
 970976 
 971977 static void
 972978 chknl(int ignore)
 973979 {
 974980         int t;
 975981 
 976982         while ((t = sloscan()) == WSPACE)
 977983                 ;
 978984         if (t != '\n') {
<>979 -                if (t && t != (usch)-1) {
  985+                if (t) {
980986                         if (ignore) {
 981987                                 warning("newline expected, got \"%s\"", yytext);
 982988                                 /* ignore rest of line */
 983989                                 while ((t = sloscan()) && t != '\n')
 984990                                         ;
 985991                         }
 986992                         else
 987993                                 error("newline expected, got \"%s\"", yytext);
 988994                 } else {
 989995                         if (ignore)
 990996                                 warning("no newline at end of file");
 991997                         else
 992998                                 error("no newline at end of file");
 993999                 }
 9941000         }
 9951001 }
 9961002 
 9971003 static void
 9981004 elsestmt(void)
 9991005 {
 10001006         if (flslvl) {
 10011007                 if (elflvl > trulvl)
 10021008                         ;
 10031009                 else if (--flslvl!=0) {
 10041010                         flslvl++;
 10051011                 } else {
 10061012                         trulvl++;
 10071013                         prtline();
 10081014                 }
 10091015         } else if (trulvl) {
 10101016                 flslvl++;
 10111017                 trulvl--;
 10121018         } else
 10131019                 error("If-less else");
 10141020         if (elslvl==trulvl+flslvl)
 10151021                 error("Too many else");
 10161022         elslvl=trulvl+flslvl;
 10171023         chknl(1);
 10181024 }
 10191025 
 10201026 static void
 10211027 skpln(void)
 10221028 {
<> 1029+        int ch;
  1030+
10231031         /* just ignore the rest of the line */
<>1024 -        while (inch() != '\n')
 1025 -                ;
 1026 -        unch('\n');
  1032+        while ((ch = inch()) != -1) {
  1033+                if (ch == '\n') {
  1034+                        unch('\n');
  1035+                        break;
  1036+                }
  1037+        }
10271038         flslvl++;
 10281039 }
 10291040 
 10301041 static void
 10311042 ifdefstmt(void)         
 10321043 {
 10331044         int t;
 10341045 
 10351046         if (flslvl) {
 10361047                 skpln();
 10371048                 return;
 10381049         }
 10391050         do
 10401051                 t = sloscan();
 10411052         while (t == WSPACE);
 10421053         if (t != IDENT)
 10431054                 error("bad #ifdef");
 10441055         if (lookup(yytext, FIND) == NULL) {
 10451056                 putch('\n');
 10461057                 flslvl++;
 10471058         } else
 10481059                 trulvl++;
 10491060         chknl(0);
 10501061 }
 10511062 
 10521063 static void
 10531064 ifndefstmt(void)         
 10541065 {
 10551066         int t;
 10561067 
 10571068         if (flslvl) {
 10581069                 skpln();
 10591070                 return;
 10601071         }
 10611072         do
 10621073                 t = sloscan();
 10631074         while (t == WSPACE);
 10641075         if (t != IDENT)
 10651076                 error("bad #ifndef");
 10661077         if (lookup(yytext, FIND) != NULL) {
 10671078                 putch('\n');
 10681079                 flslvl++;
 10691080         } else
 10701081                 trulvl++;
 10711082         chknl(0);
 10721083 }
 10731084 
 10741085 static void
 10751086 endifstmt(void)         
 10761087 {
 10771088         if (flslvl) {
 10781089                 flslvl--;
 10791090                 if (flslvl == 0) {
 10801091                         putch('\n');
 10811092                         prtline();
 10821093                 }
 10831094         } else if (trulvl)
 10841095                 trulvl--;
 10851096         else
 10861097                 error("If-less endif");
 10871098         if (flslvl == 0)
 10881099                 elflvl = 0;
 10891100         elslvl = 0;
 10901101         chknl(1);
 10911102 }
 10921103 
 10931104 static void
 10941105 ifstmt(void)
 10951106 {
 10961107         if (flslvl == 0) {
 10971108                 if (yyparse() == 0) {
 10981109                         putch('\n');
 10991110                         ++flslvl;
 11001111                 } else
 11011112                         ++trulvl;
 11021113         } else
 11031114                 ++flslvl;
 11041115 }
 11051116 
 11061117 static void
 11071118 elifstmt(void)
 11081119 {
 11091120         if (flslvl == 0)
 11101121                 elflvl = trulvl;
 11111122         if (flslvl) {
 11121123                 if (elflvl > trulvl)
 11131124                         ;
 11141125                 else if (--flslvl!=0)
 11151126                         ++flslvl;
 11161127                 else {
 11171128                         if (yyparse()) {
 11181129                                 ++trulvl;
 11191130                                 prtline();
 11201131                         } else {
 11211132                                 putch('\n');
 11221133                                 ++flslvl;
 11231134                         }
 11241135                 }
 11251136         } else if (trulvl) {
 11261137                 ++flslvl;
 11271138                 --trulvl;
 11281139         } else
 11291140                 error("If-less elif");
 11301141 }
 11311142 
 11321143 /* save line into stringbuf */
 11331144 static usch *
 11341145 savln(void)
 11351146 {
 11361147         int c;
 11371148         usch *cp = stringbuf;
 11381149 
<>1139 -        while ((c = inch()) != 0) {
  1150+        while ((c = inch()) != -1) {
<_11401151                 if (c == '\n') {
 11411152                         unch(c);
 11421153                         break;
 11431154                 }
 11441155                 savch(c);
 11451156         }
 11461157         savch(0);
 11471158 
 11481159         return cp;
 11491160 }
 11501161 
 11511162 static void
 11521163 cpperror(void)
 11531164 {
 11541165         usch *cp;
 11551166         int c;
 11561167 
 11571168         if (flslvl)
 11581169                 return;
 11591170         c = sloscan();
 11601171         if (c != WSPACE && c != '\n')
 11611172                 error("bad #error");
 11621173         cp = savln();
 11631174         error("#error %s", cp);
 11641175 }
 11651176 
 11661177 static void
 11671178 cppwarning(void)
 11681179 {
 11691180         usch *cp;
 11701181         int c;
 11711182 
 11721183         if (flslvl)
 11731184                 return;
 11741185         c = sloscan();
 11751186         if (c != WSPACE && c != '\n')
 11761187                 error("bad #warning");
 11771188         cp = savln();
 11781189         warning("#warning %s", cp);
 11791190         stringbuf = cp;
 11801191 }
 11811192 
 11821193 static void
 11831194 undefstmt(void)
 11841195 {
 11851196         struct symtab *np;
 11861197 
 11871198         if (flslvl)
 11881199                 return;
 11891200         if (sloscan() != WSPACE || sloscan() != IDENT)
 11901201                 error("bad #undef");
 11911202         if ((np = lookup(yytext, FIND)) != NULL)
 11921203                 np->value = 0;
 11931204         chknl(0);
 11941205 }
 11951206 
 11961207 static void
 11971208 pragmastmt(void)
 11981209 {
 11991210         usch *sb;
 12001211 
 12011212         if (flslvl)
 12021213                 return;
 12031214         if (sloscan() != WSPACE)
 12041215                 error("bad #pragma");
 12051216         sb = stringbuf;
 12061217         savstr((const usch *)"#pragma ");
 12071218         savln();
 12081219         putstr(sb);
 12091220         stringbuf = sb;
 12101221 }
 12111222 
 12121223 int
 12131224 cinput(void)
 12141225 {
 12151226         return inch();
 12161227 }
 12171228 
 12181229 /*
 12191230  * Check for (and convert) trigraphs.
 12201231  */
 12211232 int
 12221233 chktg(void)
 12231234 {
 12241235         int c;
 12251236 
 12261237         if ((c = inpch()) != '?') {
 12271238                 unch(c);
 12281239                 return 0;
 12291240         }
 12301241         switch (c = inpch()) {
 12311242         case '=': c = '#'; break;
 12321243         case '(': c = '['; break;
 12331244         case ')': c = ']'; break;
 12341245         case '<': c = '{'; break;
 12351246         case '>': c = '}'; break;
 12361247         case '/': c = '\\'; break;
 12371248         case '\'': c = '^'; break;
 12381249         case '!': c = '|'; break;
 12391250         case '-': c = '~'; break;
 12401251         default:
 12411252                 unch(c);
 12421253                 unch('?');
 12431254                 c = 0;
 12441255         }
 12451256         return c;
 12461257 }
 12471258 
 12481259 static struct {
 12491260         const char *name;
 12501261         void (*fun)(void);
 12511262 } ppd[] = {
 12521263         { "ifndef", ifndefstmt },
 12531264         { "ifdef", ifdefstmt },
 12541265         { "if", ifstmt },
 12551266         { "include", include },
 12561267         { "else", elsestmt },
 12571268         { "endif", endifstmt },
 12581269         { "error", cpperror },
 12591270         { "warning", cppwarning },
 12601271         { "define", define },
 12611272         { "undef", undefstmt },
 12621273         { "line", line },
 12631274         { "pragma", pragmastmt },
 12641275         { "elif", elifstmt },
 12651276 #ifdef GCC_COMPAT
 12661277         { "include_next", include_next },
 12671278 #endif
 12681279 };
 12691280 
 12701281 /*
 12711282  * Handle a preprocessor directive.
 12721283  */
 12731284 void
 12741285 ppdir(void)
 12751286 {
 12761287         char bp[20];
 12771288         int ch, i;
 12781289 
 12791290         while ((ch = inch()) == ' ' || ch == '\t')
 12801291                 ;
 12811292         if (ch == '\n') { /* empty directive */
 12821293                 unch(ch);
 12831294                 return;
 12841295         }
 12851296         if (ch < 'a' || ch > 'z')
 12861297                 goto out; /* something else, ignore */
 12871298         i = 0;
 12881299         do {
 12891300                 bp[i++] = (usch)ch;
 12901301                 if (i == sizeof(bp)-1)
 12911302                         goto out; /* too long */
 12921303                 ch = inch();
 12931304         } while ((ch >= 'a' && ch <= 'z') || (ch == '_'));
 12941305         unch(ch);
 12951306         bp[i++] = 0;
 12961307 
 12971308         /* got keyword */
 12981309 #define SZ (int)(sizeof(ppd)/sizeof(ppd[0]))
 12991310         for (i = 0; i < SZ; i++)
 13001311                 if (bp[0] == ppd[i].name[0] && strcmp(bp, ppd[i].name) == 0)
 13011312                         break;
 13021313         if (i == SZ)
 13031314                 goto out;
 13041315 
 13051316         /* Found matching keyword */
 13061317         (*ppd[i].fun)();
 13071318         return;
 13081319 
 13091320 out:    while ((ch = inch()) != '\n' && ch != -1)
 13101321                 ;
 13111322         unch('\n');
 13121323 }
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-17 15:33 +0200