parser.c (16205B)
1 #include <assert.h> 2 #include <ctype.h> 3 #include <errno.h> 4 #include <limits.h> 5 #include <stdarg.h> 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <string.h> 9 10 #include "make.h" 11 12 #define MAXREPL 30 13 #define TABSIZ 64 14 #define MAXTOKEN FILENAME_MAX 15 #define ITEM 128 16 17 typedef struct macro Macro; 18 19 enum inputype { 20 FTFILE, 21 FTEXPAN, 22 }; 23 24 enum { 25 STBEGIN, 26 STINTERNAL, 27 STREPLACE, 28 STTO, 29 STEND, 30 }; 31 32 struct input { 33 int siz; 34 int type; 35 36 FILE *fp; 37 struct loc loc; 38 39 int pos; 40 char *buf; 41 42 struct input *prev; 43 }; 44 45 struct macro { 46 char *name; 47 char *value; 48 int where; 49 50 struct macro *next; 51 }; 52 53 static struct input *input; 54 static char token[MAXTOKEN]; 55 static int tok; 56 static Macro *htab[TABSIZ]; 57 58 void 59 dumpmacros(void) 60 { 61 Macro **pp, *p; 62 63 for (pp = htab; pp < &htab[TABSIZ]; ++pp) { 64 for (p = *pp; p; p = p->next) 65 printf("%s = %s\n", p->name, getmacro(p->name)); 66 } 67 } 68 69 static Macro * 70 lookup(char *name) 71 { 72 Macro *mp; 73 int h = hash(name) & TABSIZ-1; 74 75 for (mp = htab[h]; mp && strcmp(mp->name, name); mp = mp->next) 76 ; 77 78 if (mp) 79 return mp; 80 81 mp = emalloc(sizeof(*mp)); 82 mp->name = estrdup(name); 83 mp->value = estrdup(""); 84 mp->next = htab[h]; 85 mp->where = UNDEF; 86 htab[h] = mp; 87 88 return mp; 89 } 90 91 static char * 92 macroinfo(char *name, int *pwhere, Macro **mpp) 93 { 94 char *s, *t; 95 int hide, where; 96 Macro *mp = lookup(name); 97 98 hide = 0; 99 if (!strcmp(name, "SHELL") || !strcmp(name, "MAKEFLAGS")) 100 hide = 1; 101 102 s = mp->value; 103 where = mp->where; 104 105 if (!hide && (where == UNDEF || where == INTERNAL || eflag)) { 106 t = getenv(name); 107 if (t) { 108 where = ENVIRON; 109 s = t; 110 } 111 } 112 113 if (pwhere) 114 *pwhere = where; 115 if (mpp) 116 *mpp = mp; 117 118 return s; 119 } 120 121 char * 122 getmacro(char *name) 123 { 124 return macroinfo(name, NULL, NULL); 125 } 126 127 void 128 setmacro(char *name, char *val, int where, int export) 129 { 130 int owhere, set; 131 char *s; 132 Macro *mp; 133 134 assert(where != ENVIRON); 135 136 s = macroinfo(name, &owhere, &mp); 137 138 /* 139 * Default values are defined before anything else, and marked 140 * as INTERNAL because they are injected as parseable text, and 141 * MAKEFILE and INTERNAL variables are always overriden. ENVIRON 142 * macros are generated in macroinfo() and this is why this function 143 * should not receive a where == ENVIRON ever. 144 */ 145 switch (owhere) { 146 case UNDEF: 147 case INTERNAL: 148 case MAKEFILE: 149 set = 1; 150 break; 151 case ENVIRON: 152 set = (where == MAKEFLAGS || where == CMDLINE); 153 set |= (where == MAKEFILE && !eflag); 154 break; 155 case MAKEFLAGS: 156 set = (where == CMDLINE || where == MAKEFLAGS); 157 break; 158 case CMDLINE: 159 set = (where == CMDLINE); 160 break; 161 default: 162 abort(); 163 } 164 165 if (!set) { 166 debug("hidding override of %s from '%s' to '%s'", name, s, val); 167 } else { 168 debug("override %s from '%s' to '%s'", name, s, val); 169 free(mp->value); 170 mp->value = estrdup(val); 171 mp->where = where; 172 173 if (export && strcmp(name, "SHELL") != 0) { 174 debug("exporting macro %s", name); 175 exportvar(name, val); 176 } 177 } 178 } 179 180 void 181 freeloc(struct loc *loc) 182 { 183 free(loc->fname); 184 } 185 186 static struct loc * 187 getloc(void) 188 { 189 struct input *ip; 190 191 for (ip = input; ip && ip->type != FTFILE; ip = ip->prev) 192 ; 193 if (!ip) 194 return NULL; 195 196 return &ip->loc; 197 } 198 199 200 void 201 error(char *fmt, ...) 202 { 203 va_list va; 204 struct loc *loc; 205 206 fprintf(stderr, "make: error: "); 207 if ((loc = getloc()) != NULL) 208 fprintf(stderr, "%s:%d: ", loc->fname, loc->lineno); 209 210 va_start(va, fmt); 211 vfprintf(stderr, fmt, va); 212 va_end(va); 213 putc('\n', stderr); 214 215 exit(EXIT_FAILURE); 216 } 217 218 void 219 warning(char *fmt, ...) 220 { 221 va_list va; 222 struct loc *loc; 223 224 fprintf(stderr, "make: warning: "); 225 if ((loc = getloc()) != NULL) 226 fprintf(stderr, "%s:%d: ", loc->fname, loc->lineno); 227 228 va_start(va, fmt); 229 vfprintf(stderr, fmt, va); 230 va_end(va); 231 putc('\n', stderr); 232 } 233 234 static void 235 pop(void) 236 { 237 struct input *ip = input->prev; 238 239 if (input->type == FTFILE) { 240 if (input->fp) 241 fclose(input->fp); 242 freeloc(&input->loc); 243 } 244 free(input->buf); 245 free(input); 246 247 input = ip; 248 } 249 250 static void 251 push(int type, ...) 252 { 253 int line, len, pos; 254 FILE *fp = NULL; 255 char *buf, *s, *fname = NULL; 256 va_list va; 257 struct input *ip; 258 259 va_start(va, type); 260 switch (type) { 261 case FTFILE: 262 fp = va_arg(va, FILE *); 263 s = va_arg(va, char *); 264 line = va_arg(va, int); 265 fname = estrdup(s); 266 buf = emalloc(BUFSIZ); 267 pos = len = BUFSIZ; 268 break; 269 case FTEXPAN: 270 s = va_arg(va, char *); 271 buf = estrdup(s); 272 line = pos = 0; 273 len = strlen(s); 274 break; 275 } 276 va_end(va); 277 278 ip = emalloc(sizeof(*ip)); 279 ip->siz = len; 280 ip->buf = buf; 281 ip->type = type; 282 ip->fp = fp; 283 ip->loc.fname = fname; 284 ip->loc.lineno = line; 285 ip->pos = pos; 286 ip->prev = input; 287 288 input = ip; 289 } 290 291 static char * 292 trim(char *s) 293 { 294 size_t len; 295 296 while (isspace(*s)) 297 s++; 298 299 for (len = strlen(s); len > 0 && isspace(s[len-1]); --len) 300 s[len-1] = '\0'; 301 302 return s; 303 } 304 305 static void 306 include(char *s) 307 { 308 int len; 309 FILE *fp; 310 char *fil, *t; 311 312 s = trim(s); 313 fil = expandstring(s, NULL, getloc()); 314 315 t = trim(fil); 316 if (strlen(t) != 0) { 317 debug("including '%s'", t); 318 if ((fp = fopen(t, "r")) == NULL) 319 error("opening %s:%s", t, strerror(errno)); 320 push(FTFILE, fp, t, 0); 321 } 322 323 free(fil); 324 } 325 326 static char * 327 nextline(void) 328 { 329 int c; 330 FILE *fp; 331 char *s, *lim; 332 333 assert(input->type == FTFILE); 334 335 repeat: 336 fp = input->fp; 337 if (!fp || feof(fp)) 338 return NULL; 339 340 lim = &input->buf[input->siz]; 341 for (s = input->buf; s < lim; *s++ = c) { 342 c = getc(fp); 343 if (c == '\n' || c == EOF) { 344 input->loc.lineno++; 345 *s++ = '\n'; 346 break; 347 } 348 if (c > UCHAR_MAX || c < 0) 349 error("invalid character '%c' (%d)", c, c); 350 } 351 352 353 if (s == lim) 354 error("too long line"); 355 if (ferror(fp)) 356 error(strerror(errno)); 357 *s = '\0'; 358 359 if (!strcmp(input->buf, "")) 360 goto repeat; 361 362 if (!strncmp(input->buf, "include", 7) && isblank(input->buf[7])) { 363 input->pos = input->siz; 364 include(input->buf+7); 365 goto repeat; 366 } 367 368 input->pos = 0; 369 370 371 return input->buf; 372 } 373 374 static int 375 empty(struct input *ip) 376 { 377 return ip->pos == ip->siz || ip->buf[ip->pos] == '\0'; 378 } 379 380 static int 381 moreinput(void) 382 { 383 while (input) { 384 if (!empty(input)) 385 break; 386 387 switch (input->type) { 388 case FTEXPAN: 389 pop(); 390 break; 391 case FTFILE: 392 if (!nextline()) 393 pop(); 394 break; 395 } 396 } 397 398 return input != NULL; 399 } 400 401 static int 402 nextc(void) 403 { 404 if (!moreinput()) 405 return EOF; 406 407 return input->buf[input->pos++]; 408 } 409 410 /* 411 * This function only can be called after a call to nextc 412 * that didn't return EOF. It can return '\0', but as 413 * it is used only to check against '$' then it is not 414 * a problem. 415 */ 416 static int 417 ahead(void) 418 { 419 return input->buf[input->pos]; 420 } 421 422 static int 423 back(int c) 424 { 425 if (c == EOF) 426 return c; 427 assert(input->pos > 0); 428 return input->buf[--input->pos] = c; 429 } 430 431 static void 432 comment(void) 433 { 434 int c; 435 436 while ((c = nextc()) != EOF && c != '\n') { 437 if (c == '\\' && nextc() == EOF) 438 break; 439 } 440 } 441 442 static void 443 skipspaces(void) 444 { 445 int c; 446 447 for (c = nextc(); c == ' ' || c == '\t'; c = nextc()) 448 ; 449 back(c); 450 } 451 452 static int 453 validchar(int c) 454 { 455 if (c == EOF) 456 return 0; 457 return c == '.' || c == '/' || c == '_' || c == '-' || isalnum(c); 458 } 459 460 static char * 461 expandmacro(char *name) 462 { 463 char *s; 464 465 s = expandstring(getmacro(name), NULL, getloc()); 466 debug("macro %s expanded to '%s'", name, s); 467 468 return s; 469 } 470 471 static void 472 replace(char *line, char *repl, char *to) 473 { 474 int siz, at, len, replsiz, tosiz, sep, pos; 475 char *oline, *s, *cur, *buf; 476 477 debug("replacing '%s', with '%s' to '%s'", line, repl, to); 478 oline = line; 479 tosiz = strlen(to); 480 replsiz = strlen(repl); 481 482 buf = NULL; 483 for (pos = 0; *line; pos += siz) { 484 cur = NULL; 485 siz = 0; 486 487 for (siz = 0; *line == ' ' || *line == '\t'; ++siz) { 488 cur = erealloc(cur, siz+1); 489 cur[siz] = *line++; 490 } 491 492 len = strcspn(line, " \t"); 493 at = len - replsiz; 494 if (at < 0 || memcmp(line + at, repl, replsiz)) { 495 cur = erealloc(cur, siz + len); 496 memcpy(cur + siz, line, len); 497 siz += len; 498 } else { 499 cur = erealloc(cur, siz + at + tosiz); 500 memcpy(cur + siz, line, at); 501 memcpy(cur + siz + at, to, tosiz); 502 siz += at + tosiz; 503 } 504 505 line += len; 506 buf = erealloc(buf, pos + siz); 507 memcpy(buf + pos, cur, siz); 508 free(cur); 509 } 510 511 if (pos > 0) { 512 buf = erealloc(buf, pos + 1); 513 buf[pos] = '\0'; 514 debug("\treplace '%s' with '%s'", oline, buf); 515 push(FTEXPAN, buf); 516 } 517 518 free(buf); 519 } 520 521 static void 522 expandsimple(Target *tp) 523 { 524 char *s; 525 Target **p; 526 int len, c; 527 528 switch (c = nextc()) { 529 case '@': 530 if (!tp || !tp->target) 531 return; 532 push(FTEXPAN, tp->target); 533 break; 534 case '<': 535 if (!tp || !tp->req) 536 return; 537 push(FTEXPAN, tp->req); 538 break; 539 case '*': 540 if (!tp || !tp->target) 541 return; 542 s = strrchr(tp->target, '.'); 543 if (!s) { 544 push(FTEXPAN, tp->target); 545 return; 546 } 547 548 len = s - tp->target; 549 s = emalloc(len+1); 550 memcpy(s, tp->target, len); 551 s[len] = '\0'; 552 push(FTEXPAN, s); 553 free(s); 554 break; 555 case '?': 556 if (!tp) 557 return; 558 559 if (tp->req && stamp(tp->req) > tp->stamp) { 560 push(FTEXPAN, " "); 561 push(FTEXPAN, tp->req); 562 } 563 564 for (p = tp->deps; p && *p; ++p) { 565 if (stamp((*p)->name) > tp->stamp) { 566 push(FTEXPAN, " "); 567 push(FTEXPAN, (*p)->name); 568 } 569 } 570 break; 571 default: 572 token[0] = c; 573 token[1] = '\0'; 574 s = expandmacro(token); 575 push(FTEXPAN, s); 576 free(s); 577 break; 578 } 579 } 580 581 static int 582 internal(int ch) 583 { 584 switch (ch) { 585 case '@': 586 case '?': 587 case '*': 588 case '<': 589 return 1; 590 default: 591 return 0; 592 } 593 } 594 595 static void 596 expansion(Target *tp) 597 { 598 int delim, c, repli, toi, namei, st; 599 char name[MAXTOKEN], repl[MAXREPL], to[MAXREPL]; 600 char *s, *erepl; 601 602 c = nextc(); 603 if (c == '(') 604 delim = ')'; 605 else if (c == '{') 606 delim = '}'; 607 else 608 delim = 0; 609 610 if (!delim) { 611 back(c); 612 expandsimple(tp); 613 return; 614 } 615 616 s = NULL; 617 namei = repli = toi = 0; 618 st = STBEGIN; 619 620 while (st != STEND && (c = nextc()) != EOF) { 621 switch (st) { 622 case STBEGIN: 623 if (c == ':') { 624 st = STREPLACE; 625 name[namei] = '\0'; 626 s = expandmacro(name); 627 break; 628 } 629 if (c == delim) { 630 name[namei] = '\0'; 631 s = expandmacro(name); 632 goto no_replace; 633 } 634 if (namei == MAXTOKEN-1) 635 error("expansion text too long"); 636 637 if (namei == 0 && internal(c)) { 638 name[namei++] = '$'; 639 name[namei++] = c; 640 name[namei] = '\0'; 641 st = STINTERNAL; 642 s = expandstring(name, tp, getloc()); 643 break; 644 } 645 646 if (!validchar(c)) 647 error("invalid macro name in expansion"); 648 name[namei++] = c; 649 break; 650 case STINTERNAL: 651 if (c == delim) 652 goto no_replace; 653 if (c != ':') 654 error("invalid internal macro in expansion"); 655 st = STREPLACE; 656 break; 657 case STREPLACE: 658 if (c == '=') { 659 st = STTO; 660 break; 661 } 662 if (c == delim) 663 error("invalid replacement pattern in expansion"); 664 if (repli == MAXREPL-1) 665 error("macro replacement too big"); 666 repl[repli++] = c; 667 break; 668 case STTO: 669 if (c == delim) { 670 st = STEND; 671 break; 672 } 673 674 if (toi == MAXREPL-1) 675 error("macro substiturion too big"); 676 to[toi++] = c; 677 break; 678 } 679 } 680 681 if (c == EOF) 682 error("found eof while parsing expansion"); 683 684 repl[repli] = '\0'; 685 to[toi] = '\0'; 686 687 erepl = expandstring(repl, tp, getloc()); 688 replace(s, erepl, to); 689 690 free(erepl); 691 free(s); 692 return; 693 694 no_replace: 695 push(FTEXPAN, s); 696 free(s); 697 } 698 699 /* 700 * Horrible hack to do string expansion. 701 * We cannot use normal push and nextc because that 702 * would consume characters of the current file too. 703 * For that reason it cleans the input and it recovers 704 * it later. 705 */ 706 char * 707 expandstring(char *line, Target *tp, struct loc *loc) 708 { 709 int c, n; 710 char *s; 711 struct input *ip = input; 712 713 input = NULL; 714 push(FTFILE, NULL, loc->fname, loc->lineno); 715 push(FTEXPAN, line); 716 717 n = 0; 718 s = NULL; 719 while ((c = nextc()) != EOF) { 720 if (c != '$') { 721 s = erealloc(s, ++n); 722 s[n-1] = c; 723 continue; 724 } 725 726 if ((c = nextc()) == '$') { 727 s = erealloc(s, n += 2); 728 s[n-2] = '$'; 729 s[n-1] = '$'; 730 } else { 731 back(c); 732 expansion(tp); 733 } 734 } 735 736 s = erealloc(s, n+1); 737 s[n] = '\0'; 738 input = ip; 739 740 return s; 741 } 742 743 static int 744 item(void) 745 { 746 int c; 747 char *s; 748 char buf[MAXTOKEN]; 749 750 for (s = buf; s < &buf[MAXTOKEN] - 1; ) { 751 c = nextc(); 752 if (c == '$' && ahead() != '$') 753 expansion(NULL); 754 else if (validchar(c)) 755 *s++ = c; 756 else 757 break; 758 } 759 back(c); 760 761 if (s >= &buf[MAXTOKEN] - 1) 762 error("token too long"); 763 if (s == buf) 764 error("invalid empty token"); 765 *s++ = '\0'; 766 memcpy(token, buf, s - buf); 767 768 return ITEM; 769 } 770 771 static int 772 next(void) 773 { 774 int c; 775 776 repeat: 777 /* 778 * It is better to avoid skipspaces() here, because 779 * it can generate the need for 2 calls to back(), 780 * and we need the character anyway. 781 */ 782 c = nextc(); 783 if (c == ' ' || c == '\t') 784 goto repeat; 785 786 if (c == '\\') { 787 if ((c = nextc()) == '\n') 788 goto repeat; 789 back(c); 790 c = '\\'; 791 } 792 793 switch (c) { 794 case EOF: 795 strcpy(token, "<EOF>"); 796 tok = EOF; 797 break; 798 case '$': 799 if ((c = nextc()) == '$') 800 goto single; 801 back(c); 802 expansion(NULL); 803 goto repeat; 804 case '#': 805 comment(); 806 c = '\n'; 807 case ';': 808 case ':': 809 case '=': 810 case '\n': 811 single: 812 token[0] = c; 813 token[1] = '\0'; 814 tok = c; 815 break; 816 default: 817 if (!validchar(c)) 818 error("unexpected character '%c'", c); 819 back(c); 820 tok = item(); 821 break; 822 } 823 824 return tok; 825 } 826 827 static char * 828 readmacrodef(void) 829 { 830 int n, c; 831 char *line; 832 833 n = 0; 834 line = NULL; 835 while ((c = nextc()) != EOF) { 836 line = erealloc(line, n+1); 837 if (c == '\n') 838 break; 839 if (c == '#') { 840 comment(); 841 break; 842 } 843 if (c == '\\') { 844 if ((c = nextc()) != '\n') { 845 back(c); 846 c = '\\'; 847 } else { 848 skipspaces(); 849 c = ' '; 850 } 851 } 852 853 line[n++] = c; 854 } 855 if (c == EOF) 856 error("EOF while looking for end of line"); 857 line[n] = '\0'; 858 859 return line; 860 } 861 862 static struct action 863 readcmd(void) 864 { 865 int n, c; 866 struct loc *loc; 867 struct action act; 868 869 skipspaces(); 870 871 loc = getloc(); 872 act.loc.fname = estrdup(loc->fname); 873 act.loc.lineno = loc->lineno; 874 875 n = 0; 876 act.line = NULL; 877 while ((c = nextc()) != EOF) { 878 act.line = erealloc(act.line, n+1); 879 if (c == '\n') 880 break; 881 if (c == '\\') { 882 if ((c = nextc()) == '\n') { 883 if ((c = nextc()) != '\t') 884 back(c); 885 continue; 886 } 887 back(c); 888 c = '\\'; 889 } 890 act.line[n++] = c; 891 } 892 if (c == EOF) 893 error("EOF while looking for end of command"); 894 act.line[n] = '\0'; 895 896 return act; 897 } 898 899 static void 900 rule(char *targets[], int ntargets) 901 { 902 int c, i, j, ndeps, nactions; 903 struct action *acts; 904 char **deps = NULL; 905 906 if (ntargets == 0) 907 error("missing target"); 908 909 for (ndeps = 0; next() == ITEM; ++ndeps) { 910 deps = erealloc(deps, (ndeps+1) * sizeof(char *)); 911 deps[ndeps] = estrdup(token); 912 } 913 914 if (tok != '\n' && tok != ';') 915 error("garbage at the end of the line"); 916 917 nactions = 0; 918 acts = NULL; 919 if (tok == ';') { 920 nactions++; 921 acts = erealloc(acts, nactions * sizeof(*acts)); 922 acts[nactions-1] = readcmd(); 923 } 924 925 for (;;) { 926 if ((c = nextc()) == '#') { 927 comment(); 928 continue; 929 } 930 if (c != '\t') 931 break; 932 nactions++; 933 acts = erealloc(acts, nactions * sizeof(*acts)); 934 acts[nactions-1] = readcmd(); 935 } 936 back(c); 937 938 for (i = 0; i < ntargets; i++) { 939 addtarget(targets[i], ndeps); 940 for (j = 0; j < ndeps; j++) 941 adddep(targets[i], deps[j]); 942 if (nactions > 0) 943 addrule(targets[i], acts, nactions); 944 } 945 946 for (i = 0; i < ndeps; i++) 947 free(deps[i]); 948 free(deps); 949 950 for (i = 0; i < nactions; i++) { 951 free(acts[i].line); 952 freeloc(&acts[i].loc); 953 } 954 free(acts); 955 } 956 957 static void 958 assign(char *macros[], int where, int n) 959 { 960 char *defs; 961 962 if (n != 1) 963 error("invalid macro definition"); 964 965 skipspaces(); 966 defs = readmacrodef(); 967 setmacro(*macros, defs, where, NOEXPORT); 968 free(defs); 969 } 970 971 void 972 parseinput(int where) 973 { 974 int i, n; 975 char **targets; 976 977 while (moreinput()) { 978 n = 0; 979 targets = NULL; 980 981 next(); 982 if (tok == '\n') 983 continue; 984 985 while (tok == ITEM) { 986 n++; 987 targets = erealloc(targets, n * sizeof(char *)); 988 targets[n-1] = estrdup(token); 989 next(); 990 } 991 992 switch (tok) { 993 case ':': 994 rule(targets, n); 995 break; 996 case '=': 997 assign(targets, where, n); 998 break; 999 default: 1000 error("unexpected token '%s'(%d)", token, tok); 1001 } 1002 1003 for (i = 0; i < n; i++) 1004 free(targets[i]); 1005 free(targets); 1006 } 1007 } 1008 1009 int 1010 parse(char *fname) 1011 { 1012 FILE *fp; 1013 1014 if (!fname) { 1015 fp = stdin; 1016 fname = "<stdin>"; 1017 } else if ((fp = fopen(fname, "r")) == NULL) { 1018 return 0; 1019 } 1020 1021 debug("parsing %s", fname); 1022 push(FTFILE, fp, fname, 0); 1023 parseinput(MAKEFILE); 1024 1025 return 1; 1026 } 1027 1028 void 1029 inject(char *s) 1030 { 1031 push(FTFILE, NULL, "<internal>", 0); 1032 push(FTEXPAN, s); 1033 parseinput(INTERNAL); 1034 }