Quick Search:

Mode

Context

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

Other Diffs

Ignore

Blank Lines Whitespace: Expand:

Diff

1.43
 
1.44
 
MAIN:ragge:20110116115554
 
token.c
_>11 /*      $Id$    */
 22 
 33 /*
 44  * Copyright (c) 2004,2009 Anders Magnusson. All rights reserved.
 55  *
 66  * Redistribution and use in source and binary forms, with or without
 77  * modification, are permitted provided that the following conditions
 88  * are met:
 99  * 1. Redistributions of source code must retain the above copyright
 1010  *    notice, this list of conditions and the following disclaimer.
 1111  * 2. Redistributions in binary form must reproduce the above copyright
 1212  *    notice, this list of conditions and the following disclaimer in the
 1313  *    documentation and/or other materials provided with the distribution.
 1414  *
 1515  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 1616  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 1717  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 1818  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 1919  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 2020  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 2121  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 2222  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 2323  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 2424  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 2525  */
 2626 
 2727 /*
 2828  * Tokenizer for the C preprocessor.
 2929  * There are three main routines:
 3030  *      - fastscan() loops over the input stream searching for magic
 3131  *              characters that may require actions.
 3232  *      - sloscan() tokenize the input stream and returns tokens.
 3333  *              It may recurse into itself during expansion.
 3434  *      - yylex() returns something from the input stream that
 3535  *              is suitable for yacc.
 3636  *
 3737  *      Other functions of common use:
 3838  *      - inpch() returns a raw character from the current input stream.
 3939  *      - inch() is like inpch but \\n and trigraphs are expanded.
 4040  *      - unch() pushes back a character to the input stream.
 4141  */
 4242 
 4343 #include "config.h"
 4444 
 4545 #include <stdlib.h>
 4646 #include <string.h>
 4747 #include <ctype.h>
 4848 #ifdef HAVE_UNISTD_H
 4949 #include <unistd.h>
 5050 #endif
 5151 #include <fcntl.h>
 5252 #include <errno.h>
 5353 
 5454 #include "compat.h"
 5555 #include "cpp.h"
 5656 #include "y.tab.h"
 5757 
 5858 static void cvtdig(int rad);
 5959 static int charcon(usch *);
 6060 static void elsestmt(void);
 6161 static void ifdefstmt(void);
 6262 static void ifndefstmt(void);
 6363 static void endifstmt(void);
 6464 static void ifstmt(void);
 6565 static void cpperror(void);
 6666 static void pragmastmt(void);
 6767 static void undefstmt(void);
 6868 static void cppwarning(void);
 6969 static void elifstmt(void);
 7070 static void badop(const char *);
 7171 static int chktg(void);
 7272 static void ppdir(void);
 7373 void  include(void);
 7474 void  include_next(void);
 7575 void  define(void);
 7676 static int inpch(void);
 7777 
 7878 extern int yyget_lineno (void);
 7979 extern void yyset_lineno (int);
 8080 
 8181 static int inch(void);
 8282 
 8383 int inif;
 8484 extern int dflag;
 8585 
 8686 #define PUTCH(ch) if (!flslvl) putch(ch)
 8787 /* protection against recursion in #include */
 8888 #define MAX_INCLEVEL    100
 8989 static int inclevel;
 9090 
 9191 /* get next character unaltered */
 9292 #define NXTCH() (ifiles->curptr < ifiles->maxread ? *ifiles->curptr++ : inpch())
 9393 
<>94 -#ifdef YYTEXT_POINTER
 95 -static char buf[CPPBUF];
 96 -char *yytext = buf;
 97 -#else
 98 -char yytext[CPPBUF];
 99 -#endif
  94+usch yytext[CPPBUF];
10095 
 10196 char spechr[256] = {
 10297         0,      0,      0,      0,      C_SPECC_SPEC0,      0,
 10398         0,      C_WSNLC_SPEC|C_WSNL,  0,
 10499         0,      C_WSNL0,      0,
 105100         0,      0,      0,      0,      0,      0,      0,      0,
 106101         0,      0,      0,      0,      0,      0,      0,      0,
 107102 
 108103         C_WSNLC_2,    C_SPEC0,      0,      0,      C_2,    C_SPEC,
 109104         0,      0,      0,      C_2,    0,      C_2,    0,      C_SPEC|C_2,
 110105         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 111106         C_I,    C_I,    0,      0,      C_2,    C_2,    C_2,    C_SPEC,
 112107 
 113108         0,      C_I,    C_I,    C_I,    C_I,    C_I|C_EP, C_I,  C_I,
 114109         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 115110         C_I|C_EP, C_I,  C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 116111         C_I,    C_I,    C_I,    0,      C_I,    0,      0,      C_I,
 117112 
 118113         0,      C_I,    C_I,    C_I,    C_I,    C_I|C_EP, C_I,  C_I,
 119114         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 120115         C_I|C_EP, C_I,  C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 121116         C_I,    C_I,    C_I,    0,      C_2,    0,      0,      0,
 122117 
 123118 };
 124119 
 125120 /*
 126121  * No-replacement array.  If a macro is found and exists in this array
 127122  * then no replacement shall occur.  This is a stack.
 128123  */
 129124 struct symtab *norep[RECMAX];   /* Symbol table index table */
 130125 int norepptr = 1;                       /* Top of index table */
 131126 unsigned char bptr[RECMAX];     /* currently active noexpand macro stack */
 132127 int bidx;                       /* Top of bptr stack */
 133128 
 134129 static void
 135130 unch(int c)
 136131 {
 137132                 
 138133         --ifiles->curptr;
 139134         if (ifiles->curptr < ifiles->bbuf)
 140135                 error("pushback buffer full");
 141136         *ifiles->curptr = (usch)c;
 142137 }
 143138 
 144139 /*
 145140  * Scan quickly the input file searching for:
 146141  *      - '#' directives
 147142  *      - keywords (if not flslvl)
 148143  *      - comments
 149144  *
 150145  *      Handle strings, numbers and trigraphs with care.
 151146  *      Only data from pp files are scanned here, never any rescans.
 152147  *      TODO: Only print out strings before calling other functions.
 153148  */
 154149 static void
 155150 fastscan(void)
 156151 {
 157152         struct symtab *nl;
 158153         int ch, i, ccnt, onemore;
 159154 
 160155         goto run;
 161156         for (;;) {
 162157                 ch = NXTCH();
 163158 xloop:          if (ch == -1)
 164159                         return;
 165160                 if (dflag>1)
 166161                         printf("fastscan ch %d (%c)\n", ch, ch > 31 ? ch : '@');
 167162                 if ((spechr[ch] & C_SPEC) == 0) {
 168163                         PUTCH(ch);
 169164                         continue;
 170165                 }
 171166                 switch (ch) {
<>172 -                case EXP:
 173 -                case NEX:
  167+                case EBLOCK:
174168                 case WARN:
 175169                 case CONC:
 176170                         error("bad char passed");
 177171                         break;
 178172 
 179173                 case '/': /* Comments */
 180174                         if ((ch = inch()) == '/') {
 181175                                 if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
 182176                                 do {
 183177                                         if (Cflag) PUTCH(ch);
 184178                                         ch = inch();
 185179                                 } while (ch != -1 && ch != '\n');
 186180                                 goto xloop;
 187181                         } else if (ch == '*') {
 188182                                 if (Cflag) { PUTCH('/'); PUTCH('*'); }
 189183                                 for (;;) {
 190184                                         ch = inch();
 191185                                         if (ch == '\n') {
 192186                                                 ifiles->lineno++;
 193187                                                 PUTCH('\n');
 194188                                         }
 195189                                         if (ch == -1)
 196190                                                 return;
 197191                                         if (ch == '*') {
 198192                                                 ch = inch();
 199193                                                 if (ch == '/') {
 200194                                                         if (Cflag) {
 201195                                                                 PUTCH('*');
 202196                                                                 PUTCH('/');
 203197                                                         } else
 204198                                                                 PUTCH(' ');
 205199                                                         break;
 206200                                                 }
 207201                                                 unch(ch);
 208202                                                 ch = '*';
 209203                                         }
 210204                                         if (Cflag) PUTCH(ch);
 211205                                 }
 212206                         } else {
 213207                                 PUTCH('/');
 214208                                 goto xloop;
 215209                         }
 216210                         break;
 217211 
 218212                 case '?'/* trigraphs */
 219213                         if ((ch = chktg()))
 220214                                 goto xloop;
 221215                         PUTCH('?');
 222216                         break;
 223217 
 224218                 case '\\':
 225219                         if ((ch = NXTCH()) == '\n') {
 226220                                 ifiles->lineno++;
 227221                                 continue;
 228222                         } else {
 229223                                 PUTCH('\\');
 230224                         }
 231225                         goto xloop;
 232226 
 233227                 case '\n': /* newlines, for pp directives */
 234228                         ifiles->lineno++;
 235229                         do {
 236230                                 PUTCH(ch);
 237231 run:                            ch = NXTCH();
 238232                         } while (ch == ' ' || ch == '\t');
 239233                         if (ch == '#') {
 240234                                 ppdir();
 241235                                 continue;
 242236                         } else if (ch == '%') {
 243237                                 ch = NXTCH();
 244238                                 if (ch == ':') {
 245239                                         ppdir();
 246240                                         continue;
 247241                                 } else {
 248242                                         unch(ch);
 249243                                         ch = '%';
 250244                                 }
 251245                         }
 252246                         goto xloop;
 253247 
 254248                 case '\"': /* strings */
 255249 str:                    PUTCH(ch);
 256250                         while ((ch = inch()) != '\"') {
<>257 -                                if (ch == EXP)
 258 -                                        doexp();
 259 -                                else if (ch == NEX)
 260 -                                        donex();
 261 -                                else if (ch != CONC) /* XXX ??? */
262251                                         PUTCH(ch);
 263252                                 if (ch == '\\') {
 264253                                         ch = inch();
 265254                                         PUTCH(ch);
 266255                                 }
 267256                                 if (ch < 0)
 268257                                         return;
 269258                         }
 270259                         PUTCH(ch);
 271260                         break;
 272261 
 273262                 case '.'/* for pp-number */
 274263                         PUTCH(ch);
 275264                         ch = NXTCH();
 276265                         if (ch < '0' || ch > '9')
 277266                                 goto xloop;
 278267                         /* FALLTHROUGH */
 279268                 case '0': case '1': case '2': case '3': case '4':
 280269                 case '5': case '6': case '7': case '8': case '9':
 281270                         do {
 282271                                 PUTCH(ch);
 283272                                 ch = NXTCH();
 284273                                 if (spechr[ch] & C_EP) {
 285274                                         PUTCH(ch);
 286275                                         ch = NXTCH();
 287276                                         if (ch == '-' || ch == '+')
 288277                                                 continue;
 289278                                 }
 290279                         } while ((spechr[ch] & C_ID) || (ch == '.'));
 291280                         goto xloop;
 292281 
 293282                 case '\'': /* character literal */
 294283 con:                    PUTCH(ch);
 295284                         if (tflag)
 296285                                 continue; /* character constants ignored */
 297286                         while ((ch = NXTCH()) != '\'') {
 298287                                 PUTCH(ch);
 299288                                 if (ch == '\\') {
 300289                                         ch = NXTCH();
 301290                                         PUTCH(ch);
 302291                                 } else if (ch < 0)
 303292                                         return;
 304293                                 else if (ch == '\n')
 305294                                         goto xloop;
 306295                         }
 307296                         PUTCH(ch);
 308297                         break;
 309298 
 310299                 case 'L':
 311300                         ch = NXTCH();
 312301                         if (ch == '\"') {
 313302                                 PUTCH('L');
 314303                                 goto str;
 315304                         }
 316305                         if (ch == '\'') {
 317306                                 PUTCH('L');
 318307                                 goto con;
 319308                         }
 320309                         unch(ch);
 321310                         ch = 'L';
 322311                         /* FALLTHROUGH */
 323312                 default:
 324313                         if ((spechr[ch] & C_ID) == 0)
 325314                                 error("fastscan");
 326315                         if (flslvl) {
 327316                                 while (spechr[ch] & C_ID)
 328317                                         ch = NXTCH();
 329318                                 goto xloop;
 330319                         }
 331320                         onemore = i = ccnt = 0;
 332321                         do {
 333322                                 yytext[i++] = (usch)ch;
 334323                                 ch = NXTCH();
 335324                                 if (ch == '\\') {
 336325                                         ch = NXTCH();
 337326                                         if (ch != '\n') {
 338327                                                 unch('\n');
 339328                                                 ch = '\\';
 340329                                         } else {
 341330                                                 ifiles->lineno++;
 342331                                                 ch = NXTCH();
 343332                                         }
 344333                                 }
 345334                                 if (ch < 0)
 346335                                         return;
 347336                         } while (spechr[ch] & C_ID);
 348337 
 349338                         yytext[i] = 0;
 350339                         unch(ch);
 351340 
 352341                         if ((nl = lookup((usch *)yytext, FIND)) && kfind(nl)) {
 353342                                 putstr(stringbuf);
 354343                         } else
 355344                                 putstr((usch *)yytext);
 356345 
 357346                         break;
 358347                 }
 359348         }
 360349 }
 361350 
 362351 int
 363352 sloscan()
 364353 {
 365354         int ch;
 366355         int yyp;
 367356 
 368357 zagain:
 369358         yyp = 0;
 370359         ch = inch();
 371360         yytext[yyp++] = (usch)ch;
 372361         switch (ch) {
 373362         case -1:
 374363                 return 0;
 375364         case '\n':
 376365                 /* sloscan() never passes \n, that's up to fastscan() */
 377366                 unch(ch);
 378367                 goto yyret;
 379368 
 380369         case '\r': /* Ignore CR's */
 381370                 yyp = 0;
 382371                 break;
 383372 
 384373         case '0': case '1': case '2': case '3': case '4': case '5':
 385374         case '6': case '7': case '8': case '9':
 386375                 /* readin a "pp-number" */
 387376 ppnum:          for (;;) {
 388377                         ch = inch();
 389378                         if (spechr[ch] & C_EP) {
 390379                                 yytext[yyp++] = (usch)ch;
 391380                                 ch = inch();
 392381                                 if (ch == '-' || ch == '+') {
 393382                                         yytext[yyp++] = (usch)ch;
 394383                                 } else
 395384                                         unch(ch);
 396385                                 continue;
 397386                         }
 398387                         if ((spechr[ch] & C_ID) || ch == '.') {
 399388                                 yytext[yyp++] = (usch)ch;
 400389                                 continue;
 401390                         }
 402391                         break;
 403392                 }
 404393                 unch(ch);
 405394                 yytext[yyp] = 0;
 406395 
 407396                 return NUMBER;
 408397 
 409398         case '\'':
 410399 chlit:          
 411400                 for (;;) {
 412401                         if ((ch = inch()) == '\\') {
 413402                                 yytext[yyp++] = (usch)ch;
 414403                                 yytext[yyp++] = (usch)inch();
 415404                                 continue;
 416405                         } else if (ch == '\n') {
 417406                                 /* not a constant */
 418407                                 while (yyp > 1)
 419408                                         unch(yytext[--yyp]);
 420409                                 ch = '\'';
 421410                                 goto any;
 422411                         } else
 423412                                 yytext[yyp++] = (usch)ch;
 424413                         if (ch == '\'')
 425414                                 break;
 426415                 }
 427416                 yytext[yyp] = 0;
 428417 
 429418                 return (NUMBER);
 430419 
 431420         case ' ':
 432421         case '\t':
 433422                 while ((ch = inch()) == ' ' || ch == '\t')
 434423                         yytext[yyp++] = (usch)ch;
 435424                 unch(ch);
 436425                 yytext[yyp] = 0;
 437426                 return(WSPACE);
 438427 
 439428         case '/':
 440429                 if ((ch = inch()) == '/') {
 441430                         do {
 442431                                 yytext[yyp++] = (usch)ch;
 443432                                 ch = inch();
 444433                         } while (ch && ch != '\n');
 445434                         yytext[yyp] = 0;
 446435                         unch(ch);
 447436                         goto zagain;
 448437                 } else if (ch == '*') {
 449438                         int c, wrn;
 450439                         extern int readmac;
 451440 
 452441                         if (Cflag && !flslvl && readmac) {
 453442                                 unch(ch);
 454443                                 yytext[yyp] = 0;
 455444                                 return CMNT;
 456445                         }
 457446 
 458447                         wrn = 0;
 459448                 more:   while ((c = inch()) && c != '*') {
 460449                                 if (c == '\n')
 461450                                         putch(c), ifiles->lineno++;
 462451                                 else if (c == 1) /* WARN */
 463452                                         wrn = 1;
 464453                         }
 465454                         if (c == 0)
 466455                                 return 0;
 467456                         if ((c = inch()) && c != '/') {
 468457                                 unch(c);
 469458                                 goto more;
 470459                         }
 471460                         if (c == 0)
 472461                                 return 0;
 473462                         if (!tflag && !Cflag && !flslvl)
 474463                                 unch(' ');
 475464                         if (wrn)
 476465                                 unch(1);
 477466                         goto zagain;
 478467                 }
 479468                 unch(ch);
 480469                 ch = '/';
 481470                 goto any;
 482471 
 483472         case '.':
 484473                 ch = inch();
 485474                 if (isdigit(ch)) {
 486475                         yytext[yyp++] = (usch)ch;
 487476                         goto ppnum;
 488477                 } else {
 489478                         unch(ch);
 490479                         ch = '.';
 491480                 }
 492481                 goto any;
 493482 
 494483         case '\"':
 495484                 if (tflag)
 496485                         goto any;
 497486         strng:
 498487                 for (;;) {
 499488                         if ((ch = inch()) == '\\') {
 500489                                 yytext[yyp++] = (usch)ch;
 501490                                 yytext[yyp++] = (usch)inch();
 502491                                 continue;
 503492                         } else
 504493                                 yytext[yyp++] = (usch)ch;
 505494                         if (ch == '\"')
 506495                                 break;
 507496                 }
 508497                 yytext[yyp] = 0;
 509498                 return(STRING);
 510499 
 511500         case 'L':
 512501                 if ((ch = inch()) == '\"' && !tflag) {
 513502                         yytext[yyp++] = (usch)ch;
 514503                         goto strng;
 515504                 } else if (ch == '\'' && !tflag) {
 516505                         yytext[yyp++] = (usch)ch;
 517506                         goto chlit;
 518507                 }
 519508                 unch(ch);
 520509                 /* FALLTHROUGH */
 521510 
 522511         /* Yetch, all identifiers */
 523512         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
 524513         case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
 525514         case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
 526515         case 's': case 't': case 'u': case 'v': case 'w': case 'x':
 527516         case 'y': case 'z':
 528517         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
 529518         case 'G': case 'H': case 'I': case 'J': case 'K':
 530519         case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
 531520         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
 532521         case 'Y': case 'Z':
 533522         case '_': /* {L}({L}|{D})* */
 534523 
 535524                 /* Special hacks */
 536525                 for (;;) { /* get chars */
 537526                         ch = inch();
 538527                         if (isalpha(ch) || isdigit(ch) || ch == '_') {
 539528                                 yytext[yyp++] = (usch)ch;
 540529                         } else {
 541530                                 unch(ch);
 542531                                 break;
 543532                         }
 544533                 }
 545534                 yytext[yyp] = 0; /* need already string */
 546535                 /* end special hacks */
 547536 
 548537                 return IDENT;
 549538         default:
 550539         any:
 551540                 yytext[yyp] = 0;
 552541                 return yytext[0];
 553542 
 554543         } /* endcase */
 555544         goto zagain;
 556545 
 557546 yyret:
 558547         yytext[yyp] = 0;
 559548         return ch;
 560549 }
 561550 
 562551 int
 563552 yylex()
 564553 {
 565554         static int ifdef, noex;
 566555         struct symtab *nl;
 567556         int ch, c2;
 568557 
 569558         while ((ch = sloscan()) == WSPACE)
 570559                 ;
 571560         if (ch < 128 && spechr[ch] & C_2)
 572561                 c2 = inpch();
 573562         else
 574563                 c2 = 0;
 575564 
 576565 #define C2(a,b,c) case a: if (c2 == b) return c; break
 577566         switch (ch) {
 578567         C2('=', '=', EQ);
 579568         C2('!', '=', NE);
 580569         C2('|', '|', OROR);
 581570         C2('&', '&', ANDAND);
 582571         case '<':
 583572                 if (c2 == '<') return LS;
 584573                 if (c2 == '=') return LE;
 585574                 break;
 586575         case '>':
 587576                 if (c2 == '>') return RS;
 588577                 if (c2 == '=') return GE;
 589578                 break;
 590579         case '+':
 591580         case '-':
 592581                 if (ch == c2)
 593582                         badop("");
 594583                 break;
 595584 
 596585         case '/':
 597586                 if (Cflag == 0 || c2 != '*')
 598587                         break;
 599588                 /* Found comment that need to be skipped */
 600589                 for (;;) {
 601590                         ch = inpch();
 602591                 c1:     if (ch != '*')
 603592                                 continue;
 604593                         if ((ch = inpch()) == '/')
 605594                                 break;
 606595                         goto c1;
 607596                 }
 608597                 return yylex();
 609598 
 610599         case NUMBER:
 611600                 if (yytext[0] == '\'') {
 612601                         yylval.node.op = NUMBER;
 613602                         yylval.node.nd_val = charcon((usch *)yytext);
 614603                 } else
 615604                         cvtdig(yytext[0] != '0' ? 10 :
 616605                             yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
 617606                 return NUMBER;
 618607 
 619608         case IDENT:
<>620 -                if (strcmp(yytext, "defined") == 0) {
  609+                if (strcmp((char *)yytext, "defined") == 0) {
621610                         ifdef = 1;
 622611                         return DEFINED;
 623612                 }
 624613                 nl = lookup((usch *)yytext, FIND);
 625614                 if (ifdef) {
 626615                         yylval.node.nd_val = nl != NULL;
 627616                         ifdef = 0;
 628617                 } else if (nl && noex == 0) {
 629618                         usch *och = stringbuf;
 630619                         int i;
 631620 
 632621                         i = kfind(nl);
 633622                         unch(WARN);
 634623                         if (i)
 635624                                 unpstr(stringbuf);
 636625                         else
 637626                                 unpstr(nl->namep);
 638627                         stringbuf = och;
 639628                         noex = 1;
 640629                         return yylex();
 641630                 } else {
 642631                         yylval.node.nd_val = 0;
 643632                 }
 644633                 yylval.node.op = NUMBER;
 645634                 return NUMBER;
 646635         case WARN:
 647636                 noex = 0;
 648637                 return yylex();
 649638         default:
 650639                 return ch;
 651640         }
 652641         unch(c2);
 653642         return ch;
 654643 }
 655644 
 656645 usch *yyp, yybuf[CPPBUF];
 657646 
 658647 int yywrap(void);
 659648 
 660649 static int
 661650 inpch(void)
 662651 {
 663652         int len;
 664653 
 665654         if (ifiles->curptr < ifiles->maxread)
 666655                 return *ifiles->curptr++;
 667656 
 668657         if (ifiles->infil == -1)
 669658                 return -1;
 670659         if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0)
 671660                 error("read error on file %s", ifiles->orgfn);
 672661         if (len == 0)
 673662                 return -1;
 674663         ifiles->curptr = ifiles->buffer;
 675664         ifiles->maxread = ifiles->buffer + len;
 676665         return inpch();
 677666 }
 678667 
 679668 static int
 680669 inch(void)
 681670 {
 682671         int c;
 683672 
 684673 again:  switch (c = inpch()) {
 685674         case '\\': /* continued lines */
 686675 msdos:          if ((c = inpch()) == '\n') {
 687676                         ifiles->lineno++;
 688677                         goto again;
 689678                 } else if (c == '\r')
 690679                         goto msdos;
 691680                 unch(c);
 692681                 return '\\';
 693682         case '?': /* trigraphs */
 694683                 if ((c = chktg())) {
 695684                         unch(c);
 696685                         goto again;
 697686                 }
 698687                 return '?';
 699688         default:
 700689                 return c;
 701690         }
 702691 }
 703692 
 704693 /*
 705694  * Let the command-line args be faked defines at beginning of file.
 706695  */
 707696 static void
 708697 prinit(struct initar *it, struct includ *ic)
 709698 {
 710699         const char *pre, *post;
 711700         char *a;
 712701 
 713702         if (it->next)
 714703                 prinit(it->next, ic);
 715704         pre = post = NULL; /* XXX gcc */
 716705         switch (it->type) {
 717706         case 'D':
 718707                 pre = "#define ";
 719708                 if ((a = strchr(it->str, '=')) != NULL) {
 720709                         *a = ' ';
 721710                         post = "\n";
 722711                 } else
 723712                         post = " 1\n";
 724713                 break;
 725714         case 'U':
 726715                 pre = "#undef ";
 727716                 post = "\n";
 728717                 break;
 729718         case 'i':
 730719                 pre = "#include \"";
 731720                 post = "\"\n";
 732721                 break;
 733722         default:
 734723                 error("prinit");
 735724         }
 736725         strlcat((char *)ic->buffer, pre, CPPBUF+1);
 737726         strlcat((char *)ic->buffer, it->str, CPPBUF+1);
 738727         if (strlcat((char *)ic->buffer, post, CPPBUF+1) >= CPPBUF+1)
 739728                 error("line exceeds buffer size");
 740729 
 741730         ic->lineno--;
 742731         while (*ic->maxread)
 743732                 ic->maxread++;
 744733 }
 745734 
 746735 /*
 747736  * A new file included.
 748737  * If ifiles == NULL, this is the first file and already opened (stdin).
 749738  * Return 0 on success, -1 if file to be included is not found.
 750739  */
 751740 int
 752741 pushfile(const usch *file, const usch *fn, int idx, void *incs)
 753742 {
 754743         extern struct initar *initar;
 755744         struct includ ibuf;
 756745         struct includ *ic;
 757746         int otrulvl;
 758747 
 759748         ic = &ibuf;
 760749         ic->next = ifiles;
 761750 
 762751         if (file != NULL) {
 763752                 if ((ic->infil = open((const char *)file, O_RDONLY)) < 0)
 764753                         return -1;
 765754                 ic->orgfn = ic->fname = file;
 766755                 if (++inclevel > MAX_INCLEVEL)
 767756                         error("Limit for nested includes exceeded");
 768757         } else {
 769758                 ic->infil = 0;
 770759                 ic->orgfn = ic->fname = (const usch *)"<stdin>";
 771760         }
 772761         ic->buffer = ic->bbuf+NAMEMAX;
 773762         ic->curptr = ic->buffer;
 774763         ifiles = ic;
 775764         ic->lineno = 1;
 776765         ic->maxread = ic->curptr;
 777766         ic->idx = idx;
 778767         ic->incs = incs;
 779768         ic->fn = fn;
 780769         prtline();
 781770         if (initar) {
 782771                 int oin = ic->infil;
 783772                 ic->infil = -1;
 784773                 *ic->maxread = 0;
 785774                 prinit(initar, ic);
 786775                 initar = NULL;
 787776                 if (dMflag)
 788777                         write(ofd, ic->buffer, strlen((char *)ic->buffer));
 789778                 fastscan();
 790779                 prtline();
 791780                 ic->infil = oin;
 792781         }
 793782 
 794783         otrulvl = trulvl;
 795784 
 796785         fastscan();
 797786 
 798787         if (otrulvl != trulvl || flslvl)
 799788                 error("unterminated conditional");
 800789 
 801790         ifiles = ic->next;
 802791         close(ic->infil);
 803792         inclevel--;
 804793         return 0;
 805794 }
 806795 
 807796 /*
 808797  * Print current position to output file.
 809798  */
 810799 void
 811800 prtline()
 812801 {
 813802         usch *s, *os = stringbuf;
 814803 
 815804         if (Mflag) {
 816805                 if (dMflag)
 817806                         return; /* no output */
 818807                 if (ifiles->lineno == 1) {
 819808                         s = sheap("%s: %s\n", Mfile, ifiles->fname);
 820809                         write(ofd, s, strlen((char *)s));
 821810                 }
 822811         } else if (!Pflag)
 823812                 putstr(sheap("\n# %d \"%s\"\n", ifiles->lineno, ifiles->fname));
 824813         stringbuf = os;
 825814 }
 826815 
 827816 void
 828817 cunput(int c)
 829818 {
 830819 #ifdef CPP_DEBUG
 831820 //      extern int dflag;
 832821 //      if (dflag)printf(": '%c'(%d)\n", c > 31 ? c : ' ', c);
 833822 #endif
 834823 #if 0
 835824 if (c == 10) {
 836825         printf("c == 10!!!\n");
 837826 }
 838827 #endif
 839828         unch(c);
 840829 }
 841830 
 842831 int yywrap(void) { return 1; }
 843832 
 844833 static int
 845834 dig2num(int c)
 846835 {
 847836         if (c >= 'a')
 848837                 c = c - 'a' + 10;
 849838         else if (c >= 'A')
 850839                 c = c - 'A' + 10;
 851840         else
 852841                 c = c - '0';
 853842         return c;
 854843 }
 855844 
 856845 /*
 857846  * Convert string numbers to unsigned long long and check overflow.
 858847  */
 859848 static void
 860849 cvtdig(int rad)
 861850 {
 862851         unsigned long long rv = 0;
 863852         unsigned long long rv2 = 0;
<>864 -        char *y = yytext;
  853+        usch *y = yytext;
865854         int c;
 866855 
 867856         c = *y++;
 868857         if (rad == 16)
 869858                 y++;
 870859         while (isxdigit(c)) {
 871860                 rv = rv * rad + dig2num(c);
 872861                 /* check overflow */
 873862                 if (rv / rad < rv2)
 874863                         error("Constant \"%s\" is out of range", yytext);
 875864                 rv2 = rv;
 876865                 c = *y++;
 877866         }
 878867         y--;
 879868         while (*y == 'l' || *y == 'L')
 880869                 y++;
 881870         yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER;
 882871         yylval.node.nd_uval = rv;
 883872         if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0)
 884873                 yylval.node.op = UNUMBER;
 885874         if (yylval.node.op == NUMBER && yylval.node.nd_val < 0)
 886875                 /* too large for signed, see 6.4.4.1 */
 887876                 error("Constant \"%s\" is out of range", yytext);
 888877 }
 889878 
 890879 static int
 891880 charcon(usch *p)
 892881 {
 893882         int val, c;
 894883 
 895884         p++; /* skip first ' */
 896885         val = 0;
 897886         if (*p++ == '\\') {
 898887                 switch (*p++) {
 899888                 case 'a': val = '\a'; break;
 900889                 case 'b': val = '\b'; break;
 901890                 case 'f': val = '\f'; break;
 902891                 case 'n': val = '\n'; break;
 903892                 case 'r': val = '\r'; break;
 904893                 case 't': val = '\t'; break;
 905894                 case 'v': val = '\v'; break;
 906895                 case '\"': val = '\"'; break;
 907896                 case '\'': val = '\''; break;
 908897                 case '\\': val = '\\'; break;
 909898                 case 'x':
 910899                         while (isxdigit(c = *p)) {
 911900                                 val = val * 16 + dig2num(c);
 912901                                 p++;
 913902                         }
 914903                         break;
 915904                 case '0': case '1': case '2': case '3': case '4':
 916905                 case '5': case '6': case '7':
 917906                         p--;
 918907                         while (isdigit(c = *p)) {
 919908                                 val = val * 8 + (c - '0');
 920909                                 p++;
 921910                         }
 922911                         break;
 923912                 default: val = p[-1];
 924913                 }
 925914 
 926915         } else
 927916                 val = p[-1];
 928917         return val;
 929918 }
 930919 
 931920 static void
 932921 chknl(int ignore)
 933922 {
 934923         int t;
 935924 
 936925         while ((t = sloscan()) == WSPACE)
 937926                 ;
 938927         if (t != '\n') {
 939928                 if (ignore) {
 940929                         warning("newline expected, got \"%s\"", yytext);
 941930                         /* ignore rest of line */
 942931                         while ((t = sloscan()) && t != '\n')
 943932                                 ;
 944933                 }
 945934                 else
 946935                         error("newline expected, got \"%s\"", yytext);
 947936         }
 948937 }
 949938 
 950939 static void
 951940 elsestmt(void)
 952941 {
 953942         if (flslvl) {
 954943                 if (elflvl > trulvl)
 955944                         ;
 956945                 else if (--flslvl!=0) {
 957946                         flslvl++;
 958947                 } else {
 959948                         trulvl++;
 960949                         prtline();
 961950                 }
 962951         } else if (trulvl) {
 963952                 flslvl++;
 964953                 trulvl--;
 965954         } else
 966955                 error("If-less else");
 967956         if (elslvl==trulvl+flslvl)
 968957                 error("Too many else");
 969958         elslvl=trulvl+flslvl;
 970959         chknl(1);
 971960 }
 972961 
 973962 static void
 974963 skpln(void)
 975964 {
 976965         /* just ignore the rest of the line */
 977966         while (inch() != '\n')
 978967                 ;
 979968         unch('\n');
 980969         flslvl++;
 981970 }
 982971 
 983972 static void
 984973 ifdefstmt(void)         
 985974 {
 986975         int t;
 987976 
 988977         if (flslvl) {
 989978                 skpln();
 990979                 return;
 991980         }
 992981         do
 993982                 t = sloscan();
 994983         while (t == WSPACE);
 995984         if (t != IDENT)
 996985                 error("bad ifdef");
 997986         if (lookup((usch *)yytext, FIND) == 0) {
 998987                 putch('\n');
 999988                 flslvl++;
 1000989         } else
 1001990                 trulvl++;
 1002991         chknl(0);
 1003992 }
 1004993 
 1005994 static void
 1006995 ifndefstmt(void)         
 1007996 {
 1008997         int t;
 1009998 
 1010999         if (flslvl) {
 10111000                 skpln();
 10121001                 return;
 10131002         }
 10141003         do
 10151004                 t = sloscan();
 10161005         while (t == WSPACE);
 10171006         if (t != IDENT)
 10181007                 error("bad ifndef");
 10191008         if (lookup((usch *)yytext, FIND) != 0) {
 10201009                 putch('\n');
 10211010                 flslvl++;
 10221011         } else
 10231012                 trulvl++;
 10241013         chknl(0);
 10251014 }
 10261015 
 10271016 static void
 10281017 endifstmt(void)         
 10291018 {
 10301019         if (flslvl) {
 10311020                 flslvl--;
 10321021                 if (flslvl == 0) {
 10331022                         putch('\n');
 10341023                         prtline();
 10351024                 }
 10361025         } else if (trulvl)
 10371026                 trulvl--;
 10381027         else
 10391028                 error("If-less endif");
 10401029         if (flslvl == 0)
 10411030                 elflvl = 0;
 10421031         elslvl = 0;
 10431032         chknl(1);
 10441033 }
 10451034 
 10461035 static void
 10471036 ifstmt(void)
 10481037 {
 10491038         if (flslvl == 0) {
 10501039                 if (yyparse() == 0) {
 10511040                         putch('\n');
 10521041                         ++flslvl;
 10531042                 } else
 10541043                         ++trulvl;
 10551044         } else
 10561045                 ++flslvl;
 10571046 }
 10581047 
 10591048 static void
 10601049 elifstmt(void)
 10611050 {
 10621051         if (flslvl == 0)
 10631052                 elflvl = trulvl;
 10641053         if (flslvl) {
 10651054                 if (elflvl > trulvl)
 10661055                         ;
 10671056                 else if (--flslvl!=0)
 10681057                         ++flslvl;
 10691058                 else {
 10701059                         if (yyparse()) {
 10711060                                 ++trulvl;
 10721061                                 prtline();
 10731062                         } else {
 10741063                                 putch('\n');
 10751064                                 ++flslvl;
 10761065                         }
 10771066                 }
 10781067         } else if (trulvl) {
 10791068                 ++flslvl;
 10801069                 --trulvl;
 10811070         } else
 10821071                 error("If-less elif");
 10831072 }
 10841073 
 10851074 static usch *
 10861075 svinp(void)
 10871076 {
 10881077         int c;
 10891078         usch *cp = stringbuf;
 10901079 
 10911080         while ((c = inch()) && c != '\n')
 10921081                 savch(c);
 10931082         savch('\n');
 10941083         savch(0);
 10951084         return cp;
 10961085 }
 10971086 
 10981087 static void
 10991088 cpperror(void)
 11001089 {
 11011090         usch *cp;
 11021091         int c;
 11031092 
 11041093         if (flslvl)
 11051094                 return;
 11061095         c = sloscan();
 11071096         if (c != WSPACE && c != '\n')
 11081097                 error("bad error");
 11091098         cp = svinp();
 11101099         if (flslvl)
 11111100                 stringbuf = cp;
 11121101         else
 11131102                 error("%s", cp);
 11141103 }
 11151104 
 11161105 static void
 11171106 cppwarning(void)
 11181107 {
 11191108         usch *cp;
 11201109         int c;
 11211110 
 11221111         if (flslvl)
 11231112                 return;
 11241113         c = sloscan();
 11251114         if (c != WSPACE && c != '\n')
 11261115                 error("bad warning");
 11271116 
 11281117         /* svinp() add an unwanted \n */
 11291118         cp = stringbuf;
 11301119         while ((c = inch()) && c != '\n')
 11311120                 savch(c);
 11321121         savch(0);
 11331122 
 11341123         if (flslvl)
 11351124                 stringbuf = cp;
 11361125         else
 11371126                 warning("#warning %s", cp);
 11381127 
 11391128         unch('\n');
 11401129 }
 11411130 
 11421131 static void
 11431132 undefstmt(void)
 11441133 {
 11451134         struct symtab *np;
 11461135 
 11471136         if (sloscan() != WSPACE || sloscan() != IDENT)
 11481137                 error("bad undef");
 11491138         if (flslvl == 0 && (np = lookup((usch *)yytext, FIND)))
 11501139                 np->value = 0;
 11511140         chknl(0);
 11521141 }
 11531142 
 11541143 static void
 11551144 pragmastmt(void)
 11561145 {
 11571146         int c;
 11581147 
 11591148         if (sloscan() != WSPACE)
 11601149                 error("bad pragma");
 11611150         if (!flslvl)
<>1162 -                putstr((const usch *)"#pragma ");
  1151+                putstr((const usch *)"\n#pragma ");
<_11631152         do {
 11641153                 c = inch();
 11651154                 if (!flslvl)
 11661155                         putch(c);       /* Do arg expansion instead? */
 11671156         } while (c && c != '\n');
 11681157         if (c == '\n')
 11691158                 unch(c);
 11701159         prtline();
 11711160 }
 11721161 
 11731162 static void
 11741163 badop(const char *op)
 11751164 {
 11761165         error("invalid operator in preprocessor expression: %s", op);
 11771166 }
 11781167 
 11791168 int
 11801169 cinput()
 11811170 {
 11821171         return inch();
 11831172 }
 11841173 
 11851174 /*
 11861175  * Check for (and convert) trigraphs.
 11871176  */
 11881177 int
 11891178 chktg()
 11901179 {
 11911180         int c;
 11921181 
 11931182         if ((c = inpch()) != '?') {
 11941183                 unch(c);
 11951184                 return 0;
 11961185         }
 11971186         switch (c = inpch()) {
 11981187         case '=': c = '#'; break;
 11991188         case '(': c = '['; break;
 12001189         case ')': c = ']'; break;
 12011190         case '<': c = '{'; break;
 12021191         case '>': c = '}'; break;
 12031192         case '/': c = '\\'; break;
 12041193         case '\'': c = '^'; break;
 12051194         case '!': c = '|'; break;
 12061195         case '-': c = '~'; break;
 12071196         default:
 12081197                 unch(c);
 12091198                 unch('?');
 12101199                 c = 0;
 12111200         }
 12121201         return c;
 12131202 }
 12141203 
 12151204 static struct {
 12161205         const char *name;
 12171206         void (*fun)(void);
 12181207 } ppd[] = {
 12191208         { "ifndef", ifndefstmt },
 12201209         { "ifdef", ifdefstmt },
 12211210         { "if", ifstmt },
 12221211         { "include", include },
 12231212         { "else", elsestmt },
 12241213         { "endif", endifstmt },
 12251214         { "error", cpperror },
 12261215         { "warning", cppwarning },
 12271216         { "define", define },
 12281217         { "undef", undefstmt },
 12291218         { "line", line },
 12301219         { "pragma", pragmastmt },
 12311220         { "elif", elifstmt },
 12321221 #ifdef GCC_COMPAT
 12331222         { "include_next", include_next },
 12341223 #endif
 12351224 };
 12361225 
 12371226 /*
 12381227  * Handle a preprocessor directive.
 12391228  */
 12401229 void
 12411230 ppdir(void)
 12421231 {
 12431232         char bp[20];
 12441233         int ch, i;
 12451234 
 12461235         while ((ch = inch()) == ' ' || ch == '\t')
 12471236                 ;
 12481237         if (ch == '\n') { /* empty directive */
 12491238                 unch(ch);
 12501239                 return;
 12511240         }
 12521241         if (ch < 'a' || ch > 'z')
 12531242                 goto out; /* something else, ignore */
 12541243         i = 0;
 12551244         do {
 12561245                 bp[i++] = (usch)ch;
 12571246                 if (i == sizeof(bp)-1)
 12581247                         goto out; /* too long */
 12591248                 ch = inch();
 12601249         } while ((ch >= 'a' && ch <= 'z') || (ch == '_'));
 12611250         unch(ch);
 12621251         bp[i++] = 0;
 12631252 
 12641253         /* got keyword */
 12651254 #define SZ (int)(sizeof(ppd)/sizeof(ppd[0]))
 12661255         for (i = 0; i < SZ; i++)
 12671256                 if (bp[0] == ppd[i].name[0] && strcmp(bp, ppd[i].name) == 0)
 12681257                         break;
 12691258         if (i == SZ)
 12701259                 goto out;
 12711260 
 12721261         /* Found matching keyword */
 12731262         (*ppd[i].fun)();
 12741263         return;
 12751264 
 12761265 out:    while ((ch = inch()) != '\n' && ch != -1)
 12771266                 ;
 12781267         unch('\n');
 12791268 }
FishEye: Open Source License registered to PCC.
Your maintenance has expired. You can renew your license at http://www.atlassian.com/fisheye/renew
Atlassian FishEye, CVS analysis. (Version:1.6.3 Build:build-336 2008-11-04) - Administration - Page generated 2014-09-21 16:11 +0200