Quick Search:

Mode

Context

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

Other Diffs

Ignore

Blank Lines Whitespace: Expand:

Diff

1.96
 
1.97
 
MAIN:plunky:20121031115454
 
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>
<>47 -#include <ctype.h>
4847 #ifdef HAVE_UNISTD_H
 4948 #include <unistd.h>
 5049 #endif
 5150 #include <fcntl.h>
 5251 
 5352 #include "compat.h"
 5453 #include "cpp.h"
 5554 #include "cpy.h"
 5655 
 5756 static void cvtdig(int rad);
 5857 static int charcon(usch *);
 5958 static void elsestmt(void);
 6059 static void ifdefstmt(void);
 6160 static void ifndefstmt(void);
 6261 static void endifstmt(void);
 6362 static void ifstmt(void);
 6463 static void cpperror(void);
 6564 static void pragmastmt(void);
 6665 static void undefstmt(void);
 6766 static void cppwarning(void);
 6867 static void elifstmt(void);
 6968 static int chktg(void);
 7069 static int inpch(void);
 7170 static int inch(void);
 7271 
 7372 #define PUTCH(ch) if (!flslvl) putch(ch)
 7473 /* protection against recursion in #include */
 7574 #define MAX_INCLEVEL    100
 7675 static int inclevel;
 7776 
 7877 /* get next character unaltered */
 7978 #define NXTCH() (ifiles->curptr < ifiles->maxread ? *ifiles->curptr++ : inpch())
 8079 
 8180 usch yytext[CPPBUF];
 8281 
 8382 struct includ *ifiles;
 8483 
<>85 -char spechr[256] = {
  84+/* some common special combos for init */
  85+#define C_NL    (C_SPEC|C_WSNL)
  86+#define C_DX    (C_SPEC|C_ID|C_DIGIT|C_HEX)
  87+#define C_I     (C_SPEC|C_ID|C_ID0)
  88+#define C_IP    (C_SPEC|C_ID|C_ID0|C_EP)
  89+#define C_IX    (C_SPEC|C_ID|C_ID0|C_HEX)
  90+#define C_IXE   (C_SPEC|C_ID|C_ID0|C_HEX|C_EP)
  91+
  92+usch spechr[256] = {
8693         0,      0,      0,      0,      C_SPECC_SPEC0,      0,
<>87 -        0,      C_WSNLC_SPEC|C_WSNL,  0,
 88 -        0,      C_WSNL0,      0,
  94+        0,      C_WSNLC_NL,   0,      0,      C_WSNL0,      0,
8995         0,      0,      0,      0,      0,      0,      0,      0,
 9096         0,      0,      0,      0,      0,      0,      0,      0,
 9197 
 9298         C_WSNLC_2,    C_SPEC0,      0,      0,      C_2,    C_SPEC,
 9399         0,      0,      0,      C_2,    0,      C_2,    0,      C_SPEC|C_2,
<>94 -        C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 95 -        C_I,    C_I,    0,      0,      C_2,    C_2,    C_2,    C_SPEC,
  100+        C_DX,   C_DX,   C_DX,   C_DX,   C_DX,   C_DX,   C_DX,   C_DX,
  101+        C_DX,   C_DX,   0,      0,      C_2,    C_2,    C_2,    C_SPEC,
96102 
<>97 -        0,      C_I,    C_I,    C_I,    C_I,    C_I|C_EP, C_I,  C_I,
  103+        0,      C_IX,   C_IX,   C_IX,   C_IX,   C_IXE,  C_IX,   C_I,
98104         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
<>99 -        C_I|C_EP, C_I,  C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
  105+        C_IP,   C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
100106         C_I,    C_I,    C_I,    0,      C_SPEC0,      0,      C_I,
 101107 
<>102 -        0,      C_I,    C_I,    C_I,    C_I,    C_I|C_EP, C_I,  C_I,
  108+        0,      C_IX,   C_IX,   C_IX,   C_IX,   C_IXE,  C_IX,   C_I,
103109         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
<>104 -        C_I|C_EP, C_I,  C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
  110+        C_IP,   C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
105111         C_I,    C_I,    C_I,    0,      C_2,    0,      0,      0,
<>106 -
107112 };
 108113 
 109114 static void
 110115 unch(int c)
 111116 {
 112117         if (c == -1)
 113118                 return;
 114119                 
 115120         --ifiles->curptr;
 116121         if (ifiles->curptr < ifiles->bbuf)
 117122                 error("pushback buffer full");
 118123         *ifiles->curptr = (usch)c;
 119124 }
 120125 
 121126 static void
 122127 eatcmnt(void)
 123128 {
 124129         int ch;
 125130 
 126131         if (Cflag) { PUTCH('/'); PUTCH('*'); }
 127132         for (;;) {
 128133                 ch = inch();
 129134                 if (ch == '\n') {
 130135                         ifiles->lineno++;
 131136                         if (!Cflag) PUTCH('\n');
 132137                 }
 133138                 if (ch == -1)
 134139                         break;
 135140                 if (ch == '*') {
 136141                         ch = inch();
 137142                         if (ch == '/') {
 138143                                 if (Cflag) {
 139144                                         PUTCH('*');
 140145                                         PUTCH('/');
 141146                                 } else
 142147                                         PUTCH(' ');
 143148                                 break;
 144149                         }
 145150                         unch(ch);
 146151                         ch = '*';
 147152                 }
 148153                 if (Cflag) PUTCH(ch);
 149154         }
 150155 }
 151156 
 152157 /*
 153158  * Scan quickly the input file searching for:
 154159  *      - '#' directives
 155160  *      - keywords (if not flslvl)
 156161  *      - comments
 157162  *
 158163  *      Handle strings, numbers and trigraphs with care.
 159164  *      Only data from pp files are scanned here, never any rescans.
 160165  *      TODO: Only print out strings before calling other functions.
 161166  */
 162167 static void
 163168 fastscan(void)
 164169 {
 165170         struct symtab *nl;
 166171         int ch, i = 0;
 167172         int nnl = 0;
 168173         usch *cp;
 169174 
 170175         goto run;
 171176         for (;;) {
 172177                 ch = NXTCH();
 173178 xloop:          if (ch == -1)
 174179                         return;
 175180 #ifdef PCC_DEBUG
 176181                 if (dflag>1)
 177182                         printf("fastscan ch %d (%c)\n", ch, ch > 31 ? ch : '@');
 178183 #endif
 179184                 if ((spechr[ch] & C_SPEC) == 0) {
 180185                         PUTCH(ch);
 181186                         continue;
 182187                 }
 183188                 switch (ch) {
 184189                 case EBLOCK:
 185190                 case WARN:
 186191                 case CONC:
 187192                         error("bad char passed");
 188193                         break;
 189194 
 190195                 case '/': /* Comments */
 191196                         if ((ch = inch()) == '/') {
 192197 cppcmt:                         if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
 193198                                 do {
 194199                                         if (Cflag) PUTCH(ch);
 195200                                         ch = inch();
 196201                                 } while (ch != -1 && ch != '\n');
 197202                                 goto xloop;
 198203                         } else if (ch == '*') {
 199204                                 eatcmnt();
 200205                                 continue;
 201206                         } else {
 202207                                 PUTCH('/');
 203208                                 goto xloop;
 204209                         }
 205210                         break;
 206211 
 207212                 case '?'/* trigraphs */
 208213                         if ((ch = chktg()))
 209214                                 goto xloop;
 210215                         PUTCH('?');
 211216                         break;
 212217 
 213218                 case '\\':
 214219                         if ((ch = NXTCH()) == '\n') {
 215220                                 ifiles->lineno++;
 216221                                 continue;
 217222                         }
 218223                         PUTCH('\\');
 219224                         goto xloop;
 220225 
 221226                 case '\n': /* newlines, for pp directives */
 222227                         while (nnl > 0) { PUTCH('\n'); nnl--; ifiles->lineno++; }
 223228 run2:                   ifiles->lineno++;
 224229                         do {
 225230                                 PUTCH(ch);
 226231 run:                            ch = NXTCH();
 227232                                 if (ch == '/') {
 228233                                         ch = NXTCH();
 229234                                         if (ch == '/')
 230235                                                 goto cppcmt;
 231236                                         if (ch == '*') {
 232237                                                 eatcmnt();
 233238                                                 goto run;
 234239                                         }
 235240                                         unch(ch);
 236241                                         ch = '/';
 237242                                 }
 238243                         } while (ch == ' ' || ch == '\t');
 239244                         if (ch == '\\') {
 240245                                 ch = NXTCH();
 241246                                 if (ch == '\n')
 242247                                         goto run2;
 243248                                 unch(ch);
 244249                                 ch = '\\';
 245250                         }
 246251                         if (ch == '#') {
 247252                                 ppdir();
 248253                                 continue;
 249254                         } else if (ch == '%') {
 250255                                 ch = NXTCH();
 251256                                 if (ch == ':') {
 252257                                         ppdir();
 253258                                         continue;
 254259                                 }
 255260                                 unch(ch);
 256261                                 ch = '%';
 257262                         } else if (ch == '?') {
 258263                                 if ((ch = chktg()) == '#') {
 259264                                         ppdir();
 260265                                         continue;
 261266                                 } else if (ch == 0)
 262267                                         ch = '?';
 263268                         }
 264269                         goto xloop;
 265270 
 266271                 case '\"': /* strings */
 267272 str:                    PUTCH(ch);
 268273                         while ((ch = NXTCH()) != '\"') {
 269274                                 if (ch == '\n')
 270275                                         goto xloop;
 271276                                 if (ch == '\\') {
 272277                                         if ((ch = NXTCH()) != '\n') {
 273278                                                 PUTCH('\\');
 274279                                                 PUTCH(ch);
 275280                                         } else
 276281                                                 nnl++;
 277282                                         continue;
 278283                                 }
 279284                                 if (ch == -1)
 280285                                         return;
 281286                                 PUTCH(ch);
 282287                         }
 283288                         PUTCH(ch);
 284289                         break;
 285290 
 286291                 case '.'/* for pp-number */
 287292                         PUTCH(ch);
 288293                         ch = NXTCH();
 289294                         if (ch < '0' || ch > '9')
 290295                                 goto xloop;
 291296                         /* FALLTHROUGH */
 292297                 case '0': case '1': case '2': case '3': case '4':
 293298                 case '5': case '6': case '7': case '8': case '9':
 294299                         do {
 295300                                 PUTCH(ch);
 296301 nxt:                            ch = NXTCH();
 297302                                 if (ch == '\\') {
 298303                                         ch = NXTCH();
 299304                                         if (ch == '\n') {
 300305                                                 nnl++;
 301306                                                 goto nxt;
 302307                                         }
 303308                                         unch(ch);
 304309                                         ch = '\\';
 305310                                 }
 306311                                 if (ch == -1)
 307312                                         return;
 308313                                 if (spechr[ch] & C_EP) {
 309314                                         PUTCH(ch);
 310315                                         ch = NXTCH();
 311316                                         if (ch == '-' || ch == '+')
 312317                                                 continue;
 313318                                         if (ch == -1)
 314319                                                 return;
 315320                                 }
 316321                         } while ((spechr[ch] & C_ID) || (ch == '.'));
 317322                         goto xloop;
 318323 
 319324                 case '\'': /* character literal */
 320325 con:                    PUTCH(ch);
 321326                         if (tflag)
 322327                                 continue; /* character constants ignored */
 323328                         while ((ch = NXTCH()) != '\'') {
 324329                                 if (ch == '\n')
 325330                                         goto xloop;
 326331                                 if (ch == '\\') {
 327332                                         if ((ch = NXTCH()) != '\n') {
 328333                                                 PUTCH('\\');
 329334                                                 PUTCH(ch);
 330335                                         } else
 331336                                                 nnl++;
 332337                                         continue;
 333338                                 }
 334339                                 if (ch == -1)
 335340                                         return;
 336341                                 PUTCH(ch);
 337342                         }
 338343                         PUTCH(ch);
 339344                         break;
 340345 
 341346                 case 'L':
 342347                         ch = NXTCH();
 343348                         if (ch == '\"') {
 344349                                 PUTCH('L');
 345350                                 goto str;
 346351                         }
 347352                         if (ch == '\'') {
 348353                                 PUTCH('L');
 349354                                 goto con;
 350355                         }
 351356                         unch(ch);
 352357                         ch = 'L';
 353358                         /* FALLTHROUGH */
 354359                 default:
 355360                         if ((spechr[ch] & C_ID) == 0)
 356361                                 error("fastscan");
 357362                         if (flslvl) {
 358363                                 while (ch != -1 && (spechr[ch] & C_ID))
 359364                                         ch = NXTCH();
 360365                                 goto xloop;
 361366                         }
 362367                         i = 0;
 363368                         do {
 364369                                 yytext[i++] = (usch)ch;
 365370                                 ch = NXTCH();
 366371                                 if (ch == '\\') {
 367372                                         ch = NXTCH();
 368373                                         if (ch != '\n') {
 369374                                                 unch(ch);
 370375                                                 ch = '\\';
 371376                                         } else {
 372377                                                 putch('\n');
 373378                                                 ifiles->lineno++;
 374379                                                 ch = NXTCH();
 375380                                         }
 376381                                 }
 377382                                 if (ch == -1)
 378383                                         return;
 379384                         } while (spechr[ch] & C_ID);
 380385 
 381386                         yytext[i] = 0;
 382387                         unch(ch);
 383388 
 384389                         cp = stringbuf;
 385390                         if ((nl = lookup(yytext, FIND)) && kfind(nl)) {
 386391                                 putstr(stringbuf);
 387392                         } else
 388393                                 putstr(yytext);
 389394                         stringbuf = cp;
 390395 
 391396                         break;
 392397                 }
 393398         }
 394399 }
 395400 
 396401 int
 397402 sloscan(void)
 398403 {
 399404         int ch;
 400405         int yyp;
 401406 
 402407 zagain:
 403408         yyp = 0;
 404409         ch = inch();
 405410         yytext[yyp++] = (usch)ch;
 406411         switch (ch) {
 407412         case -1:
 408413                 return 0;
 409414         case '\n':
 410415                 /* sloscan() never passes \n, that's up to fastscan() */
 411416                 unch(ch);
 412417                 yytext[yyp] = 0;
 413418                 return ch;
 414419 
 415420         case '\r': /* Ignore CR's */
 416421                 yyp = 0;
 417422                 break;
 418423 
 419424         case '0': case '1': case '2': case '3': case '4': case '5':
 420425         case '6': case '7': case '8': case '9':
 421426                 /* readin a "pp-number" */
 422427 ppnum:          for (;;) {
 423428                         ch = inch();
 424429                         if (ch == -1)
 425430                                 break;
 426431                         if (spechr[ch] & C_EP) {
 427432                                 yytext[yyp++] = (usch)ch;
 428433                                 ch = inch();
 429434                                 if (ch == '-' || ch == '+') {
 430435                                         yytext[yyp++] = (usch)ch;
 431436                                 } else
 432437                                         unch(ch);
 433438                                 continue;
 434439                         }
 435440                         if ((spechr[ch] & C_ID) || ch == '.') {
 436441                                 yytext[yyp++] = (usch)ch;
 437442                                 continue;
 438443                         }
 439444                         break;
 440445                 }
 441446                 unch(ch);
 442447                 yytext[yyp] = 0;
 443448 
 444449                 return NUMBER;
 445450 
 446451         case '\'':
 447452 chlit:          
 448453                 for (;;) {
 449454                         if ((ch = inch()) == '\\') {
 450455                                 yytext[yyp++] = (usch)ch;
 451456                                 yytext[yyp++] = (usch)inch();
 452457                                 continue;
 453458                         } else if (ch == -1 || ch == '\n') {
 454459                                 /* not a constant */
 455460                                 while (yyp > 1)
 456461                                         unch(yytext[--yyp]);
 457462                                 ch = '\'';
 458463                                 goto any;
 459464                         } else
 460465                                 yytext[yyp++] = (usch)ch;
 461466                         if (ch == '\'')
 462467                                 break;
 463468                 }
 464469                 yytext[yyp] = 0;
 465470 
 466471                 return NUMBER;
 467472 
 468473         case ' ':
 469474         case '\t':
 470475                 while ((ch = inch()) == ' ' || ch == '\t')
 471476                         yytext[yyp++] = (usch)ch;
 472477                 unch(ch);
 473478                 yytext[yyp] = 0;
 474479                 return WSPACE;
 475480 
 476481         case '/':
 477482                 if ((ch = inch()) == '/') {
 478483                         do {
 479484                                 yytext[yyp++] = (usch)ch;
 480485                                 ch = inch();
 481486                         } while (ch != -1 && ch != '\n');
 482487                         yytext[yyp] = 0;
 483488                         unch(ch);
 484489                         goto zagain;
 485490                 } else if (ch == '*') {
 486491                         int c, wrn;
 487492                         extern int readmac;
 488493 
 489494                         if (Cflag && !flslvl && readmac) {
 490495                                 unch(ch);
 491496                                 yytext[yyp] = 0;
 492497                                 return CMNT;
 493498                         }
 494499 
 495500                         wrn = 0;
 496501                 more:   while ((c = inch()) != '*') {
 497502                                 if (c == -1)
 498503                                         return 0;       
 499504                                 if (c == '\n')
 500505                                         putch(c), ifiles->lineno++;
 501506                                 else if (c == EBLOCK) {
 502507                                         (void)inch();
 503508                                         (void)inch();
 504509                                 } else if (c == WARN)
 505510                                         wrn = 1;
 506511                         }
 507512                         if ((c = inch()) == -1)
 508513                                 return 0;
 509514                         if (c != '/') {
 510515                                 unch(c);
 511516                                 goto more;
 512517                         }
 513518                         if (!tflag && !Cflag && !flslvl)
 514519                                 unch(' ');
 515520                         if (wrn)
 516521                                 unch(WARN);
 517522                         goto zagain;
 518523                 }
 519524                 unch(ch);
 520525                 ch = '/';
 521526                 goto any;
 522527 
 523528         case '.':
 524529                 if ((ch = inch()) == -1)
 525530                         return 0;
<>526 -                if (isdigit(ch)) {
  531+                if ((spechr[ch] & C_DIGIT)) {
527532                         yytext[yyp++] = (usch)ch;
 528533                         goto ppnum;
 529534                 } else {
 530535                         unch(ch);
 531536                         ch = '.';
 532537                 }
 533538                 goto any;
 534539 
 535540         case '\"':
 536541                 if (tflag && defining)
 537542                         goto any;
 538543         strng:
 539544                 for (;;) {
 540545                         if ((ch = inch()) == '\\') {
 541546                                 yytext[yyp++] = (usch)ch;
 542547                                 yytext[yyp++] = (usch)inch();
 543548                                 continue;
 544549                         } else if (ch == -1) {
 545550                                 break;
 546551                         } else
 547552                                 yytext[yyp++] = (usch)ch;
 548553                         if (ch == '\"')
 549554                                 break;
 550555                 }
 551556                 yytext[yyp] = 0;
 552557                 return STRING;
 553558 
 554559         case 'L':
 555560                 if ((ch = inch()) == '\"' && !tflag) {
 556561                         yytext[yyp++] = (usch)ch;
 557562                         goto strng;
 558563                 } else if (ch == '\'' && !tflag) {
 559564                         yytext[yyp++] = (usch)ch;
 560565                         goto chlit;
 561566                 }
 562567                 unch(ch);
 563568                 /* FALLTHROUGH */
 564569 
 565570         /* Yetch, all identifiers */
 566571         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
 567572         case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
 568573         case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
 569574         case 's': case 't': case 'u': case 'v': case 'w': case 'x':
 570575         case 'y': case 'z':
 571576         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
 572577         case 'G': case 'H': case 'I': case 'J': case 'K':
 573578         case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
 574579         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
 575580         case 'Y': case 'Z':
 576581         case '_': /* {L}({L}|{D})* */
 577582 
 578583                 /* Special hacks */
 579584                 for (;;) { /* get chars */
 580585                         if ((ch = inch()) == -1)
 581586                                 break;
<>582 -                        if (isalpha(ch) || isdigit(ch) || ch == '_') {
  587+                        if ((spechr[ch] & C_ID)) {
583588                                 yytext[yyp++] = (usch)ch;
 584589                         } else {
 585590                                 unch(ch);
 586591                                 break;
 587592                         }
 588593                 }
 589594                 yytext[yyp] = 0; /* need already string */
 590595                 /* end special hacks */
 591596 
 592597                 return IDENT;
 593598         default:
 594599         any:
 595600                 yytext[yyp] = 0;
 596601                 return yytext[0];
 597602 
 598603         } /* endcase */
 599604         goto zagain;
 600605 }
 601606 
 602607 int
 603608 yylex(void)
 604609 {
 605610         static int ifdef, noex;
 606611         struct symtab *nl;
 607612         int ch, c2;
 608613 
 609614         while ((ch = sloscan()) == WSPACE)
 610615                 ;
<>611 -        if (ch < 128 && spechr[ch] & C_2)
  616+        if (ch < 128 && (spechr[ch] & C_2))
612617                 c2 = inpch();
 613618         else
 614619                 c2 = 0;
 615620 
<>616 -#define C2(a,b,c) case a: if (c2 == b) return c; break
617621         switch (ch) {
<>618 -        C2('=', '=', EQ);
 619 -        C2('!', '=', NE);
 620 -        C2('|', '|', OROR);
 621 -        C2('&', '&', ANDAND);
  622+        case '=':
  623+                if (c2 == '=') return EQ;
  624+                break;
  625+        case '!':
  626+                if (c2 == '=') return NE;
  627+                break;
  628+        case '|':
  629+                if (c2 == '|') return OROR;
  630+                break;
  631+        case '&':
  632+                if (c2 == '&') return ANDAND;
  633+                break;
622634         case '<':
 623635                 if (c2 == '<') return LS;
 624636                 if (c2 == '=') return LE;
 625637                 break;
 626638         case '>':
 627639                 if (c2 == '>') return RS;
 628640                 if (c2 == '=') return GE;
 629641                 break;
 630642         case '+':
 631643         case '-':
 632644                 if (ch == c2)
 633645                         error("invalid preprocessor operator %c%c", ch, c2);
 634646                 break;
 635647 
 636648         case '/':
 637649                 if (Cflag == 0 || c2 != '*')
 638650                         break;
 639651                 /* Found comment that need to be skipped */
 640652                 for (;;) {
 641653                         ch = inpch();
 642654                 c1:     if (ch != '*')
 643655                                 continue;
 644656                         if ((ch = inpch()) == '/')
 645657                                 break;
 646658                         goto c1;
 647659                 }
 648660                 return yylex();
 649661 
 650662         case NUMBER:
 651663                 if (yytext[0] == '\'') {
 652664                         yylval.node.op = NUMBER;
 653665                         yylval.node.nd_val = charcon(yytext);
 654666                 } else
 655667                         cvtdig(yytext[0] != '0' ? 10 :
 656668                             yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
 657669                 return NUMBER;
 658670 
 659671         case IDENT:
 660672                 if (strcmp((char *)yytext, "defined") == 0) {
 661673                         ifdef = 1;
 662674                         return DEFINED;
 663675                 }
 664676                 nl = lookup(yytext, FIND);
 665677                 if (ifdef) {
 666678                         yylval.node.nd_val = nl != NULL;
 667679                         ifdef = 0;
 668680                 } else if (nl && noex == 0) {
 669681                         usch *och = stringbuf;
 670682                         int i;
 671683 
 672684                         i = kfind(nl);
 673685                         unch(WARN);
 674686                         if (i)
 675687                                 unpstr(stringbuf);
 676688                         else
 677689                                 unpstr(nl->namep);
 678690                         stringbuf = och;
 679691                         noex = 1;
 680692                         return yylex();
 681693                 } else {
 682694                         yylval.node.nd_val = 0;
 683695                 }
 684696                 yylval.node.op = NUMBER;
 685697                 return NUMBER;
 686698         case WARN:
 687699                 noex = 0;
 688700                 /* FALLTHROUGH */
 689701         case PHOLD:
 690702                 return yylex();
 691703         default:
 692704                 return ch;
 693705         }
 694706         unch(c2);
 695707         return ch;
 696708 }
 697709 
 698710 static int
 699711 inpch(void)
 700712 {
 701713         int len;
 702714 
 703715         if (ifiles->curptr < ifiles->maxread)
 704716                 return *ifiles->curptr++;
 705717 
 706718         if (ifiles->infil == -1)
 707719                 return -1;
 708720         if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0)
 709721                 error("read error on file %s", ifiles->orgfn);
 710722         if (len == 0)
 711723                 return -1;
 712724         ifiles->buffer[len] = 0;
 713725         ifiles->curptr = ifiles->buffer;
 714726         ifiles->maxread = ifiles->buffer + len;
 715727         return inpch();
 716728 }
 717729 
 718730 static int
 719731 inch(void)
 720732 {
 721733         int c;
 722734 
 723735 again:  switch (c = inpch()) {
 724736         case '\\': /* continued lines */
 725737 msdos:          if ((c = inpch()) == '\n') {
 726738                         ifiles->lineno++;
 727739                         putch('\n');
 728740                         goto again;
 729741                 } else if (c == '\r')
 730742                         goto msdos;
 731743                 unch(c);
 732744                 return '\\';
 733745         case '?': /* trigraphs */
 734746                 if ((c = chktg())) {
 735747                         unch(c);
 736748                         goto again;
 737749                 }
 738750                 return '?';
 739751         default:
 740752                 return c;
 741753         }
 742754 }
 743755 
 744756 /*
 745757  * Let the command-line args be faked defines at beginning of file.
 746758  */
 747759 static void
 748760 prinit(struct initar *it, struct includ *ic)
 749761 {
 750762         const char *pre, *post;
 751763         char *a;
 752764 
 753765         if (it->next)
 754766                 prinit(it->next, ic);
 755767         pre = post = NULL; /* XXX gcc */
 756768         switch (it->type) {
 757769         case 'D':
 758770                 pre = "#define ";
 759771                 if ((a = strchr(it->str, '=')) != NULL) {
 760772                         *a = ' ';
 761773                         post = "\n";
 762774                 } else
 763775                         post = " 1\n";
 764776                 break;
 765777         case 'U':
 766778                 pre = "#undef ";
 767779                 post = "\n";
 768780                 break;
 769781         case 'i':
 770782                 pre = "#include \"";
 771783                 post = "\"\n";
 772784                 break;
 773785         default:
 774786                 error("prinit");
 775787         }
 776788         strlcat((char *)ic->buffer, pre, CPPBUF+1);
 777789         strlcat((char *)ic->buffer, it->str, CPPBUF+1);
 778790         if (strlcat((char *)ic->buffer, post, CPPBUF+1) >= CPPBUF+1)
 779791                 error("line exceeds buffer size");
 780792 
 781793         ic->lineno--;
 782794         while (*ic->maxread)
 783795                 ic->maxread++;
 784796 }
 785797 
 786798 /*
 787799  * A new file included.
 788800  * If ifiles == NULL, this is the first file and already opened (stdin).
 789801  * Return 0 on success, -1 if file to be included is not found.
 790802  */
 791803 int
 792804 pushfile(const usch *file, const usch *fn, int idx, void *incs)
 793805 {
 794806         extern struct initar *initar;
 795807         struct includ ibuf;
 796808         struct includ *ic;
 797809         int otrulvl;
 798810 
 799811         ic = &ibuf;
 800812         ic->next = ifiles;
 801813 
 802814         if (file != NULL) {
 803815                 if ((ic->infil = open((const char *)file, O_RDONLY)) < 0)
 804816                         return -1;
 805817                 ic->orgfn = ic->fname = file;
 806818                 if (++inclevel > MAX_INCLEVEL)
 807819                         error("Limit for nested includes exceeded");
 808820         } else {
 809821                 ic->infil = 0;
 810822                 ic->orgfn = ic->fname = (const usch *)"<stdin>";
 811823         }
 812824 #ifndef BUF_STACK
 813825         ic->bbuf = malloc(BBUFSZ);
 814826 #endif
 815827         ic->buffer = ic->bbuf+NAMEMAX;
 816828         ic->curptr = ic->buffer;
 817829         ifiles = ic;
 818830         ic->lineno = 1;
 819831         ic->maxread = ic->curptr;
 820832         ic->idx = idx;
 821833         ic->incs = incs;
 822834         ic->fn = fn;
 823835         prtline();
 824836         if (initar) {
 825837                 int oin = ic->infil;
 826838                 ic->infil = -1;
 827839                 *ic->maxread = 0;
 828840                 prinit(initar, ic);
 829841                 initar = NULL;
 830842                 if (dMflag)
 831843                         xwrite(ofd, ic->buffer, strlen((char *)ic->buffer));
 832844                 fastscan();
 833845                 prtline();
 834846                 ic->infil = oin;
 835847         }
 836848 
 837849         otrulvl = trulvl;
 838850 
 839851         fastscan();
 840852 
 841853         if (otrulvl != trulvl || flslvl)
 842854                 error("unterminated conditional");
 843855 
 844856 #ifndef BUF_STACK
 845857         free(ic->bbuf);
 846858 #endif
 847859         ifiles = ic->next;
 848860         close(ic->infil);
 849861         inclevel--;
 850862         return 0;
 851863 }
 852864 
 853865 /*
 854866  * Print current position to output file.
 855867  */
 856868 void
 857869 prtline(void)
 858870 {
 859871         usch *sb = stringbuf;
 860872 
 861873         if (Mflag) {
 862874                 if (dMflag)
 863875                         return; /* no output */
 864876                 if (ifiles->lineno == 1) {
 865877                         sheap("%s: %s\n", Mfile, ifiles->fname);
 866878                         if (MPflag &&
 867879                             strcmp((const char *)ifiles->fname, (char *)MPfile))
 868880                                 sheap("%s:\n", ifiles->fname);
 869881                         xwrite(ofd, sb, stringbuf - sb);
 870882                 }
 871883         } else if (!Pflag) {
 872884                 sheap("\n# %d \"%s\"", ifiles->lineno, ifiles->fname);
 873885                 if (ifiles->idx == SYSINC)
 874886                         sheap(" 3");
 875887                 sheap("\n");
 876888                 putstr(sb);
 877889         }
 878890         stringbuf = sb;
 879891 }
 880892 
 881893 void
 882894 cunput(int c)
 883895 {
 884896 #ifdef PCC_DEBUG
 885897 //      if (dflag)printf(": '%c'(%d)\n", c > 31 ? c : ' ', c);
 886898 #endif
 887899         unch(c);
 888900 }
 889901 
 890902 static int
 891903 dig2num(int c)
 892904 {
 893905         if (c >= 'a')
 894906                 c = c - 'a' + 10;
 895907         else if (c >= 'A')
 896908                 c = c - 'A' + 10;
 897909         else
 898910                 c = c - '0';
 899911         return c;
 900912 }
 901913 
 902914 /*
 903915  * Convert string numbers to unsigned long long and check overflow.
 904916  */
 905917 static void
 906918 cvtdig(int rad)
 907919 {
 908920         unsigned long long rv = 0;
 909921         unsigned long long rv2 = 0;
 910922         usch *y = yytext;
 911923         int c;
 912924 
 913925         c = *y++;
 914926         if (rad == 16)
 915927                 y++;
<>916 -        while (isxdigit(c)) {
  928+        while ((spechr[c] & C_HEX)) {
917929                 rv = rv * rad + dig2num(c);
 918930                 /* check overflow */
 919931                 if (rv / rad < rv2)
 920932                         error("Constant \"%s\" is out of range", yytext);
 921933                 rv2 = rv;
 922934                 c = *y++;
 923935         }
 924936         y--;
 925937         while (*y == 'l' || *y == 'L')
 926938                 y++;
 927939         yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER;
 928940         yylval.node.nd_uval = rv;
 929941         if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0)
 930942                 yylval.node.op = UNUMBER;
 931943         if (yylval.node.op == NUMBER && yylval.node.nd_val < 0)
 932944                 /* too large for signed, see 6.4.4.1 */
 933945                 error("Constant \"%s\" is out of range", yytext);
 934946 }
 935947 
 936948 static int
 937949 charcon(usch *p)
 938950 {
 939951         int val, c;
 940952 
 941953         p++; /* skip first ' */
 942954         val = 0;
 943955         if (*p++ == '\\') {
 944956                 switch (*p++) {
 945957                 case 'a': val = '\a'; break;
 946958                 case 'b': val = '\b'; break;
 947959                 case 'f': val = '\f'; break;
 948960                 case 'n': val = '\n'; break;
 949961                 case 'r': val = '\r'; break;
 950962                 case 't': val = '\t'; break;
 951963                 case 'v': val = '\v'; break;
 952964                 case '\"': val = '\"'; break;
 953965                 case '\'': val = '\''; break;
 954966                 case '\\': val = '\\'; break;
 955967                 case 'x':
<>956 -                        while (isxdigit(c = *p)) {
  968+                        while ((spechr[c = *p] & C_HEX)) {
957969                                 val = val * 16 + dig2num(c);
 958970                                 p++;
 959971                         }
 960972                         break;
 961973                 case '0': case '1': case '2': case '3': case '4':
 962974                 case '5': case '6': case '7':
 963975                         p--;
<>964 -                        while (isdigit(c = *p)) {
  976+                        while ((spechr[c = *p] & C_DIGIT)) {
<_965977                                 val = val * 8 + (c - '0');
 966978                                 p++;
 967979                         }
 968980                         break;
 969981                 default: val = p[-1];
 970982                 }
 971983 
 972984         } else
 973985                 val = p[-1];
 974986         return val;
 975987 }
 976988 
 977989 static void
 978990 chknl(int ignore)
 979991 {
 980992         int t;
 981993 
 982994         while ((t = sloscan()) == WSPACE)
 983995                 ;
 984996         if (t != '\n') {
 985997                 if (t) {
 986998                         if (ignore) {
 987999                                 warning("newline expected, got \"%s\"", yytext);
 9881000                                 /* ignore rest of line */
 9891001                                 while ((t = sloscan()) && t != '\n')
 9901002                                         ;
 9911003                         }
 9921004                         else
 9931005                                 error("newline expected, got \"%s\"", yytext);
 9941006                 } else {
 9951007                         if (ignore)
 9961008                                 warning("no newline at end of file");
 9971009                         else
 9981010                                 error("no newline at end of file");
 9991011                 }
 10001012         }
 10011013 }
 10021014 
 10031015 static void
 10041016 elsestmt(void)
 10051017 {
 10061018         if (flslvl) {
 10071019                 if (elflvl > trulvl)
 10081020                         ;
 10091021                 else if (--flslvl!=0) {
 10101022                         flslvl++;
 10111023                 } else {
 10121024                         trulvl++;
 10131025                         prtline();
 10141026                 }
 10151027         } else if (trulvl) {
 10161028                 flslvl++;
 10171029                 trulvl--;
 10181030         } else
 10191031                 error("If-less else");
 10201032         if (elslvl==trulvl+flslvl)
 10211033                 error("Too many else");
 10221034         elslvl=trulvl+flslvl;
 10231035         chknl(1);
 10241036 }
 10251037 
 10261038 static void
 10271039 skpln(void)
 10281040 {
 10291041         int ch;
 10301042 
 10311043         /* just ignore the rest of the line */
 10321044         while ((ch = inch()) != -1) {
 10331045                 if (ch == '\n') {
 10341046                         unch('\n');
 10351047                         break;
 10361048                 }
 10371049         }
 10381050         flslvl++;
 10391051 }
 10401052 
 10411053 static void
 10421054 ifdefstmt(void)         
 10431055 {
 10441056         int t;
 10451057 
 10461058         if (flslvl) {
 10471059                 skpln();
 10481060                 return;
 10491061         }
 10501062         do
 10511063                 t = sloscan();
 10521064         while (t == WSPACE);
 10531065         if (t != IDENT)
 10541066                 error("bad #ifdef");
 10551067         if (lookup(yytext, FIND) == NULL) {
 10561068                 putch('\n');
 10571069                 flslvl++;
 10581070         } else
 10591071                 trulvl++;
 10601072         chknl(0);
 10611073 }
 10621074 
 10631075 static void
 10641076 ifndefstmt(void)         
 10651077 {
 10661078         int t;
 10671079 
 10681080         if (flslvl) {
 10691081                 skpln();
 10701082                 return;
 10711083         }
 10721084         do
 10731085                 t = sloscan();
 10741086         while (t == WSPACE);
 10751087         if (t != IDENT)
 10761088                 error("bad #ifndef");
 10771089         if (lookup(yytext, FIND) != NULL) {
 10781090                 putch('\n');
 10791091                 flslvl++;
 10801092         } else
 10811093                 trulvl++;
 10821094         chknl(0);
 10831095 }
 10841096 
 10851097 static void
 10861098 endifstmt(void)         
 10871099 {
 10881100         if (flslvl) {
 10891101                 flslvl--;
 10901102                 if (flslvl == 0) {
 10911103                         putch('\n');
 10921104                         prtline();
 10931105                 }
 10941106         } else if (trulvl)
 10951107                 trulvl--;
 10961108         else
 10971109                 error("If-less endif");
 10981110         if (flslvl == 0)
 10991111                 elflvl = 0;
 11001112         elslvl = 0;
 11011113         chknl(1);
 11021114 }
 11031115 
 11041116 static void
 11051117 ifstmt(void)
 11061118 {
 11071119         if (flslvl == 0) {
 11081120                 if (yyparse() == 0) {
 11091121                         putch('\n');
 11101122                         ++flslvl;
 11111123                 } else
 11121124                         ++trulvl;
 11131125         } else
 11141126                 ++flslvl;
 11151127 }
 11161128 
 11171129 static void
 11181130 elifstmt(void)
 11191131 {
 11201132         if (flslvl == 0)
 11211133                 elflvl = trulvl;
 11221134         if (flslvl) {
 11231135                 if (elflvl > trulvl)
 11241136                         ;
 11251137                 else if (--flslvl!=0)
 11261138                         ++flslvl;
 11271139                 else {
 11281140                         if (yyparse()) {
 11291141                                 ++trulvl;
 11301142                                 prtline();
 11311143                         } else {
 11321144                                 putch('\n');
 11331145                                 ++flslvl;
 11341146                         }
 11351147                 }
 11361148         } else if (trulvl) {
 11371149                 ++flslvl;
 11381150                 --trulvl;
 11391151         } else
 11401152                 error("If-less elif");
 11411153 }
 11421154 
 11431155 /* save line into stringbuf */
 11441156 static usch *
 11451157 savln(void)
 11461158 {
 11471159         int c;
 11481160         usch *cp = stringbuf;
 11491161 
 11501162         while ((c = inch()) != -1) {
 11511163                 if (c == '\n') {
 11521164                         unch(c);
 11531165                         break;
 11541166                 }
 11551167                 savch(c);
 11561168         }
 11571169         savch(0);
 11581170 
 11591171         return cp;
 11601172 }
 11611173 
 11621174 static void
 11631175 cpperror(void)
 11641176 {
 11651177         usch *cp;
 11661178         int c;
 11671179 
 11681180         if (flslvl)
 11691181                 return;
 11701182         c = sloscan();
 11711183         if (c != WSPACE && c != '\n')
 11721184                 error("bad #error");
 11731185         cp = savln();
 11741186         error("#error %s", cp);
 11751187 }
 11761188 
 11771189 static void
 11781190 cppwarning(void)
 11791191 {
 11801192         usch *cp;
 11811193         int c;
 11821194 
 11831195         if (flslvl)
 11841196                 return;
 11851197         c = sloscan();
 11861198         if (c != WSPACE && c != '\n')
 11871199                 error("bad #warning");
 11881200         cp = savln();
 11891201         warning("#warning %s", cp);
 11901202         stringbuf = cp;
 11911203 }
 11921204 
 11931205 static void
 11941206 undefstmt(void)
 11951207 {
 11961208         struct symtab *np;
 11971209 
 11981210         if (flslvl)
 11991211                 return;
 12001212         if (sloscan() != WSPACE || sloscan() != IDENT)
 12011213                 error("bad #undef");
 12021214         if ((np = lookup(yytext, FIND)) != NULL)
 12031215                 np->value = 0;
 12041216         chknl(0);
 12051217 }
 12061218 
 12071219 static void
 12081220 pragmastmt(void)
 12091221 {
 12101222         usch *sb;
 12111223 
 12121224         if (flslvl)
 12131225                 return;
 12141226         if (sloscan() != WSPACE)
 12151227                 error("bad #pragma");
 12161228         sb = stringbuf;
 12171229         savstr((const usch *)"#pragma ");
 12181230         savln();
 12191231         putstr(sb);
 12201232         stringbuf = sb;
 12211233 }
 12221234 
 12231235 int
 12241236 cinput(void)
 12251237 {
 12261238         return inch();
 12271239 }
 12281240 
 12291241 /*
 12301242  * Check for (and convert) trigraphs.
 12311243  */
 12321244 int
 12331245 chktg(void)
 12341246 {
 12351247         int c;
 12361248 
 12371249         if ((c = inpch()) != '?') {
 12381250                 unch(c);
 12391251                 return 0;
 12401252         }
 12411253         switch (c = inpch()) {
 12421254         case '=': c = '#'; break;
 12431255         case '(': c = '['; break;
 12441256         case ')': c = ']'; break;
 12451257         case '<': c = '{'; break;
 12461258         case '>': c = '}'; break;
 12471259         case '/': c = '\\'; break;
 12481260         case '\'': c = '^'; break;
 12491261         case '!': c = '|'; break;
 12501262         case '-': c = '~'; break;
 12511263         default:
 12521264                 unch(c);
 12531265                 unch('?');
 12541266                 c = 0;
 12551267         }
 12561268         return c;
 12571269 }
 12581270 
 12591271 static struct {
 12601272         const char *name;
 12611273         void (*fun)(void);
 12621274 } ppd[] = {
 12631275         { "ifndef", ifndefstmt },
 12641276         { "ifdef", ifdefstmt },
 12651277         { "if", ifstmt },
 12661278         { "include", include },
 12671279         { "else", elsestmt },
 12681280         { "endif", endifstmt },
 12691281         { "error", cpperror },
 12701282         { "warning", cppwarning },
 12711283         { "define", define },
 12721284         { "undef", undefstmt },
 12731285         { "line", line },
 12741286         { "pragma", pragmastmt },
 12751287         { "elif", elifstmt },
 12761288 #ifdef GCC_COMPAT
 12771289         { "include_next", include_next },
 12781290 #endif
 12791291 };
 12801292 
 12811293 /*
 12821294  * Handle a preprocessor directive.
 12831295  */
 12841296 void
 12851297 ppdir(void)
 12861298 {
 12871299         char bp[20];
 12881300         int ch, i;
 12891301 
 12901302         while ((ch = inch()) == ' ' || ch == '\t')
 12911303                 ;
 12921304         if (ch == '\n') { /* empty directive */
 12931305                 unch(ch);
 12941306                 return;
 12951307         }
 12961308         if (ch < 'a' || ch > 'z')
 12971309                 goto out; /* something else, ignore */
 12981310         i = 0;
 12991311         do {
 13001312                 bp[i++] = (usch)ch;
 13011313                 if (i == sizeof(bp)-1)
 13021314                         goto out; /* too long */
 13031315                 ch = inch();
 13041316         } while ((ch >= 'a' && ch <= 'z') || (ch == '_'));
 13051317         unch(ch);
 13061318         bp[i++] = 0;
 13071319 
 13081320         /* got keyword */
 13091321 #define SZ (int)(sizeof(ppd)/sizeof(ppd[0]))
 13101322         for (i = 0; i < SZ; i++)
 13111323                 if (bp[0] == ppd[i].name[0] && strcmp(bp, ppd[i].name) == 0)
 13121324                         break;
 13131325         if (i == SZ)
 13141326                 goto out;
 13151327 
 13161328         /* Found matching keyword */
 13171329         (*ppd[i].fun)();
 13181330         return;
 13191331 
 13201332 out:    while ((ch = inch()) != '\n' && ch != -1)
 13211333                 ;
 13221334         unch('\n');
 13231335 }
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-10-01 20:24 +0200