Quick Search:

Mode

Context

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

Other Diffs

Ignore

Blank Lines Whitespace: Expand:

Diff

1.81
 
1.82
 
MAIN:plunky:20121017101444
 
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 
 5353 #include "compat.h"
 5454 #include "cpp.h"
 5555 #include "cpy.h"
 5656 
 5757 static void cvtdig(int rad);
 5858 static int charcon(usch *);
 5959 static void elsestmt(void);
 6060 static void ifdefstmt(void);
 6161 static void ifndefstmt(void);
 6262 static void endifstmt(void);
 6363 static void ifstmt(void);
 6464 static void cpperror(void);
 6565 static void pragmastmt(void);
 6666 static void undefstmt(void);
 6767 static void cppwarning(void);
 6868 static void elifstmt(void);
 6969 static int chktg(void);
 7070 static int inpch(void);
 7171 static int inch(void);
 7272 
 7373 #define PUTCH(ch) if (!flslvl) putch(ch)
 7474 /* protection against recursion in #include */
 7575 #define MAX_INCLEVEL    100
 7676 static int inclevel;
 7777 
 7878 /* get next character unaltered */
 7979 #define NXTCH() (ifiles->curptr < ifiles->maxread ? *ifiles->curptr++ : inpch())
 8080 
 8181 usch yytext[CPPBUF];
 8282 
 8383 struct includ *ifiles;
 8484 
 8585 char spechr[256] = {
 8686         0,      0,      0,      0,      C_SPECC_SPEC0,      0,
 8787         0,      C_WSNLC_SPEC|C_WSNL,  0,
 8888         0,      C_WSNL0,      0,
 8989         0,      0,      0,      0,      0,      0,      0,      0,
 9090         0,      0,      0,      0,      0,      0,      0,      0,
 9191 
 9292         C_WSNLC_2,    C_SPEC0,      0,      0,      C_2,    C_SPEC,
 9393         0,      0,      0,      C_2,    0,      C_2,    0,      C_SPEC|C_2,
 9494         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 9595         C_I,    C_I,    0,      0,      C_2,    C_2,    C_2,    C_SPEC,
 9696 
 9797         0,      C_I,    C_I,    C_I,    C_I,    C_I|C_EP, C_I,  C_I,
 9898         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 9999         C_I|C_EP, C_I,  C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 100100         C_I,    C_I,    C_I,    0,      C_SPEC0,      0,      C_I,
 101101 
 102102         0,      C_I,    C_I,    C_I,    C_I,    C_I|C_EP, C_I,  C_I,
 103103         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 104104         C_I|C_EP, C_I,  C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 105105         C_I,    C_I,    C_I,    0,      C_2,    0,      0,      0,
 106106 
 107107 };
 108108 
 109109 static void
 110110 unch(int c)
 111111 {
 112112                 
 113113         --ifiles->curptr;
 114114         if (ifiles->curptr < ifiles->bbuf)
 115115                 error("pushback buffer full");
 116116         *ifiles->curptr = (usch)c;
 117117 }
 118118 
 119119 static int
 120120 eatcmnt(void)
 121121 {
 122122         int ch;
 123123 
 124124         if (Cflag) { PUTCH('/'); PUTCH('*'); }
 125125         for (;;) {
 126126                 ch = inch();
 127127                 if (ch == '\n') {
 128128                         ifiles->lineno++;
 129129                         PUTCH('\n');
 130130                 }
 131131                 if (ch == -1)
 132132                         return -1;
 133133                 if (ch == '*') {
 134134                         ch = inch();
 135135                         if (ch == '/') {
 136136                                 if (Cflag) {
 137137                                         PUTCH('*');
 138138                                         PUTCH('/');
 139139                                 } else
 140140                                         PUTCH(' ');
 141141                                 break;
 142142                         }
 143143                         unch(ch);
 144144                         ch = '*';
 145145                 }
 146146                 if (Cflag) PUTCH(ch);
 147147         }
 148148         return 0;
 149149 }
 150150 
 151151 /*
 152152  * Scan quickly the input file searching for:
 153153  *      - '#' directives
 154154  *      - keywords (if not flslvl)
 155155  *      - comments
 156156  *
 157157  *      Handle strings, numbers and trigraphs with care.
 158158  *      Only data from pp files are scanned here, never any rescans.
 159159  *      TODO: Only print out strings before calling other functions.
 160160  */
 161161 static void
 162162 fastscan(void)
 163163 {
 164164         struct symtab *nl;
 165165         int ch, i = 0;
 166166         int nnl = 0;
 167167         usch *cp;
 168168 
 169169         goto run;
 170170         for (;;) {
 171171                 ch = NXTCH();
 172172 xloop:          if (ch == -1)
 173173                         return;
 174174 #ifdef PCC_DEBUG
 175175                 if (dflag>1)
 176176                         printf("fastscan ch %d (%c)\n", ch, ch > 31 ? ch : '@');
 177177 #endif
 178178                 if ((spechr[ch] & C_SPEC) == 0) {
 179179                         PUTCH(ch);
 180180                         continue;
 181181                 }
 182182                 switch (ch) {
 183183                 case EBLOCK:
 184184                 case WARN:
 185185                 case CONC:
 186186                         error("bad char passed");
 187187                         break;
 188188 
 189189                 case '/': /* Comments */
 190190                         if ((ch = inch()) == '/') {
 191191 cppcmt:                         if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
 192192                                 do {
 193193                                         if (Cflag) PUTCH(ch);
 194194                                         ch = inch();
 195195                                 } while (ch != -1 && ch != '\n');
 196196                                 goto xloop;
 197197                         } else if (ch == '*') {
 198198                                 if (eatcmnt())
 199199                                         return;
 200200                         } else {
 201201                                 PUTCH('/');
 202202                                 goto xloop;
 203203                         }
 204204                         break;
 205205 
 206206                 case '?'/* trigraphs */
 207207                         if ((ch = chktg()))
 208208                                 goto xloop;
 209209                         PUTCH('?');
 210210                         break;
 211211 
 212212                 case '\\':
 213213                         if ((ch = NXTCH()) == '\n') {
 214214                                 ifiles->lineno++;
 215215                                 continue;
 216216                         } else {
 217217                                 PUTCH('\\');
 218218                         }
 219219                         goto xloop;
 220220 
 221221                 case '\n': /* newlines, for pp directives */
 222222                         while (nnl > 0) { PUTCH('\n'); nnl--; }
 223223 run2:                   ifiles->lineno++;
 224224                         do {
 225225                                 PUTCH(ch);
 226226 run:                            ch = NXTCH();
 227227                                 if (ch == '/') {
 228228                                         ch = NXTCH();
 229229                                         if (ch == '/')
 230230                                                 goto cppcmt;
 231231                                         if (ch == '*') {
 232232                                                 if (eatcmnt())
 233233                                                         return;
 234234                                                 goto run;
 235235                                         }
 236236                                         unch(ch);
 237237                                         ch = '/';
 238238                                 }
 239239                         } while (ch == ' ' || ch == '\t');
 240240                         if (ch == '\\') {
 241241                                 ch = NXTCH();
 242242                                 if (ch == '\n')
 243243                                         goto run2;
 244244                                 unch(ch);
 245245                                 ch = '\\';
 246246                         }
 247247                         if (ch == '#') {
 248248                                 ppdir();
 249249                                 continue;
 250250                         } else if (ch == '%') {
 251251                                 ch = NXTCH();
 252252                                 if (ch == ':') {
 253253                                         ppdir();
 254254                                         continue;
 255255                                 } else {
 256256                                         unch(ch);
 257257                                         ch = '%';
 258258                                 }
 259259                         } else if (ch == '?') {
 260260                                 if ((ch = chktg()) == '#') {
 261261                                         ppdir();
 262262                                         continue;
 263263                                 } else if (ch == 0)
 264264                                         ch = '?';
 265265                         }
 266266                         goto xloop;
 267267 
 268268                 case '\"': /* strings */
 269269 str:                    PUTCH(ch);
 270270                         while ((ch = NXTCH()) != '\"') {
 271271                                 if (ch == '\n')
 272272                                         goto xloop;
 273273                                 if (ch == '\\') {
 274274                                         if ((ch = NXTCH()) != '\n') {
 275275                                                 PUTCH('\\');
 276276                                                 PUTCH(ch);
 277277                                         } else
 278278                                                 nnl++;
 279279                                         continue;
 280280                                 }
 281281                                 if (ch < 0)
 282282                                         return;
 283283                                 PUTCH(ch);
 284284                         }
 285285                         PUTCH(ch);
 286286                         break;
 287287 
 288288                 case '.'/* for pp-number */
 289289                         PUTCH(ch);
 290290                         ch = NXTCH();
 291291                         if (ch < '0' || ch > '9')
 292292                                 goto xloop;
 293293                         /* FALLTHROUGH */
 294294                 case '0': case '1': case '2': case '3': case '4':
 295295                 case '5': case '6': case '7': case '8': case '9':
 296296                         do {
 297297                                 PUTCH(ch);
 298298 nxt:                            ch = NXTCH();
 299299                                 if (ch == '\\') {
 300300                                         ch = NXTCH();
 301301                                         if (ch == '\n') {
 302302                                                 goto nxt;
 303303                                         } else {
 304304                                                 unch(ch);
 305305                                                 ch = '\\';
 306306                                         }
 307307                                 }
 308308                                 if (spechr[ch] & C_EP) {
 309309                                         PUTCH(ch);
 310310                                         ch = NXTCH();
 311311                                         if (ch == '-' || ch == '+')
 312312                                                 continue;
 313313                                 }
 314314                         } while ((spechr[ch] & C_ID) || (ch == '.'));
 315315                         goto xloop;
 316316 
 317317                 case '\'': /* character literal */
 318318 con:                    PUTCH(ch);
 319319                         if (tflag)
 320320                                 continue; /* character constants ignored */
 321321                         while ((ch = NXTCH()) != '\'') {
 322322                                 if (ch == '\n')
 323323                                         goto xloop;
 324324                                 if (ch == '\\') {
 325325                                         if ((ch = NXTCH()) != '\n') {
 326326                                                 PUTCH('\\');
 327327                                                 PUTCH(ch);
 328328                                         } else
 329329                                                 nnl++;
 330330                                         continue;
 331331                                 }
 332332                                 if (ch < 0)
 333333                                         return;
 334334                                 PUTCH(ch);
 335335                         }
 336336                         PUTCH(ch);
 337337                         break;
 338338 
 339339                 case 'L':
 340340                         ch = NXTCH();
 341341                         if (ch == '\"') {
 342342                                 PUTCH('L');
 343343                                 goto str;
 344344                         }
 345345                         if (ch == '\'') {
 346346                                 PUTCH('L');
 347347                                 goto con;
 348348                         }
 349349                         unch(ch);
 350350                         ch = 'L';
 351351                         /* FALLTHROUGH */
 352352                 default:
 353353                         if ((spechr[ch] & C_ID) == 0)
 354354                                 error("fastscan");
 355355                         if (flslvl) {
 356356                                 while (spechr[ch] & C_ID)
 357357                                         ch = NXTCH();
 358358                                 goto xloop;
 359359                         }
 360360                         i = 0;
 361361                         do {
 362362                                 yytext[i++] = (usch)ch;
 363363                                 ch = NXTCH();
 364364                                 if (ch == '\\') {
 365365                                         ch = NXTCH();
 366366                                         if (ch != '\n') {
 367367                                                 unch(ch);
 368368                                                 ch = '\\';
 369369                                         } else {
 370370                                                 putch('\n');
 371371                                                 ifiles->lineno++;
 372372                                                 ch = NXTCH();
 373373                                         }
 374374                                 }
 375375                                 if (ch < 0)
 376376                                         return;
 377377                         } while (spechr[ch] & C_ID);
 378378 
 379379                         yytext[i] = 0;
 380380                         unch(ch);
 381381 
 382382                         cp = stringbuf;
 383383                         if ((nl = lookup(yytext, FIND)) && kfind(nl)) {
 384384                                 putstr(stringbuf);
 385385                         } else
 386386                                 putstr(yytext);
 387387                         stringbuf = cp;
 388388 
 389389                         break;
 390390                 }
 391391         }
 392392 }
 393393 
 394394 int
 395395 sloscan(void)
 396396 {
 397397         int ch;
 398398         int yyp;
 399399 
 400400 zagain:
 401401         yyp = 0;
 402402         ch = inch();
 403403         yytext[yyp++] = (usch)ch;
 404404         switch (ch) {
 405405         case -1:
 406406                 return 0;
 407407         case '\n':
 408408                 /* sloscan() never passes \n, that's up to fastscan() */
 409409                 unch(ch);
 410410                 goto yyret;
 411411 
 412412         case '\r': /* Ignore CR's */
 413413                 yyp = 0;
 414414                 break;
 415415 
 416416         case '0': case '1': case '2': case '3': case '4': case '5':
 417417         case '6': case '7': case '8': case '9':
 418418                 /* readin a "pp-number" */
 419419 ppnum:          for (;;) {
 420420                         ch = inch();
 421421                         if (spechr[ch] & C_EP) {
 422422                                 yytext[yyp++] = (usch)ch;
 423423                                 ch = inch();
 424424                                 if (ch == '-' || ch == '+') {
 425425                                         yytext[yyp++] = (usch)ch;
 426426                                 } else
 427427                                         unch(ch);
 428428                                 continue;
 429429                         }
 430430                         if ((spechr[ch] & C_ID) || ch == '.') {
 431431                                 yytext[yyp++] = (usch)ch;
 432432                                 continue;
 433433                         }
 434434                         break;
 435435                 }
 436436                 unch(ch);
 437437                 yytext[yyp] = 0;
 438438 
 439439                 return NUMBER;
 440440 
 441441         case '\'':
 442442 chlit:          
 443443                 for (;;) {
 444444                         if ((ch = inch()) == '\\') {
 445445                                 yytext[yyp++] = (usch)ch;
 446446                                 yytext[yyp++] = (usch)inch();
 447447                                 continue;
 448448                         } else if (ch == '\n') {
 449449                                 /* not a constant */
 450450                                 while (yyp > 1)
 451451                                         unch(yytext[--yyp]);
 452452                                 ch = '\'';
 453453                                 goto any;
 454454                         } else
 455455                                 yytext[yyp++] = (usch)ch;
 456456                         if (ch == '\'')
 457457                                 break;
 458458                 }
 459459                 yytext[yyp] = 0;
 460460 
 461461                 return NUMBER;
 462462 
 463463         case ' ':
 464464         case '\t':
 465465                 while ((ch = inch()) == ' ' || ch == '\t')
 466466                         yytext[yyp++] = (usch)ch;
 467467                 unch(ch);
 468468                 yytext[yyp] = 0;
 469469                 return WSPACE;
 470470 
 471471         case '/':
 472472                 if ((ch = inch()) == '/') {
 473473                         do {
 474474                                 yytext[yyp++] = (usch)ch;
 475475                                 ch = inch();
 476476                         } while (ch && ch != '\n');
 477477                         yytext[yyp] = 0;
 478478                         unch(ch);
 479479                         goto zagain;
 480480                 } else if (ch == '*') {
 481481                         int c, wrn;
 482482                         extern int readmac;
 483483 
 484484                         if (Cflag && !flslvl && readmac) {
 485485                                 unch(ch);
 486486                                 yytext[yyp] = 0;
 487487                                 return CMNT;
 488488                         }
 489489 
 490490                         wrn = 0;
 491491                 more:   while ((c = inch()) && c != '*') {
 492492                                 if (c == '\n')
 493493                                         putch(c), ifiles->lineno++;
 494494                                 else if (c == EBLOCK) {
 495495                                         (void)inch();
 496496                                         (void)inch();
 497497                                 } else if (c == 1) /* WARN */
 498498                                         wrn = 1;
 499499                         }
 500500                         if (c == 0)
 501501                                 return 0;
 502502                         if ((c = inch()) && c != '/') {
 503503                                 unch(c);
 504504                                 goto more;
 505505                         }
 506506                         if (c == 0)
 507507                                 return 0;
 508508                         if (!tflag && !Cflag && !flslvl)
 509509                                 unch(' ');
 510510                         if (wrn)
 511511                                 unch(1);
 512512                         goto zagain;
 513513                 }
 514514                 unch(ch);
 515515                 ch = '/';
 516516                 goto any;
 517517 
 518518         case '.':
 519519                 ch = inch();
 520520                 if (isdigit(ch)) {
 521521                         yytext[yyp++] = (usch)ch;
 522522                         goto ppnum;
 523523                 } else {
 524524                         unch(ch);
 525525                         ch = '.';
 526526                 }
 527527                 goto any;
 528528 
 529529         case '\"':
 530530                 if (tflag && defining)
 531531                         goto any;
 532532         strng:
 533533                 for (;;) {
 534534                         if ((ch = inch()) == '\\') {
 535535                                 yytext[yyp++] = (usch)ch;
 536536                                 yytext[yyp++] = (usch)inch();
 537537                                 continue;
 538538                         } else
 539539                                 yytext[yyp++] = (usch)ch;
 540540                         if (ch == '\"')
 541541                                 break;
 542542                 }
 543543                 yytext[yyp] = 0;
 544544                 return STRING;
 545545 
 546546         case 'L':
 547547                 if ((ch = inch()) == '\"' && !tflag) {
 548548                         yytext[yyp++] = (usch)ch;
 549549                         goto strng;
 550550                 } else if (ch == '\'' && !tflag) {
 551551                         yytext[yyp++] = (usch)ch;
 552552                         goto chlit;
 553553                 }
 554554                 unch(ch);
 555555                 /* FALLTHROUGH */
 556556 
 557557         /* Yetch, all identifiers */
 558558         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
 559559         case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
 560560         case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
 561561         case 's': case 't': case 'u': case 'v': case 'w': case 'x':
 562562         case 'y': case 'z':
 563563         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
 564564         case 'G': case 'H': case 'I': case 'J': case 'K':
 565565         case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
 566566         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
 567567         case 'Y': case 'Z':
 568568         case '_': /* {L}({L}|{D})* */
 569569 
 570570                 /* Special hacks */
 571571                 for (;;) { /* get chars */
 572572                         ch = inch();
 573573                         if (isalpha(ch) || isdigit(ch) || ch == '_') {
 574574                                 yytext[yyp++] = (usch)ch;
 575575                         } else {
 576576                                 if (ch != -1)
 577577                                         unch(ch);
 578578                                 break;
 579579                         }
 580580                 }
 581581                 yytext[yyp] = 0; /* need already string */
 582582                 /* end special hacks */
 583583 
 584584                 return IDENT;
 585585         default:
 586586         any:
 587587                 yytext[yyp] = 0;
 588588                 return yytext[0];
 589589 
 590590         } /* endcase */
 591591         goto zagain;
 592592 
 593593 yyret:
 594594         yytext[yyp] = 0;
 595595         return ch;
 596596 }
 597597 
 598598 int
 599599 yylex(void)
 600600 {
 601601         static int ifdef, noex;
 602602         struct symtab *nl;
 603603         int ch, c2;
 604604 
 605605         while ((ch = sloscan()) == WSPACE)
 606606                 ;
 607607         if (ch < 128 && spechr[ch] & C_2)
 608608                 c2 = inpch();
 609609         else
 610610                 c2 = 0;
 611611 
 612612 #define C2(a,b,c) case a: if (c2 == b) return c; break
 613613         switch (ch) {
 614614         C2('=', '=', EQ);
 615615         C2('!', '=', NE);
 616616         C2('|', '|', OROR);
 617617         C2('&', '&', ANDAND);
 618618         case '<':
 619619                 if (c2 == '<') return LS;
 620620                 if (c2 == '=') return LE;
 621621                 break;
 622622         case '>':
 623623                 if (c2 == '>') return RS;
 624624                 if (c2 == '=') return GE;
 625625                 break;
 626626         case '+':
 627627         case '-':
 628628                 if (ch == c2)
 629629                         error("invalid preprocessor operator %c%c", ch, c2);
 630630                 break;
 631631 
 632632         case '/':
 633633                 if (Cflag == 0 || c2 != '*')
 634634                         break;
 635635                 /* Found comment that need to be skipped */
 636636                 for (;;) {
 637637                         ch = inpch();
 638638                 c1:     if (ch != '*')
 639639                                 continue;
 640640                         if ((ch = inpch()) == '/')
 641641                                 break;
 642642                         goto c1;
 643643                 }
 644644                 return yylex();
 645645 
 646646         case NUMBER:
 647647                 if (yytext[0] == '\'') {
 648648                         yylval.node.op = NUMBER;
 649649                         yylval.node.nd_val = charcon(yytext);
 650650                 } else
 651651                         cvtdig(yytext[0] != '0' ? 10 :
 652652                             yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
 653653                 return NUMBER;
 654654 
 655655         case IDENT:
 656656                 if (strcmp((char *)yytext, "defined") == 0) {
 657657                         ifdef = 1;
 658658                         return DEFINED;
 659659                 }
 660660                 nl = lookup(yytext, FIND);
 661661                 if (ifdef) {
 662662                         yylval.node.nd_val = nl != NULL;
 663663                         ifdef = 0;
 664664                 } else if (nl && noex == 0) {
 665665                         usch *och = stringbuf;
 666666                         int i;
 667667 
 668668                         i = kfind(nl);
 669669                         unch(WARN);
 670670                         if (i)
 671671                                 unpstr(stringbuf);
 672672                         else
 673673                                 unpstr(nl->namep);
 674674                         stringbuf = och;
 675675                         noex = 1;
 676676                         return yylex();
 677677                 } else {
 678678                         yylval.node.nd_val = 0;
 679679                 }
 680680                 yylval.node.op = NUMBER;
 681681                 return NUMBER;
 682682         case WARN:
 683683                 noex = 0;
 684684                 /* FALLTHROUGH */
 685685         case PHOLD:
 686686                 return yylex();
 687687         default:
 688688                 return ch;
 689689         }
 690690         unch(c2);
 691691         return ch;
 692692 }
 693693 
 694694 static int
 695695 inpch(void)
 696696 {
 697697         int len;
 698698 
 699699         if (ifiles->curptr < ifiles->maxread)
 700700                 return *ifiles->curptr++;
 701701 
 702702         if (ifiles->infil == -1)
 703703                 return -1;
 704704         if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0)
 705705                 error("read error on file %s", ifiles->orgfn);
 706706         if (len == 0)
 707707                 return -1;
 708708         ifiles->buffer[len] = 0;
 709709         ifiles->curptr = ifiles->buffer;
 710710         ifiles->maxread = ifiles->buffer + len;
 711711         return inpch();
 712712 }
 713713 
 714714 static int
 715715 inch(void)
 716716 {
 717717         int c;
 718718 
 719719 again:  switch (c = inpch()) {
 720720         case '\\': /* continued lines */
 721721 msdos:          if ((c = inpch()) == '\n') {
 722722                         ifiles->lineno++;
 723723                         putch('\n');
 724724                         goto again;
 725725                 } else if (c == '\r')
 726726                         goto msdos;
 727727                 unch(c);
 728728                 return '\\';
 729729         case '?': /* trigraphs */
 730730                 if ((c = chktg())) {
 731731                         unch(c);
 732732                         goto again;
 733733                 }
 734734                 return '?';
 735735         default:
 736736                 return c;
 737737         }
 738738 }
 739739 
 740740 /*
 741741  * Let the command-line args be faked defines at beginning of file.
 742742  */
 743743 static void
 744744 prinit(struct initar *it, struct includ *ic)
 745745 {
 746746         const char *pre, *post;
 747747         char *a;
 748748 
 749749         if (it->next)
 750750                 prinit(it->next, ic);
 751751         pre = post = NULL; /* XXX gcc */
 752752         switch (it->type) {
 753753         case 'D':
 754754                 pre = "#define ";
 755755                 if ((a = strchr(it->str, '=')) != NULL) {
 756756                         *a = ' ';
 757757                         post = "\n";
 758758                 } else
 759759                         post = " 1\n";
 760760                 break;
 761761         case 'U':
 762762                 pre = "#undef ";
 763763                 post = "\n";
 764764                 break;
 765765         case 'i':
 766766                 pre = "#include \"";
 767767                 post = "\"\n";
 768768                 break;
 769769         default:
 770770                 error("prinit");
 771771         }
 772772         strlcat((char *)ic->buffer, pre, CPPBUF+1);
 773773         strlcat((char *)ic->buffer, it->str, CPPBUF+1);
 774774         if (strlcat((char *)ic->buffer, post, CPPBUF+1) >= CPPBUF+1)
 775775                 error("line exceeds buffer size");
 776776 
 777777         ic->lineno--;
 778778         while (*ic->maxread)
 779779                 ic->maxread++;
 780780 }
 781781 
 782782 /*
 783783  * A new file included.
 784784  * If ifiles == NULL, this is the first file and already opened (stdin).
 785785  * Return 0 on success, -1 if file to be included is not found.
 786786  */
 787787 int
 788788 pushfile(const usch *file, const usch *fn, int idx, void *incs)
 789789 {
 790790         extern struct initar *initar;
 791791         struct includ ibuf;
 792792         struct includ *ic;
<>793 -        int otrulvl, i;
  793+        int otrulvl;
794794 
 795795         ic = &ibuf;
 796796         ic->next = ifiles;
 797797 
 798798         if (file != NULL) {
 799799                 if ((ic->infil = open((const char *)file, O_RDONLY)) < 0)
 800800                         return -1;
 801801                 ic->orgfn = ic->fname = file;
 802802                 if (++inclevel > MAX_INCLEVEL)
 803803                         error("Limit for nested includes exceeded");
 804804         } else {
 805805                 ic->infil = 0;
 806806                 ic->orgfn = ic->fname = (const usch *)"<stdin>";
 807807         }
 808808 #ifndef BUF_STACK
 809809         ic->bbuf = malloc(BBUFSZ);
 810810 #endif
 811811         ic->buffer = ic->bbuf+NAMEMAX;
 812812         ic->curptr = ic->buffer;
 813813         ifiles = ic;
 814814         ic->lineno = 1;
 815815         ic->maxread = ic->curptr;
 816816         ic->idx = idx;
 817817         ic->incs = incs;
 818818         ic->fn = fn;
 819819         prtline();
 820820         if (initar) {
 821821                 int oin = ic->infil;
 822822                 ic->infil = -1;
 823823                 *ic->maxread = 0;
 824824                 prinit(initar, ic);
 825825                 initar = NULL;
 826826                 if (dMflag)
<>827 -                        i = write(ofd, ic->buffer, strlen((char *)ic->buffer));
  827+                        xwrite(ofd, ic->buffer, strlen((char *)ic->buffer));
828828                 fastscan();
 829829                 prtline();
 830830                 ic->infil = oin;
 831831         }
 832832 
 833833         otrulvl = trulvl;
 834834 
 835835         fastscan();
 836836 
 837837         if (otrulvl != trulvl || flslvl)
 838838                 error("unterminated conditional");
 839839 
 840840 #ifndef BUF_STACK
 841841         free(ic->bbuf);
 842842 #endif
 843843         ifiles = ic->next;
 844844         close(ic->infil);
 845845         inclevel--;
 846846         return 0;
 847847 }
 848848 
 849849 /*
 850850  * Print current position to output file.
 851851  */
 852852 void
 853853 prtline(void)
 854854 {
 855855         usch *s, *os = stringbuf;
<>856 -        int i;
857856 
 858857         if (Mflag) {
 859858                 if (dMflag)
 860859                         return; /* no output */
 861860                 if (ifiles->lineno == 1) {
 862861                         s = sheap("%s: %s\n", Mfile, ifiles->fname);
<>863 -                        i = write(ofd, s, strlen((char *)s));
  862+                        xwrite(ofd, s, strlen((char *)s));
864863                         if (MPflag &&
 865864                             strcmp((const char *)ifiles->fname, (char *)MPfile)) {
 866865                                 s = sheap("%s:\n", ifiles->fname);
<>867 -                                i = write(ofd, s, strlen((char *)s));
  866+                                xwrite(ofd, s, strlen((char *)s));
<_868867                         }
 869868                 }
 870869         } else if (!Pflag) {
 871870                 putstr(sheap("\n# %d \"%s\"", ifiles->lineno, ifiles->fname));
 872871                 if (ifiles->idx == SYSINC)
 873872                         putstr(sheap(" 3"));
 874873                 putstr(sheap("\n"));
 875874         }
 876875         stringbuf = os;
 877876 }
 878877 
 879878 void
 880879 cunput(int c)
 881880 {
 882881 #ifdef PCC_DEBUG
 883882 //      if (dflag)printf(": '%c'(%d)\n", c > 31 ? c : ' ', c);
 884883 #endif
 885884         unch(c);
 886885 }
 887886 
 888887 static int
 889888 dig2num(int c)
 890889 {
 891890         if (c >= 'a')
 892891                 c = c - 'a' + 10;
 893892         else if (c >= 'A')
 894893                 c = c - 'A' + 10;
 895894         else
 896895                 c = c - '0';
 897896         return c;
 898897 }
 899898 
 900899 /*
 901900  * Convert string numbers to unsigned long long and check overflow.
 902901  */
 903902 static void
 904903 cvtdig(int rad)
 905904 {
 906905         unsigned long long rv = 0;
 907906         unsigned long long rv2 = 0;
 908907         usch *y = yytext;
 909908         int c;
 910909 
 911910         c = *y++;
 912911         if (rad == 16)
 913912                 y++;
 914913         while (isxdigit(c)) {
 915914                 rv = rv * rad + dig2num(c);
 916915                 /* check overflow */
 917916                 if (rv / rad < rv2)
 918917                         error("Constant \"%s\" is out of range", yytext);
 919918                 rv2 = rv;
 920919                 c = *y++;
 921920         }
 922921         y--;
 923922         while (*y == 'l' || *y == 'L')
 924923                 y++;
 925924         yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER;
 926925         yylval.node.nd_uval = rv;
 927926         if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0)
 928927                 yylval.node.op = UNUMBER;
 929928         if (yylval.node.op == NUMBER && yylval.node.nd_val < 0)
 930929                 /* too large for signed, see 6.4.4.1 */
 931930                 error("Constant \"%s\" is out of range", yytext);
 932931 }
 933932 
 934933 static int
 935934 charcon(usch *p)
 936935 {
 937936         int val, c;
 938937 
 939938         p++; /* skip first ' */
 940939         val = 0;
 941940         if (*p++ == '\\') {
 942941                 switch (*p++) {
 943942                 case 'a': val = '\a'; break;
 944943                 case 'b': val = '\b'; break;
 945944                 case 'f': val = '\f'; break;
 946945                 case 'n': val = '\n'; break;
 947946                 case 'r': val = '\r'; break;
 948947                 case 't': val = '\t'; break;
 949948                 case 'v': val = '\v'; break;
 950949                 case '\"': val = '\"'; break;
 951950                 case '\'': val = '\''; break;
 952951                 case '\\': val = '\\'; break;
 953952                 case 'x':
 954953                         while (isxdigit(c = *p)) {
 955954                                 val = val * 16 + dig2num(c);
 956955                                 p++;
 957956                         }
 958957                         break;
 959958                 case '0': case '1': case '2': case '3': case '4':
 960959                 case '5': case '6': case '7':
 961960                         p--;
 962961                         while (isdigit(c = *p)) {
 963962                                 val = val * 8 + (c - '0');
 964963                                 p++;
 965964                         }
 966965                         break;
 967966                 default: val = p[-1];
 968967                 }
 969968 
 970969         } else
 971970                 val = p[-1];
 972971         return val;
 973972 }
 974973 
 975974 static void
 976975 chknl(int ignore)
 977976 {
 978977         int t;
 979978 
 980979         while ((t = sloscan()) == WSPACE)
 981980                 ;
 982981         if (t != '\n') {
 983982                 if (t && t != (usch)-1) {
 984983                         if (ignore) {
 985984                                 warning("newline expected, got \"%s\"", yytext);
 986985                                 /* ignore rest of line */
 987986                                 while ((t = sloscan()) && t != '\n')
 988987                                         ;
 989988                         }
 990989                         else
 991990                                 error("newline expected, got \"%s\"", yytext);
 992991                 } else {
 993992                         if (ignore)
 994993                                 warning("no newline at end of file");
 995994                         else
 996995                                 error("no newline at end of file");
 997996                 }
 998997         }
 999998 }
 1000999 
 10011000 static void
 10021001 elsestmt(void)
 10031002 {
 10041003         if (flslvl) {
 10051004                 if (elflvl > trulvl)
 10061005                         ;
 10071006                 else if (--flslvl!=0) {
 10081007                         flslvl++;
 10091008                 } else {
 10101009                         trulvl++;
 10111010                         prtline();
 10121011                 }
 10131012         } else if (trulvl) {
 10141013                 flslvl++;
 10151014                 trulvl--;
 10161015         } else
 10171016                 error("If-less else");
 10181017         if (elslvl==trulvl+flslvl)
 10191018                 error("Too many else");
 10201019         elslvl=trulvl+flslvl;
 10211020         chknl(1);
 10221021 }
 10231022 
 10241023 static void
 10251024 skpln(void)
 10261025 {
 10271026         /* just ignore the rest of the line */
 10281027         while (inch() != '\n')
 10291028                 ;
 10301029         unch('\n');
 10311030         flslvl++;
 10321031 }
 10331032 
 10341033 static void
 10351034 ifdefstmt(void)         
 10361035 {
 10371036         int t;
 10381037 
 10391038         if (flslvl) {
 10401039                 skpln();
 10411040                 return;
 10421041         }
 10431042         do
 10441043                 t = sloscan();
 10451044         while (t == WSPACE);
 10461045         if (t != IDENT)
 10471046                 error("bad ifdef");
 10481047         if (lookup(yytext, FIND) == 0) {
 10491048                 putch('\n');
 10501049                 flslvl++;
 10511050         } else
 10521051                 trulvl++;
 10531052         chknl(0);
 10541053 }
 10551054 
 10561055 static void
 10571056 ifndefstmt(void)         
 10581057 {
 10591058         int t;
 10601059 
 10611060         if (flslvl) {
 10621061                 skpln();
 10631062                 return;
 10641063         }
 10651064         do
 10661065                 t = sloscan();
 10671066         while (t == WSPACE);
 10681067         if (t != IDENT)
 10691068                 error("bad ifndef");
 10701069         if (lookup(yytext, FIND) != 0) {
 10711070                 putch('\n');
 10721071                 flslvl++;
 10731072         } else
 10741073                 trulvl++;
 10751074         chknl(0);
 10761075 }
 10771076 
 10781077 static void
 10791078 endifstmt(void)         
 10801079 {
 10811080         if (flslvl) {
 10821081                 flslvl--;
 10831082                 if (flslvl == 0) {
 10841083                         putch('\n');
 10851084                         prtline();
 10861085                 }
 10871086         } else if (trulvl)
 10881087                 trulvl--;
 10891088         else
 10901089                 error("If-less endif");
 10911090         if (flslvl == 0)
 10921091                 elflvl = 0;
 10931092         elslvl = 0;
 10941093         chknl(1);
 10951094 }
 10961095 
 10971096 static void
 10981097 ifstmt(void)
 10991098 {
 11001099         if (flslvl == 0) {
 11011100                 if (yyparse() == 0) {
 11021101                         putch('\n');
 11031102                         ++flslvl;
 11041103                 } else
 11051104                         ++trulvl;
 11061105         } else
 11071106                 ++flslvl;
 11081107 }
 11091108 
 11101109 static void
 11111110 elifstmt(void)
 11121111 {
 11131112         if (flslvl == 0)
 11141113                 elflvl = trulvl;
 11151114         if (flslvl) {
 11161115                 if (elflvl > trulvl)
 11171116                         ;
 11181117                 else if (--flslvl!=0)
 11191118                         ++flslvl;
 11201119                 else {
 11211120                         if (yyparse()) {
 11221121                                 ++trulvl;
 11231122                                 prtline();
 11241123                         } else {
 11251124                                 putch('\n');
 11261125                                 ++flslvl;
 11271126                         }
 11281127                 }
 11291128         } else if (trulvl) {
 11301129                 ++flslvl;
 11311130                 --trulvl;
 11321131         } else
 11331132                 error("If-less elif");
 11341133 }
 11351134 
 11361135 /* save line into stringbuf */
 11371136 static usch *
 11381137 savln(void)
 11391138 {
 11401139         int c;
 11411140         usch *cp = stringbuf;
 11421141 
 11431142         while ((c = inch()) != 0) {
 11441143                 if (c == '\n') {
 11451144                         unch(c);
 11461145                         break;
 11471146                 }
 11481147                 savch(c);
 11491148         }
 11501149         savch(0);
 11511150 
 11521151         return cp;
 11531152 }
 11541153 
 11551154 static void
 11561155 cpperror(void)
 11571156 {
 11581157         usch *cp;
 11591158         int c;
 11601159 
 11611160         if (flslvl)
 11621161                 return;
 11631162         c = sloscan();
 11641163         if (c != WSPACE && c != '\n')
 11651164                 error("bad #error");
 11661165         cp = savln();
 11671166         error("#error %s", cp);
 11681167 }
 11691168 
 11701169 static void
 11711170 cppwarning(void)
 11721171 {
 11731172         usch *cp;
 11741173         int c;
 11751174 
 11761175         if (flslvl)
 11771176                 return;
 11781177         c = sloscan();
 11791178         if (c != WSPACE && c != '\n')
 11801179                 error("bad #warning");
 11811180         cp = savln();
 11821181         warning("#warning %s", cp);
 11831182         stringbuf = cp;
 11841183 }
 11851184 
 11861185 static void
 11871186 undefstmt(void)
 11881187 {
 11891188         struct symtab *np;
 11901189 
 11911190         if (flslvl)
 11921191                 return;
 11931192         if (sloscan() != WSPACE || sloscan() != IDENT)
 11941193                 error("bad undef");
 11951194         if (flslvl == 0 && (np = lookup(yytext, FIND)))
 11961195                 np->value = 0;
 11971196         chknl(0);
 11981197 }
 11991198 
 12001199 static void
 12011200 pragmastmt(void)
 12021201 {
 12031202         int c;
 12041203         usch *sb = stringbuf;
 12051204 
 12061205         if (sloscan() != WSPACE)
 12071206                 error("bad pragma");
 12081207         savstr((const usch *)"\n#pragma ");
 12091208         do {
 12101209                 savch(c = inch());
 12111210         } while (c && c != '\n');
 12121211         if (c == '\n')
 12131212                 unch(c);
 12141213         savch(0);
 12151214         if (!flslvl)
 12161215                 putstr(sb);
 12171216         stringbuf = sb;
 12181217         prtline();
 12191218 }
 12201219 
 12211220 int
 12221221 cinput(void)
 12231222 {
 12241223         return inch();
 12251224 }
 12261225 
 12271226 /*
 12281227  * Check for (and convert) trigraphs.
 12291228  */
 12301229 int
 12311230 chktg(void)
 12321231 {
 12331232         int c;
 12341233 
 12351234         if ((c = inpch()) != '?') {
 12361235                 unch(c);
 12371236                 return 0;
 12381237         }
 12391238         switch (c = inpch()) {
 12401239         case '=': c = '#'; break;
 12411240         case '(': c = '['; break;
 12421241         case ')': c = ']'; break;
 12431242         case '<': c = '{'; break;
 12441243         case '>': c = '}'; break;
 12451244         case '/': c = '\\'; break;
 12461245         case '\'': c = '^'; break;
 12471246         case '!': c = '|'; break;
 12481247         case '-': c = '~'; break;
 12491248         default:
 12501249                 unch(c);
 12511250                 unch('?');
 12521251                 c = 0;
 12531252         }
 12541253         return c;
 12551254 }
 12561255 
 12571256 static struct {
 12581257         const char *name;
 12591258         void (*fun)(void);
 12601259 } ppd[] = {
 12611260         { "ifndef", ifndefstmt },
 12621261         { "ifdef", ifdefstmt },
 12631262         { "if", ifstmt },
 12641263         { "include", include },
 12651264         { "else", elsestmt },
 12661265         { "endif", endifstmt },
 12671266         { "error", cpperror },
 12681267         { "warning", cppwarning },
 12691268         { "define", define },
 12701269         { "undef", undefstmt },
 12711270         { "line", line },
 12721271         { "pragma", pragmastmt },
 12731272         { "elif", elifstmt },
 12741273 #ifdef GCC_COMPAT
 12751274         { "include_next", include_next },
 12761275 #endif
 12771276 };
 12781277 
 12791278 /*
 12801279  * Handle a preprocessor directive.
 12811280  */
 12821281 void
 12831282 ppdir(void)
 12841283 {
 12851284         char bp[20];
 12861285         int ch, i;
 12871286 
 12881287         while ((ch = inch()) == ' ' || ch == '\t')
 12891288                 ;
 12901289         if (ch == '\n') { /* empty directive */
 12911290                 unch(ch);
 12921291                 return;
 12931292         }
 12941293         if (ch < 'a' || ch > 'z')
 12951294                 goto out; /* something else, ignore */
 12961295         i = 0;
 12971296         do {
 12981297                 bp[i++] = (usch)ch;
 12991298                 if (i == sizeof(bp)-1)
 13001299                         goto out; /* too long */
 13011300                 ch = inch();
 13021301         } while ((ch >= 'a' && ch <= 'z') || (ch == '_'));
 13031302         unch(ch);
 13041303         bp[i++] = 0;
 13051304 
 13061305         /* got keyword */
 13071306 #define SZ (int)(sizeof(ppd)/sizeof(ppd[0]))
 13081307         for (i = 0; i < SZ; i++)
 13091308                 if (bp[0] == ppd[i].name[0] && strcmp(bp, ppd[i].name) == 0)
 13101309                         break;
 13111310         if (i == SZ)
 13121311                 goto out;
 13131312 
 13141313         /* Found matching keyword */
 13151314         (*ppd[i].fun)();
 13161315         return;
 13171316 
 13181317 out:    while ((ch = inch()) != '\n' && ch != -1)
 13191318                 ;
 13201319         unch('\n');
 13211320 }
FishEye: Open Source License registered to PCC.
Your maintenance has expired. You can renew your license at http://www.atlassian.com/fisheye/renew
Atlassian FishEye, CVS analysis. (Version:1.6.3 Build:build-336 2008-11-04) - Administration - Page generated 2014-10-31 05:53 +0100