Quick Search:

Mode

Context

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

Other Diffs

Ignore

Blank Lines Whitespace: Expand:

Diff

1.79
 
1.80
 
MAIN:plunky:20121011101742
 
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 char spechr[256] = {
 8484         0,      0,      0,      0,      C_SPECC_SPEC0,      0,
 8585         0,      C_WSNLC_SPEC|C_WSNL,  0,
 8686         0,      C_WSNL0,      0,
 8787         0,      0,      0,      0,      0,      0,      0,      0,
 8888         0,      0,      0,      0,      0,      0,      0,      0,
 8989 
 9090         C_WSNLC_2,    C_SPEC0,      0,      0,      C_2,    C_SPEC,
 9191         0,      0,      0,      C_2,    0,      C_2,    0,      C_SPEC|C_2,
 9292         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 9393         C_I,    C_I,    0,      0,      C_2,    C_2,    C_2,    C_SPEC,
 9494 
 9595         0,      C_I,    C_I,    C_I,    C_I,    C_I|C_EP, C_I,  C_I,
 9696         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 9797         C_I|C_EP, C_I,  C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 9898         C_I,    C_I,    C_I,    0,      C_SPEC0,      0,      C_I,
 9999 
 100100         0,      C_I,    C_I,    C_I,    C_I,    C_I|C_EP, C_I,  C_I,
 101101         C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 102102         C_I|C_EP, C_I,  C_I,    C_I,    C_I,    C_I,    C_I,    C_I,
 103103         C_I,    C_I,    C_I,    0,      C_2,    0,      0,      0,
 104104 
 105105 };
 106106 
 107107 static void
 108108 unch(int c)
 109109 {
 110110                 
 111111         --ifiles->curptr;
 112112         if (ifiles->curptr < ifiles->bbuf)
 113113                 error("pushback buffer full");
 114114         *ifiles->curptr = (usch)c;
 115115 }
 116116 
 117117 static int
 118118 eatcmnt(void)
 119119 {
 120120         int ch;
 121121 
 122122         if (Cflag) { PUTCH('/'); PUTCH('*'); }
 123123         for (;;) {
 124124                 ch = inch();
 125125                 if (ch == '\n') {
 126126                         ifiles->lineno++;
 127127                         PUTCH('\n');
 128128                 }
 129129                 if (ch == -1)
 130130                         return -1;
 131131                 if (ch == '*') {
 132132                         ch = inch();
 133133                         if (ch == '/') {
 134134                                 if (Cflag) {
 135135                                         PUTCH('*');
 136136                                         PUTCH('/');
 137137                                 } else
 138138                                         PUTCH(' ');
 139139                                 break;
 140140                         }
 141141                         unch(ch);
 142142                         ch = '*';
 143143                 }
 144144                 if (Cflag) PUTCH(ch);
 145145         }
 146146         return 0;
 147147 }
 148148 
 149149 /*
 150150  * Scan quickly the input file searching for:
 151151  *      - '#' directives
 152152  *      - keywords (if not flslvl)
 153153  *      - comments
 154154  *
 155155  *      Handle strings, numbers and trigraphs with care.
 156156  *      Only data from pp files are scanned here, never any rescans.
 157157  *      TODO: Only print out strings before calling other functions.
 158158  */
 159159 static void
 160160 fastscan(void)
 161161 {
 162162         struct symtab *nl;
 163163         int ch, i = 0;
 164164         int nnl = 0;
 165165         usch *cp;
 166166 
 167167         goto run;
 168168         for (;;) {
 169169                 ch = NXTCH();
 170170 xloop:          if (ch == -1)
 171171                         return;
 172172 #ifdef PCC_DEBUG
 173173                 if (dflag>1)
 174174                         printf("fastscan ch %d (%c)\n", ch, ch > 31 ? ch : '@');
 175175 #endif
 176176                 if ((spechr[ch] & C_SPEC) == 0) {
 177177                         PUTCH(ch);
 178178                         continue;
 179179                 }
 180180                 switch (ch) {
 181181                 case EBLOCK:
 182182                 case WARN:
 183183                 case CONC:
 184184                         error("bad char passed");
 185185                         break;
 186186 
 187187                 case '/': /* Comments */
 188188                         if ((ch = inch()) == '/') {
 189189 cppcmt:                         if (Cflag) { PUTCH(ch); } else { PUTCH(' '); }
 190190                                 do {
 191191                                         if (Cflag) PUTCH(ch);
 192192                                         ch = inch();
 193193                                 } while (ch != -1 && ch != '\n');
 194194                                 goto xloop;
 195195                         } else if (ch == '*') {
 196196                                 if (eatcmnt())
 197197                                         return;
 198198                         } else {
 199199                                 PUTCH('/');
 200200                                 goto xloop;
 201201                         }
 202202                         break;
 203203 
 204204                 case '?'/* trigraphs */
 205205                         if ((ch = chktg()))
 206206                                 goto xloop;
 207207                         PUTCH('?');
 208208                         break;
 209209 
 210210                 case '\\':
 211211                         if ((ch = NXTCH()) == '\n') {
 212212                                 ifiles->lineno++;
 213213                                 continue;
 214214                         } else {
 215215                                 PUTCH('\\');
 216216                         }
 217217                         goto xloop;
 218218 
 219219                 case '\n': /* newlines, for pp directives */
 220220                         while (nnl > 0) { PUTCH('\n'); nnl--; }
 221221 run2:                   ifiles->lineno++;
 222222                         do {
 223223                                 PUTCH(ch);
 224224 run:                            ch = NXTCH();
 225225                                 if (ch == '/') {
 226226                                         ch = NXTCH();
 227227                                         if (ch == '/')
 228228                                                 goto cppcmt;
 229229                                         if (ch == '*') {
 230230                                                 if (eatcmnt())
 231231                                                         return;
 232232                                                 goto run;
 233233                                         }
 234234                                         unch(ch);
 235235                                         ch = '/';
 236236                                 }
 237237                         } while (ch == ' ' || ch == '\t');
 238238                         if (ch == '\\') {
 239239                                 ch = NXTCH();
 240240                                 if (ch == '\n')
 241241                                         goto run2;
 242242                                 unch(ch);
 243243                                 ch = '\\';
 244244                         }
 245245                         if (ch == '#') {
 246246                                 ppdir();
 247247                                 continue;
 248248                         } else if (ch == '%') {
 249249                                 ch = NXTCH();
 250250                                 if (ch == ':') {
 251251                                         ppdir();
 252252                                         continue;
 253253                                 } else {
 254254                                         unch(ch);
 255255                                         ch = '%';
 256256                                 }
 257257                         } else if (ch == '?') {
 258258                                 if ((ch = chktg()) == '#') {
 259259                                         ppdir();
 260260                                         continue;
 261261                                 } else if (ch == 0)
 262262                                         ch = '?';
 263263                         }
 264264                         goto xloop;
 265265 
 266266                 case '\"': /* strings */
 267267 str:                    PUTCH(ch);
 268268                         while ((ch = NXTCH()) != '\"') {
 269269                                 if (ch == '\n')
 270270                                         goto xloop;
 271271                                 if (ch == '\\') {
 272272                                         if ((ch = NXTCH()) != '\n') {
 273273                                                 PUTCH('\\');
 274274                                                 PUTCH(ch);
 275275                                         } else
 276276                                                 nnl++;
 277277                                         continue;
 278278                                 }
 279279                                 if (ch < 0)
 280280                                         return;
 281281                                 PUTCH(ch);
 282282                         }
 283283                         PUTCH(ch);
 284284                         break;
 285285 
 286286                 case '.'/* for pp-number */
 287287                         PUTCH(ch);
 288288                         ch = NXTCH();
 289289                         if (ch < '0' || ch > '9')
 290290                                 goto xloop;
 291291                         /* FALLTHROUGH */
 292292                 case '0': case '1': case '2': case '3': case '4':
 293293                 case '5': case '6': case '7': case '8': case '9':
 294294                         do {
 295295                                 PUTCH(ch);
 296296 nxt:                            ch = NXTCH();
 297297                                 if (ch == '\\') {
 298298                                         ch = NXTCH();
 299299                                         if (ch == '\n') {
 300300                                                 goto nxt;
 301301                                         } else {
 302302                                                 unch(ch);
 303303                                                 ch = '\\';
 304304                                         }
 305305                                 }
 306306                                 if (spechr[ch] & C_EP) {
 307307                                         PUTCH(ch);
 308308                                         ch = NXTCH();
 309309                                         if (ch == '-' || ch == '+')
 310310                                                 continue;
 311311                                 }
 312312                         } while ((spechr[ch] & C_ID) || (ch == '.'));
 313313                         goto xloop;
 314314 
 315315                 case '\'': /* character literal */
 316316 con:                    PUTCH(ch);
 317317                         if (tflag)
 318318                                 continue; /* character constants ignored */
 319319                         while ((ch = NXTCH()) != '\'') {
 320320                                 if (ch == '\n')
 321321                                         goto xloop;
 322322                                 if (ch == '\\') {
 323323                                         if ((ch = NXTCH()) != '\n') {
 324324                                                 PUTCH('\\');
 325325                                                 PUTCH(ch);
 326326                                         } else
 327327                                                 nnl++;
 328328                                         continue;
 329329                                 }
 330330                                 if (ch < 0)
 331331                                         return;
 332332                                 PUTCH(ch);
 333333                         }
 334334                         PUTCH(ch);
 335335                         break;
 336336 
 337337                 case 'L':
 338338                         ch = NXTCH();
 339339                         if (ch == '\"') {
 340340                                 PUTCH('L');
 341341                                 goto str;
 342342                         }
 343343                         if (ch == '\'') {
 344344                                 PUTCH('L');
 345345                                 goto con;
 346346                         }
 347347                         unch(ch);
 348348                         ch = 'L';
 349349                         /* FALLTHROUGH */
 350350                 default:
 351351                         if ((spechr[ch] & C_ID) == 0)
 352352                                 error("fastscan");
 353353                         if (flslvl) {
 354354                                 while (spechr[ch] & C_ID)
 355355                                         ch = NXTCH();
 356356                                 goto xloop;
 357357                         }
 358358                         i = 0;
 359359                         do {
 360360                                 yytext[i++] = (usch)ch;
 361361                                 ch = NXTCH();
 362362                                 if (ch == '\\') {
 363363                                         ch = NXTCH();
 364364                                         if (ch != '\n') {
 365365                                                 unch(ch);
 366366                                                 ch = '\\';
 367367                                         } else {
 368368                                                 putch('\n');
 369369                                                 ifiles->lineno++;
 370370                                                 ch = NXTCH();
 371371                                         }
 372372                                 }
 373373                                 if (ch < 0)
 374374                                         return;
 375375                         } while (spechr[ch] & C_ID);
 376376 
 377377                         yytext[i] = 0;
 378378                         unch(ch);
 379379 
 380380                         cp = stringbuf;
 381381                         if ((nl = lookup(yytext, FIND)) && kfind(nl)) {
 382382                                 putstr(stringbuf);
 383383                         } else
 384384                                 putstr(yytext);
 385385                         stringbuf = cp;
 386386 
 387387                         break;
 388388                 }
 389389         }
 390390 }
 391391 
 392392 int
 393393 sloscan(void)
 394394 {
 395395         int ch;
 396396         int yyp;
 397397 
 398398 zagain:
 399399         yyp = 0;
 400400         ch = inch();
 401401         yytext[yyp++] = (usch)ch;
 402402         switch (ch) {
 403403         case -1:
 404404                 return 0;
 405405         case '\n':
 406406                 /* sloscan() never passes \n, that's up to fastscan() */
 407407                 unch(ch);
 408408                 goto yyret;
 409409 
 410410         case '\r': /* Ignore CR's */
 411411                 yyp = 0;
 412412                 break;
 413413 
 414414         case '0': case '1': case '2': case '3': case '4': case '5':
 415415         case '6': case '7': case '8': case '9':
 416416                 /* readin a "pp-number" */
 417417 ppnum:          for (;;) {
 418418                         ch = inch();
 419419                         if (spechr[ch] & C_EP) {
 420420                                 yytext[yyp++] = (usch)ch;
 421421                                 ch = inch();
 422422                                 if (ch == '-' || ch == '+') {
 423423                                         yytext[yyp++] = (usch)ch;
 424424                                 } else
 425425                                         unch(ch);
 426426                                 continue;
 427427                         }
 428428                         if ((spechr[ch] & C_ID) || ch == '.') {
 429429                                 yytext[yyp++] = (usch)ch;
 430430                                 continue;
 431431                         }
 432432                         break;
 433433                 }
 434434                 unch(ch);
 435435                 yytext[yyp] = 0;
 436436 
 437437                 return NUMBER;
 438438 
 439439         case '\'':
 440440 chlit:          
 441441                 for (;;) {
 442442                         if ((ch = inch()) == '\\') {
 443443                                 yytext[yyp++] = (usch)ch;
 444444                                 yytext[yyp++] = (usch)inch();
 445445                                 continue;
 446446                         } else if (ch == '\n') {
 447447                                 /* not a constant */
 448448                                 while (yyp > 1)
 449449                                         unch(yytext[--yyp]);
 450450                                 ch = '\'';
 451451                                 goto any;
 452452                         } else
 453453                                 yytext[yyp++] = (usch)ch;
 454454                         if (ch == '\'')
 455455                                 break;
 456456                 }
 457457                 yytext[yyp] = 0;
 458458 
 459459                 return NUMBER;
 460460 
 461461         case ' ':
 462462         case '\t':
 463463                 while ((ch = inch()) == ' ' || ch == '\t')
 464464                         yytext[yyp++] = (usch)ch;
 465465                 unch(ch);
 466466                 yytext[yyp] = 0;
 467467                 return WSPACE;
 468468 
 469469         case '/':
 470470                 if ((ch = inch()) == '/') {
 471471                         do {
 472472                                 yytext[yyp++] = (usch)ch;
 473473                                 ch = inch();
 474474                         } while (ch && ch != '\n');
 475475                         yytext[yyp] = 0;
 476476                         unch(ch);
 477477                         goto zagain;
 478478                 } else if (ch == '*') {
 479479                         int c, wrn;
 480480                         extern int readmac;
 481481 
 482482                         if (Cflag && !flslvl && readmac) {
 483483                                 unch(ch);
 484484                                 yytext[yyp] = 0;
 485485                                 return CMNT;
 486486                         }
 487487 
 488488                         wrn = 0;
 489489                 more:   while ((c = inch()) && c != '*') {
 490490                                 if (c == '\n')
 491491                                         putch(c), ifiles->lineno++;
 492492                                 else if (c == EBLOCK) {
 493493                                         (void)inch();
 494494                                         (void)inch();
 495495                                 } else if (c == 1) /* WARN */
 496496                                         wrn = 1;
 497497                         }
 498498                         if (c == 0)
 499499                                 return 0;
 500500                         if ((c = inch()) && c != '/') {
 501501                                 unch(c);
 502502                                 goto more;
 503503                         }
 504504                         if (c == 0)
 505505                                 return 0;
 506506                         if (!tflag && !Cflag && !flslvl)
 507507                                 unch(' ');
 508508                         if (wrn)
 509509                                 unch(1);
 510510                         goto zagain;
 511511                 }
 512512                 unch(ch);
 513513                 ch = '/';
 514514                 goto any;
 515515 
 516516         case '.':
 517517                 ch = inch();
 518518                 if (isdigit(ch)) {
 519519                         yytext[yyp++] = (usch)ch;
 520520                         goto ppnum;
 521521                 } else {
 522522                         unch(ch);
 523523                         ch = '.';
 524524                 }
 525525                 goto any;
 526526 
 527527         case '\"':
 528528                 if (tflag && defining)
 529529                         goto any;
 530530         strng:
 531531                 for (;;) {
 532532                         if ((ch = inch()) == '\\') {
 533533                                 yytext[yyp++] = (usch)ch;
 534534                                 yytext[yyp++] = (usch)inch();
 535535                                 continue;
 536536                         } else
 537537                                 yytext[yyp++] = (usch)ch;
 538538                         if (ch == '\"')
 539539                                 break;
 540540                 }
 541541                 yytext[yyp] = 0;
 542542                 return STRING;
 543543 
 544544         case 'L':
 545545                 if ((ch = inch()) == '\"' && !tflag) {
 546546                         yytext[yyp++] = (usch)ch;
 547547                         goto strng;
 548548                 } else if (ch == '\'' && !tflag) {
 549549                         yytext[yyp++] = (usch)ch;
 550550                         goto chlit;
 551551                 }
 552552                 unch(ch);
 553553                 /* FALLTHROUGH */
 554554 
 555555         /* Yetch, all identifiers */
 556556         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
 557557         case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
 558558         case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
 559559         case 's': case 't': case 'u': case 'v': case 'w': case 'x':
 560560         case 'y': case 'z':
 561561         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
 562562         case 'G': case 'H': case 'I': case 'J': case 'K':
 563563         case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
 564564         case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
 565565         case 'Y': case 'Z':
 566566         case '_': /* {L}({L}|{D})* */
 567567 
 568568                 /* Special hacks */
 569569                 for (;;) { /* get chars */
 570570                         ch = inch();
 571571                         if (isalpha(ch) || isdigit(ch) || ch == '_') {
 572572                                 yytext[yyp++] = (usch)ch;
 573573                         } else {
 574574                                 if (ch != -1)
 575575                                         unch(ch);
 576576                                 break;
 577577                         }
 578578                 }
 579579                 yytext[yyp] = 0; /* need already string */
 580580                 /* end special hacks */
 581581 
 582582                 return IDENT;
 583583         default:
 584584         any:
 585585                 yytext[yyp] = 0;
 586586                 return yytext[0];
 587587 
 588588         } /* endcase */
 589589         goto zagain;
 590590 
 591591 yyret:
 592592         yytext[yyp] = 0;
 593593         return ch;
 594594 }
 595595 
 596596 int
 597597 yylex(void)
 598598 {
 599599         static int ifdef, noex;
 600600         struct symtab *nl;
 601601         int ch, c2;
 602602 
 603603         while ((ch = sloscan()) == WSPACE)
 604604                 ;
 605605         if (ch < 128 && spechr[ch] & C_2)
 606606                 c2 = inpch();
 607607         else
 608608                 c2 = 0;
 609609 
 610610 #define C2(a,b,c) case a: if (c2 == b) return c; break
 611611         switch (ch) {
 612612         C2('=', '=', EQ);
 613613         C2('!', '=', NE);
 614614         C2('|', '|', OROR);
 615615         C2('&', '&', ANDAND);
 616616         case '<':
 617617                 if (c2 == '<') return LS;
 618618                 if (c2 == '=') return LE;
 619619                 break;
 620620         case '>':
 621621                 if (c2 == '>') return RS;
 622622                 if (c2 == '=') return GE;
 623623                 break;
 624624         case '+':
 625625         case '-':
 626626                 if (ch == c2)
 627627                         error("invalid preprocessor operator %c%c", ch, c2);
 628628                 break;
 629629 
 630630         case '/':
 631631                 if (Cflag == 0 || c2 != '*')
 632632                         break;
 633633                 /* Found comment that need to be skipped */
 634634                 for (;;) {
 635635                         ch = inpch();
 636636                 c1:     if (ch != '*')
 637637                                 continue;
 638638                         if ((ch = inpch()) == '/')
 639639                                 break;
 640640                         goto c1;
 641641                 }
 642642                 return yylex();
 643643 
 644644         case NUMBER:
 645645                 if (yytext[0] == '\'') {
 646646                         yylval.node.op = NUMBER;
 647647                         yylval.node.nd_val = charcon(yytext);
 648648                 } else
 649649                         cvtdig(yytext[0] != '0' ? 10 :
 650650                             yytext[1] == 'x' || yytext[1] == 'X' ? 16 : 8);
 651651                 return NUMBER;
 652652 
 653653         case IDENT:
 654654                 if (strcmp((char *)yytext, "defined") == 0) {
 655655                         ifdef = 1;
 656656                         return DEFINED;
 657657                 }
 658658                 nl = lookup(yytext, FIND);
 659659                 if (ifdef) {
 660660                         yylval.node.nd_val = nl != NULL;
 661661                         ifdef = 0;
 662662                 } else if (nl && noex == 0) {
 663663                         usch *och = stringbuf;
 664664                         int i;
 665665 
 666666                         i = kfind(nl);
 667667                         unch(WARN);
 668668                         if (i)
 669669                                 unpstr(stringbuf);
 670670                         else
 671671                                 unpstr(nl->namep);
 672672                         stringbuf = och;
 673673                         noex = 1;
 674674                         return yylex();
 675675                 } else {
 676676                         yylval.node.nd_val = 0;
 677677                 }
 678678                 yylval.node.op = NUMBER;
 679679                 return NUMBER;
 680680         case WARN:
 681681                 noex = 0;
 682682                 /* FALLTHROUGH */
 683683         case PHOLD:
 684684                 return yylex();
 685685         default:
 686686                 return ch;
 687687         }
 688688         unch(c2);
 689689         return ch;
 690690 }
 691691 
 692692 static int
 693693 inpch(void)
 694694 {
 695695         int len;
 696696 
 697697         if (ifiles->curptr < ifiles->maxread)
 698698                 return *ifiles->curptr++;
 699699 
 700700         if (ifiles->infil == -1)
 701701                 return -1;
 702702         if ((len = read(ifiles->infil, ifiles->buffer, CPPBUF)) < 0)
 703703                 error("read error on file %s", ifiles->orgfn);
 704704         if (len == 0)
 705705                 return -1;
 706706         ifiles->buffer[len] = 0;
 707707         ifiles->curptr = ifiles->buffer;
 708708         ifiles->maxread = ifiles->buffer + len;
 709709         return inpch();
 710710 }
 711711 
 712712 static int
 713713 inch(void)
 714714 {
 715715         int c;
 716716 
 717717 again:  switch (c = inpch()) {
 718718         case '\\': /* continued lines */
 719719 msdos:          if ((c = inpch()) == '\n') {
 720720                         ifiles->lineno++;
 721721                         putch('\n');
 722722                         goto again;
 723723                 } else if (c == '\r')
 724724                         goto msdos;
 725725                 unch(c);
 726726                 return '\\';
 727727         case '?': /* trigraphs */
 728728                 if ((c = chktg())) {
 729729                         unch(c);
 730730                         goto again;
 731731                 }
 732732                 return '?';
 733733         default:
 734734                 return c;
 735735         }
 736736 }
 737737 
 738738 /*
 739739  * Let the command-line args be faked defines at beginning of file.
 740740  */
 741741 static void
 742742 prinit(struct initar *it, struct includ *ic)
 743743 {
 744744         const char *pre, *post;
 745745         char *a;
 746746 
 747747         if (it->next)
 748748                 prinit(it->next, ic);
 749749         pre = post = NULL; /* XXX gcc */
 750750         switch (it->type) {
 751751         case 'D':
 752752                 pre = "#define ";
 753753                 if ((a = strchr(it->str, '=')) != NULL) {
 754754                         *a = ' ';
 755755                         post = "\n";
 756756                 } else
 757757                         post = " 1\n";
 758758                 break;
 759759         case 'U':
 760760                 pre = "#undef ";
 761761                 post = "\n";
 762762                 break;
 763763         case 'i':
 764764                 pre = "#include \"";
 765765                 post = "\"\n";
 766766                 break;
 767767         default:
 768768                 error("prinit");
 769769         }
 770770         strlcat((char *)ic->buffer, pre, CPPBUF+1);
 771771         strlcat((char *)ic->buffer, it->str, CPPBUF+1);
 772772         if (strlcat((char *)ic->buffer, post, CPPBUF+1) >= CPPBUF+1)
 773773                 error("line exceeds buffer size");
 774774 
 775775         ic->lineno--;
 776776         while (*ic->maxread)
 777777                 ic->maxread++;
 778778 }
 779779 
 780780 /*
 781781  * A new file included.
 782782  * If ifiles == NULL, this is the first file and already opened (stdin).
 783783  * Return 0 on success, -1 if file to be included is not found.
 784784  */
 785785 int
 786786 pushfile(const usch *file, const usch *fn, int idx, void *incs)
 787787 {
 788788         extern struct initar *initar;
 789789         struct includ ibuf;
 790790         struct includ *ic;
 791791         int otrulvl, i;
 792792 
 793793         ic = &ibuf;
 794794         ic->next = ifiles;
 795795 
 796796         if (file != NULL) {
 797797                 if ((ic->infil = open((const char *)file, O_RDONLY)) < 0)
 798798                         return -1;
 799799                 ic->orgfn = ic->fname = file;
 800800                 if (++inclevel > MAX_INCLEVEL)
 801801                         error("Limit for nested includes exceeded");
 802802         } else {
 803803                 ic->infil = 0;
 804804                 ic->orgfn = ic->fname = (const usch *)"<stdin>";
 805805         }
 806806 #ifndef BUF_STACK
 807807         ic->bbuf = malloc(BBUFSZ);
 808808 #endif
 809809         ic->buffer = ic->bbuf+NAMEMAX;
 810810         ic->curptr = ic->buffer;
 811811         ifiles = ic;
 812812         ic->lineno = 1;
 813813         ic->maxread = ic->curptr;
 814814         ic->idx = idx;
 815815         ic->incs = incs;
 816816         ic->fn = fn;
 817817         prtline();
 818818         if (initar) {
 819819                 int oin = ic->infil;
 820820                 ic->infil = -1;
 821821                 *ic->maxread = 0;
 822822                 prinit(initar, ic);
 823823                 initar = NULL;
 824824                 if (dMflag)
 825825                         i = write(ofd, ic->buffer, strlen((char *)ic->buffer));
 826826                 fastscan();
 827827                 prtline();
 828828                 ic->infil = oin;
 829829         }
 830830 
 831831         otrulvl = trulvl;
 832832 
 833833         fastscan();
 834834 
 835835         if (otrulvl != trulvl || flslvl)
 836836                 error("unterminated conditional");
 837837 
 838838 #ifndef BUF_STACK
 839839         free(ic->bbuf);
 840840 #endif
 841841         ifiles = ic->next;
 842842         close(ic->infil);
 843843         inclevel--;
 844844         return 0;
 845845 }
 846846 
 847847 /*
 848848  * Print current position to output file.
 849849  */
 850850 void
 851851 prtline(void)
 852852 {
 853853         usch *s, *os = stringbuf;
 854854         int i;
 855855 
 856856         if (Mflag) {
 857857                 if (dMflag)
 858858                         return; /* no output */
 859859                 if (ifiles->lineno == 1) {
 860860                         s = sheap("%s: %s\n", Mfile, ifiles->fname);
 861861                         i = write(ofd, s, strlen((char *)s));
 862862                         if (MPflag &&
 863863                             strcmp((const char *)ifiles->fname, (char *)MPfile)) {
 864864                                 s = sheap("%s:\n", ifiles->fname);
 865865                                 i = write(ofd, s, strlen((char *)s));
 866866                         }
 867867                 }
 868868         } else if (!Pflag) {
 869869                 putstr(sheap("\n# %d \"%s\"", ifiles->lineno, ifiles->fname));
 870870                 if (ifiles->idx == SYSINC)
 871871                         putstr(sheap(" 3"));
 872872                 putstr(sheap("\n"));
 873873         }
 874874         stringbuf = os;
 875875 }
 876876 
 877877 void
 878878 cunput(int c)
 879879 {
 880880 #ifdef PCC_DEBUG
 881881 //      if (dflag)printf(": '%c'(%d)\n", c > 31 ? c : ' ', c);
 882882 #endif
 883883         unch(c);
 884884 }
 885885 
 886886 static int
 887887 dig2num(int c)
 888888 {
 889889         if (c >= 'a')
 890890                 c = c - 'a' + 10;
 891891         else if (c >= 'A')
 892892                 c = c - 'A' + 10;
 893893         else
 894894                 c = c - '0';
 895895         return c;
 896896 }
 897897 
 898898 /*
 899899  * Convert string numbers to unsigned long long and check overflow.
 900900  */
 901901 static void
 902902 cvtdig(int rad)
 903903 {
 904904         unsigned long long rv = 0;
 905905         unsigned long long rv2 = 0;
 906906         usch *y = yytext;
 907907         int c;
 908908 
 909909         c = *y++;
 910910         if (rad == 16)
 911911                 y++;
 912912         while (isxdigit(c)) {
 913913                 rv = rv * rad + dig2num(c);
 914914                 /* check overflow */
 915915                 if (rv / rad < rv2)
 916916                         error("Constant \"%s\" is out of range", yytext);
 917917                 rv2 = rv;
 918918                 c = *y++;
 919919         }
 920920         y--;
 921921         while (*y == 'l' || *y == 'L')
 922922                 y++;
 923923         yylval.node.op = *y == 'u' || *y == 'U' ? UNUMBER : NUMBER;
 924924         yylval.node.nd_uval = rv;
 925925         if ((rad == 8 || rad == 16) && yylval.node.nd_val < 0)
 926926                 yylval.node.op = UNUMBER;
 927927         if (yylval.node.op == NUMBER && yylval.node.nd_val < 0)
 928928                 /* too large for signed, see 6.4.4.1 */
 929929                 error("Constant \"%s\" is out of range", yytext);
 930930 }
 931931 
 932932 static int
 933933 charcon(usch *p)
 934934 {
 935935         int val, c;
 936936 
 937937         p++; /* skip first ' */
 938938         val = 0;
 939939         if (*p++ == '\\') {
 940940                 switch (*p++) {
 941941                 case 'a': val = '\a'; break;
 942942                 case 'b': val = '\b'; break;
 943943                 case 'f': val = '\f'; break;
 944944                 case 'n': val = '\n'; break;
 945945                 case 'r': val = '\r'; break;
 946946                 case 't': val = '\t'; break;
 947947                 case 'v': val = '\v'; break;
 948948                 case '\"': val = '\"'; break;
 949949                 case '\'': val = '\''; break;
 950950                 case '\\': val = '\\'; break;
 951951                 case 'x':
 952952                         while (isxdigit(c = *p)) {
 953953                                 val = val * 16 + dig2num(c);
 954954                                 p++;
 955955                         }
 956956                         break;
 957957                 case '0': case '1': case '2': case '3': case '4':
 958958                 case '5': case '6': case '7':
 959959                         p--;
 960960                         while (isdigit(c = *p)) {
 961961                                 val = val * 8 + (c - '0');
 962962                                 p++;
 963963                         }
 964964                         break;
 965965                 default: val = p[-1];
 966966                 }
 967967 
 968968         } else
 969969                 val = p[-1];
 970970         return val;
 971971 }
 972972 
 973973 static void
 974974 chknl(int ignore)
 975975 {
 976976         int t;
 977977 
 978978         while ((t = sloscan()) == WSPACE)
 979979                 ;
 980980         if (t != '\n') {
 981981                 if (t && t != (usch)-1) {
 982982                         if (ignore) {
 983983                                 warning("newline expected, got \"%s\"", yytext);
 984984                                 /* ignore rest of line */
 985985                                 while ((t = sloscan()) && t != '\n')
 986986                                         ;
 987987                         }
 988988                         else
 989989                                 error("newline expected, got \"%s\"", yytext);
 990990                 } else {
 991991                         if (ignore)
 992992                                 warning("no newline at end of file");
 993993                         else
 994994                                 error("no newline at end of file");
 995995                 }
 996996         }
 997997 }
 998998 
 999999 static void
 10001000 elsestmt(void)
 10011001 {
 10021002         if (flslvl) {
 10031003                 if (elflvl > trulvl)
 10041004                         ;
 10051005                 else if (--flslvl!=0) {
 10061006                         flslvl++;
 10071007                 } else {
 10081008                         trulvl++;
 10091009                         prtline();
 10101010                 }
 10111011         } else if (trulvl) {
 10121012                 flslvl++;
 10131013                 trulvl--;
 10141014         } else
 10151015                 error("If-less else");
 10161016         if (elslvl==trulvl+flslvl)
 10171017                 error("Too many else");
 10181018         elslvl=trulvl+flslvl;
 10191019         chknl(1);
 10201020 }
 10211021 
 10221022 static void
 10231023 skpln(void)
 10241024 {
 10251025         /* just ignore the rest of the line */
 10261026         while (inch() != '\n')
 10271027                 ;
 10281028         unch('\n');
 10291029         flslvl++;
 10301030 }
 10311031 
 10321032 static void
 10331033 ifdefstmt(void)         
 10341034 {
 10351035         int t;
 10361036 
 10371037         if (flslvl) {
 10381038                 skpln();
 10391039                 return;
 10401040         }
 10411041         do
 10421042                 t = sloscan();
 10431043         while (t == WSPACE);
 10441044         if (t != IDENT)
 10451045                 error("bad ifdef");
 10461046         if (lookup(yytext, FIND) == 0) {
 10471047                 putch('\n');
 10481048                 flslvl++;
 10491049         } else
 10501050                 trulvl++;
 10511051         chknl(0);
 10521052 }
 10531053 
 10541054 static void
 10551055 ifndefstmt(void)         
 10561056 {
 10571057         int t;
 10581058 
 10591059         if (flslvl) {
 10601060                 skpln();
 10611061                 return;
 10621062         }
 10631063         do
 10641064                 t = sloscan();
 10651065         while (t == WSPACE);
 10661066         if (t != IDENT)
 10671067                 error("bad ifndef");
 10681068         if (lookup(yytext, FIND) != 0) {
 10691069                 putch('\n');
 10701070                 flslvl++;
 10711071         } else
 10721072                 trulvl++;
 10731073         chknl(0);
 10741074 }
 10751075 
 10761076 static void
 10771077 endifstmt(void)         
 10781078 {
 10791079         if (flslvl) {
 10801080                 flslvl--;
 10811081                 if (flslvl == 0) {
 10821082                         putch('\n');
 10831083                         prtline();
 10841084                 }
 10851085         } else if (trulvl)
 10861086                 trulvl--;
 10871087         else
 10881088                 error("If-less endif");
 10891089         if (flslvl == 0)
 10901090                 elflvl = 0;
 10911091         elslvl = 0;
 10921092         chknl(1);
 10931093 }
 10941094 
 10951095 static void
 10961096 ifstmt(void)
 10971097 {
 10981098         if (flslvl == 0) {
 10991099                 if (yyparse() == 0) {
 11001100                         putch('\n');
 11011101                         ++flslvl;
 11021102                 } else
 11031103                         ++trulvl;
 11041104         } else
 11051105                 ++flslvl;
 11061106 }
 11071107 
 11081108 static void
 11091109 elifstmt(void)
 11101110 {
 11111111         if (flslvl == 0)
 11121112                 elflvl = trulvl;
 11131113         if (flslvl) {
 11141114                 if (elflvl > trulvl)
 11151115                         ;
 11161116                 else if (--flslvl!=0)
 11171117                         ++flslvl;
 11181118                 else {
 11191119                         if (yyparse()) {
 11201120                                 ++trulvl;
 11211121                                 prtline();
 11221122                         } else {
 11231123                                 putch('\n');
 11241124                                 ++flslvl;
 11251125                         }
 11261126                 }
 11271127         } else if (trulvl) {
 11281128                 ++flslvl;
 11291129                 --trulvl;
 11301130         } else
 11311131                 error("If-less elif");
 11321132 }
 11331133 
<> 1134+/* save line into stringbuf */
11341135 static usch *
<>1135 -svinp(void)
  1136+savln(void)
11361137 {
 11371138         int c;
 11381139         usch *cp = stringbuf;
 11391140 
<>1140 -        while ((c = inch()) && c != '\n')
  1141+        while ((c = inch()) != 0) {
  1142+                if (c == '\n') {
  1143+                        unch(c);
  1144+                        break;
  1145+                }
11411146                 savch(c);
<>1142 -        savch('\n');
  1147+        }
11431148         savch(0);
<> 1149+
11441150         return cp;
 11451151 }
 11461152 
 11471153 static void
 11481154 cpperror(void)
 11491155 {
 11501156         usch *cp;
 11511157         int c;
 11521158 
 11531159         if (flslvl)
 11541160                 return;
 11551161         c = sloscan();
 11561162         if (c != WSPACE && c != '\n')
<>1157 -                error("bad error");
 1158 -        cp = svinp();
 1159 -        if (flslvl)
 1160 -                stringbuf = cp;
 1161 -        else
 1162 -                error("%s", cp);
  1163+                error("bad #error");
  1164+        cp = savln();
  1165+        error("#error %s", cp);
11631166 }
 11641167 
 11651168 static void
 11661169 cppwarning(void)
 11671170 {
 11681171         usch *cp;
 11691172         int c;
 11701173 
 11711174         if (flslvl)
 11721175                 return;
 11731176         c = sloscan();
 11741177         if (c != WSPACE && c != '\n')
<>1175 -                error("bad warning");
 1176 -
 1177 -        /* svinp() add an unwanted \n */
 1178 -        cp = stringbuf;
 1179 -        while ((c = inch()) && c != '\n')
 1180 -                savch(c);
 1181 -        savch(0);
 1182 -
 1183 -        if (flslvl)
 1184 -                stringbuf = cp;
 1185 -        else
 1186 -                warning("#warning %s", cp);
 1187 -
 1188 -        unch('\n');
  1178+                error("bad #warning");
  1179+        cp = savln();
  1180+        warning("#warning %s", cp);
  1181+        stringbuf = cp;
<_11891182 }
 11901183 
 11911184 static void
 11921185 undefstmt(void)
 11931186 {
 11941187         struct symtab *np;
 11951188 
 11961189         if (flslvl)
 11971190                 return;
 11981191         if (sloscan() != WSPACE || sloscan() != IDENT)
 11991192                 error("bad undef");
 12001193         if (flslvl == 0 && (np = lookup(yytext, FIND)))
 12011194                 np->value = 0;
 12021195         chknl(0);
 12031196 }
 12041197 
 12051198 static void
 12061199 pragmastmt(void)
 12071200 {
 12081201         int c;
 12091202         usch *sb = stringbuf;
 12101203 
 12111204         if (sloscan() != WSPACE)
 12121205                 error("bad pragma");
 12131206         savstr((const usch *)"\n#pragma ");
 12141207         do {
 12151208                 savch(c = inch());
 12161209         } while (c && c != '\n');
 12171210         if (c == '\n')
 12181211                 unch(c);
 12191212         savch(0);
 12201213         if (!flslvl)
 12211214                 putstr(sb);
 12221215         stringbuf = sb;
 12231216         prtline();
 12241217 }
 12251218 
 12261219 int
 12271220 cinput(void)
 12281221 {
 12291222         return inch();
 12301223 }
 12311224 
 12321225 /*
 12331226  * Check for (and convert) trigraphs.
 12341227  */
 12351228 int
 12361229 chktg(void)
 12371230 {
 12381231         int c;
 12391232 
 12401233         if ((c = inpch()) != '?') {
 12411234                 unch(c);
 12421235                 return 0;
 12431236         }
 12441237         switch (c = inpch()) {
 12451238         case '=': c = '#'; break;
 12461239         case '(': c = '['; break;
 12471240         case ')': c = ']'; break;
 12481241         case '<': c = '{'; break;
 12491242         case '>': c = '}'; break;
 12501243         case '/': c = '\\'; break;
 12511244         case '\'': c = '^'; break;
 12521245         case '!': c = '|'; break;
 12531246         case '-': c = '~'; break;
 12541247         default:
 12551248                 unch(c);
 12561249                 unch('?');
 12571250                 c = 0;
 12581251         }
 12591252         return c;
 12601253 }
 12611254 
 12621255 static struct {
 12631256         const char *name;
 12641257         void (*fun)(void);
 12651258 } ppd[] = {
 12661259         { "ifndef", ifndefstmt },
 12671260         { "ifdef", ifdefstmt },
 12681261         { "if", ifstmt },
 12691262         { "include", include },
 12701263         { "else", elsestmt },
 12711264         { "endif", endifstmt },
 12721265         { "error", cpperror },
 12731266         { "warning", cppwarning },
 12741267         { "define", define },
 12751268         { "undef", undefstmt },
 12761269         { "line", line },
 12771270         { "pragma", pragmastmt },
 12781271         { "elif", elifstmt },
 12791272 #ifdef GCC_COMPAT
 12801273         { "include_next", include_next },
 12811274 #endif
 12821275 };
 12831276 
 12841277 /*
 12851278  * Handle a preprocessor directive.
 12861279  */
 12871280 void
 12881281 ppdir(void)
 12891282 {
 12901283         char bp[20];
 12911284         int ch, i;
 12921285 
 12931286         while ((ch = inch()) == ' ' || ch == '\t')
 12941287                 ;
 12951288         if (ch == '\n') { /* empty directive */
 12961289                 unch(ch);
 12971290                 return;
 12981291         }
 12991292         if (ch < 'a' || ch > 'z')
 13001293                 goto out; /* something else, ignore */
 13011294         i = 0;
 13021295         do {
 13031296                 bp[i++] = (usch)ch;
 13041297                 if (i == sizeof(bp)-1)
 13051298                         goto out; /* too long */
 13061299                 ch = inch();
 13071300         } while ((ch >= 'a' && ch <= 'z') || (ch == '_'));
 13081301         unch(ch);
 13091302         bp[i++] = 0;
 13101303 
 13111304         /* got keyword */
 13121305 #define SZ (int)(sizeof(ppd)/sizeof(ppd[0]))
 13131306         for (i = 0; i < SZ; i++)
 13141307                 if (bp[0] == ppd[i].name[0] && strcmp(bp, ppd[i].name) == 0)
 13151308                         break;
 13161309         if (i == SZ)
 13171310                 goto out;
 13181311 
 13191312         /* Found matching keyword */
 13201313         (*ppd[i].fun)();
 13211314         return;
 13221315 
 13231316 out:    while ((ch = inch()) != '\n' && ch != -1)
 13241317                 ;
 13251318         unch('\n');
 13261319 }
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-23 02:38 +0100