Quick Search:

Mode

Context

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

Other Diffs

Ignore

Blank Lines Whitespace: Expand:

Diff

1.91
 
1.92
 
MAIN:plunky:20121029172313
 
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                 
 113113         --ifiles->curptr;
 114114         if (ifiles->curptr < ifiles->bbuf)
 115115                 error("pushback buffer full");
 116116         *ifiles->curptr = (usch)c;
 117117 }
 118118 
<>119 -static int
  119+static void
120120 eatcmnt(void)
 121121 {
 122122         int ch;
 123123 
 124124         if (Cflag) { PUTCH('/'); PUTCH('*'); }
 125125         for (;;) {
 126126                 ch = inch();
 127127                 if (ch == '\n') {
 128128                         ifiles->lineno++;
 129129                         if (!Cflag) PUTCH('\n');
 130130                 }
 131131                 if (ch == -1)
<>132 -                        return -1;
  132+                        break;
133133                 if (ch == '*') {
 134134                         ch = inch();
 135135                         if (ch == '/') {
 136136                                 if (Cflag) {
 137137                                         PUTCH('*');
 138138                                         PUTCH('/');
 139139                                 } else
 140140                                         PUTCH(' ');
 141141                                 break;
 142142                         }
 143143                         unch(ch);
 144144                         ch = '*';
 145145                 }
 146146                 if (Cflag) PUTCH(ch);
 147147         }
<>148 -        return 0;
149148 }
 150149 
 151150 /*
 152151  * Scan quickly the input file searching for:
 153152  *      - '#' directives
 154153  *      - keywords (if not flslvl)
 155154  *      - comments
 156155  *
 157156  *      Handle strings, numbers and trigraphs with care.
 158157  *      Only data from pp files are scanned here, never any rescans.
 159158  *      TODO: Only print out strings before calling other functions.
 160159  */
 161160 static void
 162161 fastscan(void)
 163162 {
 164163         struct symtab *nl;
 165164         int ch, i = 0;
 166165         int nnl = 0;
 167166         usch *cp;
 168167 
 169168         goto run;
 170169         for (;;) {
 171170                 ch = NXTCH();
 172171 xloop:          if (ch == -1)
 173172                         return;
 174173 #ifdef PCC_DEBUG
 175174                 if (dflag>1)
 176175                         printf("fastscan ch %d (%c)\n", ch, ch > 31 ? ch : '@');
 177176 #endif
 178177                 if ((spechr[ch] & C_SPEC) == 0) {
 179178                         PUTCH(ch);
 180179                         continue;
 181180                 }
 182181                 switch (ch) {
 183182                 case EBLOCK:
 184183                 case WARN:
 185184                 case CONC:
 186185                         error("bad char passed");
 187186                         break;
 188187 
 189188                 case '/': /* Comments */
 190189                         if ((ch = inch()) == '/') {
 191190 cppcmt:                         if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
 192191                                 do {
 193192                                         if (Cflag) PUTCH(ch);
 194193                                         ch = inch();
 195194                                 } while (ch != -1 && ch != '\n');
 196195                                 goto xloop;
 197196                         } else if (ch == '*') {
<>198 -                                if (eatcmnt() == -1)
 199 -                                        return;
  197+                                eatcmnt();
  198+                                continue;
200199                         } else {
 201200                                 PUTCH('/');
 202201                                 goto xloop;
 203202                         }
 204203                         break;
 205204 
 206205                 case '?'/* trigraphs */
 207206                         if ((ch = chktg()))
 208207                                 goto xloop;
 209208                         PUTCH('?');
 210209                         break;
 211210 
 212211                 case '\\':
 213212                         if ((ch = NXTCH()) == '\n') {
 214213                                 ifiles->lineno++;
 215214                                 continue;
<>216 -                        } else {
 217 -                                PUTCH('\\');
218215                         }
<> 216+                        PUTCH('\\');
219217                         goto xloop;
 220218 
 221219                 case '\n': /* newlines, for pp directives */
 222220                         while (nnl > 0) { PUTCH('\n'); nnl--; ifiles->lineno++; }
 223221 run2:                   ifiles->lineno++;
 224222                         do {
 225223                                 PUTCH(ch);
 226224 run:                            ch = NXTCH();
 227225                                 if (ch == '/') {
 228226                                         ch = NXTCH();
 229227                                         if (ch == '/')
 230228                                                 goto cppcmt;
 231229                                         if (ch == '*') {
<>232 -                                                if (eatcmnt() == -1)
 233 -                                                        return;
  230+                                                eatcmnt();
234231                                                 goto run;
<>235 -                                        }
  232+                                        }
236233                                         unch(ch);
 237234                                         ch = '/';
 238235                                 }
 239236                         } while (ch == ' ' || ch == '\t');
 240237                         if (ch == '\\') {
 241238                                 ch = NXTCH();
 242239                                 if (ch == '\n')
 243240                                         goto run2;
 244241                                 unch(ch);
 245242                                 ch = '\\';
 246243                         }
 247244                         if (ch == '#') {
 248245                                 ppdir();
 249246                                 continue;
 250247                         } else if (ch == '%') {
 251248                                 ch = NXTCH();
 252249                                 if (ch == ':') {
 253250                                         ppdir();
 254251                                         continue;
<>255 -                                } else {
 256 -                                        unch(ch);
 257 -                                        ch = '%';
258252                                 }
<> 253+                                unch(ch);
  254+                                ch = '%';
259255                         } else if (ch == '?') {
 260256                                 if ((ch = chktg()) == '#') {
 261257                                         ppdir();
 262258                                         continue;
 263259                                 } else if (ch == 0)
 264260                                         ch = '?';
 265261                         }
 266262                         goto xloop;
 267263 
 268264                 case '\"': /* strings */
 269265 str:                    PUTCH(ch);
 270266                         while ((ch = NXTCH()) != '\"') {
 271267                                 if (ch == '\n')
 272268                                         goto xloop;
 273269                                 if (ch == '\\') {
 274270                                         if ((ch = NXTCH()) != '\n') {
 275271                                                 PUTCH('\\');
 276272                                                 PUTCH(ch);
 277273                                         } else
 278274                                                 nnl++;
 279275                                         continue;
 280276                                 }
 281277                                 if (ch == -1)
 282278                                         return;
 283279                                 PUTCH(ch);
 284280                         }
 285281                         PUTCH(ch);
 286282                         break;
 287283 
 288284                 case '.'/* for pp-number */
 289285                         PUTCH(ch);
 290286                         ch = NXTCH();
 291287                         if (ch < '0' || ch > '9')
 292288                                 goto xloop;
 293289                         /* FALLTHROUGH */
 294290                 case '0': case '1': case '2': case '3': case '4':
 295291                 case '5': case '6': case '7': case '8': case '9':
 296292                         do {
 297293                                 PUTCH(ch);
 298294 nxt:                            ch = NXTCH();
 299295                                 if (ch == '\\') {
 300296                                         ch = NXTCH();
 301297                                         if (ch == '\n') {
 302298                                                 nnl++;
 303299                                                 goto nxt;
<>304 -                                        } else {
 305 -                                                unch(ch);
 306 -                                                ch = '\\';
307300                                         }
<> 301+                                        unch(ch);
  302+                                        ch = '\\';
<_308303                                 }
 309304                                 if (spechr[ch] & C_EP) {
 310305                                         PUTCH(ch);
 311306                                         ch = NXTCH();
 312307                                         if (ch == '-' || ch == '+')
 313308                                                 continue;
 314309                                 }
 315310                         } while ((spechr[ch] & C_ID) || (ch == '.'));
 316311                         goto xloop;
 317312 
 318313                 case '\'': /* character literal */
 319314 con:                    PUTCH(ch);
 320315                         if (tflag)
 321316                                 continue; /* character constants ignored */
 322317                         while ((ch = NXTCH()) != '\'') {
 323318                                 if (ch == '\n')
 324319                                         goto xloop;
 325320                                 if (ch == '\\') {
 326321                                         if ((ch = NXTCH()) != '\n') {
 327322                                                 PUTCH('\\');
 328323                                                 PUTCH(ch);
 329324                                         } else
 330325                                                 nnl++;
 331326                                         continue;
 332327                                 }
 333328                                 if (ch == -1)
 334329                                         return;
 335330                                 PUTCH(ch);
 336331                         }
 337332                         PUTCH(ch);
 338333                         break;
 339334 
 340335                 case 'L':
 341336                         ch = NXTCH();
 342337                         if (ch == '\"') {
 343338                                 PUTCH('L');
 344339                                 goto str;
 345340                         }
 346341                         if (ch == '\'') {
 347342                                 PUTCH('L');
 348343                                 goto con;
 349344                         }
 350345                         unch(ch);
 351346                         ch = 'L';
 352347                         /* FALLTHROUGH */
 353348                 default:
 354349                         if ((spechr[ch] & C_ID) == 0)
 355350                                 error("fastscan");
 356351                         if (flslvl) {
 357352                                 while (spechr[ch] & C_ID)
 358353                                         ch = NXTCH();
 359354                                 goto xloop;
 360355                         }
 361356                         i = 0;
 362357                         do {
 363358                                 yytext[i++] = (usch)ch;
 364359                                 ch = NXTCH();
 365360                                 if (ch == '\\') {
 366361                                         ch = NXTCH();
 367362                                         if (ch != '\n') {
 368363                                                 unch(ch);
 369364                                                 ch = '\\';
 370365                                         } else {
 371366                                                 putch('\n');
 372367                                                 ifiles->lineno++;
 373368                                                 ch = NXTCH();
 374369                                         }
 375370                                 }
 376371                                 if (ch == -1)
 377372                                         return;
 378373                         } while (spechr[ch] & C_ID);
 379374 
 380375                         yytext[i] = 0;
 381376                         unch(ch);
 382377 
 383378                         cp = stringbuf;
 384379                         if ((nl = lookup(yytext, FIND)) && kfind(nl)) {
 385380                                 putstr(stringbuf);
 386381                         } else
 387382                                 putstr(yytext);
 388383                         stringbuf = cp;
 389384 
 390385                         break;
 391386                 }
 392387         }
 393388 }
 394389 
 395390 int
 396391 sloscan(void)
 397392 {
 398393         int ch;
 399394         int yyp;
 400395 
 401396 zagain:
 402397         yyp = 0;
 403398         ch = inch();
 404399         yytext[yyp++] = (usch)ch;
 405400         switch (ch) {
 406401         case -1:
 407402                 return 0;
 408403         case '\n':
 409404                 /* sloscan() never passes \n, that's up to fastscan() */
 410405                 unch(ch);
 411406                 goto yyret;
 412407 
 413408         case '\r': /* Ignore CR's */
 414409                 yyp = 0;
 415410                 break;
 416411 
 417412         case '0': case '1': case '2': case '3': case '4': case '5':
 418413         case '6': case '7': case '8': case '9':
 419414                 /* readin a "pp-number" */
 420415 ppnum:          for (;;) {
 421416                         ch = inch();
 422417                         if (spechr[ch] & C_EP) {
 423418                                 yytext[yyp++] = (usch)ch;
 424419                                 ch = inch();
 425420                                 if (ch == '-' || ch == '+') {
 426421                                         yytext[yyp++] = (usch)ch;
 427422                                 } else
 428423                                         unch(ch);
 429424                                 continue;
 430425                         }
 431426                         if ((spechr[ch] & C_ID) || ch == '.') {
 432427                                 yytext[yyp++] = (usch)ch;
 433428                                 continue;
 434429                         }
 435430                         break;
 436431                 }
 437432                 unch(ch);
 438433                 yytext[yyp] = 0;
 439434 
 440435                 return NUMBER;
 441436 
 442437         case '\'':
 443438 chlit:          
 444439                 for (;;) {
 445440                         if ((ch = inch()) == '\\') {
 446441                                 yytext[yyp++] = (usch)ch;
 447442                                 yytext[yyp++] = (usch)inch();
 448443                                 continue;
 449444                         } else if (ch == '\n') {
 450445                                 /* not a constant */
 451446                                 while (yyp > 1)
 452447                                         unch(yytext[--yyp]);
 453448                                 ch = '\'';
 454449                                 goto any;
 455450                         } else
 456451                                 yytext[yyp++] = (usch)ch;
 457452                         if (ch == '\'')
 458453                                 break;
 459454                 }
 460455                 yytext[yyp] = 0;
 461456 
 462457                 return NUMBER;
 463458 
 464459         case ' ':
 465460         case '\t':
 466461                 while ((ch = inch()) == ' ' || ch == '\t')
 467462                         yytext[yyp++] = (usch)ch;
 468463                 unch(ch);
 469464                 yytext[yyp] = 0;
 470465                 return WSPACE;
 471466 
 472467         case '/':
 473468                 if ((ch = inch()) == '/') {
 474469                         do {
 475470                                 yytext[yyp++] = (usch)ch;
 476471                                 ch = inch();
 477472                         } while (ch && ch != '\n');
 478473                         yytext[yyp] = 0;
 479474                         unch(ch);
 480475                         goto zagain;
 481476                 } else if (ch == '*') {
 482477                         int c, wrn;
 483478                         extern int readmac;
 484479 
 485480                         if (Cflag && !flslvl && readmac) {
 486481                                 unch(ch);
 487482                                 yytext[yyp] = 0;
 488483                                 return CMNT;
 489484                         }
 490485 
 491486                         wrn = 0;
 492487                 more:   while ((c = inch()) && c != '*') {
 493488                                 if (c == '\n')
 494489                                         putch(c), ifiles->lineno++;
 495490                                 else if (c == EBLOCK) {
 496491                                         (void)inch();
 497492                                         (void)inch();
 498493                                 } else if (c == 1) /* WARN */
 499494                                         wrn = 1;
 500495                         }
 501496                         if (c == 0)
 502497                                 return 0;
 503498                         if ((c = inch()) && c != '/') {
 504499                                 unch(c);
 505500                                 goto more;
 506501                         }
 507502                         if (c == 0)
 508503                                 return 0;
 509504                         if (!tflag && !Cflag && !flslvl)
 510505                                 unch(' ');
 511506                         if (wrn)
 512507                                 unch(1);
 513508                         goto zagain;
 514509                 }
 515510                 unch(ch);
 516511                 ch = '/';
 517512                 goto any;
 518513 
 519514         case '.':
 520515                 ch = inch();
 521516                 if (isdigit(ch)) {
 522517                         yytext[yyp++] = (usch)ch;
 523518                         goto ppnum;
 524519                 } else {
 525520                         unch(ch);
 526521                         ch = '.';
 527522                 }
 528523                 goto any;
 529524 
 530525         case '\"':
 531526                 if (tflag && defining)
 532527                         goto any;
 533528         strng:
 534529                 for (;;) {
 535530                         if ((ch = inch()) == '\\') {
 536531                                 yytext[yyp++] = (usch)ch;
 537532                                 yytext[yyp++] = (usch)inch();
 538533                                 continue;
 539534                         } else
 540535                                 yytext[yyp++] = (usch)ch;
 541536                         if (ch == '\"')
 542537                                 break;
 543538                 }
 544539                 yytext[yyp] = 0;
 545540                 return STRING;
 546541 
 547542         case 'L':
 548543                 if ((ch = inch()) == '\"' && !tflag) {
 549544                         yytext[yyp++] = (usch)ch;
 550545                         goto strng;
 551546                 } else if (ch == '\'' && !tflag) {
 552547                         yytext[yyp++] = (usch)ch;
 553548                         goto chlit;
 554549                 }
 555550                 unch(ch);
 556551                 /* FALLTHROUGH */
 557552 
 558553         /* Yetch, all identifiers */
 559554         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
 560555         case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
 561556         case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
 562557         case 's': case 't': case 'u': case 'v': case 'w': case 'x':
 563558         case 'y': case 'z':
 564559         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
 565560         case 'G': case 'H': case 'I': case 'J': case 'K':
 566561         case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
 567562         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
 568563         case 'Y': case 'Z':
 569564         case '_': /* {L}({L}|{D})* */
 570565 
 571566                 /* Special hacks */
 572567                 for (;;) { /* get chars */
 573568                         ch = inch();
 574569                         if (isalpha(ch) || isdigit(ch) || ch == '_') {
 575570                                 yytext[yyp++] = (usch)ch;
 576571                         } else {
 577572                                 if (ch != -1)
 578573                                         unch(ch);
 579574                                 break;
 580575                         }
 581576                 }
 582577                 yytext[yyp] = 0; /* need already string */
 583578                 /* end special hacks */
 584579 
 585580                 return IDENT;
 586581         default:
 587582         any:
 588583                 yytext[yyp] = 0;
 589584                 return yytext[0];
 590585 
 591586         } /* endcase */
 592587         goto zagain;
 593588 
 594589 yyret:
 595590         yytext[yyp] = 0;
 596591         return ch;
 597592 }
 598593 
 599594 int
 600595 yylex(void)
 601596 {
 602597         static int ifdef, noex;
 603598         struct symtab *nl;
 604599         int ch, c2;
 605600 
 606601         while ((ch = sloscan()) == WSPACE)
 607602                 ;
 608603         if (ch < 128 && spechr[ch] & C_2)
 609604                 c2 = inpch();
 610605         else
 611606                 c2 = 0;
 612607 
 613608 #define C2(a,b,c) case a: if (c2 == b) return c; break
 614609         switch (ch) {
 615610         C2('=', '=', EQ);
 616611         C2('!', '=', NE);
 617612         C2('|', '|', OROR);
 618613         C2('&', '&', ANDAND);
 619614         case '<':
 620615                 if (c2 == '<') return LS;
 621616                 if (c2 == '=') return LE;
 622617                 break;
 623618         case '>':
 624619                 if (c2 == '>') return RS;
 625620                 if (c2 == '=') return GE;
 626621                 break;
 627622         case '+':
 628623         case '-':
 629624                 if (ch == c2)
 630625                         error("invalid preprocessor operator %c%c", ch, c2);
 631626                 break;
 632627 
 633628         case '/':
 634629                 if (Cflag == 0 || c2 != '*')
 635630                         break;
 636631                 /* Found comment that need to be skipped */
 637632                 for (;;) {
 638633                         ch = inpch();
 639634                 c1:     if (ch != '*')
 640635                                 continue;
 641636                         if ((ch = inpch()) == '/')
 642637                                 break;
 643638                         goto c1;
 644639                 }
 645640                 return yylex();
 646641 
 647642         case NUMBER:
 648643                 if (yytext[0] == '\'') {
 649644                         yylval.node.op = NUMBER;
 650645                         yylval.node.nd_val = charcon(yytext);
 651646                 } else
 652647                         cvtdig(yytext[0] != '0' ? 10 :
 653648                             yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
 654649                 return NUMBER;
 655650 
 656651         case IDENT:
 657652                 if (strcmp((char *)yytext, "defined") == 0) {
 658653                         ifdef = 1;
 659654                         return DEFINED;
 660655                 }
 661656                 nl = lookup(yytext, FIND);
 662657                 if (ifdef) {
 663658                         yylval.node.nd_val = nl != NULL;
 664659                         ifdef = 0;
 665660                 } else if (nl && noex == 0) {
 666661                         usch *och = stringbuf;
 667662                         int i;
 668663 
 669664                         i = kfind(nl);
 670665                         unch(WARN);
 671666                         if (i)
 672667                                 unpstr(stringbuf);
 673668                         else
 674669                                 unpstr(nl->namep);
 675670                         stringbuf = och;
 676671                         noex = 1;
 677672                         return yylex();
 678673                 } else {
 679674                         yylval.node.nd_val = 0;
 680675                 }
 681676                 yylval.node.op = NUMBER;
 682677                 return NUMBER;
 683678         case WARN:
 684679                 noex = 0;
 685680                 /* FALLTHROUGH */
 686681         case PHOLD:
 687682                 return yylex();
 688683         default:
 689684                 return ch;
 690685         }
 691686         unch(c2);
 692687         return ch;
 693688 }
 694689 
 695690 static int
 696691 inpch(void)
 697692 {
 698693         int len;
 699694 
 700695         if (ifiles->curptr < ifiles->maxread)
 701696                 return *ifiles->curptr++;
 702697 
 703698         if (ifiles->infil == -1)
 704699                 return -1;
 705700         if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0)
 706701                 error("read error on file %s", ifiles->orgfn);
 707702         if (len == 0)
 708703                 return -1;
 709704         ifiles->buffer[len] = 0;
 710705         ifiles->curptr = ifiles->buffer;
 711706         ifiles->maxread = ifiles->buffer + len;
 712707         return inpch();
 713708 }
 714709 
 715710 static int
 716711 inch(void)
 717712 {
 718713         int c;
 719714 
 720715 again:  switch (c = inpch()) {
 721716         case '\\': /* continued lines */
 722717 msdos:          if ((c = inpch()) == '\n') {
 723718                         ifiles->lineno++;
 724719                         putch('\n');
 725720                         goto again;
 726721                 } else if (c == '\r')
 727722                         goto msdos;
 728723                 unch(c);
 729724                 return '\\';
 730725         case '?': /* trigraphs */
 731726                 if ((c = chktg())) {
 732727                         unch(c);
 733728                         goto again;
 734729                 }
 735730                 return '?';
 736731         default:
 737732                 return c;
 738733         }
 739734 }
 740735 
 741736 /*
 742737  * Let the command-line args be faked defines at beginning of file.
 743738  */
 744739 static void
 745740 prinit(struct initar *it, struct includ *ic)
 746741 {
 747742         const char *pre, *post;
 748743         char *a;
 749744 
 750745         if (it->next)
 751746                 prinit(it->next, ic);
 752747         pre = post = NULL; /* XXX gcc */
 753748         switch (it->type) {
 754749         case 'D':
 755750                 pre = "#define ";
 756751                 if ((a = strchr(it->str, '=')) != NULL) {
 757752                         *a = ' ';
 758753                         post = "\n";
 759754                 } else
 760755                         post = " 1\n";
 761756                 break;
 762757         case 'U':
 763758                 pre = "#undef ";
 764759                 post = "\n";
 765760                 break;
 766761         case 'i':
 767762                 pre = "#include \"";
 768763                 post = "\"\n";
 769764                 break;
 770765         default:
 771766                 error("prinit");
 772767         }
 773768         strlcat((char *)ic->buffer, pre, CPPBUF+1);
 774769         strlcat((char *)ic->buffer, it->str, CPPBUF+1);
 775770         if (strlcat((char *)ic->buffer, post, CPPBUF+1) >= CPPBUF+1)
 776771                 error("line exceeds buffer size");
 777772 
 778773         ic->lineno--;
 779774         while (*ic->maxread)
 780775                 ic->maxread++;
 781776 }
 782777 
 783778 /*
 784779  * A new file included.
 785780  * If ifiles == NULL, this is the first file and already opened (stdin).
 786781  * Return 0 on success, -1 if file to be included is not found.
 787782  */
 788783 int
 789784 pushfile(const usch *file, const usch *fn, int idx, void *incs)
 790785 {
 791786         extern struct initar *initar;
 792787         struct includ ibuf;
 793788         struct includ *ic;
 794789         int otrulvl;
 795790 
 796791         ic = &ibuf;
 797792         ic->next = ifiles;
 798793 
 799794         if (file != NULL) {
 800795                 if ((ic->infil = open((const char *)file, O_RDONLY)) < 0)
 801796                         return -1;
 802797                 ic->orgfn = ic->fname = file;
 803798                 if (++inclevel > MAX_INCLEVEL)
 804799                         error("Limit for nested includes exceeded");
 805800         } else {
 806801                 ic->infil = 0;
 807802                 ic->orgfn = ic->fname = (const usch *)"<stdin>";
 808803         }
 809804 #ifndef BUF_STACK
 810805         ic->bbuf = malloc(BBUFSZ);
 811806 #endif
 812807         ic->buffer = ic->bbuf+NAMEMAX;
 813808         ic->curptr = ic->buffer;
 814809         ifiles = ic;
 815810         ic->lineno = 1;
 816811         ic->maxread = ic->curptr;
 817812         ic->idx = idx;
 818813         ic->incs = incs;
 819814         ic->fn = fn;
 820815         prtline();
 821816         if (initar) {
 822817                 int oin = ic->infil;
 823818                 ic->infil = -1;
 824819                 *ic->maxread = 0;
 825820                 prinit(initar, ic);
 826821                 initar = NULL;
 827822                 if (dMflag)
 828823                         xwrite(ofd, ic->buffer, strlen((char *)ic->buffer));
 829824                 fastscan();
 830825                 prtline();
 831826                 ic->infil = oin;
 832827         }
 833828 
 834829         otrulvl = trulvl;
 835830 
 836831         fastscan();
 837832 
 838833         if (otrulvl != trulvl || flslvl)
 839834                 error("unterminated conditional");
 840835 
 841836 #ifndef BUF_STACK
 842837         free(ic->bbuf);
 843838 #endif
 844839         ifiles = ic->next;
 845840         close(ic->infil);
 846841         inclevel--;
 847842         return 0;
 848843 }
 849844 
 850845 /*
 851846  * Print current position to output file.
 852847  */
 853848 void
 854849 prtline(void)
 855850 {
 856851         usch *sb = stringbuf;
 857852 
 858853         if (Mflag) {
 859854                 if (dMflag)
 860855                         return; /* no output */
 861856                 if (ifiles->lineno == 1) {
 862857                         sheap("%s: %s\n", Mfile, ifiles->fname);
 863858                         if (MPflag &&
 864859                             strcmp((const char *)ifiles->fname, (char *)MPfile))
 865860                                 sheap("%s:\n", ifiles->fname);
 866861                         xwrite(ofd, sb, stringbuf - sb);
 867862                 }
 868863         } else if (!Pflag) {
 869864                 sheap("\n# %d \"%s\"", ifiles->lineno, ifiles->fname);
 870865                 if (ifiles->idx == SYSINC)
 871866                         sheap(" 3");
 872867                 sheap("\n");
 873868                 putstr(sb);
 874869         }
 875870         stringbuf = sb;
 876871 }
 877872 
 878873 void
 879874 cunput(int c)
 880875 {
 881876 #ifdef PCC_DEBUG
 882877 //      if (dflag)printf(": '%c'(%d)\n", c > 31 ? c : ' ', c);
 883878 #endif
 884879         unch(c);
 885880 }
 886881 
 887882 static int
 888883 dig2num(int c)
 889884 {
 890885         if (c >= 'a')
 891886                 c = c - 'a' + 10;
 892887         else if (c >= 'A')
 893888                 c = c - 'A' + 10;
 894889         else
 895890                 c = c - '0';
 896891         return c;
 897892 }
 898893 
 899894 /*
 900895  * Convert string numbers to unsigned long long and check overflow.
 901896  */
 902897 static void
 903898 cvtdig(int rad)
 904899 {
 905900         unsigned long long rv = 0;
 906901         unsigned long long rv2 = 0;
 907902         usch *y = yytext;
 908903         int c;
 909904 
 910905         c = *y++;
 911906         if (rad == 16)
 912907                 y++;
 913908         while (isxdigit(c)) {
 914909                 rv = rv * rad + dig2num(c);
 915910                 /* check overflow */
 916911                 if (rv / rad < rv2)
 917912                         error("Constant \"%s\" is out of range", yytext);
 918913                 rv2 = rv;
 919914                 c = *y++;
 920915         }
 921916         y--;
 922917         while (*y == 'l' || *y == 'L')
 923918                 y++;
 924919         yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER;
 925920         yylval.node.nd_uval = rv;
 926921         if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0)
 927922                 yylval.node.op = UNUMBER;
 928923         if (yylval.node.op == NUMBER && yylval.node.nd_val < 0)
 929924                 /* too large for signed, see 6.4.4.1 */
 930925                 error("Constant \"%s\" is out of range", yytext);
 931926 }
 932927 
 933928 static int
 934929 charcon(usch *p)
 935930 {
 936931         int val, c;
 937932 
 938933         p++; /* skip first ' */
 939934         val = 0;
 940935         if (*p++ == '\\') {
 941936                 switch (*p++) {
 942937                 case 'a': val = '\a'; break;
 943938                 case 'b': val = '\b'; break;
 944939                 case 'f': val = '\f'; break;
 945940                 case 'n': val = '\n'; break;
 946941                 case 'r': val = '\r'; break;
 947942                 case 't': val = '\t'; break;
 948943                 case 'v': val = '\v'; break;
 949944                 case '\"': val = '\"'; break;
 950945                 case '\'': val = '\''; break;
 951946                 case '\\': val = '\\'; break;
 952947                 case 'x':
 953948                         while (isxdigit(c = *p)) {
 954949                                 val = val * 16 + dig2num(c);
 955950                                 p++;
 956951                         }
 957952                         break;
 958953                 case '0': case '1': case '2': case '3': case '4':
 959954                 case '5': case '6': case '7':
 960955                         p--;
 961956                         while (isdigit(c = *p)) {
 962957                                 val = val * 8 + (c - '0');
 963958                                 p++;
 964959                         }
 965960                         break;
 966961                 default: val = p[-1];
 967962                 }
 968963 
 969964         } else
 970965                 val = p[-1];
 971966         return val;
 972967 }
 973968 
 974969 static void
 975970 chknl(int ignore)
 976971 {
 977972         int t;
 978973 
 979974         while ((t = sloscan()) == WSPACE)
 980975                 ;
 981976         if (t != '\n') {
 982977                 if (t && t != (usch)-1) {
 983978                         if (ignore) {
 984979                                 warning("newline expected, got \"%s\"", yytext);
 985980                                 /* ignore rest of line */
 986981                                 while ((t = sloscan()) && t != '\n')
 987982                                         ;
 988983                         }
 989984                         else
 990985                                 error("newline expected, got \"%s\"", yytext);
 991986                 } else {
 992987                         if (ignore)
 993988                                 warning("no newline at end of file");
 994989                         else
 995990                                 error("no newline at end of file");
 996991                 }
 997992         }
 998993 }
 999994 
 1000995 static void
 1001996 elsestmt(void)
 1002997 {
 1003998         if (flslvl) {
 1004999                 if (elflvl > trulvl)
 10051000                         ;
 10061001                 else if (--flslvl!=0) {
 10071002                         flslvl++;
 10081003                 } else {
 10091004                         trulvl++;
 10101005                         prtline();
 10111006                 }
 10121007         } else if (trulvl) {
 10131008                 flslvl++;
 10141009                 trulvl--;
 10151010         } else
 10161011                 error("If-less else");
 10171012         if (elslvl==trulvl+flslvl)
 10181013                 error("Too many else");
 10191014         elslvl=trulvl+flslvl;
 10201015         chknl(1);
 10211016 }
 10221017 
 10231018 static void
 10241019 skpln(void)
 10251020 {
 10261021         /* just ignore the rest of the line */
 10271022         while (inch() != '\n')
 10281023                 ;
 10291024         unch('\n');
 10301025         flslvl++;
 10311026 }
 10321027 
 10331028 static void
 10341029 ifdefstmt(void)         
 10351030 {
 10361031         int t;
 10371032 
 10381033         if (flslvl) {
 10391034                 skpln();
 10401035                 return;
 10411036         }
 10421037         do
 10431038                 t = sloscan();
 10441039         while (t == WSPACE);
 10451040         if (t != IDENT)
 10461041                 error("bad #ifdef");
 10471042         if (lookup(yytext, FIND) == NULL) {
 10481043                 putch('\n');
 10491044                 flslvl++;
 10501045         } else
 10511046                 trulvl++;
 10521047         chknl(0);
 10531048 }
 10541049 
 10551050 static void
 10561051 ifndefstmt(void)         
 10571052 {
 10581053         int t;
 10591054 
 10601055         if (flslvl) {
 10611056                 skpln();
 10621057                 return;
 10631058         }
 10641059         do
 10651060                 t = sloscan();
 10661061         while (t == WSPACE);
 10671062         if (t != IDENT)
 10681063                 error("bad #ifndef");
 10691064         if (lookup(yytext, FIND) != NULL) {
 10701065                 putch('\n');
 10711066                 flslvl++;
 10721067         } else
 10731068                 trulvl++;
 10741069         chknl(0);
 10751070 }
 10761071 
 10771072 static void
 10781073 endifstmt(void)         
 10791074 {
 10801075         if (flslvl) {
 10811076                 flslvl--;
 10821077                 if (flslvl == 0) {
 10831078                         putch('\n');
 10841079                         prtline();
 10851080                 }
 10861081         } else if (trulvl)
 10871082                 trulvl--;
 10881083         else
 10891084                 error("If-less endif");
 10901085         if (flslvl == 0)
 10911086                 elflvl = 0;
 10921087         elslvl = 0;
 10931088         chknl(1);
 10941089 }
 10951090 
 10961091 static void
 10971092 ifstmt(void)
 10981093 {
 10991094         if (flslvl == 0) {
 11001095                 if (yyparse() == 0) {
 11011096                         putch('\n');
 11021097                         ++flslvl;
 11031098                 } else
 11041099                         ++trulvl;
 11051100         } else
 11061101                 ++flslvl;
 11071102 }
 11081103 
 11091104 static void
 11101105 elifstmt(void)
 11111106 {
 11121107         if (flslvl == 0)
 11131108                 elflvl = trulvl;
 11141109         if (flslvl) {
 11151110                 if (elflvl > trulvl)
 11161111                         ;
 11171112                 else if (--flslvl!=0)
 11181113                         ++flslvl;
 11191114                 else {
 11201115                         if (yyparse()) {
 11211116                                 ++trulvl;
 11221117                                 prtline();
 11231118                         } else {
 11241119                                 putch('\n');
 11251120                                 ++flslvl;
 11261121                         }
 11271122                 }
 11281123         } else if (trulvl) {
 11291124                 ++flslvl;
 11301125                 --trulvl;
 11311126         } else
 11321127                 error("If-less elif");
 11331128 }
 11341129 
 11351130 /* save line into stringbuf */
 11361131 static usch *
 11371132 savln(void)
 11381133 {
 11391134         int c;
 11401135         usch *cp = stringbuf;
 11411136 
 11421137         while ((c = inch()) != 0) {
 11431138                 if (c == '\n') {
 11441139                         unch(c);
 11451140                         break;
 11461141                 }
 11471142                 savch(c);
 11481143         }
 11491144         savch(0);
 11501145 
 11511146         return cp;
 11521147 }
 11531148 
 11541149 static void
 11551150 cpperror(void)
 11561151 {
 11571152         usch *cp;
 11581153         int c;
 11591154 
 11601155         if (flslvl)
 11611156                 return;
 11621157         c = sloscan();
 11631158         if (c != WSPACE && c != '\n')
 11641159                 error("bad #error");
 11651160         cp = savln();
 11661161         error("#error %s", cp);
 11671162 }
 11681163 
 11691164 static void
 11701165 cppwarning(void)
 11711166 {
 11721167         usch *cp;
 11731168         int c;
 11741169 
 11751170         if (flslvl)
 11761171                 return;
 11771172         c = sloscan();
 11781173         if (c != WSPACE && c != '\n')
 11791174                 error("bad #warning");
 11801175         cp = savln();
 11811176         warning("#warning %s", cp);
 11821177         stringbuf = cp;
 11831178 }
 11841179 
 11851180 static void
 11861181 undefstmt(void)
 11871182 {
 11881183         struct symtab *np;
 11891184 
 11901185         if (flslvl)
 11911186                 return;
 11921187         if (sloscan() != WSPACE || sloscan() != IDENT)
 11931188                 error("bad #undef");
 11941189         if ((np = lookup(yytext, FIND)) != NULL)
 11951190                 np->value = 0;
 11961191         chknl(0);
 11971192 }
 11981193 
 11991194 static void
 12001195 pragmastmt(void)
 12011196 {
 12021197         usch *sb;
 12031198 
 12041199         if (flslvl)
 12051200                 return;
 12061201         if (sloscan() != WSPACE)
 12071202                 error("bad #pragma");
 12081203         sb = stringbuf;
 12091204         savstr((const usch *)"#pragma ");
 12101205         savln();
 12111206         putstr(sb);
 12121207         stringbuf = sb;
 12131208 }
 12141209 
 12151210 int
 12161211 cinput(void)
 12171212 {
 12181213         return inch();
 12191214 }
 12201215 
 12211216 /*
 12221217  * Check for (and convert) trigraphs.
 12231218  */
 12241219 int
 12251220 chktg(void)
 12261221 {
 12271222         int c;
 12281223 
 12291224         if ((c = inpch()) != '?') {
 12301225                 unch(c);
 12311226                 return 0;
 12321227         }
 12331228         switch (c = inpch()) {
 12341229         case '=': c = '#'; break;
 12351230         case '(': c = '['; break;
 12361231         case ')': c = ']'; break;
 12371232         case '<': c = '{'; break;
 12381233         case '>': c = '}'; break;
 12391234         case '/': c = '\\'; break;
 12401235         case '\'': c = '^'; break;
 12411236         case '!': c = '|'; break;
 12421237         case '-': c = '~'; break;
 12431238         default:
 12441239                 unch(c);
 12451240                 unch('?');
 12461241                 c = 0;
 12471242         }
 12481243         return c;
 12491244 }
 12501245 
 12511246 static struct {
 12521247         const char *name;
 12531248         void (*fun)(void);
 12541249 } ppd[] = {
 12551250         { "ifndef", ifndefstmt },
 12561251         { "ifdef", ifdefstmt },
 12571252         { "if", ifstmt },
 12581253         { "include", include },
 12591254         { "else", elsestmt },
 12601255         { "endif", endifstmt },
 12611256         { "error", cpperror },
 12621257         { "warning", cppwarning },
 12631258         { "define", define },
 12641259         { "undef", undefstmt },
 12651260         { "line", line },
 12661261         { "pragma", pragmastmt },
 12671262         { "elif", elifstmt },
 12681263 #ifdef GCC_COMPAT
 12691264         { "include_next", include_next },
 12701265 #endif
 12711266 };
 12721267 
 12731268 /*
 12741269  * Handle a preprocessor directive.
 12751270  */
 12761271 void
 12771272 ppdir(void)
 12781273 {
 12791274         char bp[20];
 12801275         int ch, i;
 12811276 
 12821277         while ((ch = inch()) == ' ' || ch == '\t')
 12831278                 ;
 12841279         if (ch == '\n') { /* empty directive */
 12851280                 unch(ch);
 12861281                 return;
 12871282         }
 12881283         if (ch < 'a' || ch > 'z')
 12891284                 goto out; /* something else, ignore */
 12901285         i = 0;
 12911286         do {
 12921287                 bp[i++] = (usch)ch;
 12931288                 if (i == sizeof(bp)-1)
 12941289                         goto out; /* too long */
 12951290                 ch = inch();
 12961291         } while ((ch >= 'a' && ch <= 'z') || (ch == '_'));
 12971292         unch(ch);
 12981293         bp[i++] = 0;
 12991294 
 13001295         /* got keyword */
 13011296 #define SZ (int)(sizeof(ppd)/sizeof(ppd[0]))
 13021297         for (i = 0; i < SZ; i++)
 13031298                 if (bp[0] == ppd[i].name[0] && strcmp(bp, ppd[i].name) == 0)
 13041299                         break;
 13051300         if (i == SZ)
 13061301                 goto out;
 13071302 
 13081303         /* Found matching keyword */
 13091304         (*ppd[i].fun)();
 13101305         return;
 13111306 
 13121307 out:    while ((ch = inch()) != '\n' && ch != -1)
 13131308                 ;
 13141309         unch('\n');
 13151310 }
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-11-01 07:10 +0100