Quick Search:

Mode

Context

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

Other Diffs

Ignore

Blank Lines Whitespace: Expand:

Diff

1.36
 
1.37
 
MAIN:ragge:20100607071035
 
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 cpperror(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 
 8585 #define PUTCH(ch) if (!flslvl) putch(ch)
 8686 /* protection against recursion in #include */
 8787 #define MAX_INCLEVEL    100
 8888 static int inclevel;
 8989 
 9090 /* get next character unaltered */
 9191 #define NXTCH() (ifiles->curptr < ifiles->maxread ? *ifiles->curptr++ : inpch())
 9292 
 9393 #ifdef YYTEXT_POINTER
 9494 static char buf[CPPBUF];
 9595 char *yytext = buf;
 9696 #else
 9797 char yytext[CPPBUF];
 9898 #endif
 9999 
 100100 #define C_SPEC  1
 101101 #define C_EP    2
 102102 #define C_ID    4
 103103 #define C_I     (C_SPEC|C_ID)
 104104 #define C_2     8               /* for yylex() tokenizing */
 105105 static char spechr[256] = {
 106106         0,      0,      0,      0,      0,      0,      0,      0,
 107107         0,      0,      C_SPEC0,      0,      0,      0,      0,
 108108         0,      0,      0,      0,      0,      0,      0,      0,
 109109         0,      0,      0,      0,      0,      0,      0,      0,
 110110 
 111111         0,      C_2,    C_SPEC0,      0,      0,      C_2,    C_SPEC,
 112112         0,      0,      0,      C_2,    0,      C_2,    0,      C_SPEC|C_2,
 113113         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 114114         C_I,    C_I,    0,      0,      C_2,    C_2,    C_2,    C_SPEC,
 115115 
 116116         0,      C_I,    C_I,    C_I,    C_I,    C_I|C_EP, C_I,  C_I,
 117117         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 118118         C_I|C_EP, C_I,  C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
<>119 -        C_I,    C_I,    C_I,    0,      0,      0,      0,      C_I,
  119+        C_I,    C_I,    C_I,    0,      C_I,    0,      0,      C_I,
120120 
 121121         0,      C_I,    C_I,    C_I,    C_I,    C_I|C_EP, C_I,  C_I,
 122122         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 123123         C_I|C_EP, C_I,  C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 124124         C_I,    C_I,    C_I,    0,      C_2,    0,      0,      0,
 125125 
 126126 };
 127127 
 128128 static void
 129129 unch(int c)
 130130 {
 131131                 
 132132         --ifiles->curptr;
 133133         if (ifiles->curptr < ifiles->bbuf)
 134134                 error("pushback buffer full");
 135135         *ifiles->curptr = (usch)c;
 136136 }
 137137 
 138138 /*
 139139  * Scan quickly the input file searching for:
 140140  *      - '#' directives
 141141  *      - keywords (if not flslvl)
 142142  *      - comments
 143143  *
 144144  *      Handle strings, numbers and trigraphs with care.
 145145  *      Only data from pp files are scanned here, never any rescans.
 146146  *      TODO: Only print out strings before calling other functions.
 147147  */
 148148 static void
 149149 fastscan(void)
 150150 {
 151151         struct symtab *nl;
 152152         int ch, i;
 153153 
 154154         goto run;
 155155         for (;;) {
 156156                 ch = NXTCH();
 157157 xloop:          if (ch == -1)
 158158                         return;
 159159                 if ((spechr[ch] & C_SPEC) == 0) {
 160160                         PUTCH(ch);
 161161                         continue;
 162162                 }
 163163                 switch (ch) {
 164164                 case '/': /* Comments */
 165165                         if ((ch = inch()) == '/') {
 166166                                 if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
 167167                                 do {
 168168                                         if (Cflag) PUTCH(ch);
 169169                                         ch = inch();
 170170                                 } while (ch != -1 && ch != '\n');
 171171                                 goto xloop;
 172172                         } else if (ch == '*') {
 173173                                 if (Cflag) { PUTCH('/'); PUTCH('*'); }
 174174                                 for (;;) {
 175175                                         ch = inch();
 176176                                         if (ch == '\n') {
 177177                                                 ifiles->lineno++;
 178178                                                 PUTCH('\n');
 179179                                         }
 180180                                         if (ch == -1)
 181181                                                 return;
 182182                                         if (ch == '*') {
 183183                                                 ch = inch();
 184184                                                 if (ch == '/') {
 185185                                                         if (Cflag) {
 186186                                                                 PUTCH('*');
 187187                                                                 PUTCH('/');
 188188                                                         } else
 189189                                                                 PUTCH(' ');
 190190                                                         break;
 191191                                                 }
 192192                                                 unch(ch);
 193193                                                 ch = '*';
 194194                                         }
 195195                                         if (Cflag) PUTCH(ch);
 196196                                 }
 197197                         } else {
 198198                                 PUTCH('/');
 199199                                 goto xloop;
 200200                         }
 201201                         break;
 202202 
 203203                 case '?'/* trigraphs */
 204204                         if ((ch = chktg()))
 205205                                 goto xloop;
 206206                         PUTCH('?');
 207207                         break;
 208208 
<> 209+                case '\\':
  210+                        if ((ch = NXTCH()) == '\n') {
  211+                                ifiles->lineno++;
  212+                                continue;
  213+                        } else {
  214+                                PUTCH('\\');
  215+                        }
  216+                        goto xloop;
  217+
<_209218                 case '\n': /* newlines, for pp directives */
 210219                         ifiles->lineno++;
 211220                         do {
 212221                                 PUTCH(ch);
 213222 run:                            ch = NXTCH();
 214223                         } while (ch == ' ' || ch == '\t');
 215224                         if (ch == '#') {
 216225                                 ppdir();
 217226                                 continue;
 218227                         }
 219228                         goto xloop;
 220229 
 221230                 case '\"': /* strings */
 222231 str:                    PUTCH(ch);
 223232                         while ((ch = inch()) != '\"') {
 224233                                 PUTCH(ch);
 225234                                 if (ch == '\\') {
 226235                                         ch = inch();
 227236                                         PUTCH(ch);
 228237                                 }
 229238                                 if (ch < 0)
 230239                                         return;
 231240                         }
 232241                         PUTCH(ch);
 233242                         break;
 234243 
 235244                 case '.'/* for pp-number */
 236245                         PUTCH(ch);
 237246                         ch = NXTCH();
 238247                         if (ch < '0' || ch > '9')
 239248                                 goto xloop;
 240249                         /* FALLTHROUGH */
 241250                 case '0': case '1': case '2': case '3': case '4':
 242251                 case '5': case '6': case '7': case '8': case '9':
 243252                         do {
 244253                                 PUTCH(ch);
 245254                                 ch = NXTCH();
 246255                                 if (spechr[ch] & C_EP) {
 247256                                         PUTCH(ch);
 248257                                         ch = NXTCH();
 249258                                         if (ch == '-' || ch == '+')
 250259                                                 continue;
 251260                                 }
 252261                         } while ((spechr[ch] & C_ID) || (ch == '.'));
 253262                         goto xloop;
 254263 
 255264                 case '\'': /* character literal */
 256265 con:                    PUTCH(ch);
 257266                         if (tflag)
 258267                                 continue; /* character constants ignored */
 259268                         while ((ch = NXTCH()) != '\'') {
 260269                                 PUTCH(ch);
 261270                                 if (ch == '\\') {
 262271                                         ch = NXTCH();
 263272                                         PUTCH(ch);
 264273                                 } else if (ch < 0)
 265274                                         return;
 266275                                 else if (ch == '\n')
 267276                                         goto xloop;
 268277                         }
 269278                         PUTCH(ch);
 270279                         break;
 271280 
 272281                 case 'L':
 273282                         ch = NXTCH();
 274283                         if (ch == '\"') {
 275284                                 PUTCH('L');
 276285                                 goto str;
 277286                         }
 278287                         if (ch == '\'') {
 279288                                 PUTCH('L');
 280289                                 goto con;
 281290                         }
 282291                         unch(ch);
 283292                         ch = 'L';
 284293                         /* FALLTHROUGH */
 285294                 default:
 286295                         if ((spechr[ch] & C_ID) == 0)
 287296                                 error("fastscan");
 288297                         if (flslvl) {
 289298                                 while (spechr[ch] & C_ID)
 290299                                         ch = NXTCH();
 291300                                 goto xloop;
 292301                         }
 293302                         i = 0;
 294303                         do {
 295304                                 yytext[i++] = (usch)ch;
 296305                                 ch = NXTCH();
 297306                                 if (ch == '\\') {
 298307                                         ch = NXTCH();
 299308                                         if (ch != '\n') {
 300309                                                 unch('\n');
 301310                                                 ch = '\\';
 302311                                         } else {
 303312                                                 ifiles->lineno++;
 304313                                                 ch = NXTCH();
 305314                                         }
 306315                                 }
 307316                                 if (ch < 0)
 308317                                         return;
 309318                         } while (spechr[ch] & C_ID);
 310319                         yytext[i] = 0;
 311320                         unch(ch);
 312321                         if ((nl = lookup((usch *)yytext, FIND)) != 0) {
 313322                                 usch *op = stringbuf;
 314323                                 putstr(gotident(nl));
 315324                                 stringbuf = op;
 316325                         } else
 317326                                 putstr((usch *)yytext);
 318327                         break;
 319328                 }
 320329         }
 321330 }
 322331 
 323332 int
 324333 sloscan()
 325334 {
 326335         int ch;
 327336         int yyp;
 328337 
 329338 zagain:
 330339         yyp = 0;
 331340         ch = inch();
 332341         yytext[yyp++] = (usch)ch;
 333342         switch (ch) {
 334343         case -1:
 335344                 return 0;
 336345         case '\n':
 337346                 /* sloscan() never passes \n, that's up to fastscan() */
 338347                 unch(ch);
 339348                 goto yyret;
 340349 
 341350         case '\r': /* Ignore CR's */
 342351                 yyp = 0;
 343352                 break;
 344353 
 345354         case '0': case '1': case '2': case '3': case '4': case '5':
 346355         case '6': case '7': case '8': case '9':
 347356                 /* readin a "pp-number" */
 348357 ppnum:          for (;;) {
 349358                         ch = inch();
 350359                         if (spechr[ch] & C_EP) {
 351360                                 yytext[yyp++] = (usch)ch;
 352361                                 ch = inch();
 353362                                 if (ch == '-' || ch == '+') {
 354363                                         yytext[yyp++] = (usch)ch;
 355364                                 } else
 356365                                         unch(ch);
 357366                                 continue;
 358367                         }
 359368                         if ((spechr[ch] & C_ID) || ch == '.') {
 360369                                 yytext[yyp++] = (usch)ch;
 361370                                 continue;
 362371                         }
 363372                         break;
 364373                 }
 365374                 unch(ch);
 366375                 yytext[yyp] = 0;
 367376 
 368377                 return NUMBER;
 369378 
 370379         case '\'':
 371380 chlit:          
 372381                 for (;;) {
 373382                         if ((ch = inch()) == '\\') {
 374383                                 yytext[yyp++] = (usch)ch;
 375384                                 yytext[yyp++] = (usch)inch();
 376385                                 continue;
 377386                         } else if (ch == '\n') {
 378387                                 /* not a constant */
 379388                                 while (yyp > 1)
 380389                                         unch(yytext[--yyp]);
 381390                                 ch = '\'';
 382391                                 goto any;
 383392                         } else
 384393                                 yytext[yyp++] = (usch)ch;
 385394                         if (ch == '\'')
 386395                                 break;
 387396                 }
 388397                 yytext[yyp] = 0;
 389398 
 390399                 return (NUMBER);
 391400 
 392401         case ' ':
 393402         case '\t':
 394403                 while ((ch = inch()) == ' ' || ch == '\t')
 395404                         yytext[yyp++] = (usch)ch;
 396405                 unch(ch);
 397406                 yytext[yyp] = 0;
 398407                 return(WSPACE);
 399408 
 400409         case '/':
 401410                 if ((ch = inch()) == '/') {
 402411                         do {
 403412                                 yytext[yyp++] = (usch)ch;
 404413                                 ch = inch();
 405414                         } while (ch && ch != '\n');
 406415                         yytext[yyp] = 0;
 407416                         unch(ch);
 408417                         goto zagain;
 409418                 } else if (ch == '*') {
 410419                         int c, wrn;
 411420                         extern int readmac;
 412421 
 413422                         if (Cflag && !flslvl && readmac) {
 414423                                 unch(ch);
 415424                                 yytext[yyp] = 0;
 416425                                 return CMNT;
 417426                         }
 418427 
 419428                         wrn = 0;
 420429                 more:   while ((c = inch()) && c != '*') {
 421430                                 if (c == '\n')
 422431                                         putch(c), ifiles->lineno++;
 423432                                 else if (c == 1) /* WARN */
 424433                                         wrn = 1;
 425434                         }
 426435                         if (c == 0)
 427436                                 return 0;
 428437                         if ((c = inch()) && c != '/') {
 429438                                 unch(c);
 430439                                 goto more;
 431440                         }
 432441                         if (c == 0)
 433442                                 return 0;
 434443                         if (!tflag && !Cflag && !flslvl)
 435444                                 unch(' ');
 436445                         if (wrn)
 437446                                 unch(1);
 438447                         goto zagain;
 439448                 }
 440449                 unch(ch);
 441450                 ch = '/';
 442451                 goto any;
 443452 
 444453         case '.':
 445454                 ch = inch();
 446455                 if (isdigit(ch)) {
 447456                         yytext[yyp++] = (usch)ch;
 448457                         goto ppnum;
 449458                 } else {
 450459                         unch(ch);
 451460                         ch = '.';
 452461                 }
 453462                 goto any;
 454463 
 455464         case '\"':
 456465         strng:
 457466                 for (;;) {
 458467                         if ((ch = inch()) == '\\') {
 459468                                 yytext[yyp++] = (usch)ch;
 460469                                 yytext[yyp++] = (usch)inch();
 461470                                 continue;
 462471                         } else
 463472                                 yytext[yyp++] = (usch)ch;
 464473                         if (ch == '\"')
 465474                                 break;
 466475                 }
 467476                 yytext[yyp] = 0;
 468477                 return(STRING);
 469478 
 470479         case 'L':
 471480                 if ((ch = inch()) == '\"') {
 472481                         yytext[yyp++] = (usch)ch;
 473482                         goto strng;
 474483                 } else if (ch == '\'') {
 475484                         yytext[yyp++] = (usch)ch;
 476485                         goto chlit;
 477486                 }
 478487                 unch(ch);
 479488                 /* FALLTHROUGH */
 480489 
 481490         /* Yetch, all identifiers */
 482491         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
 483492         case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
 484493         case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
 485494         case 's': case 't': case 'u': case 'v': case 'w': case 'x':
 486495         case 'y': case 'z':
 487496         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
 488497         case 'G': case 'H': case 'I': case 'J': case 'K':
 489498         case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
 490499         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
 491500         case 'Y': case 'Z':
 492501         case '_': /* {L}({L}|{D})* */
 493502 
 494503                 /* Special hacks */
 495504                 for (;;) { /* get chars */
 496505                         ch = inch();
 497506                         if (isalpha(ch) || isdigit(ch) || ch == '_') {
 498507                                 yytext[yyp++] = (usch)ch;
 499508                         } else {
 500509                                 unch(ch);
 501510                                 break;
 502511                         }
 503512                 }
 504513                 yytext[yyp] = 0; /* need already string */
 505514                 /* end special hacks */
 506515 
 507516                 return IDENT;
 508517         default:
 509518         any:
 510519                 yytext[yyp] = 0;
 511520                 return yytext[0];
 512521 
 513522         } /* endcase */
 514523         goto zagain;
 515524 
 516525 yyret:
 517526         yytext[yyp] = 0;
 518527         return ch;
 519528 }
 520529 
 521530 int
 522531 yylex()
 523532 {
 524533         static int ifdef, noex;
 525534         struct symtab *nl;
 526535         int ch, c2;
 527536 
 528537         while ((ch = sloscan()) == WSPACE)
 529538                 ;
 530539         if (ch < 128 && spechr[ch] & C_2)
 531540                 c2 = inpch();
 532541         else
 533542                 c2 = 0;
 534543 
 535544 #define C2(a,b,c) case a: if (c2 == b) return c; break
 536545         switch (ch) {
 537546         C2('=', '=', EQ);
 538547         C2('!', '=', NE);
 539548         C2('|', '|', OROR);
 540549         C2('&', '&', ANDAND);
 541550         case '<':
 542551                 if (c2 == '<') return LS;
 543552                 if (c2 == '=') return LE;
 544553                 break;
 545554         case '>':
 546555                 if (c2 == '>') return RS;
 547556                 if (c2 == '=') return GE;
 548557                 break;
 549558         case '+':
 550559         case '-':
 551560                 if (ch == c2)
 552561                         badop("");
 553562                 break;
 554563 
 555564         case '/':
 556565                 if (Cflag == 0 || c2 != '*')
 557566                         break;
 558567                 /* Found comment that need to be skipped */
 559568                 for (;;) {
 560569                         ch = inpch();
 561570                 c1:     if (ch != '*')
 562571                                 continue;
 563572                         if ((ch = inpch()) == '/')
 564573                                 break;
 565574                         goto c1;
 566575                 }
 567576                 return yylex();
 568577 
 569578         case NUMBER:
 570579                 if (yytext[0] == '\'') {
 571580                         yylval.node.op = NUMBER;
 572581                         yylval.node.nd_val = charcon((usch *)yytext);
 573582                 } else
 574583                         cvtdig(yytext[0] != '0' ? 10 :
 575584                             yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
 576585                 return NUMBER;
 577586 
 578587         case IDENT:
 579588                 if (strcmp(yytext, "defined") == 0) {
 580589                         ifdef = 1;
 581590                         return DEFINED;
 582591                 }
 583592                 nl = lookup((usch *)yytext, FIND);
 584593                 if (ifdef) {
 585594                         yylval.node.nd_val = nl != NULL;
 586595                         ifdef = 0;
 587596                 } else if (nl && noex == 0) {
 588597                         usch *c, *och = stringbuf;
 589598 
 590599                         c = gotident(nl);
 591600                         unch(1);
 592601                         unpstr(c);
 593602                         stringbuf = och;
 594603                         noex = 1;
 595604                         return yylex();
 596605                 } else {
 597606                         yylval.node.nd_val = 0;
 598607                 }
 599608                 yylval.node.op = NUMBER;
 600609                 return NUMBER;
 601610         case 1: /* WARN */
 602611                 noex = 0;
 603612                 return yylex();
 604613         default:
 605614                 return ch;
 606615         }
 607616         unch(c2);
 608617         return ch;
 609618 }
 610619 
 611620 usch *yyp, yybuf[CPPBUF];
 612621 
 613622 int yywrap(void);
 614623 
 615624 static int
 616625 inpch(void)
 617626 {
 618627         int len;
 619628 
 620629         if (ifiles->curptr < ifiles->maxread)
 621630                 return *ifiles->curptr++;
 622631 
 623632         if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0)
 624633                 error("read error on file %s", ifiles->orgfn);
 625634         if (len == 0)
 626635                 return -1;
 627636         ifiles->curptr = ifiles->buffer;
 628637         ifiles->maxread = ifiles->buffer + len;
 629638         return inpch();
 630639 }
 631640 
 632641 static int
 633642 inch(void)
 634643 {
 635644         int c;
 636645 
 637646 again:  switch (c = inpch()) {
 638647         case '\\': /* continued lines */
 639648 msdos:          if ((c = inpch()) == '\n') {
 640649                         ifiles->lineno++;
 641650                         goto again;
 642651                 } else if (c == '\r')
 643652                         goto msdos;
 644653                 unch(c);
 645654                 return '\\';
 646655         case '?': /* trigraphs */
 647656                 if ((c = chktg())) {
 648657                         unch(c);
 649658                         goto again;
 650659                 }
 651660                 return '?';
 652661         default:
 653662                 return c;
 654663         }
 655664 }
 656665 
 657666 /*
 658667  * Let the command-line args be faked defines at beginning of file.
 659668  */
 660669 static void
 661670 prinit(struct initar *it, struct includ *ic)
 662671 {
 663672         const char *pre, *post;
 664673         char *a;
 665674 
 666675         if (it->next)
 667676                 prinit(it->next, ic);
 668677         pre = post = NULL; /* XXX gcc */
 669678         switch (it->type) {
 670679         case 'D':
 671680                 pre = "#define ";
 672681                 if ((a = strchr(it->str, '=')) != NULL) {
 673682                         *a = ' ';
 674683                         post = "\n";
 675684                 } else
 676685                         post = " 1\n";
 677686                 break;
 678687         case 'U':
 679688                 pre = "#undef ";
 680689                 post = "\n";
 681690                 break;
 682691         case 'i':
 683692                 pre = "#include \"";
 684693                 post = "\"\n";
 685694                 break;
 686695         default:
 687696                 error("prinit");
 688697         }
 689698         strlcat((char *)ic->buffer, pre, CPPBUF+1);
 690699         strlcat((char *)ic->buffer, it->str, CPPBUF+1);
 691700         if (strlcat((char *)ic->buffer, post, CPPBUF+1) >= CPPBUF+1)
 692701                 error("line exceeds buffer size");
 693702 
 694703         ic->lineno--;
 695704         while (*ic->maxread)
 696705                 ic->maxread++;
 697706 }
 698707 
 699708 /*
 700709  * A new file included.
 701710  * If ifiles == NULL, this is the first file and already opened (stdin).
 702711  * Return 0 on success, -1 if file to be included is not found.
 703712  */
 704713 int
 705714 pushfile(const usch *file, const usch *fn, int idx, void *incs)
 706715 {
 707716         extern struct initar *initar;
 708717         struct includ ibuf;
 709718         struct includ *ic;
 710719         int otrulvl;
 711720 
 712721         ic = &ibuf;
 713722         ic->next = ifiles;
 714723 
 715724         if (file != NULL) {
 716725                 if ((ic->infil = open((const char *)file, O_RDONLY)) < 0)
 717726                         return -1;
 718727                 ic->orgfn = ic->fname = file;
 719728                 if (++inclevel > MAX_INCLEVEL)
 720729                         error("Limit for nested includes exceeded");
 721730         } else {
 722731                 ic->infil = 0;
 723732                 ic->orgfn = ic->fname = (const usch *)"<stdin>";
 724733         }
 725734         ic->buffer = ic->bbuf+NAMEMAX;
 726735         ic->curptr = ic->buffer;
 727736         ifiles = ic;
 728737         ic->lineno = 1;
 729738         ic->maxread = ic->curptr;
 730739         ic->idx = idx;
 731740         ic->incs = incs;
 732741         ic->fn = fn;
 733742         prtline();
 734743         if (initar) {
 735744                 *ic->maxread = 0;
 736745                 prinit(initar, ic);
 737746                 if (dMflag)
 738747                         write(ofd, ic->buffer, strlen((char *)ic->buffer));
 739748                 initar = NULL;
 740749         }
 741750 
 742751         otrulvl = trulvl;
 743752 
 744753         fastscan();
 745754 
 746755         if (otrulvl != trulvl || flslvl)
 747756                 error("unterminated conditional");
 748757 
 749758         ifiles = ic->next;
 750759         close(ic->infil);
 751760         inclevel--;
 752761         return 0;
 753762 }
 754763 
 755764 /*
 756765  * Print current position to output file.
 757766  */
 758767 void
 759768 prtline()
 760769 {
 761770         usch *s, *os = stringbuf;
 762771 
 763772         if (Mflag) {
 764773                 if (dMflag)
 765774                         return; /* no output */
 766775                 if (ifiles->lineno == 1) {
 767776                         s = sheap("%s: %s\n", Mfile, ifiles->fname);
 768777                         write(ofd, s, strlen((char *)s));
 769778                 }
 770779         } else if (!Pflag)
 771780                 putstr(sheap("\n# %d \"%s\"\n", ifiles->lineno, ifiles->fname));
 772781         stringbuf = os;
 773782 }
 774783 
 775784 void
 776785 cunput(int c)
 777786 {
 778787 #ifdef CPP_DEBUG
 779788         extern int dflag;
 780789         if (dflag)printf(": '%c'(%d)", c > 31 ? c : ' ', c);
 781790 #endif
 782791 #if 0
 783792 if (c == 10) {
 784793         printf("c == 10!!!\n");
 785794 }
 786795 #endif
 787796         unch(c);
 788797 }
 789798 
 790799 int yywrap(void) { return 1; }
 791800 
 792801 static int
 793802 dig2num(int c)
 794803 {
 795804         if (c >= 'a')
 796805                 c = c - 'a' + 10;
 797806         else if (c >= 'A')
 798807                 c = c - 'A' + 10;
 799808         else
 800809                 c = c - '0';
 801810         return c;
 802811 }
 803812 
 804813 /*
 805814  * Convert string numbers to unsigned long long and check overflow.
 806815  */
 807816 static void
 808817 cvtdig(int rad)
 809818 {
 810819         unsigned long long rv = 0;
 811820         unsigned long long rv2 = 0;
 812821         char *y = yytext;
 813822         int c;
 814823 
 815824         c = *y++;
 816825         if (rad == 16)
 817826                 y++;
 818827         while (isxdigit(c)) {
 819828                 rv = rv * rad + dig2num(c);
 820829                 /* check overflow */
 821830                 if (rv / rad < rv2)
 822831                         error("Constant \"%s\" is out of range", yytext);
 823832                 rv2 = rv;
 824833                 c = *y++;
 825834         }
 826835         y--;
 827836         while (*y == 'l' || *y == 'L')
 828837                 y++;
 829838         yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER;
 830839         yylval.node.nd_uval = rv;
 831840         if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0)
 832841                 yylval.node.op = UNUMBER;
 833842         if (yylval.node.op == NUMBER && yylval.node.nd_val < 0)
 834843                 /* too large for signed, see 6.4.4.1 */
 835844                 error("Constant \"%s\" is out of range", yytext);
 836845 }
 837846 
 838847 static int
 839848 charcon(usch *p)
 840849 {
 841850         int val, c;
 842851 
 843852         p++; /* skip first ' */
 844853         val = 0;
 845854         if (*p++ == '\\') {
 846855                 switch (*p++) {
 847856                 case 'a': val = '\a'; break;
 848857                 case 'b': val = '\b'; break;
 849858                 case 'f': val = '\f'; break;
 850859                 case 'n': val = '\n'; break;
 851860                 case 'r': val = '\r'; break;
 852861                 case 't': val = '\t'; break;
 853862                 case 'v': val = '\v'; break;
 854863                 case '\"': val = '\"'; break;
 855864                 case '\'': val = '\''; break;
 856865                 case '\\': val = '\\'; break;
 857866                 case 'x':
 858867                         while (isxdigit(c = *p)) {
 859868                                 val = val * 16 + dig2num(c);
 860869                                 p++;
 861870                         }
 862871                         break;
 863872                 case '0': case '1': case '2': case '3': case '4':
 864873                 case '5': case '6': case '7':
 865874                         p--;
 866875                         while (isdigit(c = *p)) {
 867876                                 val = val * 8 + (c - '0');
 868877                                 p++;
 869878                         }
 870879                         break;
 871880                 default: val = p[-1];
 872881                 }
 873882 
 874883         } else
 875884                 val = p[-1];
 876885         return val;
 877886 }
 878887 
 879888 static void
 880889 chknl(int ignore)
 881890 {
 882891         int t;
 883892 
 884893         while ((t = sloscan()) == WSPACE)
 885894                 ;
 886895         if (t != '\n') {
 887896                 if (ignore) {
 888897                         warning("newline expected, got \"%s\"", yytext);
 889898                         /* ignore rest of line */
 890899                         while ((t = sloscan()) && t != '\n')
 891900                                 ;
 892901                 }
 893902                 else
 894903                         error("newline expected, got \"%s\"", yytext);
 895904         }
 896905 }
 897906 
 898907 static void
 899908 elsestmt(void)
 900909 {
 901910         if (flslvl) {
 902911                 if (elflvl > trulvl)
 903912                         ;
 904913                 else if (--flslvl!=0) {
 905914                         flslvl++;
 906915                 } else {
 907916                         trulvl++;
 908917                         prtline();
 909918                 }
 910919         } else if (trulvl) {
 911920                 flslvl++;
 912921                 trulvl--;
 913922         } else
 914923                 error("If-less else");
 915924         if (elslvl==trulvl+flslvl)
 916925                 error("Too many else");
 917926         elslvl=trulvl+flslvl;
 918927         chknl(1);
 919928 }
 920929 
 921930 static void
 922931 skpln(void)
 923932 {
 924933         /* just ignore the rest of the line */
 925934         while (inch() != '\n')
 926935                 ;
 927936         unch('\n');
 928937         flslvl++;
 929938 }
 930939 
 931940 static void
 932941 ifdefstmt(void)         
 933942 {
 934943         int t;
 935944 
 936945         if (flslvl) {
 937946                 skpln();
 938947                 return;
 939948         }
 940949         do
 941950                 t = sloscan();
 942951         while (t == WSPACE);
 943952         if (t != IDENT)
 944953                 error("bad ifdef");
 945954         if (lookup((usch *)yytext, FIND) == 0) {
 946955                 putch('\n');
 947956                 flslvl++;
 948957         } else
 949958                 trulvl++;
 950959         chknl(0);
 951960 }
 952961 
 953962 static void
 954963 ifndefstmt(void)         
 955964 {
 956965         int t;
 957966 
 958967         if (flslvl) {
 959968                 skpln();
 960969                 return;
 961970         }
 962971         do
 963972                 t = sloscan();
 964973         while (t == WSPACE);
 965974         if (t != IDENT)
 966975                 error("bad ifndef");
 967976         if (lookup((usch *)yytext, FIND) != 0) {
 968977                 putch('\n');
 969978                 flslvl++;
 970979         } else
 971980                 trulvl++;
 972981         chknl(0);
 973982 }
 974983 
 975984 static void
 976985 endifstmt(void)         
 977986 {
 978987         if (flslvl) {
 979988                 flslvl--;
 980989                 if (flslvl == 0) {
 981990                         putch('\n');
 982991                         prtline();
 983992                 }
 984993         } else if (trulvl)
 985994                 trulvl--;
 986995         else
 987996                 error("If-less endif");
 988997         if (flslvl == 0)
 989998                 elflvl = 0;
 990999         elslvl = 0;
 9911000         chknl(1);
 9921001 }
 9931002 
 9941003 static void
 9951004 ifstmt(void)
 9961005 {
 9971006         if (flslvl == 0) {
 9981007                 if (yyparse() == 0) {
 9991008                         putch('\n');
 10001009                         ++flslvl;
 10011010                 } else
 10021011                         ++trulvl;
 10031012         } else
 10041013                 ++flslvl;
 10051014 }
 10061015 
 10071016 static void
 10081017 elifstmt(void)
 10091018 {
 10101019         if (flslvl == 0)
 10111020                 elflvl = trulvl;
 10121021         if (flslvl) {
 10131022                 if (elflvl > trulvl)
 10141023                         ;
 10151024                 else if (--flslvl!=0)
 10161025                         ++flslvl;
 10171026                 else {
 10181027                         if (yyparse()) {
 10191028                                 ++trulvl;
 10201029                                 prtline();
 10211030                         } else {
 10221031                                 putch('\n');
 10231032                                 ++flslvl;
 10241033                         }
 10251034                 }
 10261035         } else if (trulvl) {
 10271036                 ++flslvl;
 10281037                 --trulvl;
 10291038         } else
 10301039                 error("If-less elif");
 10311040 }
 10321041 
 10331042 static usch *
 10341043 svinp(void)
 10351044 {
 10361045         int c;
 10371046         usch *cp = stringbuf;
 10381047 
 10391048         while ((c = inch()) && c != '\n')
 10401049                 savch(c);
 10411050         savch('\n');
 10421051         savch(0);
 10431052         return cp;
 10441053 }
 10451054 
 10461055 static void
 10471056 cpperror(void)
 10481057 {
 10491058         usch *cp;
 10501059         int c;
 10511060 
 10521061         if (flslvl)
 10531062                 return;
 10541063         c = sloscan();
 10551064         if (c != WSPACE && c != '\n')
 10561065                 error("bad error");
 10571066         cp = svinp();
 10581067         if (flslvl)
 10591068                 stringbuf = cp;
 10601069         else
 10611070                 error("%s", cp);
 10621071 }
 10631072 
 10641073 static void
 10651074 undefstmt(void)
 10661075 {
 10671076         struct symtab *np;
 10681077 
 10691078         if (sloscan() != WSPACE || sloscan() != IDENT)
 10701079                 error("bad undef");
 10711080         if (flslvl == 0 && (np = lookup((usch *)yytext, FIND)))
 10721081                 np->value = 0;
 10731082         chknl(0);
 10741083 }
 10751084 
 10761085 static void
 10771086 pragmastmt(void)
 10781087 {
 10791088         int c;
 10801089 
 10811090         if (sloscan() != WSPACE)
 10821091                 error("bad pragma");
 10831092         if (!flslvl)
 10841093                 putstr((const usch *)"#pragma ");
 10851094         do {
 10861095                 c = inch();
 10871096                 if (!flslvl)
 10881097                         putch(c);       /* Do arg expansion instead? */
 10891098         } while (c && c != '\n');
 10901099         if (c == '\n')
 10911100                 unch(c);
 10921101         prtline();
 10931102 }
 10941103 
 10951104 static void
 10961105 badop(const char *op)
 10971106 {
 10981107         error("invalid operator in preprocessor expression: %s", op);
 10991108 }
 11001109 
 11011110 int
 11021111 cinput()
 11031112 {
 11041113         return inch();
 11051114 }
 11061115 
 11071116 /*
 11081117  * Check for (and convert) trigraphs.
 11091118  */
 11101119 int
 11111120 chktg()
 11121121 {
 11131122         int c;
 11141123 
 11151124         if ((c = inpch()) != '?') {
 11161125                 unch(c);
 11171126                 return 0;
 11181127         }
 11191128         switch (c = inpch()) {
 11201129         case '=': c = '#'; break;
 11211130         case '(': c = '['; break;
 11221131         case ')': c = ']'; break;
 11231132         case '<': c = '{'; break;
 11241133         case '>': c = '}'; break;
 11251134         case '/': c = '\\'; break;
 11261135         case '\'': c = '^'; break;
 11271136         case '!': c = '|'; break;
 11281137         case '-': c = '~'; break;
 11291138         default:
 11301139                 unch(c);
 11311140                 unch('?');
 11321141                 c = 0;
 11331142         }
 11341143         return c;
 11351144 }
 11361145 
 11371146 static struct {
 11381147         const char *name;
 11391148         void (*fun)(void);
 11401149 } ppd[] = {
 11411150         { "ifndef", ifndefstmt },
 11421151         { "ifdef", ifdefstmt },
 11431152         { "if", ifstmt },
 11441153         { "include", include },
 11451154         { "else", elsestmt },
 11461155         { "endif", endifstmt },
 11471156         { "error", cpperror },
 11481157         { "define", define },
 11491158         { "undef", undefstmt },
 11501159         { "line", line },
 11511160         { "pragma", pragmastmt },
 11521161         { "elif", elifstmt },
 11531162 #ifdef GCC_COMPAT
 11541163         { "include_next", include_next },
 11551164 #endif
 11561165 };
 11571166 
 11581167 /*
 11591168  * Handle a preprocessor directive.
 11601169  */
 11611170 void
 11621171 ppdir(void)
 11631172 {
 11641173         char bp[20];
 11651174         int ch, i;
 11661175 
 11671176         while ((ch = inch()) == ' ' || ch == '\t')
 11681177                 ;
 11691178         if (ch == '\n') { /* empty directive */
 11701179                 unch(ch);
 11711180                 return;
 11721181         }
 11731182         if (ch < 'a' || ch > 'z')
 11741183                 goto out; /* something else, ignore */
 11751184         i = 0;
 11761185         do {
 11771186                 bp[i++] = (usch)ch;
 11781187                 if (i == sizeof(bp)-1)
 11791188                         goto out; /* too long */
 11801189                 ch = inch();
 11811190         } while ((ch >= 'a' && ch <= 'z') || (ch == '_'));
 11821191         unch(ch);
 11831192         bp[i++] = 0;
 11841193 
 11851194         /* got keyword */
 11861195 #define SZ (int)(sizeof(ppd)/sizeof(ppd[0]))
 11871196         for (i = 0; i < SZ; i++)
 11881197                 if (bp[0] == ppd[i].name[0] && strcmp(bp, ppd[i].name) == 0)
 11891198                         break;
 11901199         if (i == SZ)
 11911200                 goto out;
 11921201 
 11931202         /* Found matching keyword */
 11941203         (*ppd[i].fun)();
 11951204         return;
 11961205 
 11971206 out:    while ((ch = inch()) != '\n' && ch != -1)
 11981207                 ;
 11991208         unch('\n');
 12001209 }
FishEye: Open Source License registered to PCC.
Atlassian FishEye, CVS analysis. (Version:1.6.3 Build:build-336 2008-11-04) - Administration - Page generated 2014-12-22 12:20 +0100