Quick Search:

Mode

Context

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

Other Diffs

Ignore

Blank Lines Whitespace: Expand:

Diff

1.42
 
1.43
 
MAIN:ragge:20110109152539
 
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;
<> 84+extern int dflag;
8485 
 8586 #define PUTCH(ch) if (!flslvl) putch(ch)
 8687 /* protection against recursion in #include */
 8788 #define MAX_INCLEVEL    100
 8889 static int inclevel;
 8990 
 9091 /* get next character unaltered */
 9192 #define NXTCH() (ifiles->curptr < ifiles->maxread ? *ifiles->curptr++ : inpch())
 9293 
 9394 #ifdef YYTEXT_POINTER
 9495 static char buf[CPPBUF];
 9596 char *yytext = buf;
 9697 #else
 9798 char yytext[CPPBUF];
 9899 #endif
 99100 
<>100 -#define C_SPEC  1
 101 -#define C_EP    2
 102 -#define C_ID    4
 103 -#define C_I     (C_SPEC|C_ID)
 104 -#define C_2     8               /* for yylex() tokenizing */
 105 -static char spechr[256] = {
  101+char spechr[256] = {
  102+        0,      0,      0,      0,      C_SPEC, C_SPEC, 0,      0,
  103+        0,      C_WSNL, C_SPEC|C_WSNL,  0,
  104+        0,      C_WSNL, 0,      0,
106105         0,      0,      0,      0,      0,      0,      0,      0,
<>107 -        0,      0,      C_SPEC0,      0,      0,      0,      0,
108106         0,      0,      0,      0,      0,      0,      0,      0,
<>109 -        0,      0,      0,      0,      0,      0,      0,      0,
110107 
<>111 -        0,      C_2,    C_SPEC0,      0,      0,      C_2,    C_SPEC,
  108+        C_WSNLC_2,    C_SPEC0,      0,      0,      C_2,    C_SPEC,
112109         0,      0,      0,      C_2,    0,      C_2,    0,      C_SPEC|C_2,
 113110         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 114111         C_I,    C_I,    0,      0,      C_2,    C_2,    C_2,    C_SPEC,
 115112 
 116113         0,      C_I,    C_I,    C_I,    C_I,    C_I|C_EP, C_I,  C_I,
 117114         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 118115         C_I|C_EP, C_I,  C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 119116         C_I,    C_I,    C_I,    0,      C_I,    0,      0,      C_I,
 120117 
 121118         0,      C_I,    C_I,    C_I,    C_I,    C_I|C_EP, C_I,  C_I,
 122119         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 123120         C_I|C_EP, C_I,  C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 124121         C_I,    C_I,    C_I,    0,      C_2,    0,      0,      0,
 125122 
 126123 };
 127124 
<> 125+/*
  126+ * No-replacement array.  If a macro is found and exists in this array
  127+ * then no replacement shall occur.  This is a stack.
  128+ */
  129+struct symtab *norep[RECMAX];   /* Symbol table index table */
  130+int norepptr = 1;                       /* Top of index table */
  131+unsigned char bptr[RECMAX];     /* currently active noexpand macro stack */
  132+int bidx;                       /* Top of bptr stack */
  133+
128134 static void
 129135 unch(int c)
 130136 {
 131137                 
 132138         --ifiles->curptr;
 133139         if (ifiles->curptr < ifiles->bbuf)
 134140                 error("pushback buffer full");
 135141         *ifiles->curptr = (usch)c;
 136142 }
 137143 
 138144 /*
 139145  * Scan quickly the input file searching for:
 140146  *      - '#' directives
 141147  *      - keywords (if not flslvl)
 142148  *      - comments
 143149  *
 144150  *      Handle strings, numbers and trigraphs with care.
 145151  *      Only data from pp files are scanned here, never any rescans.
 146152  *      TODO: Only print out strings before calling other functions.
 147153  */
 148154 static void
 149155 fastscan(void)
 150156 {
 151157         struct symtab *nl;
<>152 -        int ch, i;
  158+        int ch, i, ccnt, onemore;
153159 
 154160         goto run;
 155161         for (;;) {
 156162                 ch = NXTCH();
 157163 xloop:          if (ch == -1)
 158164                         return;
<> 165+                if (dflag>1)
  166+                        printf("fastscan ch %d (%c)\n", ch, ch > 31 ? ch : '@');
159167                 if ((spechr[ch] & C_SPEC) == 0) {
 160168                         PUTCH(ch);
 161169                         continue;
 162170                 }
 163171                 switch (ch) {
<> 172+                case EXP:
  173+                case NEX:
  174+                case WARN:
  175+                case CONC:
  176+                        error("bad char passed");
  177+                        break;
  178+
164179                 case '/': /* Comments */
 165180                         if ((ch = inch()) == '/') {
 166181                                 if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
 167182                                 do {
 168183                                         if (Cflag) PUTCH(ch);
 169184                                         ch = inch();
 170185                                 } while (ch != -1 && ch != '\n');
 171186                                 goto xloop;
 172187                         } else if (ch == '*') {
 173188                                 if (Cflag) { PUTCH('/'); PUTCH('*'); }
 174189                                 for (;;) {
 175190                                         ch = inch();
 176191                                         if (ch == '\n') {
 177192                                                 ifiles->lineno++;
 178193                                                 PUTCH('\n');
 179194                                         }
 180195                                         if (ch == -1)
 181196                                                 return;
 182197                                         if (ch == '*') {
 183198                                                 ch = inch();
 184199                                                 if (ch == '/') {
 185200                                                         if (Cflag) {
 186201                                                                 PUTCH('*');
 187202                                                                 PUTCH('/');
 188203                                                         } else
 189204                                                                 PUTCH(' ');
 190205                                                         break;
 191206                                                 }
 192207                                                 unch(ch);
 193208                                                 ch = '*';
 194209                                         }
 195210                                         if (Cflag) PUTCH(ch);
 196211                                 }
 197212                         } else {
 198213                                 PUTCH('/');
 199214                                 goto xloop;
 200215                         }
 201216                         break;
 202217 
 203218                 case '?'/* trigraphs */
 204219                         if ((ch = chktg()))
 205220                                 goto xloop;
 206221                         PUTCH('?');
 207222                         break;
 208223 
 209224                 case '\\':
 210225                         if ((ch = NXTCH()) == '\n') {
 211226                                 ifiles->lineno++;
 212227                                 continue;
 213228                         } else {
 214229                                 PUTCH('\\');
 215230                         }
 216231                         goto xloop;
 217232 
 218233                 case '\n': /* newlines, for pp directives */
 219234                         ifiles->lineno++;
 220235                         do {
 221236                                 PUTCH(ch);
 222237 run:                            ch = NXTCH();
 223238                         } while (ch == ' ' || ch == '\t');
 224239                         if (ch == '#') {
 225240                                 ppdir();
 226241                                 continue;
 227242                         } else if (ch == '%') {
 228243                                 ch = NXTCH();
 229244                                 if (ch == ':') {
 230245                                         ppdir();
 231246                                         continue;
 232247                                 } else {
 233248                                         unch(ch);
 234249                                         ch = '%';
 235250                                 }
 236251                         }
 237252                         goto xloop;
 238253 
 239254                 case '\"': /* strings */
 240255 str:                    PUTCH(ch);
 241256                         while ((ch = inch()) != '\"') {
<>242 -                                PUTCH(ch);
  257+                                if (ch == EXP)
  258+                                        doexp();
  259+                                else if (ch == NEX)
  260+                                        donex();
  261+                                else if (ch != CONC) /* XXX ??? */
  262+                                        PUTCH(ch);
243263                                 if (ch == '\\') {
 244264                                         ch = inch();
 245265                                         PUTCH(ch);
 246266                                 }
 247267                                 if (ch < 0)
 248268                                         return;
 249269                         }
 250270                         PUTCH(ch);
 251271                         break;
 252272 
 253273                 case '.'/* for pp-number */
 254274                         PUTCH(ch);
 255275                         ch = NXTCH();
 256276                         if (ch < '0' || ch > '9')
 257277                                 goto xloop;
 258278                         /* FALLTHROUGH */
 259279                 case '0': case '1': case '2': case '3': case '4':
 260280                 case '5': case '6': case '7': case '8': case '9':
 261281                         do {
 262282                                 PUTCH(ch);
 263283                                 ch = NXTCH();
 264284                                 if (spechr[ch] & C_EP) {
 265285                                         PUTCH(ch);
 266286                                         ch = NXTCH();
 267287                                         if (ch == '-' || ch == '+')
 268288                                                 continue;
 269289                                 }
 270290                         } while ((spechr[ch] & C_ID) || (ch == '.'));
 271291                         goto xloop;
 272292 
 273293                 case '\'': /* character literal */
 274294 con:                    PUTCH(ch);
 275295                         if (tflag)
 276296                                 continue; /* character constants ignored */
 277297                         while ((ch = NXTCH()) != '\'') {
 278298                                 PUTCH(ch);
 279299                                 if (ch == '\\') {
 280300                                         ch = NXTCH();
 281301                                         PUTCH(ch);
 282302                                 } else if (ch < 0)
 283303                                         return;
 284304                                 else if (ch == '\n')
 285305                                         goto xloop;
 286306                         }
 287307                         PUTCH(ch);
 288308                         break;
 289309 
 290310                 case 'L':
 291311                         ch = NXTCH();
 292312                         if (ch == '\"') {
 293313                                 PUTCH('L');
 294314                                 goto str;
 295315                         }
 296316                         if (ch == '\'') {
 297317                                 PUTCH('L');
 298318                                 goto con;
 299319                         }
 300320                         unch(ch);
 301321                         ch = 'L';
 302322                         /* FALLTHROUGH */
 303323                 default:
 304324                         if ((spechr[ch] & C_ID) == 0)
 305325                                 error("fastscan");
 306326                         if (flslvl) {
 307327                                 while (spechr[ch] & C_ID)
 308328                                         ch = NXTCH();
 309329                                 goto xloop;
 310330                         }
<>311 -                        i = 0;
  331+                        onemore = i = ccnt = 0;
312332                         do {
 313333                                 yytext[i++] = (usch)ch;
 314334                                 ch = NXTCH();
 315335                                 if (ch == '\\') {
 316336                                         ch = NXTCH();
 317337                                         if (ch != '\n') {
 318338                                                 unch('\n');
 319339                                                 ch = '\\';
 320340                                         } else {
 321341                                                 ifiles->lineno++;
 322342                                                 ch = NXTCH();
 323343                                         }
 324344                                 }
 325345                                 if (ch < 0)
 326346                                         return;
 327347                         } while (spechr[ch] & C_ID);
<> 348+
328349                         yytext[i] = 0;
 329350                         unch(ch);
<>330 -                        if ((nl = lookup((usch *)yytext, FIND)) != 0) {
 331 -                                usch *op = stringbuf;
 332 -                                putstr(gotident(nl));
 333 -                                stringbuf = op;
  351+
  352+                        if ((nl = lookup((usch *)yytext, FIND)) && kfind(nl)) {
  353+                                putstr(stringbuf);
334354                         } else
 335355                                 putstr((usch *)yytext);
<> 356+
336357                         break;
 337358                 }
 338359         }
 339360 }
 340361 
 341362 int
 342363 sloscan()
 343364 {
 344365         int ch;
 345366         int yyp;
 346367 
 347368 zagain:
 348369         yyp = 0;
 349370         ch = inch();
 350371         yytext[yyp++] = (usch)ch;
 351372         switch (ch) {
 352373         case -1:
 353374                 return 0;
 354375         case '\n':
 355376                 /* sloscan() never passes \n, that's up to fastscan() */
 356377                 unch(ch);
 357378                 goto yyret;
 358379 
 359380         case '\r': /* Ignore CR's */
 360381                 yyp = 0;
 361382                 break;
 362383 
 363384         case '0': case '1': case '2': case '3': case '4': case '5':
 364385         case '6': case '7': case '8': case '9':
 365386                 /* readin a "pp-number" */
 366387 ppnum:          for (;;) {
 367388                         ch = inch();
 368389                         if (spechr[ch] & C_EP) {
 369390                                 yytext[yyp++] = (usch)ch;
 370391                                 ch = inch();
 371392                                 if (ch == '-' || ch == '+') {
 372393                                         yytext[yyp++] = (usch)ch;
 373394                                 } else
 374395                                         unch(ch);
 375396                                 continue;
 376397                         }
 377398                         if ((spechr[ch] & C_ID) || ch == '.') {
 378399                                 yytext[yyp++] = (usch)ch;
 379400                                 continue;
 380401                         }
 381402                         break;
 382403                 }
 383404                 unch(ch);
 384405                 yytext[yyp] = 0;
 385406 
 386407                 return NUMBER;
 387408 
 388409         case '\'':
 389410 chlit:          
 390411                 for (;;) {
 391412                         if ((ch = inch()) == '\\') {
 392413                                 yytext[yyp++] = (usch)ch;
 393414                                 yytext[yyp++] = (usch)inch();
 394415                                 continue;
 395416                         } else if (ch == '\n') {
 396417                                 /* not a constant */
 397418                                 while (yyp > 1)
 398419                                         unch(yytext[--yyp]);
 399420                                 ch = '\'';
 400421                                 goto any;
 401422                         } else
 402423                                 yytext[yyp++] = (usch)ch;
 403424                         if (ch == '\'')
 404425                                 break;
 405426                 }
 406427                 yytext[yyp] = 0;
 407428 
 408429                 return (NUMBER);
 409430 
 410431         case ' ':
 411432         case '\t':
 412433                 while ((ch = inch()) == ' ' || ch == '\t')
 413434                         yytext[yyp++] = (usch)ch;
 414435                 unch(ch);
 415436                 yytext[yyp] = 0;
 416437                 return(WSPACE);
 417438 
 418439         case '/':
 419440                 if ((ch = inch()) == '/') {
 420441                         do {
 421442                                 yytext[yyp++] = (usch)ch;
 422443                                 ch = inch();
 423444                         } while (ch && ch != '\n');
 424445                         yytext[yyp] = 0;
 425446                         unch(ch);
 426447                         goto zagain;
 427448                 } else if (ch == '*') {
 428449                         int c, wrn;
 429450                         extern int readmac;
 430451 
 431452                         if (Cflag && !flslvl && readmac) {
 432453                                 unch(ch);
 433454                                 yytext[yyp] = 0;
 434455                                 return CMNT;
 435456                         }
 436457 
 437458                         wrn = 0;
 438459                 more:   while ((c = inch()) && c != '*') {
 439460                                 if (c == '\n')
 440461                                         putch(c), ifiles->lineno++;
 441462                                 else if (c == 1) /* WARN */
 442463                                         wrn = 1;
 443464                         }
 444465                         if (c == 0)
 445466                                 return 0;
 446467                         if ((c = inch()) && c != '/') {
 447468                                 unch(c);
 448469                                 goto more;
 449470                         }
 450471                         if (c == 0)
 451472                                 return 0;
 452473                         if (!tflag && !Cflag && !flslvl)
 453474                                 unch(' ');
 454475                         if (wrn)
 455476                                 unch(1);
 456477                         goto zagain;
 457478                 }
 458479                 unch(ch);
 459480                 ch = '/';
 460481                 goto any;
 461482 
 462483         case '.':
 463484                 ch = inch();
 464485                 if (isdigit(ch)) {
 465486                         yytext[yyp++] = (usch)ch;
 466487                         goto ppnum;
 467488                 } else {
 468489                         unch(ch);
 469490                         ch = '.';
 470491                 }
 471492                 goto any;
 472493 
 473494         case '\"':
 474495                 if (tflag)
 475496                         goto any;
 476497         strng:
 477498                 for (;;) {
 478499                         if ((ch = inch()) == '\\') {
 479500                                 yytext[yyp++] = (usch)ch;
 480501                                 yytext[yyp++] = (usch)inch();
 481502                                 continue;
 482503                         } else
 483504                                 yytext[yyp++] = (usch)ch;
 484505                         if (ch == '\"')
 485506                                 break;
 486507                 }
 487508                 yytext[yyp] = 0;
 488509                 return(STRING);
 489510 
 490511         case 'L':
 491512                 if ((ch = inch()) == '\"' && !tflag) {
 492513                         yytext[yyp++] = (usch)ch;
 493514                         goto strng;
 494515                 } else if (ch == '\'' && !tflag) {
 495516                         yytext[yyp++] = (usch)ch;
 496517                         goto chlit;
 497518                 }
 498519                 unch(ch);
 499520                 /* FALLTHROUGH */
 500521 
 501522         /* Yetch, all identifiers */
 502523         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
 503524         case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
 504525         case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
 505526         case 's': case 't': case 'u': case 'v': case 'w': case 'x':
 506527         case 'y': case 'z':
 507528         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
 508529         case 'G': case 'H': case 'I': case 'J': case 'K':
 509530         case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
 510531         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
 511532         case 'Y': case 'Z':
 512533         case '_': /* {L}({L}|{D})* */
 513534 
 514535                 /* Special hacks */
 515536                 for (;;) { /* get chars */
 516537                         ch = inch();
 517538                         if (isalpha(ch) || isdigit(ch) || ch == '_') {
 518539                                 yytext[yyp++] = (usch)ch;
 519540                         } else {
 520541                                 unch(ch);
 521542                                 break;
 522543                         }
 523544                 }
 524545                 yytext[yyp] = 0; /* need already string */
 525546                 /* end special hacks */
 526547 
 527548                 return IDENT;
 528549         default:
 529550         any:
 530551                 yytext[yyp] = 0;
 531552                 return yytext[0];
 532553 
 533554         } /* endcase */
 534555         goto zagain;
 535556 
 536557 yyret:
 537558         yytext[yyp] = 0;
 538559         return ch;
 539560 }
 540561 
 541562 int
 542563 yylex()
 543564 {
 544565         static int ifdef, noex;
 545566         struct symtab *nl;
 546567         int ch, c2;
 547568 
 548569         while ((ch = sloscan()) == WSPACE)
 549570                 ;
 550571         if (ch < 128 && spechr[ch] & C_2)
 551572                 c2 = inpch();
 552573         else
 553574                 c2 = 0;
 554575 
 555576 #define C2(a,b,c) case a: if (c2 == b) return c; break
 556577         switch (ch) {
 557578         C2('=', '=', EQ);
 558579         C2('!', '=', NE);
 559580         C2('|', '|', OROR);
 560581         C2('&', '&', ANDAND);
 561582         case '<':
 562583                 if (c2 == '<') return LS;
 563584                 if (c2 == '=') return LE;
 564585                 break;
 565586         case '>':
 566587                 if (c2 == '>') return RS;
 567588                 if (c2 == '=') return GE;
 568589                 break;
 569590         case '+':
 570591         case '-':
 571592                 if (ch == c2)
 572593                         badop("");
 573594                 break;
 574595 
 575596         case '/':
 576597                 if (Cflag == 0 || c2 != '*')
 577598                         break;
 578599                 /* Found comment that need to be skipped */
 579600                 for (;;) {
 580601                         ch = inpch();
 581602                 c1:     if (ch != '*')
 582603                                 continue;
 583604                         if ((ch = inpch()) == '/')
 584605                                 break;
 585606                         goto c1;
 586607                 }
 587608                 return yylex();
 588609 
 589610         case NUMBER:
 590611                 if (yytext[0] == '\'') {
 591612                         yylval.node.op = NUMBER;
 592613                         yylval.node.nd_val = charcon((usch *)yytext);
 593614                 } else
 594615                         cvtdig(yytext[0] != '0' ? 10 :
 595616                             yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
 596617                 return NUMBER;
 597618 
 598619         case IDENT:
 599620                 if (strcmp(yytext, "defined") == 0) {
 600621                         ifdef = 1;
 601622                         return DEFINED;
 602623                 }
 603624                 nl = lookup((usch *)yytext, FIND);
 604625                 if (ifdef) {
 605626                         yylval.node.nd_val = nl != NULL;
 606627                         ifdef = 0;
 607628                 } else if (nl && noex == 0) {
<>608 -                        usch *c, *och = stringbuf;
  629+                        usch *och = stringbuf;
  630+                        int i;
609631 
<>610 -                        c = gotident(nl);
 611 -                        unch(1);
 612 -                        unpstr(c);
  632+                        i = kfind(nl);
  633+                        unch(WARN);
  634+                        if (i)
  635+                                unpstr(stringbuf);
  636+                        else
  637+                                unpstr(nl->namep);
613638                         stringbuf = och;
 614639                         noex = 1;
 615640                         return yylex();
 616641                 } else {
 617642                         yylval.node.nd_val = 0;
 618643                 }
 619644                 yylval.node.op = NUMBER;
 620645                 return NUMBER;
<>621 -        case 1: /* WARN */
  646+        case WARN:
622647                 noex = 0;
 623648                 return yylex();
 624649         default:
 625650                 return ch;
 626651         }
 627652         unch(c2);
 628653         return ch;
 629654 }
 630655 
 631656 usch *yyp, yybuf[CPPBUF];
 632657 
 633658 int yywrap(void);
 634659 
 635660 static int
 636661 inpch(void)
 637662 {
 638663         int len;
 639664 
 640665         if (ifiles->curptr < ifiles->maxread)
 641666                 return *ifiles->curptr++;
 642667 
 643668         if (ifiles->infil == -1)
 644669                 return -1;
 645670         if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0)
 646671                 error("read error on file %s", ifiles->orgfn);
 647672         if (len == 0)
 648673                 return -1;
 649674         ifiles->curptr = ifiles->buffer;
 650675         ifiles->maxread = ifiles->buffer + len;
 651676         return inpch();
 652677 }
 653678 
 654679 static int
 655680 inch(void)
 656681 {
 657682         int c;
 658683 
 659684 again:  switch (c = inpch()) {
 660685         case '\\': /* continued lines */
 661686 msdos:          if ((c = inpch()) == '\n') {
 662687                         ifiles->lineno++;
 663688                         goto again;
 664689                 } else if (c == '\r')
 665690                         goto msdos;
 666691                 unch(c);
 667692                 return '\\';
 668693         case '?': /* trigraphs */
 669694                 if ((c = chktg())) {
 670695                         unch(c);
 671696                         goto again;
 672697                 }
 673698                 return '?';
 674699         default:
 675700                 return c;
 676701         }
 677702 }
 678703 
 679704 /*
 680705  * Let the command-line args be faked defines at beginning of file.
 681706  */
 682707 static void
 683708 prinit(struct initar *it, struct includ *ic)
 684709 {
 685710         const char *pre, *post;
 686711         char *a;
 687712 
 688713         if (it->next)
 689714                 prinit(it->next, ic);
 690715         pre = post = NULL; /* XXX gcc */
 691716         switch (it->type) {
 692717         case 'D':
 693718                 pre = "#define ";
 694719                 if ((a = strchr(it->str, '=')) != NULL) {
 695720                         *a = ' ';
 696721                         post = "\n";
 697722                 } else
 698723                         post = " 1\n";
 699724                 break;
 700725         case 'U':
 701726                 pre = "#undef ";
 702727                 post = "\n";
 703728                 break;
 704729         case 'i':
 705730                 pre = "#include \"";
 706731                 post = "\"\n";
 707732                 break;
 708733         default:
 709734                 error("prinit");
 710735         }
 711736         strlcat((char *)ic->buffer, pre, CPPBUF+1);
 712737         strlcat((char *)ic->buffer, it->str, CPPBUF+1);
 713738         if (strlcat((char *)ic->buffer, post, CPPBUF+1) >= CPPBUF+1)
 714739                 error("line exceeds buffer size");
 715740 
 716741         ic->lineno--;
 717742         while (*ic->maxread)
 718743                 ic->maxread++;
 719744 }
 720745 
 721746 /*
 722747  * A new file included.
 723748  * If ifiles == NULL, this is the first file and already opened (stdin).
 724749  * Return 0 on success, -1 if file to be included is not found.
 725750  */
 726751 int
 727752 pushfile(const usch *file, const usch *fn, int idx, void *incs)
 728753 {
 729754         extern struct initar *initar;
 730755         struct includ ibuf;
 731756         struct includ *ic;
 732757         int otrulvl;
 733758 
 734759         ic = &ibuf;
 735760         ic->next = ifiles;
 736761 
 737762         if (file != NULL) {
 738763                 if ((ic->infil = open((const char *)file, O_RDONLY)) < 0)
 739764                         return -1;
 740765                 ic->orgfn = ic->fname = file;
 741766                 if (++inclevel > MAX_INCLEVEL)
 742767                         error("Limit for nested includes exceeded");
 743768         } else {
 744769                 ic->infil = 0;
 745770                 ic->orgfn = ic->fname = (const usch *)"<stdin>";
 746771         }
 747772         ic->buffer = ic->bbuf+NAMEMAX;
 748773         ic->curptr = ic->buffer;
 749774         ifiles = ic;
 750775         ic->lineno = 1;
 751776         ic->maxread = ic->curptr;
 752777         ic->idx = idx;
 753778         ic->incs = incs;
 754779         ic->fn = fn;
 755780         prtline();
 756781         if (initar) {
 757782                 int oin = ic->infil;
 758783                 ic->infil = -1;
 759784                 *ic->maxread = 0;
 760785                 prinit(initar, ic);
 761786                 initar = NULL;
 762787                 if (dMflag)
 763788                         write(ofd, ic->buffer, strlen((char *)ic->buffer));
 764789                 fastscan();
 765790                 prtline();
 766791                 ic->infil = oin;
 767792         }
 768793 
 769794         otrulvl = trulvl;
 770795 
 771796         fastscan();
 772797 
 773798         if (otrulvl != trulvl || flslvl)
 774799                 error("unterminated conditional");
 775800 
 776801         ifiles = ic->next;
 777802         close(ic->infil);
 778803         inclevel--;
 779804         return 0;
 780805 }
 781806 
 782807 /*
 783808  * Print current position to output file.
 784809  */
 785810 void
 786811 prtline()
 787812 {
 788813         usch *s, *os = stringbuf;
 789814 
 790815         if (Mflag) {
 791816                 if (dMflag)
 792817                         return; /* no output */
 793818                 if (ifiles->lineno == 1) {
 794819                         s = sheap("%s: %s\n", Mfile, ifiles->fname);
 795820                         write(ofd, s, strlen((char *)s));
 796821                 }
 797822         } else if (!Pflag)
 798823                 putstr(sheap("\n# %d \"%s\"\n", ifiles->lineno, ifiles->fname));
 799824         stringbuf = os;
 800825 }
 801826 
 802827 void
 803828 cunput(int c)
 804829 {
 805830 #ifdef CPP_DEBUG
<>806 -        extern int dflag;
 807 -        if (dflag)printf(": '%c'(%d)", c > 31 ? c : ' ', c);
  831+//      extern int dflag;
  832+//      if (dflag)printf(": '%c'(%d)\n", c > 31 ? c : ' ', c);
<_808833 #endif
 809834 #if 0
 810835 if (c == 10) {
 811836         printf("c == 10!!!\n");
 812837 }
 813838 #endif
 814839         unch(c);
 815840 }
 816841 
 817842 int yywrap(void) { return 1; }
 818843 
 819844 static int
 820845 dig2num(int c)
 821846 {
 822847         if (c >= 'a')
 823848                 c = c - 'a' + 10;
 824849         else if (c >= 'A')
 825850                 c = c - 'A' + 10;
 826851         else
 827852                 c = c - '0';
 828853         return c;
 829854 }
 830855 
 831856 /*
 832857  * Convert string numbers to unsigned long long and check overflow.
 833858  */
 834859 static void
 835860 cvtdig(int rad)
 836861 {
 837862         unsigned long long rv = 0;
 838863         unsigned long long rv2 = 0;
 839864         char *y = yytext;
 840865         int c;
 841866 
 842867         c = *y++;
 843868         if (rad == 16)
 844869                 y++;
 845870         while (isxdigit(c)) {
 846871                 rv = rv * rad + dig2num(c);
 847872                 /* check overflow */
 848873                 if (rv / rad < rv2)
 849874                         error("Constant \"%s\" is out of range", yytext);
 850875                 rv2 = rv;
 851876                 c = *y++;
 852877         }
 853878         y--;
 854879         while (*y == 'l' || *y == 'L')
 855880                 y++;
 856881         yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER;
 857882         yylval.node.nd_uval = rv;
 858883         if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0)
 859884                 yylval.node.op = UNUMBER;
 860885         if (yylval.node.op == NUMBER && yylval.node.nd_val < 0)
 861886                 /* too large for signed, see 6.4.4.1 */
 862887                 error("Constant \"%s\" is out of range", yytext);
 863888 }
 864889 
 865890 static int
 866891 charcon(usch *p)
 867892 {
 868893         int val, c;
 869894 
 870895         p++; /* skip first ' */
 871896         val = 0;
 872897         if (*p++ == '\\') {
 873898                 switch (*p++) {
 874899                 case 'a': val = '\a'; break;
 875900                 case 'b': val = '\b'; break;
 876901                 case 'f': val = '\f'; break;
 877902                 case 'n': val = '\n'; break;
 878903                 case 'r': val = '\r'; break;
 879904                 case 't': val = '\t'; break;
 880905                 case 'v': val = '\v'; break;
 881906                 case '\"': val = '\"'; break;
 882907                 case '\'': val = '\''; break;
 883908                 case '\\': val = '\\'; break;
 884909                 case 'x':
 885910                         while (isxdigit(c = *p)) {
 886911                                 val = val * 16 + dig2num(c);
 887912                                 p++;
 888913                         }
 889914                         break;
 890915                 case '0': case '1': case '2': case '3': case '4':
 891916                 case '5': case '6': case '7':
 892917                         p--;
 893918                         while (isdigit(c = *p)) {
 894919                                 val = val * 8 + (c - '0');
 895920                                 p++;
 896921                         }
 897922                         break;
 898923                 default: val = p[-1];
 899924                 }
 900925 
 901926         } else
 902927                 val = p[-1];
 903928         return val;
 904929 }
 905930 
 906931 static void
 907932 chknl(int ignore)
 908933 {
 909934         int t;
 910935 
 911936         while ((t = sloscan()) == WSPACE)
 912937                 ;
 913938         if (t != '\n') {
 914939                 if (ignore) {
 915940                         warning("newline expected, got \"%s\"", yytext);
 916941                         /* ignore rest of line */
 917942                         while ((t = sloscan()) && t != '\n')
 918943                                 ;
 919944                 }
 920945                 else
 921946                         error("newline expected, got \"%s\"", yytext);
 922947         }
 923948 }
 924949 
 925950 static void
 926951 elsestmt(void)
 927952 {
 928953         if (flslvl) {
 929954                 if (elflvl > trulvl)
 930955                         ;
 931956                 else if (--flslvl!=0) {
 932957                         flslvl++;
 933958                 } else {
 934959                         trulvl++;
 935960                         prtline();
 936961                 }
 937962         } else if (trulvl) {
 938963                 flslvl++;
 939964                 trulvl--;
 940965         } else
 941966                 error("If-less else");
 942967         if (elslvl==trulvl+flslvl)
 943968                 error("Too many else");
 944969         elslvl=trulvl+flslvl;
 945970         chknl(1);
 946971 }
 947972 
 948973 static void
 949974 skpln(void)
 950975 {
 951976         /* just ignore the rest of the line */
 952977         while (inch() != '\n')
 953978                 ;
 954979         unch('\n');
 955980         flslvl++;
 956981 }
 957982 
 958983 static void
 959984 ifdefstmt(void)         
 960985 {
 961986         int t;
 962987 
 963988         if (flslvl) {
 964989                 skpln();
 965990                 return;
 966991         }
 967992         do
 968993                 t = sloscan();
 969994         while (t == WSPACE);
 970995         if (t != IDENT)
 971996                 error("bad ifdef");
 972997         if (lookup((usch *)yytext, FIND) == 0) {
 973998                 putch('\n');
 974999                 flslvl++;
 9751000         } else
 9761001                 trulvl++;
 9771002         chknl(0);
 9781003 }
 9791004 
 9801005 static void
 9811006 ifndefstmt(void)         
 9821007 {
 9831008         int t;
 9841009 
 9851010         if (flslvl) {
 9861011                 skpln();
 9871012                 return;
 9881013         }
 9891014         do
 9901015                 t = sloscan();
 9911016         while (t == WSPACE);
 9921017         if (t != IDENT)
 9931018                 error("bad ifndef");
 9941019         if (lookup((usch *)yytext, FIND) != 0) {
 9951020                 putch('\n');
 9961021                 flslvl++;
 9971022         } else
 9981023                 trulvl++;
 9991024         chknl(0);
 10001025 }
 10011026 
 10021027 static void
 10031028 endifstmt(void)         
 10041029 {
 10051030         if (flslvl) {
 10061031                 flslvl--;
 10071032                 if (flslvl == 0) {
 10081033                         putch('\n');
 10091034                         prtline();
 10101035                 }
 10111036         } else if (trulvl)
 10121037                 trulvl--;
 10131038         else
 10141039                 error("If-less endif");
 10151040         if (flslvl == 0)
 10161041                 elflvl = 0;
 10171042         elslvl = 0;
 10181043         chknl(1);
 10191044 }
 10201045 
 10211046 static void
 10221047 ifstmt(void)
 10231048 {
 10241049         if (flslvl == 0) {
 10251050                 if (yyparse() == 0) {
 10261051                         putch('\n');
 10271052                         ++flslvl;
 10281053                 } else
 10291054                         ++trulvl;
 10301055         } else
 10311056                 ++flslvl;
 10321057 }
 10331058 
 10341059 static void
 10351060 elifstmt(void)
 10361061 {
 10371062         if (flslvl == 0)
 10381063                 elflvl = trulvl;
 10391064         if (flslvl) {
 10401065                 if (elflvl > trulvl)
 10411066                         ;
 10421067                 else if (--flslvl!=0)
 10431068                         ++flslvl;
 10441069                 else {
 10451070                         if (yyparse()) {
 10461071                                 ++trulvl;
 10471072                                 prtline();
 10481073                         } else {
 10491074                                 putch('\n');
 10501075                                 ++flslvl;
 10511076                         }
 10521077                 }
 10531078         } else if (trulvl) {
 10541079                 ++flslvl;
 10551080                 --trulvl;
 10561081         } else
 10571082                 error("If-less elif");
 10581083 }
 10591084 
 10601085 static usch *
 10611086 svinp(void)
 10621087 {
 10631088         int c;
 10641089         usch *cp = stringbuf;
 10651090 
 10661091         while ((c = inch()) && c != '\n')
 10671092                 savch(c);
 10681093         savch('\n');
 10691094         savch(0);
 10701095         return cp;
 10711096 }
 10721097 
 10731098 static void
 10741099 cpperror(void)
 10751100 {
 10761101         usch *cp;
 10771102         int c;
 10781103 
 10791104         if (flslvl)
 10801105                 return;
 10811106         c = sloscan();
 10821107         if (c != WSPACE && c != '\n')
 10831108                 error("bad error");
 10841109         cp = svinp();
 10851110         if (flslvl)
 10861111                 stringbuf = cp;
 10871112         else
 10881113                 error("%s", cp);
 10891114 }
 10901115 
 10911116 static void
 10921117 cppwarning(void)
 10931118 {
 10941119         usch *cp;
 10951120         int c;
 10961121 
 10971122         if (flslvl)
 10981123                 return;
 10991124         c = sloscan();
 11001125         if (c != WSPACE && c != '\n')
 11011126                 error("bad warning");
 11021127 
 11031128         /* svinp() add an unwanted \n */
 11041129         cp = stringbuf;
 11051130         while ((c = inch()) && c != '\n')
 11061131                 savch(c);
 11071132         savch(0);
 11081133 
 11091134         if (flslvl)
 11101135                 stringbuf = cp;
 11111136         else
 11121137                 warning("#warning %s", cp);
 11131138 
 11141139         unch('\n');
 11151140 }
 11161141 
 11171142 static void
 11181143 undefstmt(void)
 11191144 {
 11201145         struct symtab *np;
 11211146 
 11221147         if (sloscan() != WSPACE || sloscan() != IDENT)
 11231148                 error("bad undef");
 11241149         if (flslvl == 0 && (np = lookup((usch *)yytext, FIND)))
 11251150                 np->value = 0;
 11261151         chknl(0);
 11271152 }
 11281153 
 11291154 static void
 11301155 pragmastmt(void)
 11311156 {
 11321157         int c;
 11331158 
 11341159         if (sloscan() != WSPACE)
 11351160                 error("bad pragma");
 11361161         if (!flslvl)
 11371162                 putstr((const usch *)"#pragma ");
 11381163         do {
 11391164                 c = inch();
 11401165                 if (!flslvl)
 11411166                         putch(c);       /* Do arg expansion instead? */
 11421167         } while (c && c != '\n');
 11431168         if (c == '\n')
 11441169                 unch(c);
 11451170         prtline();
 11461171 }
 11471172 
 11481173 static void
 11491174 badop(const char *op)
 11501175 {
 11511176         error("invalid operator in preprocessor expression: %s", op);
 11521177 }
 11531178 
 11541179 int
 11551180 cinput()
 11561181 {
 11571182         return inch();
 11581183 }
 11591184 
 11601185 /*
 11611186  * Check for (and convert) trigraphs.
 11621187  */
 11631188 int
 11641189 chktg()
 11651190 {
 11661191         int c;
 11671192 
 11681193         if ((c = inpch()) != '?') {
 11691194                 unch(c);
 11701195                 return 0;
 11711196         }
 11721197         switch (c = inpch()) {
 11731198         case '=': c = '#'; break;
 11741199         case '(': c = '['; break;
 11751200         case ')': c = ']'; break;
 11761201         case '<': c = '{'; break;
 11771202         case '>': c = '}'; break;
 11781203         case '/': c = '\\'; break;
 11791204         case '\'': c = '^'; break;
 11801205         case '!': c = '|'; break;
 11811206         case '-': c = '~'; break;
 11821207         default:
 11831208                 unch(c);
 11841209                 unch('?');
 11851210                 c = 0;
 11861211         }
 11871212         return c;
 11881213 }
 11891214 
 11901215 static struct {
 11911216         const char *name;
 11921217         void (*fun)(void);
 11931218 } ppd[] = {
 11941219         { "ifndef", ifndefstmt },
 11951220         { "ifdef", ifdefstmt },
 11961221         { "if", ifstmt },
 11971222         { "include", include },
 11981223         { "else", elsestmt },
 11991224         { "endif", endifstmt },
 12001225         { "error", cpperror },
 12011226         { "warning", cppwarning },
 12021227         { "define", define },
 12031228         { "undef", undefstmt },
 12041229         { "line", line },
 12051230         { "pragma", pragmastmt },
 12061231         { "elif", elifstmt },
 12071232 #ifdef GCC_COMPAT
 12081233         { "include_next", include_next },
 12091234 #endif
 12101235 };
 12111236 
 12121237 /*
 12131238  * Handle a preprocessor directive.
 12141239  */
 12151240 void
 12161241 ppdir(void)
 12171242 {
 12181243         char bp[20];
 12191244         int ch, i;
 12201245 
 12211246         while ((ch = inch()) == ' ' || ch == '\t')
 12221247                 ;
 12231248         if (ch == '\n') { /* empty directive */
 12241249                 unch(ch);
 12251250                 return;
 12261251         }
 12271252         if (ch < 'a' || ch > 'z')
 12281253                 goto out; /* something else, ignore */
 12291254         i = 0;
 12301255         do {
 12311256                 bp[i++] = (usch)ch;
 12321257                 if (i == sizeof(bp)-1)
 12331258                         goto out; /* too long */
 12341259                 ch = inch();
 12351260         } while ((ch >= 'a' && ch <= 'z') || (ch == '_'));
 12361261         unch(ch);
 12371262         bp[i++] = 0;
 12381263 
 12391264         /* got keyword */
 12401265 #define SZ (int)(sizeof(ppd)/sizeof(ppd[0]))
 12411266         for (i = 0; i < SZ; i++)
 12421267                 if (bp[0] == ppd[i].name[0] && strcmp(bp, ppd[i].name) == 0)
 12431268                         break;
 12441269         if (i == SZ)
 12451270                 goto out;
 12461271 
 12471272         /* Found matching keyword */
 12481273         (*ppd[i].fun)();
 12491274         return;
 12501275 
 12511276 out:    while ((ch = inch()) != '\n' && ch != -1)
 12521277                 ;
 12531278         unch('\n');
 12541279 }
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 04:06 +0200