parser.c (16076B)
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 (!s && !hide) { 106 where = ENVIRON; 107 s = getenv(name); 108 } 109 110 if (eflag && !hide) { 111 t = getenv(name); 112 if (t) { 113 where = ENVIRON; 114 s = t; 115 } 116 } 117 118 if (pwhere) 119 *pwhere = where; 120 if (mpp) 121 *mpp = mp; 122 123 return s; 124 } 125 126 char * 127 getmacro(char *name) 128 { 129 return macroinfo(name, NULL, NULL); 130 } 131 132 void 133 setmacro(char *name, char *val, int where, int export) 134 { 135 int owhere, set; 136 char *s; 137 Macro *mp; 138 139 assert(where != ENVIRON); 140 141 s = macroinfo(name, &owhere, &mp); 142 143 /* 144 * Default values are defined before anything else, and marked 145 * as MAKEFILES because they are injected as parseable text, and 146 * MAKEFILE variables are always overriden. ENVIRON macros are 147 * generated in macroinfo() and this is why this function should 148 * not receive a where == ENVIRON ever. 149 */ 150 151 switch (owhere) { 152 case UNDEF: 153 case MAKEFILE: 154 set = 1; 155 break; 156 case ENVIRON: 157 set = (where == MAKEFLAGS || where == CMDLINE); 158 set |= (where == MAKEFILE && !eflag); 159 break; 160 case MAKEFLAGS: 161 set = (where == CMDLINE || where == MAKEFLAGS); 162 break; 163 case CMDLINE: 164 set = (where == CMDLINE); 165 break; 166 default: 167 abort(); 168 } 169 170 if (!set) { 171 debug("hidding override of %s from '%s' to '%s'", name, s, val); 172 } else { 173 debug("override %s from '%s' to '%s'", name, s, val); 174 free(mp->value); 175 mp->value = estrdup(val); 176 mp->where = where; 177 178 if (export && strcmp(name, "SHELL") != 0) { 179 debug("exporting macro %s", name); 180 exportvar(name, val); 181 } 182 } 183 } 184 185 void 186 freeloc(struct loc *loc) 187 { 188 free(loc->fname); 189 } 190 191 static struct loc * 192 getloc(void) 193 { 194 struct input *ip; 195 196 for (ip = input; ip && ip->type != FTFILE; ip = ip->prev) 197 ; 198 if (!ip) 199 return NULL; 200 201 return &ip->loc; 202 } 203 204 205 void 206 error(char *fmt, ...) 207 { 208 va_list va; 209 struct loc *loc; 210 211 fprintf(stderr, "make: error: "); 212 if ((loc = getloc()) != NULL) 213 fprintf(stderr, "%s:%d: ", loc->fname, loc->lineno); 214 215 va_start(va, fmt); 216 vfprintf(stderr, fmt, va); 217 va_end(va); 218 putc('\n', stderr); 219 220 exit(EXIT_FAILURE); 221 } 222 223 void 224 warning(char *fmt, ...) 225 { 226 va_list va; 227 struct loc *loc; 228 229 fprintf(stderr, "make: warning: "); 230 if ((loc = getloc()) != NULL) 231 fprintf(stderr, "%s:%d: ", loc->fname, loc->lineno); 232 233 va_start(va, fmt); 234 vfprintf(stderr, fmt, va); 235 va_end(va); 236 putc('\n', stderr); 237 } 238 239 static void 240 pop(void) 241 { 242 struct input *ip = input->prev; 243 244 if (input->type == FTFILE) { 245 if (input->fp) 246 fclose(input->fp); 247 freeloc(&input->loc); 248 } 249 free(input->buf); 250 free(input); 251 252 input = ip; 253 } 254 255 static void 256 push(int type, ...) 257 { 258 int line, len, pos; 259 FILE *fp = NULL; 260 char *buf, *s, *fname = NULL; 261 va_list va; 262 struct input *ip; 263 264 va_start(va, type); 265 switch (type) { 266 case FTFILE: 267 fp = va_arg(va, FILE *); 268 s = va_arg(va, char *); 269 line = va_arg(va, int); 270 fname = estrdup(s); 271 buf = emalloc(BUFSIZ); 272 pos = len = BUFSIZ; 273 break; 274 case FTEXPAN: 275 s = va_arg(va, char *); 276 buf = estrdup(s); 277 line = pos = 0; 278 len = strlen(s); 279 break; 280 } 281 va_end(va); 282 283 ip = emalloc(sizeof(*ip)); 284 ip->siz = len; 285 ip->buf = buf; 286 ip->type = type; 287 ip->fp = fp; 288 ip->loc.fname = fname; 289 ip->loc.lineno = line; 290 ip->pos = pos; 291 ip->prev = input; 292 293 input = ip; 294 } 295 296 static char * 297 trim(char *s) 298 { 299 size_t len; 300 301 while (isspace(*s)) 302 s++; 303 304 for (len = strlen(s); len > 0 && isspace(s[len-1]); --len) 305 s[len-1] = '\0'; 306 307 return s; 308 } 309 310 static void 311 include(char *s) 312 { 313 int len; 314 FILE *fp; 315 char *fil, *t; 316 317 s = trim(s); 318 fil = expandstring(s, NULL, getloc()); 319 320 t = trim(fil); 321 if (strlen(t) != 0) { 322 debug("including '%s'", t); 323 if ((fp = fopen(t, "r")) == NULL) 324 error("opening %s:%s", t, strerror(errno)); 325 push(FTFILE, fp, t, 0); 326 } 327 328 free(fil); 329 } 330 331 static char * 332 nextline(void) 333 { 334 int c; 335 FILE *fp; 336 char *s, *lim; 337 338 assert(input->type == FTFILE); 339 340 repeat: 341 fp = input->fp; 342 if (!fp || feof(fp)) 343 return NULL; 344 345 lim = &input->buf[input->siz]; 346 for (s = input->buf; s < lim; *s++ = c) { 347 c = getc(fp); 348 if (c == '\n' || c == EOF) { 349 input->loc.lineno++; 350 *s++ = '\n'; 351 break; 352 } 353 if (c > UCHAR_MAX || c < 0) 354 error("invalid character '%c' (%d)", c, c); 355 } 356 357 358 if (s == lim) 359 error("too long line"); 360 if (ferror(fp)) 361 error(strerror(errno)); 362 *s = '\0'; 363 364 if (!strcmp(input->buf, "")) 365 goto repeat; 366 367 if (strncmp(input->buf, "include", 7) == 0) { 368 input->pos = input->siz; 369 include(input->buf+7); 370 goto repeat; 371 } 372 373 input->pos = 0; 374 375 376 return input->buf; 377 } 378 379 static int 380 empty(struct input *ip) 381 { 382 return ip->pos == ip->siz || ip->buf[ip->pos] == '\0'; 383 } 384 385 static int 386 moreinput(void) 387 { 388 while (input) { 389 if (!empty(input)) 390 break; 391 392 switch (input->type) { 393 case FTEXPAN: 394 pop(); 395 break; 396 case FTFILE: 397 if (!nextline()) 398 pop(); 399 break; 400 } 401 } 402 403 return input != NULL; 404 } 405 406 static int 407 nextc(void) 408 { 409 if (!moreinput()) 410 return EOF; 411 412 return input->buf[input->pos++]; 413 } 414 415 /* 416 * This function only can be called after a call to nextc 417 * that didn't return EOF. It can return '\0', but as 418 * it is used only to check against '$' then it is not 419 * a problem. 420 */ 421 static int 422 ahead(void) 423 { 424 return input->buf[input->pos]; 425 } 426 427 static int 428 back(int c) 429 { 430 if (c == EOF) 431 return c; 432 assert(input->pos > 0); 433 return input->buf[--input->pos] = c; 434 } 435 436 static void 437 comment(void) 438 { 439 int c; 440 441 while ((c = nextc()) != EOF && c != '\n') { 442 if (c == '\\' && nextc() == EOF) 443 break; 444 } 445 } 446 447 static void 448 skipspaces(void) 449 { 450 int c; 451 452 for (c = nextc(); c == ' ' || c == '\t'; c = nextc()) 453 ; 454 back(c); 455 } 456 457 static int 458 validchar(int c) 459 { 460 if (c == EOF) 461 return 0; 462 return c == '.' || c == '/' || c == '_' || c == '-' || isalnum(c); 463 } 464 465 static char * 466 expandmacro(char *name) 467 { 468 return expandstring(getmacro(name), NULL, getloc()); 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 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, MAKEFILE, NOEXPORT); 968 free(defs); 969 } 970 971 void 972 parseinput(void) 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, 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(); 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(); 1034 }