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
17typedef struct macro Macro;
18
19enum inputype {
20 FTFILE,
21 FTEXPAN,
22};
23
24enum {
25 STBEGIN,
26 STINTERNAL,
27 STREPLACE,
28 STTO,
29 STEND,
30};
31
32struct 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
45struct macro {
46 char *name;
47 char *value;
48 int where;
49
50 struct macro *next;
51};
52
53static struct input *input;
54static char token[MAXTOKEN];
55static int tok;
56static Macro *htab[TABSIZ];
57
58void
59dumpmacros(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
69static Macro *
70lookup(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
91static char *
92macroinfo(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
121char *
122getmacro(char *name)
123{
124 return macroinfo(name, NULL, NULL);
125}
126
127void
128setmacro(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
180void
181freeloc(struct loc *loc)
182{
183 free(loc->fname);
184}
185
186static struct loc *
187getloc(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
200void
201error(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
218void
219warning(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
234static void
235pop(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
250static void
251push(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
291static char *
292trim(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
305static void
306include(char *s)
307{
308 FILE *fp;
309 char *fil, *t;
310
311 s = trim(s);
312 fil = expandstring(s, NULL, getloc());
313
314 t = trim(fil);
315 if (strlen(t) != 0) {
316 debug("including '%s'", t);
317 if ((fp = fopen(t, "r")) == NULL)
318 error("opening %s:%s", t, strerror(errno));
319 push(FTFILE, fp, t, 0);
320 }
321
322 free(fil);
323}
324
325static char *
326nextline(void)
327{
328 int c;
329 FILE *fp;
330 char *s, *lim;
331
332 assert(input->type == FTFILE);
333
334repeat:
335 fp = input->fp;
336 if (!fp || feof(fp))
337 return NULL;
338
339 lim = &input->buf[input->siz];
340 for (s = input->buf; s < lim; *s++ = c) {
341 c = getc(fp);
342 if (c == '\n' || c == EOF) {
343 input->loc.lineno++;
344 *s++ = '\n';
345 break;
346 }
347 if (c > UCHAR_MAX || c < 0)
348 error("invalid character '%c' (%d)", c, c);
349 }
350
351
352 if (s == lim)
353 error("too long line");
354 if (ferror(fp))
355 error(strerror(errno));
356 *s = '\0';
357
358 if (!strcmp(input->buf, ""))
359 goto repeat;
360
361 if (!strncmp(input->buf, "include", 7) && isblank(input->buf[7])) {
362 input->pos = input->siz;
363 include(input->buf+7);
364 goto repeat;
365 }
366
367 input->pos = 0;
368
369
370 return input->buf;
371}
372
373static int
374empty(struct input *ip)
375{
376 return ip->pos == ip->siz || ip->buf[ip->pos] == '\0';
377}
378
379static int
380moreinput(void)
381{
382 while (input) {
383 if (!empty(input))
384 break;
385
386 switch (input->type) {
387 case FTEXPAN:
388 pop();
389 break;
390 case FTFILE:
391 if (!nextline())
392 pop();
393 break;
394 }
395 }
396
397 return input != NULL;
398}
399
400static int
401nextc(void)
402{
403 if (!moreinput())
404 return EOF;
405
406 return input->buf[input->pos++];
407}
408
409/*
410 * This function only can be called after a call to nextc
411 * that didn't return EOF. It can return '\0', but as
412 * it is used only to check against '$' then it is not
413 * a problem.
414 */
415static int
416ahead(void)
417{
418 return input->buf[input->pos];
419}
420
421static int
422back(int c)
423{
424 if (c == EOF)
425 return c;
426 assert(input->pos > 0);
427 return input->buf[--input->pos] = c;
428}
429
430static void
431comment(void)
432{
433 int c;
434
435 while ((c = nextc()) != EOF && c != '\n') {
436 if (c == '\\' && nextc() == EOF)
437 break;
438 }
439}
440
441static void
442skipspaces(void)
443{
444 int c;
445
446 for (c = nextc(); c == ' ' || c == '\t'; c = nextc())
447 ;
448 back(c);
449}
450
451static int
452validchar(int c)
453{
454 if (c == EOF)
455 return 0;
456 return c == '.' || c == '/' || c == '_' || c == '-' || isalnum(c);
457}
458
459static char *
460expandmacro(char *name)
461{
462 char *s;
463
464 s = expandstring(getmacro(name), NULL, getloc());
465 debug("macro %s expanded to '%s'", name, s);
466
467 return s;
468}
469
470static void
471replace(char *line, char *repl, char *to)
472{
473 int siz, at, len, replsiz, tosiz, pos;
474 char *oline, *cur, *buf;
475
476 debug("replacing '%s', with '%s' to '%s'", line, repl, to);
477 oline = line;
478 tosiz = strlen(to);
479 replsiz = strlen(repl);
480
481 buf = NULL;
482 for (pos = 0; *line; pos += siz) {
483 cur = NULL;
484 siz = 0;
485
486 for (siz = 0; *line == ' ' || *line == '\t'; ++siz) {
487 cur = erealloc(cur, siz+1);
488 cur[siz] = *line++;
489 }
490
491 len = strcspn(line, " \t");
492 at = len - replsiz;
493 if (at < 0 || memcmp(line + at, repl, replsiz)) {
494 cur = erealloc(cur, siz + len);
495 memcpy(cur + siz, line, len);
496 siz += len;
497 } else {
498 cur = erealloc(cur, siz + at + tosiz);
499 memcpy(cur + siz, line, at);
500 memcpy(cur + siz + at, to, tosiz);
501 siz += at + tosiz;
502 }
503
504 line += len;
505 buf = erealloc(buf, pos + siz);
506 memcpy(buf + pos, cur, siz);
507 free(cur);
508 }
509
510 if (pos > 0) {
511 buf = erealloc(buf, pos + 1);
512 buf[pos] = '\0';
513 debug("\treplace '%s' with '%s'", oline, buf);
514 push(FTEXPAN, buf);
515 }
516
517 free(buf);
518}
519
520static void
521expandsimple(Target *tp)
522{
523 char *s;
524 Target **p;
525 int len, c;
526
527 switch (c = nextc()) {
528 case '@':
529 if (!tp || !tp->target)
530 return;
531 push(FTEXPAN, tp->target);
532 break;
533 case '<':
534 if (!tp || !tp->req)
535 return;
536 push(FTEXPAN, tp->req);
537 break;
538 case '*':
539 if (!tp || !tp->target)
540 return;
541 s = strrchr(tp->target, '.');
542 if (!s) {
543 push(FTEXPAN, tp->target);
544 return;
545 }
546
547 len = s - tp->target;
548 s = emalloc(len+1);
549 memcpy(s, tp->target, len);
550 s[len] = '\0';
551 push(FTEXPAN, s);
552 free(s);
553 break;
554 case '?':
555 if (!tp)
556 return;
557
558 if (tp->req && stamp(tp->req) > tp->stamp) {
559 push(FTEXPAN, " ");
560 push(FTEXPAN, tp->req);
561 }
562
563 for (p = tp->deps; p && *p; ++p) {
564 if (stamp((*p)->name) > tp->stamp) {
565 push(FTEXPAN, " ");
566 push(FTEXPAN, (*p)->name);
567 }
568 }
569 break;
570 default:
571 token[0] = c;
572 token[1] = '\0';
573 s = expandmacro(token);
574 push(FTEXPAN, s);
575 free(s);
576 break;
577 }
578}
579
580static int
581internal(int ch)
582{
583 switch (ch) {
584 case '@':
585 case '?':
586 case '*':
587 case '<':
588 return 1;
589 default:
590 return 0;
591 }
592}
593
594static void
595expansion(Target *tp)
596{
597 int delim, c, repli, toi, namei, st;
598 char name[MAXTOKEN], repl[MAXREPL], to[MAXREPL];
599 char *s, *erepl;
600
601 c = nextc();
602 if (c == '(')
603 delim = ')';
604 else if (c == '{')
605 delim = '}';
606 else
607 delim = 0;
608
609 if (!delim) {
610 back(c);
611 expandsimple(tp);
612 return;
613 }
614
615 s = NULL;
616 namei = repli = toi = 0;
617 st = STBEGIN;
618
619 while (st != STEND && (c = nextc()) != EOF) {
620 switch (st) {
621 case STBEGIN:
622 if (c == ':') {
623 st = STREPLACE;
624 name[namei] = '\0';
625 s = expandmacro(name);
626 break;
627 }
628 if (c == delim) {
629 name[namei] = '\0';
630 s = expandmacro(name);
631 goto no_replace;
632 }
633 if (namei == MAXTOKEN-1)
634 error("expansion text too long");
635
636 if (namei == 0 && internal(c)) {
637 name[namei++] = '$';
638 name[namei++] = c;
639 name[namei] = '\0';
640 st = STINTERNAL;
641 s = expandstring(name, tp, getloc());
642 break;
643 }
644
645 if (!validchar(c))
646 error("invalid macro name in expansion");
647 name[namei++] = c;
648 break;
649 case STINTERNAL:
650 if (c == delim)
651 goto no_replace;
652 if (c != ':')
653 error("invalid internal macro in expansion");
654 st = STREPLACE;
655 break;
656 case STREPLACE:
657 if (c == '=') {
658 st = STTO;
659 break;
660 }
661 if (c == delim)
662 error("invalid replacement pattern in expansion");
663 if (repli == MAXREPL-1)
664 error("macro replacement too big");
665 repl[repli++] = c;
666 break;
667 case STTO:
668 if (c == delim) {
669 st = STEND;
670 break;
671 }
672
673 if (toi == MAXREPL-1)
674 error("macro substiturion too big");
675 to[toi++] = c;
676 break;
677 }
678 }
679
680 if (c == EOF)
681 error("found eof while parsing expansion");
682
683 repl[repli] = '\0';
684 to[toi] = '\0';
685
686 erepl = expandstring(repl, tp, getloc());
687 replace(s, erepl, to);
688
689 free(erepl);
690 free(s);
691 return;
692
693no_replace:
694 push(FTEXPAN, s);
695 free(s);
696}
697
698/*
699 * Horrible hack to do string expansion.
700 * We cannot use normal push and nextc because that
701 * would consume characters of the current file too.
702 * For that reason it cleans the input and it recovers
703 * it later.
704 */
705char *
706expandstring(char *line, Target *tp, struct loc *loc)
707{
708 int c, n;
709 char *s;
710 struct input *ip = input;
711
712 input = NULL;
713 push(FTFILE, NULL, loc->fname, loc->lineno);
714 push(FTEXPAN, line);
715
716 n = 0;
717 s = NULL;
718 while ((c = nextc()) != EOF) {
719 if (c != '$') {
720 s = erealloc(s, ++n);
721 s[n-1] = c;
722 continue;
723 }
724
725 if ((c = nextc()) == '$') {
726 s = erealloc(s, n += 2);
727 s[n-2] = '$';
728 s[n-1] = '$';
729 } else {
730 back(c);
731 expansion(tp);
732 }
733 }
734
735 s = erealloc(s, n+1);
736 s[n] = '\0';
737 input = ip;
738
739 return s;
740}
741
742static int
743item(void)
744{
745 int c;
746 char *s;
747 char buf[MAXTOKEN];
748
749 for (s = buf; s < &buf[MAXTOKEN] - 1; ) {
750 c = nextc();
751 if (c == '$' && ahead() != '$')
752 expansion(NULL);
753 else if (validchar(c))
754 *s++ = c;
755 else
756 break;
757 }
758 back(c);
759
760 if (s >= &buf[MAXTOKEN] - 1)
761 error("token too long");
762 if (s == buf)
763 error("invalid empty token");
764 *s++ = '\0';
765 memcpy(token, buf, s - buf);
766
767 return ITEM;
768}
769
770static int
771next(void)
772{
773 int c;
774
775repeat:
776 /*
777 * It is better to avoid skipspaces() here, because
778 * it can generate the need for 2 calls to back(),
779 * and we need the character anyway.
780 */
781 c = nextc();
782 if (c == ' ' || c == '\t')
783 goto repeat;
784
785 if (c == '\\') {
786 if ((c = nextc()) == '\n')
787 goto repeat;
788 back(c);
789 c = '\\';
790 }
791
792 switch (c) {
793 case EOF:
794 strcpy(token, "<EOF>");
795 tok = EOF;
796 break;
797 case '$':
798 if ((c = nextc()) == '$')
799 goto single;
800 back(c);
801 expansion(NULL);
802 goto repeat;
803 case '#':
804 comment();
805 c = '\n';
806 /* fallthrough */
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
827static char *
828readmacrodef(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
862static struct action
863readcmd(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
899static void
900rule(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
957static void
958assign(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
971void
972parseinput(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
1009int
1010parse(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
1028void
1029inject(char *s)
1030{
1031 push(FTFILE, NULL, "<internal>", 0);
1032 push(FTEXPAN, s);
1033 parseinput(INTERNAL);
1034}