Quick Search:

Mode

Context

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

Other Diffs

Ignore

Blank Lines Whitespace: Expand:

Diff

1.29
 
1.30
 
MAIN:ragge:20091231131728
 
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,
 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,
 119119         C_I,    C_I,    C_I,    0,      0,      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                                                 } else
 192192                                                         unch(ch);
 193193                                         }
 194194                                         if (Cflag) PUTCH(ch);
 195195                                 }
 196196                         } else {
 197197                                 PUTCH('/');
 198198                                 goto xloop;
 199199                         }
 200200                         break;
 201201 
 202202                 case '?'/* trigraphs */
 203203                         if ((ch = chktg()))
 204204                                 goto xloop;
 205205                         PUTCH('?');
 206206                         break;
 207207 
 208208                 case '\n': /* newlines, for pp directives */
 209209                         ifiles->lineno++;
 210210                         do {
 211211                                 PUTCH(ch);
 212212 run:                            ch = NXTCH();
 213213                         } while (ch == ' ' || ch == '\t');
 214214                         if (ch == '#') {
 215215                                 ppdir();
 216216                                 continue;
 217217                         }
 218218                         goto xloop;
 219219 
 220220                 case '\"': /* strings */
 221221 str:                    PUTCH(ch);
 222222                         while ((ch = inch()) != '\"') {
 223223                                 PUTCH(ch);
 224224                                 if (ch == '\\') {
 225225                                         ch = inch();
 226226                                         PUTCH(ch);
 227227                                 }
 228228                                 if (ch < 0)
 229229                                         return;
 230230                         }
 231231                         PUTCH(ch);
 232232                         break;
 233233 
 234234                 case '.'/* for pp-number */
 235235                         PUTCH(ch);
 236236                         ch = NXTCH();
 237237                         if (ch < '0' || ch > '9')
 238238                                 goto xloop;
 239239                         /* FALLTHROUGH */
 240240                 case '0': case '1': case '2': case '3': case '4':
 241241                 case '5': case '6': case '7': case '8': case '9':
 242242                         do {
 243243                                 PUTCH(ch);
 244244                                 ch = NXTCH();
 245245                                 if (spechr[ch] & C_EP) {
 246246                                         PUTCH(ch);
 247247                                         ch = NXTCH();
 248248                                         if (ch == '-' || ch == '+')
 249249                                                 continue;
 250250                                 }
 251251                         } while ((spechr[ch] & C_ID) || (ch == '.'));
 252252                         goto xloop;
 253253 
 254254                 case '\'': /* character literal */
 255255 con:                    PUTCH(ch);
 256256                         if (tflag)
 257257                                 continue; /* character constants ignored */
 258258                         while ((ch = NXTCH()) != '\'') {
 259259                                 PUTCH(ch);
 260260                                 if (ch == '\\') {
 261261                                         ch = NXTCH();
 262262                                         PUTCH(ch);
 263263                                 } else if (ch < 0)
 264264                                         return;
 265265                                 else if (ch == '\n')
 266266                                         goto xloop;
 267267                         }
 268268                         PUTCH(ch);
 269269                         break;
 270270 
 271271                 case 'L':
 272272                         ch = NXTCH();
 273273                         if (ch == '\"') {
 274274                                 PUTCH('L');
 275275                                 goto str;
 276276                         }
 277277                         if (ch == '\'') {
 278278                                 PUTCH('L');
 279279                                 goto con;
 280280                         }
 281281                         unch(ch);
 282282                         ch = 'L';
 283283                         /* FALLTHROUGH */
 284284                 default:
 285285                         if ((spechr[ch] & C_ID) == 0)
 286286                                 error("fastscan");
 287287                         if (flslvl) {
 288288                                 while (spechr[ch] & C_ID)
 289289                                         ch = NXTCH();
 290290                                 goto xloop;
 291291                         }
 292292                         i = 0;
 293293                         do {
 294294                                 yytext[i++] = (usch)ch;
 295295                                 ch = NXTCH();
 296296                                 if (ch < 0)
 297297                                         return;
 298298                         } while (spechr[ch] & C_ID);
 299299                         yytext[i] = 0;
 300300                         unch(ch);
 301301                         if ((nl = lookup((usch *)yytext, FIND)) != 0) {
 302302                                 usch *op = stringbuf;
 303303                                 putstr(gotident(nl));
 304304                                 stringbuf = op;
 305305                         } else
 306306                                 putstr((usch *)yytext);
 307307                         break;
 308308                 }
 309309         }
 310310 }
 311311 
 312312 int
 313313 sloscan()
 314314 {
 315315         int ch;
 316316         int yyp;
 317317 
 318318 zagain:
 319319         yyp = 0;
 320320         ch = inch();
 321321         yytext[yyp++] = (usch)ch;
 322322         switch (ch) {
 323323         case -1:
 324324                 return 0;
 325325         case '\n':
 326326                 /* sloscan() never passes \n, that's up to fastscan() */
 327327                 unch(ch);
 328328                 goto yyret;
 329329 
 330330         case '\r': /* Ignore CR's */
 331331                 yyp = 0;
 332332                 break;
 333333 
 334334         case '0': case '1': case '2': case '3': case '4': case '5':
 335335         case '6': case '7': case '8': case '9':
 336336                 /* readin a "pp-number" */
 337337 ppnum:          for (;;) {
 338338                         ch = inch();
 339339                         if (spechr[ch] & C_EP) {
 340340                                 yytext[yyp++] = (usch)ch;
 341341                                 ch = inch();
 342342                                 if (ch == '-' || ch == '+') {
 343343                                         yytext[yyp++] = (usch)ch;
 344344                                 } else
 345345                                         unch(ch);
 346346                                 continue;
 347347                         }
 348348                         if ((spechr[ch] & C_ID) || ch == '.') {
 349349                                 yytext[yyp++] = (usch)ch;
 350350                                 continue;
 351351                         }
 352352                         break;
 353353                 }
 354354                 unch(ch);
 355355                 yytext[yyp] = 0;
 356356 
 357357                 return NUMBER;
 358358 
 359359         case '\'':
 360360 chlit:          
 361361                 for (;;) {
 362362                         if ((ch = inch()) == '\\') {
 363363                                 yytext[yyp++] = (usch)ch;
 364364                                 yytext[yyp++] = (usch)inch();
 365365                                 continue;
 366366                         } else if (ch == '\n') {
 367367                                 /* not a constant */
 368368                                 while (yyp > 1)
 369369                                         unch(yytext[--yyp]);
 370370                                 ch = '\'';
 371371                                 goto any;
 372372                         } else
 373373                                 yytext[yyp++] = (usch)ch;
 374374                         if (ch == '\'')
 375375                                 break;
 376376                 }
 377377                 yytext[yyp] = 0;
 378378 
 379379                 return (NUMBER);
 380380 
 381381         case ' ':
 382382         case '\t':
 383383                 while ((ch = inch()) == ' ' || ch == '\t')
 384384                         yytext[yyp++] = (usch)ch;
 385385                 unch(ch);
 386386                 yytext[yyp] = 0;
 387387                 return(WSPACE);
 388388 
 389389         case '/':
 390390                 if ((ch = inch()) == '/') {
 391391                         do {
 392392                                 yytext[yyp++] = (usch)ch;
 393393                                 ch = inch();
 394394                         } while (ch && ch != '\n');
 395395                         yytext[yyp] = 0;
 396396                         unch(ch);
 397397                         goto zagain;
 398398                 } else if (ch == '*') {
 399399                         int c, wrn;
 400400                         extern int readmac;
 401401 
 402402                         if (Cflag && !flslvl && readmac)
 403403                                 return CMNT;
 404404 
 405405                         wrn = 0;
 406406                 more:   while ((c = inch()) && c != '*') {
 407407                                 if (c == '\n')
 408408                                         putch(c), ifiles->lineno++;
 409409                                 else if (c == 1) /* WARN */
 410410                                         wrn = 1;
 411411                         }
 412412                         if (c == 0)
 413413                                 return 0;
 414414                         if ((c = inch()) && c != '/') {
 415415                                 unch(c);
 416416                                 goto more;
 417417                         }
 418418                         if (c == 0)
 419419                                 return 0;
 420420                         if (!tflag && !Cflag && !flslvl)
 421421                                 unch(' ');
 422422                         if (wrn)
 423423                                 unch(1);
 424424                         goto zagain;
 425425                 }
 426426                 unch(ch);
 427427                 ch = '/';
 428428                 goto any;
 429429 
 430430         case '.':
 431431                 ch = inch();
 432432                 if (isdigit(ch)) {
 433433                         yytext[yyp++] = (usch)ch;
 434434                         goto ppnum;
 435435                 } else {
 436436                         unch(ch);
 437437                         ch = '.';
 438438                 }
 439439                 goto any;
 440440 
 441441         case '\"':
 442442         strng:
 443443                 for (;;) {
 444444                         if ((ch = inch()) == '\\') {
 445445                                 yytext[yyp++] = (usch)ch;
 446446                                 yytext[yyp++] = (usch)inch();
 447447                                 continue;
 448448                         } else
 449449                                 yytext[yyp++] = (usch)ch;
 450450                         if (ch == '\"')
 451451                                 break;
 452452                 }
 453453                 yytext[yyp] = 0;
 454454                 return(STRING);
 455455 
 456456         case 'L':
 457457                 if ((ch = inch()) == '\"') {
 458458                         yytext[yyp++] = (usch)ch;
 459459                         goto strng;
 460460                 } else if (ch == '\'') {
 461461                         yytext[yyp++] = (usch)ch;
 462462                         goto chlit;
 463463                 }
 464464                 unch(ch);
 465465                 /* FALLTHROUGH */
 466466 
 467467         /* Yetch, all identifiers */
 468468         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
 469469         case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
 470470         case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
 471471         case 's': case 't': case 'u': case 'v': case 'w': case 'x':
 472472         case 'y': case 'z':
 473473         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
 474474         case 'G': case 'H': case 'I': case 'J': case 'K':
 475475         case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
 476476         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
 477477         case 'Y': case 'Z':
 478478         case '_': /* {L}({L}|{D})* */
 479479 
 480480                 /* Special hacks */
 481481                 for (;;) { /* get chars */
 482482                         ch = inch();
 483483                         if (isalpha(ch) || isdigit(ch) || ch == '_') {
 484484                                 yytext[yyp++] = (usch)ch;
 485485                         } else {
 486486                                 unch(ch);
 487487                                 break;
 488488                         }
 489489                 }
 490490                 yytext[yyp] = 0; /* need already string */
 491491                 /* end special hacks */
 492492 
 493493                 return IDENT;
 494494         default:
 495495         any:
 496496                 yytext[yyp] = 0;
 497497                 return yytext[0];
 498498 
 499499         } /* endcase */
 500500         goto zagain;
 501501 
 502502 yyret:
 503503         yytext[yyp] = 0;
 504504         return ch;
 505505 }
 506506 
 507507 int
 508508 yylex()
 509509 {
 510510         static int ifdef, noex;
 511511         struct symtab *nl;
 512512         int ch, c2;
 513513 
 514514         while ((ch = sloscan()) == WSPACE)
 515515                 ;
 516516         if (ch < 128 && spechr[ch] & C_2)
 517517                 c2 = inpch();
 518518         else
 519519                 c2 = 0;
 520520 
 521521 #define C2(a,b,c) case a: if (c2 == b) return c; break
 522522         switch (ch) {
 523523         C2('=', '=', EQ);
 524524         C2('!', '=', NE);
 525525         C2('|', '|', OROR);
 526526         C2('&', '&', ANDAND);
 527527         case '<':
 528528                 if (c2 == '<') return LS;
 529529                 if (c2 == '=') return LE;
 530530                 break;
 531531         case '>':
 532532                 if (c2 == '>') return RS;
 533533                 if (c2 == '=') return GE;
 534534                 break;
 535535         case '+':
 536536         case '-':
 537537                 if (ch == c2)
 538538                         badop("");
 539539                 break;
 540540 
 541541         case NUMBER:
 542542                 if (yytext[0] == '\'') {
 543543                         yylval.node.op = NUMBER;
 544544                         yylval.node.nd_val = charcon((usch *)yytext);
 545545                 } else
 546546                         cvtdig(yytext[0] != '0' ? 10 :
 547547                             yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
 548548                 return NUMBER;
 549549 
 550550         case IDENT:
 551551                 if (strcmp(yytext, "defined") == 0) {
 552552                         ifdef = 1;
 553553                         return DEFINED;
 554554                 }
 555555                 nl = lookup((usch *)yytext, FIND);
 556556                 if (ifdef) {
 557557                         yylval.node.nd_val = nl != NULL;
 558558                         ifdef = 0;
 559559                 } else if (nl && noex == 0) {
 560560                         usch *c, *och = stringbuf;
 561561 
 562562                         c = gotident(nl);
 563563                         unch(1);
 564564                         unpstr(c);
 565565                         stringbuf = och;
 566566                         noex = 1;
 567567                         return yylex();
 568568                 } else {
 569569                         yylval.node.nd_val = 0;
 570570                 }
 571571                 yylval.node.op = NUMBER;
 572572                 return NUMBER;
 573573         case 1: /* WARN */
 574574                 noex = 0;
 575575                 return yylex();
 576576         default:
 577577                 return ch;
 578578         }
 579579         unch(c2);
 580580         return ch;
 581581 }
 582582 
 583583 usch *yyp, yybuf[CPPBUF];
 584584 
 585585 int yywrap(void);
 586586 
 587587 static int
 588588 inpch(void)
 589589 {
 590590         int len;
 591591 
 592592         if (ifiles->curptr < ifiles->maxread)
 593593                 return *ifiles->curptr++;
 594594 
 595595         if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0)
 596596                 error("read error on file %s", ifiles->orgfn);
 597597         if (len == 0)
 598598                 return -1;
 599599         ifiles->curptr = ifiles->buffer;
 600600         ifiles->maxread = ifiles->buffer + len;
 601601         return inpch();
 602602 }
 603603 
 604604 static int
 605605 inch(void)
 606606 {
 607607         int c;
 608608 
 609609 again:  switch (c = inpch()) {
 610610         case '\\': /* continued lines */
 611611 msdos:          if ((c = inpch()) == '\n') {
 612612                         ifiles->lineno++;
 613613                         goto again;
 614614                 } else if (c == '\r')
 615615                         goto msdos;
 616616                 unch(c);
 617617                 return '\\';
 618618         case '?': /* trigraphs */
 619619                 if ((c = chktg())) {
 620620                         unch(c);
 621621                         goto again;
 622622                 }
 623623                 return '?';
 624624         default:
 625625                 return c;
 626626         }
 627627 }
 628628 
 629629 /*
 630630  * Let the command-line args be faked defines at beginning of file.
 631631  */
 632632 static void
 633633 prinit(struct initar *it, struct includ *ic)
 634634 {
 635635         char *a, *pre, *post;
 636636 
 637637         if (it->next)
 638638                 prinit(it->next, ic);
 639639         pre = post = NULL; /* XXX gcc */
 640640         switch (it->type) {
 641641         case 'D':
 642642                 pre = "#define ";
 643643                 if ((a = strchr(it->str, '=')) != NULL) {
 644644                         *a = ' ';
 645645                         post = "\n";
 646646                 } else
 647647                         post = " 1\n";
 648648                 break;
 649649         case 'U':
 650650                 pre = "#undef ";
 651651                 post = "\n";
 652652                 break;
 653653         case 'i':
 654654                 pre = "#include \"";
 655655                 post = "\"\n";
 656656                 break;
 657657         default:
 658658                 error("prinit");
 659659         }
 660660         strlcat((char *)ic->buffer, pre, CPPBUF+1);
 661661         strlcat((char *)ic->buffer, it->str, CPPBUF+1);
 662662         if (strlcat((char *)ic->buffer, post, CPPBUF+1) >= CPPBUF+1)
 663663                 error("line exceeds buffer size");
 664664 
 665665         ic->lineno--;
 666666         while (*ic->maxread)
 667667                 ic->maxread++;
 668668 }
 669669 
 670670 /*
 671671  * A new file included.
 672672  * If ifiles == NULL, this is the first file and already opened (stdin).
 673673  * Return 0 on success, -1 if file to be included is not found.
 674674  */
 675675 int
 676676 pushfile(usch *file, usch *fn, int idx, void *incs)
 677677 {
 678678         extern struct initar *initar;
 679679         struct includ ibuf;
 680680         struct includ *ic;
 681681         int otrulvl;
 682682 
 683683         ic = &ibuf;
 684684         ic->next = ifiles;
 685685 
 686686         if (file != NULL) {
 687687                 if ((ic->infil = open((char *)file, O_RDONLY)) < 0)
 688688                         return -1;
 689689                 ic->orgfn = ic->fname = file;
 690690                 if (++inclevel > MAX_INCLEVEL)
 691691                         error("Limit for nested includes exceeded");
 692692         } else {
 693693                 ic->infil = 0;
 694694                 ic->orgfn = ic->fname = (usch *)"<stdin>";
 695695         }
 696696         ic->buffer = ic->bbuf+NAMEMAX;
 697697         ic->curptr = ic->buffer;
 698698         ifiles = ic;
 699699         ic->lineno = 1;
 700700         ic->maxread = ic->curptr;
 701701         ic->idx = idx;
 702702         ic->incs = incs;
 703703         ic->fn = fn;
 704704         prtline();
 705705         if (initar) {
 706706                 *ic->maxread = 0;
 707707                 prinit(initar, ic);
 708708                 if (dMflag)
 709709                         write(ofd, ic->buffer, strlen((char *)ic->buffer));
 710710                 initar = NULL;
 711711         }
 712712 
 713713         otrulvl = trulvl;
 714714 
 715715         fastscan();
 716716 
 717717         if (otrulvl != trulvl || flslvl)
 718718                 error("unterminated conditional");
 719719 
 720720         ifiles = ic->next;
 721721         close(ic->infil);
 722722         inclevel--;
 723723         return 0;
 724724 }
 725725 
 726726 /*
 727727  * Print current position to output file.
 728728  */
 729729 void
 730730 prtline()
 731731 {
 732732         usch *s, *os = stringbuf;
 733733 
 734734         if (Mflag) {
 735735                 if (dMflag)
 736736                         return; /* no output */
 737737                 if (ifiles->lineno == 1) {
 738738                         s = sheap("%s: %s\n", Mfile, ifiles->fname);
 739739                         write(ofd, s, strlen((char *)s));
 740740                 }
 741741         } else if (!Pflag)
<>742 -                putstr(sheap("# %d \"%s\"\n", ifiles->lineno, ifiles->fname));
  742+                putstr(sheap("\n# %d \"%s\"\n", ifiles->lineno, ifiles->fname));
<_743743         stringbuf = os;
 744744 }
 745745 
 746746 void
 747747 cunput(int c)
 748748 {
 749749 #ifdef CPP_DEBUG
 750750         extern int dflag;
 751751         if (dflag)printf(": '%c'(%d)", c > 31 ? c : ' ', c);
 752752 #endif
 753753 #if 0
 754754 if (c == 10) {
 755755         printf("c == 10!!!\n");
 756756 }
 757757 #endif
 758758         unch(c);
 759759 }
 760760 
 761761 int yywrap(void) { return 1; }
 762762 
 763763 static int
 764764 dig2num(int c)
 765765 {
 766766         if (c >= 'a')
 767767                 c = c - 'a' + 10;
 768768         else if (c >= 'A')
 769769                 c = c - 'A' + 10;
 770770         else
 771771                 c = c - '0';
 772772         return c;
 773773 }
 774774 
 775775 /*
 776776  * Convert string numbers to unsigned long long and check overflow.
 777777  */
 778778 static void
 779779 cvtdig(int rad)
 780780 {
 781781         unsigned long long rv = 0;
 782782         unsigned long long rv2 = 0;
 783783         char *y = yytext;
 784784         int c;
 785785 
 786786         c = *y++;
 787787         if (rad == 16)
 788788                 y++;
 789789         while (isxdigit(c)) {
 790790                 rv = rv * rad + dig2num(c);
 791791                 /* check overflow */
 792792                 if (rv / rad < rv2)
 793793                         error("Constant \"%s\" is out of range", yytext);
 794794                 rv2 = rv;
 795795                 c = *y++;
 796796         }
 797797         y--;
 798798         while (*y == 'l' || *y == 'L')
 799799                 y++;
 800800         yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER;
 801801         yylval.node.nd_uval = rv;
 802802         if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0)
 803803                 yylval.node.op = UNUMBER;
 804804         if (yylval.node.op == NUMBER && yylval.node.nd_val < 0)
 805805                 /* too large for signed, see 6.4.4.1 */
 806806                 error("Constant \"%s\" is out of range", yytext);
 807807 }
 808808 
 809809 static int
 810810 charcon(usch *p)
 811811 {
 812812         int val, c;
 813813 
 814814         p++; /* skip first ' */
 815815         val = 0;
 816816         if (*p++ == '\\') {
 817817                 switch (*p++) {
 818818                 case 'a': val = '\a'; break;
 819819                 case 'b': val = '\b'; break;
 820820                 case 'f': val = '\f'; break;
 821821                 case 'n': val = '\n'; break;
 822822                 case 'r': val = '\r'; break;
 823823                 case 't': val = '\t'; break;
 824824                 case 'v': val = '\v'; break;
 825825                 case '\"': val = '\"'; break;
 826826                 case '\'': val = '\''; break;
 827827                 case '\\': val = '\\'; break;
 828828                 case 'x':
 829829                         while (isxdigit(c = *p)) {
 830830                                 val = val * 16 + dig2num(c);
 831831                                 p++;
 832832                         }
 833833                         break;
 834834                 case '0': case '1': case '2': case '3': case '4':
 835835                 case '5': case '6': case '7':
 836836                         p--;
 837837                         while (isdigit(c = *p)) {
 838838                                 val = val * 8 + (c - '0');
 839839                                 p++;
 840840                         }
 841841                         break;
 842842                 default: val = p[-1];
 843843                 }
 844844 
 845845         } else
 846846                 val = p[-1];
 847847         return val;
 848848 }
 849849 
 850850 static void
 851851 chknl(int ignore)
 852852 {
 853853         int t;
 854854 
 855855         while ((t = sloscan()) == WSPACE)
 856856                 ;
 857857         if (t != '\n') {
 858858                 if (ignore) {
 859859                         warning("newline expected, got \"%s\"", yytext);
 860860                         /* ignore rest of line */
 861861                         while ((t = sloscan()) && t != '\n')
 862862                                 ;
 863863                 }
 864864                 else
 865865                         error("newline expected, got \"%s\"", yytext);
 866866         }
 867867 }
 868868 
 869869 static void
 870870 elsestmt(void)
 871871 {
 872872         if (flslvl) {
 873873                 if (elflvl > trulvl)
 874874                         ;
 875875                 else if (--flslvl!=0) {
 876876                         flslvl++;
 877877                 } else {
 878878                         trulvl++;
 879879                         prtline();
 880880                 }
 881881         } else if (trulvl) {
 882882                 flslvl++;
 883883                 trulvl--;
 884884         } else
 885885                 error("If-less else");
 886886         if (elslvl==trulvl+flslvl)
 887887                 error("Too many else");
 888888         elslvl=trulvl+flslvl;
 889889         chknl(1);
 890890 }
 891891 
 892892 static void
 893893 skpln(void)
 894894 {
 895895         /* just ignore the rest of the line */
 896896         while (inch() != '\n')
 897897                 ;
 898898         unch('\n');
 899899         flslvl++;
 900900 }
 901901 
 902902 static void
 903903 ifdefstmt(void)         
 904904 {
 905905         int t;
 906906 
 907907         if (flslvl) {
 908908                 skpln();
 909909                 return;
 910910         }
 911911         do
 912912                 t = sloscan();
 913913         while (t == WSPACE);
 914914         if (t != IDENT)
 915915                 error("bad ifdef");
 916916         if (lookup((usch *)yytext, FIND) == 0) {
 917917                 putch('\n');
 918918                 flslvl++;
 919919         } else
 920920                 trulvl++;
 921921         chknl(0);
 922922 }
 923923 
 924924 static void
 925925 ifndefstmt(void)         
 926926 {
 927927         int t;
 928928 
 929929         if (flslvl) {
 930930                 skpln();
 931931                 return;
 932932         }
 933933         do
 934934                 t = sloscan();
 935935         while (t == WSPACE);
 936936         if (t != IDENT)
 937937                 error("bad ifndef");
 938938         if (lookup((usch *)yytext, FIND) != 0) {
 939939                 putch('\n');
 940940                 flslvl++;
 941941         } else
 942942                 trulvl++;
 943943         chknl(0);
 944944 }
 945945 
 946946 static void
 947947 endifstmt(void)         
 948948 {
 949949         if (flslvl) {
 950950                 flslvl--;
 951951                 if (flslvl == 0) {
 952952                         putch('\n');
 953953                         prtline();
 954954                 }
 955955         } else if (trulvl)
 956956                 trulvl--;
 957957         else
 958958                 error("If-less endif");
 959959         if (flslvl == 0)
 960960                 elflvl = 0;
 961961         elslvl = 0;
 962962         chknl(1);
 963963 }
 964964 
 965965 static void
 966966 ifstmt(void)
 967967 {
 968968         if (flslvl == 0) {
 969969                 if (yyparse() == 0) {
 970970                         putch('\n');
 971971                         ++flslvl;
 972972                 } else
 973973                         ++trulvl;
 974974         } else
 975975                 ++flslvl;
 976976 }
 977977 
 978978 static void
 979979 elifstmt(void)
 980980 {
 981981         if (flslvl == 0)
 982982                 elflvl = trulvl;
 983983         if (flslvl) {
 984984                 if (elflvl > trulvl)
 985985                         ;
 986986                 else if (--flslvl!=0)
 987987                         ++flslvl;
 988988                 else {
 989989                         if (yyparse()) {
 990990                                 ++trulvl;
 991991                                 prtline();
 992992                         } else {
 993993                                 putch('\n');
 994994                                 ++flslvl;
 995995                         }
 996996                 }
 997997         } else if (trulvl) {
 998998                 ++flslvl;
 999999                 --trulvl;
 10001000         } else
 10011001                 error("If-less elif");
 10021002 }
 10031003 
 10041004 static usch *
 10051005 svinp(void)
 10061006 {
 10071007         int c;
 10081008         usch *cp = stringbuf;
 10091009 
 10101010         while ((c = inch()) && c != '\n')
 10111011                 savch(c);
 10121012         savch('\n');
 10131013         savch(0);
 10141014         return cp;
 10151015 }
 10161016 
 10171017 static void
 10181018 cpperror(void)
 10191019 {
 10201020         usch *cp;
 10211021         int c;
 10221022 
 10231023         if (flslvl)
 10241024                 return;
 10251025         c = sloscan();
 10261026         if (c != WSPACE && c != '\n')
 10271027                 error("bad error");
 10281028         cp = svinp();
 10291029         if (flslvl)
 10301030                 stringbuf = cp;
 10311031         else
 10321032                 error("%s", cp);
 10331033 }
 10341034 
 10351035 static void
 10361036 undefstmt(void)
 10371037 {
 10381038         struct symtab *np;
 10391039 
 10401040         if (sloscan() != WSPACE || sloscan() != IDENT)
 10411041                 error("bad undef");
 10421042         if (flslvl == 0 && (np = lookup((usch *)yytext, FIND)))
 10431043                 np->value = 0;
 10441044         chknl(0);
 10451045 }
 10461046 
 10471047 static void
 10481048 pragmastmt(void)
 10491049 {
 10501050         int c;
 10511051 
 10521052         if (sloscan() != WSPACE)
 10531053                 error("bad pragma");
 10541054         if (!flslvl)
 10551055                 putstr((usch *)"#pragma ");
 10561056         do {
 10571057                 c = inch();
 10581058                 if (!flslvl)
 10591059                         putch(c);       /* Do arg expansion instead? */
 10601060         } while (c && c != '\n');
 10611061         if (c == '\n')
 10621062                 unch(c);
 10631063         prtline();
 10641064 }
 10651065 
 10661066 static void
 10671067 badop(const char *op)
 10681068 {
 10691069         error("invalid operator in preprocessor expression: %s", op);
 10701070 }
 10711071 
 10721072 int
 10731073 cinput()
 10741074 {
 10751075         return inch();
 10761076 }
 10771077 
 10781078 /*
 10791079  * Check for (and convert) trigraphs.
 10801080  */
 10811081 int
 10821082 chktg()
 10831083 {
 10841084         int c;
 10851085 
 10861086         if ((c = inpch()) != '?') {
 10871087                 unch(c);
 10881088                 return 0;
 10891089         }
 10901090         switch (c = inpch()) {
 10911091         case '=': c = '#'; break;
 10921092         case '(': c = '['; break;
 10931093         case ')': c = ']'; break;
 10941094         case '<': c = '{'; break;
 10951095         case '>': c = '}'; break;
 10961096         case '/': c = '\\'; break;
 10971097         case '\'': c = '^'; break;
 10981098         case '!': c = '|'; break;
 10991099         case '-': c = '~'; break;
 11001100         default:
 11011101                 unch(c);
 11021102                 unch('?');
 11031103                 c = 0;
 11041104         }
 11051105         return c;
 11061106 }
 11071107 
 11081108 static struct {
 11091109         char *name;
 11101110         void (*fun)(void);
 11111111 } ppd[] = {
 11121112         { "ifndef", ifndefstmt },
 11131113         { "ifdef", ifdefstmt },
 11141114         { "if", ifstmt },
 11151115         { "include", include },
 11161116         { "else", elsestmt },
 11171117         { "endif", endifstmt },
 11181118         { "error", cpperror },
 11191119         { "define", define },
 11201120         { "undef", undefstmt },
 11211121         { "line", line },
 11221122         { "pragma", pragmastmt },
 11231123         { "elif", elifstmt },
 11241124 #ifdef GCC_COMPAT
 11251125         { "include_next", include_next },
 11261126 #endif
 11271127 };
 11281128 
 11291129 /*
 11301130  * Handle a preprocessor directive.
 11311131  */
 11321132 void
 11331133 ppdir(void)
 11341134 {
 11351135         char bp[20];
 11361136         int ch, i;
 11371137 
 11381138         while ((ch = inch()) == ' ' || ch == '\t')
 11391139                 ;
 11401140         if (ch < 'a' || ch > 'z')
 11411141                 goto out; /* something else, ignore */
 11421142         i = 0;
 11431143         do {
 11441144                 bp[i++] = (usch)ch;
 11451145                 if (i == sizeof(bp)-1)
 11461146                         goto out; /* too long */
 11471147                 ch = inch();
 11481148         } while ((ch >= 'a' && ch <= 'z') || (ch == '_'));
 11491149         unch(ch);
 11501150         bp[i++] = 0;
 11511151 
 11521152         /* got keyword */
 11531153 #define SZ (int)(sizeof(ppd)/sizeof(ppd[0]))
 11541154         for (i = 0; i < SZ; i++)
 11551155                 if (bp[0] == ppd[i].name[0] && strcmp(bp, ppd[i].name) == 0)
 11561156                         break;
 11571157         if (i == SZ)
 11581158                 goto out;
 11591159 
 11601160         /* Found matching keyword */
 11611161         (*ppd[i].fun)();
 11621162         return;
 11631163 
 11641164 out:    while ((ch = inch()) != '\n' && ch != -1)
 11651165                 ;
 11661166         unch('\n');
 11671167 }
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-28 01:58 +0100