diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/TODO | 1 | ||||
-rw-r--r-- | tools/common.c | 6 | ||||
-rw-r--r-- | tools/common.h | 6 | ||||
-rw-r--r-- | tools/musl-make.c (renamed from tools/make.c) | 465 | ||||
-rw-r--r-- | tools/sed.c | 6 |
5 files changed, 297 insertions, 187 deletions
@@ -1,4 +1,3 @@ -* include support * Remove coping: str2 for vtable search, str_n for variable values * Cache variable values * Cache rule execution status (file status) diff --git a/tools/common.c b/tools/common.c index 8f03978..5f24811 100644 --- a/tools/common.c +++ b/tools/common.c @@ -1,3 +1,9 @@ +/* + * This file is part of musl-mod: modified version of Musl libc library. + * musl-mod in general and this file specifically are available under + * MIT license. See COPYRIGHT file. + */ + #define START "_start" #include <crt_arch.h> #include <bits/syscall.h.in> diff --git a/tools/common.h b/tools/common.h index 4ca27bd..30b70d2 100644 --- a/tools/common.h +++ b/tools/common.h @@ -1,3 +1,9 @@ +/* + * This file is part of musl-mod: modified version of Musl libc library. + * musl-mod in general and this file specifically are available under + * MIT license. See COPYRIGHT file. + */ + #ifndef COMMON_H #define COMMON_H diff --git a/tools/make.c b/tools/musl-make.c index 0b82cd0..33cc117 100644 --- a/tools/make.c +++ b/tools/musl-make.c @@ -1,7 +1,9 @@ /* - * This file is part of musl-esp: modified version of Musl libc library. - * musl-esp in general and this file specifically are available under + * This file is part of musl-mod: modified version of Musl libc library. + * musl-mod in general and this file specifically are available under * MIT license. See COPYRIGHT file. + * + * Limited make to build musl. Implements just enough to handle Makefile. */ #include "common.h" @@ -12,14 +14,20 @@ enum { buf_static_size = 512, hash_table_size = 16 * 1024, pat_rules_limit = 16, - find_body_max_depth = 2 + find_body_max_depth = 2, + file_stack_size = 8 }; const char *debug_prx = ">>> "; +struct pos { + char *fname; + int line; +}; + struct line { - int linenum; struct str str; + struct pos pos; }; struct buf { @@ -28,13 +36,14 @@ struct buf { char *cur; }; -struct augstr { - struct str str; - int auxval; +struct strbuf { + struct str *buf; + int len; + int size; }; -struct strbuf { - struct augstr *buf; +struct cmdbuf { + struct line *buf; int len; int size; }; @@ -42,8 +51,9 @@ struct strbuf { struct rule_body { struct strbuf prereqs; int normal_prereq_count; + struct pos pos; - struct strbuf *recipes; + struct cmdbuf *recipes; }; struct full_rule { @@ -55,7 +65,7 @@ struct rule_details { struct rule_body *body; struct strbuf targets; int patrule; - int lineno; + struct pos *pos; }; enum { @@ -84,8 +94,19 @@ struct rtable { int cells_occupied; }; +struct file { + char *name; + char *buf; + int line; +}; + +struct file_stack { + struct file buf[file_stack_size]; + int idx; +}; + struct world { - char *makefile; + struct file_stack fstack; struct str target; char **envp; @@ -100,7 +121,7 @@ struct world { struct eval_aux { int level; - int linenum; + struct pos *pos; struct full_rule *rule; struct buf *mainbuf; @@ -108,11 +129,11 @@ struct eval_aux { struct world *world; }; -static void lerror(int line, char *str, ...) +static void errorp(struct pos *pos, char *str, ...) { va_list vl; - eprintf("%s: line %d: ", progname, line); + eprintf("%s:%d: ", pos->fname, pos->line); va_start(vl, str); evprintf(str, vl); @@ -239,7 +260,16 @@ static int rtable_find(struct rtable *rt, struct str *key, return 1; } -static char *mmap_makefile(char *fname) +static char *strchr(char *s, char c) +{ + for (; *s; ++s) { + if (*s == c) + return s; + } + return NULL; +} + +static char *mmap_file(char *fname) { int fd = open(fname, O_RDONLY, 0); struct stat st; @@ -250,10 +280,17 @@ static char *mmap_makefile(char *fname) if (fstat(fd, &st) == -1) goto syserr; + if (st.size == 0) { + tmp = NULL; + goto end; + } + tmp = mmap(NULL, st.size + 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); if (tmp == (void*)-1) goto syserr; + +end: if (close(fd) == -1) goto syserr; return tmp; @@ -262,20 +299,26 @@ syserr: return NULL; /* unreachable */ } -static char *strchr(char *s, char c) +static int readline(struct file_stack *stack, struct line *line) { - for (; *s; ++s) { - if (*s == c) - return s; + char *tmp; + char *marker = NULL; + struct file *file; + + if (stack->idx == 0) + return 0; + file = stack->buf + stack->idx - 1; + if (file->buf == NULL) { + file->buf = mmap_file(file->name); + if (file->buf == NULL) { + --stack->idx; + return readline(stack, line); + } } - return NULL; -} -static int readline(char **makefile, struct line *line) -{ - static int linenum = 1; - char *tmp = *makefile; - char *marker = NULL; + tmp = file->buf; + + line->pos = (struct pos) { file->name, file->line }; for (; *tmp && *tmp != '\n'; ++tmp) { if (*tmp == '#' && marker == NULL) @@ -283,30 +326,35 @@ static int readline(char **makefile, struct line *line) else if (tmp[0] == '\\' && tmp[1] == '\n') { tmp[0] = tmp[1] = ' '; ++tmp; - ++linenum; + ++file->line; } } if (*tmp == 0) { - if (tmp == *makefile) - return 0; - else + if (tmp == file->buf) { + --stack->idx; + return readline(stack, line); + } else { error("last line missing '\\n'"); + } } *tmp = 0; - line->linenum = linenum; - ++linenum; - line->str.start = *makefile; + line->str.start = file->buf; line->str.end = marker ? marker : tmp; - *makefile = tmp + 1; + + file->buf = tmp + 1; + ++file->line; return 1; } -static int nextline_starts_with_tab(char *file) +/* Does not cross file end. We do not have to check if idx == 0, because + * idx is always >0, if readline did not return "end of input". + */ +static int nextline_starts_with_tab(struct file_stack *fstack) { - return file[0] == '\t'; + return *fstack->buf[fstack->idx-1].buf == '\t'; } #define buf_static_init(buf, local_buf, size) \ @@ -369,7 +417,7 @@ static int strlen(struct str *str) return str->end - str->start; } -static char *find_cparent(int line, struct str *str) +static char *find_cparent(struct str *str, struct pos *pos) { char *tmp; int level = 0; @@ -383,7 +431,7 @@ static char *find_cparent(int line, struct str *str) --level; } } - lerror(line, "missing ')'"); + errorp(pos, "missing ')'"); return NULL; /* unreachable */ } @@ -415,6 +463,7 @@ enum { struct eprofile { char type; struct str *body; + struct pos *pos; struct str from; struct str to; @@ -479,15 +528,15 @@ static int is_special_var(struct eprofile *prof, struct str *word) } static void check_var_form(struct str *word, struct str *all, - int line) + struct pos *pos) { if (word->end == all->end) return; - lerror(line, "(%S): variable name must be a single word", all); + errorp(pos, "(%S): variable name must be a single word", all); } static void parse_subref(struct eprofile *prof, struct str *vname, - struct str *all, int line) + struct str *all) { char *tmp; prof->type = id_subref; @@ -497,7 +546,7 @@ static void parse_subref(struct eprofile *prof, struct str *vname, for (tmp = all->start; tmp != all->end && *tmp != '='; ++tmp) ; if (tmp == all->end) - lerror(line, "%s: no '=' is subref expr", vname); + errorp(prof->pos, "%s: no '=' is subref expr", vname); prof->from.end = tmp; prof->to.start = tmp + 1; prof->to.end = all->end; @@ -506,8 +555,8 @@ static void parse_subref(struct eprofile *prof, struct str *vname, prof->body = all; } -static void parse_profile(struct eprofile *prof, struct str *str, int line, - struct full_rule *rule) +static void parse_profile(struct eprofile *prof, struct str *str, + struct full_rule *rule) { int i; char *wend; @@ -517,12 +566,14 @@ static void parse_profile(struct eprofile *prof, struct str *str, int line, return; wend = word_end(str); - if (wend == NULL) - lerror(line, "invalid symbol during first word parsing"); + if (wend == NULL) { + errorp(prof->pos, + "invalid symbol during first word parsing"); + } first_word = (struct str) { str->start, wend }; if (wend != str->end && *wend == ':') { - parse_subref(prof, &first_word, str, line); + parse_subref(prof, &first_word, str); return; } @@ -535,7 +586,7 @@ static void parse_profile(struct eprofile *prof, struct str *str, int line, } } prof->type = id_variable; - check_var_form(&first_word, str, line); + check_var_form(&first_word, str, prof->pos); prof->body = str; } @@ -599,7 +650,7 @@ static void expand_first_prereq(struct eval_aux *aux, { if (aux->rule->rest->prereqs.len == 0) return; - buf_puts(aux->mainbuf, &aux->rule->rest->prereqs.buf[0].str); + buf_puts(aux->mainbuf, &aux->rule->rest->prereqs.buf[0]); } static void expand_prereqs(struct eval_aux *aux, @@ -608,7 +659,7 @@ static void expand_prereqs(struct eval_aux *aux, int i; struct strbuf *prereqs = &aux->rule->rest->prereqs; for (i = 0; i < prereqs->len; ++i) { - buf_puts(aux->mainbuf, &prereqs->buf[i].str); + buf_puts(aux->mainbuf, &prereqs->buf[i]); if (i + 1 != prereqs->len) buf_putchar(aux->mainbuf, ' '); } @@ -824,7 +875,7 @@ static void dir_word(struct str *res, struct str *word) } static void extract_args(struct str *args, struct str *str, int argnum, - char *func, int linenum) + char *func, struct pos *pos) { int i; for (i = 0;; ++i) { @@ -842,7 +893,7 @@ static void extract_args(struct str *args, struct str *str, int argnum, trim(args + i); } argcount_err: - lerror(linenum, "%s expects %d argument%s", func, argnum, + errorp(pos, "%s expects %d argument%s", func, argnum, argnum > 1 ? "s" : ""); } @@ -858,7 +909,7 @@ static void expand_basename_or_dir(struct eval_aux *aux, int mode, int first = 1; char *func = mode == mode_basename ? "basename" : "dir"; - extract_args(&arg, prof->body, 1, func, aux->linenum); + extract_args(&arg, prof->body, 1, func, aux->pos); for (;; first = 0) { struct str word, res; @@ -902,10 +953,10 @@ static void expand_add(struct eval_aux *aux, int mode, int first = 1; char *func = mode == mode_prefix ? "addprefix" : "addsuffix"; - extract_args(args, prof->body, 2, func, aux->linenum); + extract_args(args, prof->body, 2, func, aux->pos); if (!arg_is_single_word(args)) - lerror(aux->linenum, "%s: accepts a single prefix", func); + errorp(aux->pos, "%s: accepts a single prefix", func); for (;; first = 0) { struct str word; @@ -936,25 +987,25 @@ static int passes_filter(struct str *str, struct strbuf *pats, int mode) int ret_when_matches = mode == mode_filter ? 1 : 0; int i; for (i = 0; i < pats->len; ++i) { - if (match_str(&pats->buf[i].str, str, NULL)) + if (match_str(pats->buf + i, str, NULL)) return ret_when_matches; } return !ret_when_matches; } -static void sbuf_init(struct strbuf *buf); -static void sbuf_save(struct strbuf *buf, struct str *str, int aux); +static void strbuf_init(struct strbuf *buf); +static void strbuf_push(struct strbuf *buf, struct str *str); static void collect_words(struct strbuf *buf, struct str *words) { - sbuf_init(buf); + strbuf_init(buf); for (;;) { struct str word; int ret = extract_word(words, &word); if (ret == 0) break; - sbuf_save(buf, &word, -1); + strbuf_push(buf, &word); } } @@ -983,7 +1034,7 @@ static void expand_filter(struct eval_aux *aux, int mode, struct strbuf pats; char *func = mode == mode_filter ? "filter" : "filter-out"; - extract_args(args, prof->body, 2, func, aux->linenum); + extract_args(args, prof->body, 2, func, aux->pos); heap_offset_save(); collect_words(&pats, args); @@ -991,30 +1042,30 @@ static void expand_filter(struct eval_aux *aux, int mode, heap_offset_restore(); } -static void merge(struct augstr *to, struct augstr *from, int n) +static void merge(struct str *to, struct str *from, int n) { int mid = n/2; int i, j, k; for (k = 0, i = 0, j = mid; i < mid && j < n; ++k) { - if (strge(&from[j].str, &from[i].str)) { - to[k].str = from[i].str; + if (strge(from + j, from + i)) { + to[k] = from[i]; ++i; } else { - to[k].str = from[j].str; + to[k] = from[j]; ++j; } } if (i < mid) { for (; i < mid; ++i, ++k) - to[k].str = from[i].str; + to[k] = from[i]; } else { for (; j < n; ++j, ++k) - to[k].str = from[j].str; + to[k] = from[j]; } } -static void mergesort(struct augstr *array, struct augstr *tmp, +static void mergesort(struct str *array, struct str *tmp, int n) { if (n < 2) @@ -1026,7 +1077,7 @@ static void mergesort(struct augstr *array, struct augstr *tmp, static void sort(struct strbuf *words) { - struct augstr *tmp = malloc(sizeof(*tmp) * words->len); + struct str *tmp = malloc(sizeof(*tmp) * words->len); int i; for (i = 0; i < words->len; ++i) tmp[i] = words->buf[i]; @@ -1037,11 +1088,11 @@ static void sort(struct strbuf *words) static void uniq(struct strbuf *words) { int i, j; - struct augstr *array = words->buf; + struct str *array = words->buf; for (i = 0, j = 0; i < words->len; ++i) { - if (j > 0 && streq(&array[i].str, &array[j-1].str)) + if (j > 0 && streq(&array[i], &array[j-1])) continue; - array[j].str = array[i].str; + array[j] = array[i]; ++j; } words->len = j; @@ -1054,7 +1105,7 @@ static void expand_sort(struct eval_aux *aux, struct eprofile *prof) int i; heap_offset_save(); - extract_args(&arg, prof->body, 1, "sort", aux->linenum); + extract_args(&arg, prof->body, 1, "sort", aux->pos); collect_words(&words, &arg); sort(&words); @@ -1063,7 +1114,7 @@ static void expand_sort(struct eval_aux *aux, struct eprofile *prof) for (i = 0; i < words.len; ++i) { if (i > 0) buf_putchar(aux->mainbuf, ' '); - buf_puts(aux->mainbuf, &words.buf[i].str); + buf_puts(aux->mainbuf, &words.buf[i]); } heap_offset_restore(); @@ -1104,7 +1155,7 @@ static void check_status(int status, char *prx); static void expand_shell(struct eval_aux *aux, struct eprofile *prof) { struct str arg; - extract_args(&arg, prof->body, 1, "shell", aux->linenum); + extract_args(&arg, prof->body, 1, "shell", aux->pos); int pipefds[2]; int status, pid; @@ -1153,7 +1204,7 @@ static void expand_subst(struct eval_aux *aux, struct eprofile *prof) struct str args[3]; int first = 1; - extract_args(args, prof->body, 3, "subst", aux->linenum); + extract_args(args, prof->body, 3, "subst", aux->pos); if (!arg_is_single_word(args)) goto single_word_err; @@ -1171,7 +1222,7 @@ static void expand_subst(struct eval_aux *aux, struct eprofile *prof) } return; single_word_err: - lerror(aux->linenum, "subst: from/to must to single words"); + errorp(aux->pos, "subst: from/to must to single words"); } static int matches(struct str *pat, struct str *str, @@ -1205,7 +1256,7 @@ static void patsubst(struct buf *buf, struct str *from, static void expand_patsubst(struct eval_aux *aux, struct eprofile *prof) { struct str args[3]; - extract_args(args, prof->body, 3, "patsubst", aux->linenum); + extract_args(args, prof->body, 3, "patsubst", aux->pos); if (!arg_is_single_word(args)) goto single_word_err; @@ -1220,9 +1271,9 @@ static void expand_patsubst(struct eval_aux *aux, struct eprofile *prof) return; single_word_err: - lerror(aux->linenum, "patsubst: from/to must be single words"); + errorp(aux->pos, "patsubst: from/to must be single words"); no_wildcard_err: - lerror(aux->linenum, "patsubst: from/to must contain '%'"); + errorp(aux->pos, "patsubst: from/to must contain '%'"); } enum { @@ -1237,7 +1288,7 @@ struct pathbuf { char *cur; int add_space; - int linenum; + struct pos *pos; struct buf *dest; }; @@ -1347,13 +1398,13 @@ static int is_special(char *dent) (dent[1] == 0 || (dent[1] == '.' && dent[2] == 0)); } -static int __match(char *pat, char *str, int line) +static int __match(char *pat, char *str, struct pos *pos) { for (; *pat; ++pat) { if (*pat == '*') { char *sc; for (sc = str; ; ++sc) { - if (__match(pat + 1, sc, line)) + if (__match(pat + 1, sc, pos)) return 1; if (*sc == 0) return 0; @@ -1370,7 +1421,7 @@ static int __match(char *pat, char *str, int line) ret = 1; } if (*pat == 0) - lerror(line, "wildcard missing ']'"); + errorp(pos, "wildcard missing ']'"); if (ret == 0) return 0; ++str; @@ -1383,14 +1434,14 @@ static int __match(char *pat, char *str, int line) return *str == 0; } -static int match_pattern(struct str *pat, char *s, int line) +static int match_pattern(struct str *pat, char *s, struct pos *pos) { char c = *pat->end; int ret; *pat->end = 0; - ret = __match(pat->start, s, line); + ret = __match(pat->start, s, pos); *pat->end = c; return ret; @@ -1419,7 +1470,7 @@ static void iterate(struct pathbuf *pbuf, int idx) continue; int res = match_pattern(pbuf->limbuf + idx, dent->name, - pbuf->linenum); + pbuf->pos); if (res) { pbuf_putlimbz(pbuf, dent->name); follow_path(pbuf, idx + 1); @@ -1459,14 +1510,14 @@ static void follow_path(struct pathbuf *pbuf, int start) } static int wexpand(struct buf *buf, struct str *path, int add_space, - int linenum) + struct pos *pos) { static struct pathbuf pbuf; pbuf.limbs = 0; pbuf.cur = pbuf.buf; pbuf.add_space = add_space; pbuf.dest = buf; - pbuf.linenum = linenum; + pbuf.pos = pos; parse_path(&pbuf, path); follow_path(&pbuf, 0); @@ -1478,13 +1529,13 @@ static void expand_wildcard(struct eval_aux *aux, struct eprofile *prof) struct str arg; int first = 1; - extract_args(&arg, prof->body, 1, "wildcard", aux->linenum); + extract_args(&arg, prof->body, 1, "wildcard", aux->pos); for (;;) { struct str word; if (extract_word(&arg, &word) == 0) break; int ret = wexpand(aux->mainbuf, &word, !first, - aux->linenum); + aux->pos); if (ret && first) first = 0; } @@ -1566,10 +1617,10 @@ static void expand(struct eval_aux *aux, struct str *str) struct str estr; if (strempty(str)) - lerror(aux->linenum, "stray '$'"); + errorp(aux->pos, "stray '$'"); if (*str->start == '(') { - char *end = find_cparent(aux->linenum, str); + char *end = find_cparent(str, aux->pos); ++str->start; estr = (struct str) { str->start, end }; @@ -1578,7 +1629,8 @@ static void expand(struct eval_aux *aux, struct str *str) estr = (struct str) { str->start, str->start + 1 }; ++str->start; } - parse_profile(&profile, &estr, aux->linenum, aux->rule); + profile.pos = aux->pos; + parse_profile(&profile, &estr, aux->rule); __expand(aux, &profile); } @@ -1631,7 +1683,7 @@ static struct buf *eval(struct world *world, struct line *line, aux = (struct eval_aux) { 0, - line->linenum, + &line->pos, rule, buffers, buffers + 1, world @@ -1714,23 +1766,15 @@ struct variable { struct str *value; char scope; - int linenum; + struct pos *pos; struct vtable *vt; }; static int check_policy(struct variable *var, struct str *name) { struct vt_cell *cell = vtable_getcell(var->vt, name); - if (cell->vname.start == NULL) - return 1; - if (var->scope == vs_makefile) { - if (cell->scope == vs_makefile) - lerror(var->linenum, "%S: variable redefinition", - name); - return 0; - } - return 1; + return !(cell->scope == vs_cmdargs && var->scope == vs_makefile); } static void set_single_var(struct variable *var, struct str *goal, int mode) @@ -1772,7 +1816,7 @@ static void setvar(struct variable *var, int mode) if (var->goals != NULL) { int i; for (i = 0; i < var->goals->len; ++i) - set_single_var(var, &var->goals->buf[i].str, mode); + set_single_var(var, &var->goals->buf[i], mode); } else { set_single_var(var, NULL, mode); } @@ -1787,8 +1831,7 @@ static void follows(struct line *line, char c) { if (is_followed(line, c)) return; - lerror(line->linenum, "expected %c after %c", c, - line->str.start[0]); + errorp(&line->pos, "expected %c after %c", c, line->str.start[0]); } static void parse_assignment(struct world *world, struct strbuf *goals, @@ -1800,13 +1843,13 @@ static void parse_assignment(struct world *world, struct strbuf *goals, &line->str, scope, - line->linenum, + &line->pos, &world->vtable }; trim(&var.name); if (!valid_var_name(&var.name)) { - lerror(line->linenum, "[%S]: invalid variable name", + errorp(&line->pos, "[%S]: invalid variable name", &var.name); } if (var.value->start[0] == '+') { @@ -1819,21 +1862,36 @@ static void parse_assignment(struct world *world, struct strbuf *goals, } } -static void sbuf_init(struct strbuf *buf) +#define SBUF_INIT(type) \ +static void type ## _init(struct type *buf) \ +{ \ + buf->size = 1; \ + buf->len = 0; \ + buf->buf = malloc(sizeof(*buf->buf) * buf->size); \ +} + +SBUF_INIT(strbuf) +SBUF_INIT(cmdbuf) + +static void strbuf_push(struct strbuf *buf, struct str *str) { - buf->size = 1; - buf->len = 0; - buf->buf = malloc(sizeof(*buf->buf) * buf->size); + if (buf->len == buf->size) { + buf->size *= 2; + realloc(buf->buf, sizeof(*buf->buf) * buf->size); + } + buf->buf[buf->len] = *str; + ++buf->len; } -static void sbuf_save(struct strbuf *buf, struct str *str, int aux) +static void cmdbuf_push(struct cmdbuf *buf, struct str *str, + struct pos *pos) { if (buf->len == buf->size) { buf->size *= 2; realloc(buf->buf, sizeof(*buf->buf) * buf->size); } buf->buf[buf->len].str = *str; - buf->buf[buf->len].auxval = aux; + buf->buf[buf->len].pos = *pos; ++buf->len; } @@ -1842,7 +1900,8 @@ static int valid_target_char(char c) return valid_var_char(c) || c == '%'; } -static void save_word(struct strbuf *buf, struct str *str, int line) +static void save_word(struct strbuf *buf, struct str *str, + struct pos *pos) { struct str word; word.start = str->start; @@ -1861,31 +1920,33 @@ static void save_word(struct strbuf *buf, struct str *str, int line) *str->start = 0; ++str->start; - sbuf_save(buf, &word, line); + strbuf_push(buf, &word); return; err: - lerror(line, "%c: invalid target/prereq name symbol", *str->start); + errorp(pos, "%c: invalid target/prereq name symbol", *str->start); } -static void parse_targets(struct strbuf *targets, struct buf *buf, int line) +static void parse_targets(struct strbuf *targets, struct buf *buf, + struct pos *pos) { struct str str = { buf->start, buf->cur }; - sbuf_init(targets); + strbuf_init(targets); for (;;) { trim_front(&str); if (strempty(&str)) break; - save_word(targets, &str, -1); + save_word(targets, &str, pos); } if (targets->len == 0) - lerror(line, "zero targets before ':'"); + errorp(pos, "zero targets before ':'"); } -static void parse_prereqs(struct rule_body *rule, struct buf *buf) +static void parse_prereqs(struct rule_body *rule, struct buf *buf, + struct pos *pos) { struct str str = { buf->start, buf->cur }; - sbuf_init(&rule->prereqs); + strbuf_init(&rule->prereqs); int i = 0; int normal = -1; @@ -1898,23 +1959,23 @@ static void parse_prereqs(struct rule_body *rule, struct buf *buf) ++str.start; trim_front(&str); } - save_word(&rule->prereqs, &str, -1); + save_word(&rule->prereqs, &str, pos); ++i; } rule->normal_prereq_count = normal == -1 ? i : normal; } -static struct strbuf *parse_recipes(char **file) +static struct cmdbuf *parse_recipes(struct file_stack *fstack) { - struct strbuf *tmp = malloc(sizeof(*tmp)); - sbuf_init(tmp); + struct cmdbuf *tmp = malloc(sizeof(*tmp)); + cmdbuf_init(tmp); - while (nextline_starts_with_tab(*file)) { + while (nextline_starts_with_tab(fstack)) { struct line line; - readline(file, &line); + readline(fstack, &line); trim(&line.str); - sbuf_save(tmp, &line.str, line.linenum); + cmdbuf_push(tmp, &line.str, &line.pos); } return tmp; } @@ -1923,11 +1984,11 @@ static void save_first_target(struct world *world, struct rule_details *rule) { if (!strempty(&world->target) || rule->patrule || - streq(&rule->targets.buf->str, &CSTR(".PRECIOUS"))) + streq(&rule->targets.buf[0], &CSTR(".PRECIOUS"))) { return; } - world->target = rule->targets.buf->str; + world->target = *rule->targets.buf; } static char *contains_char(struct str *str, char c) @@ -1940,22 +2001,22 @@ static char *contains_char(struct str *str, char c) return NULL; } -static int is_patrule(struct strbuf *targets, int line) +static int is_patrule(struct strbuf *targets, struct pos *pos) { - if (contains_char(&targets->buf[0].str, '%') == NULL) + if (contains_char(&targets->buf[0], '%') == NULL) return 0; if (targets->len == 1) return 1; - lerror(line, "multiple targets not supported in patturn rules"); + errorp(pos, "multiple targets not supported in patturn rules"); return -1; /* unreachable */ } static void add_patrule(struct world *world, struct rule_details *rule) { if (world->pat_rule_num == pat_rules_limit) - lerror(rule->lineno, "pattern rules limit reached"); + errorp(rule->pos, "pattern rules limit reached"); world->pat_rules[world->pat_rule_num] = (struct full_rule) { - &rule->targets.buf[0].str, + &rule->targets.buf[0], rule->body }; ++world->pat_rule_num; @@ -1965,8 +2026,8 @@ static void handle_normal(struct world *world, struct rule_details *rule, struct buf *buf) { int i; - parse_prereqs(rule->body, buf); - rule->body->recipes = parse_recipes(&world->makefile); + parse_prereqs(rule->body, buf, rule->pos); + rule->body->recipes = parse_recipes(&world->fstack); if (rule->patrule) { add_patrule(world, rule); @@ -1974,9 +2035,9 @@ static void handle_normal(struct world *world, struct rule_details *rule, } for (i = 0; i < rule->targets.len; ++i) { - if (streq(&rule->targets.buf[i].str, &CSTR(".PRECIOUS"))) + if (streq(&rule->targets.buf[i], &CSTR(".PRECIOUS"))) continue; - rtable_add(&world->rtable, &rule->targets.buf[i].str, 0, + rtable_add(&world->rtable, &rule->targets.buf[i], 0, rule->body); } } @@ -1988,9 +2049,9 @@ static void handle_target_spec(struct world *world, struct buf *buf, struct line *line, struct rule_details *rule) { if (rule->patrule) - lerror(line->linenum, target_spec_in_patrules); + errorp(&line->pos, target_spec_in_patrules); if (*line->str.start == ':') - lerror(line->linenum, "expected target-specific var"); + errorp(&line->pos, "expected target-specific var"); parse_assignment(world, &rule->targets, buf, line, vs_makefile); } @@ -2002,10 +2063,10 @@ static void parse_rule(struct world *world, struct buf *buf, ++line->str.start; rule.body = malloc(sizeof(*rule.body)); - rule.lineno = line->linenum; + rule.pos = &line->pos; - parse_targets(&rule.targets, buf, line->linenum); - rule.patrule = is_patrule(&rule.targets, line->linenum); + parse_targets(&rule.targets, buf, &line->pos); + rule.patrule = is_patrule(&rule.targets, &line->pos); buf = eval(world, line, NULL); if (strempty(&line->str)) @@ -2016,20 +2077,51 @@ static void parse_rule(struct world *world, struct buf *buf, save_first_target(world, &rule); } +static void fstack_add(struct file_stack *stack, char *file, + struct pos *pos) +{ + if (stack->idx == file_stack_size) { + struct pos tpos = (struct pos) { "cmdarg", 0 }; + errorp(pos ? pos : &tpos, "include nesting is too deep"); + } + stack->buf[stack->idx] = (struct file) { file, NULL, 1 }; + ++stack->idx; +} + +static int is_include_directive(struct str *line) +{ + struct str linec; + if (line->end - line->start < 8) + return 0; + linec = (struct str) { line->start, line->start + 8 }; + return streq(&CSTR("include "), &linec); +} + +static void handle_include(struct world *world, struct line *line) +{ + line->str.start += 8; + *line->str.end = 0; + fstack_add(&world->fstack, line->str.start, &line->pos); +} + static int parse_toplev(struct world *world) { struct line line; struct buf *buf; - if (!readline(&world->makefile, &line)) + if (!readline(&world->fstack, &line)) return 0; buf = eval(world, &line, NULL); if (strempty(&line.str)) { - struct str tmp = { buf->start, buf->cur }; - trim(&tmp); - if (!strempty(&tmp)) - lerror(line.linenum, "missing separator"); + struct line tmp = { { buf->start, buf->cur }, line.pos }; + trim(&tmp.str); + if (is_include_directive(&tmp.str)) { + handle_include(world, &tmp); + return 1; + } + if (!strempty(&tmp.str)) + errorp(&tmp.pos, "missing separator"); } else if (*line.str.start == ':') { parse_rule(world, buf, &line); } else { @@ -2044,14 +2136,39 @@ static void parse(struct world *world) ; } +static int is_assignment(char *arg, char **equal_sign) +{ + char *tmp = strchr(arg, '='); + if (tmp == NULL) + return 0; + *equal_sign = tmp; + return 1; +} + +static void parse_cmdarg_assignment(struct world *world, char *arg, + char *equal_sign) +{ + struct buf buf = { arg, equal_sign, equal_sign }; + char *end = equal_sign + strzlen(equal_sign); + struct line line = { { equal_sign, end }, { "cmdarg", 0 } }; + + parse_assignment(world, NULL, &buf, &line, vs_cmdargs); +} + static void world_init(struct world *world, char **envp) { + world->fstack.idx = 0; world->envp = envp; - world->pat_rule_num = 0; vtable_init(&world->vtable); rtable_init(&world->rtable); + + for (; *envp; ++envp) { + char *equal_sign; + is_assignment(*envp, &equal_sign); + parse_cmdarg_assignment(world, *envp, equal_sign); + } } static int timegt(struct time *t1, struct time *t2) @@ -2085,8 +2202,7 @@ static void exec_recipe(struct world *world, struct full_rule *rule, char *argv[] = { "/bin/sh", "-c", NULL, NULL }; int ret; int status; - struct augstr *astr = rule->rest->recipes->buf + i; - struct line line = { astr->auxval, astr->str }; + struct line line = rule->rest->recipes->buf[i]; struct buf *buf = eval(world, &line, rule); buf_put_silent_zero(buf); @@ -2197,8 +2313,8 @@ static struct rule_body *construct_prereqs(struct full_rule *patrule, prereqs->len = patrule->rest->prereqs.len; prereqs->buf = malloc(sizeof(*prereqs->buf) * prereqs->len); for (i = 0; i < prereqs->len; ++i) { - subst_pat(&prereqs->buf[i].str, - &patrule->rest->prereqs.buf[i].str, wildcard); + subst_pat(&prereqs->buf[i], &patrule->rest->prereqs.buf[i], + wildcard); } return newbody; } @@ -2237,8 +2353,8 @@ static struct rule_body *create_copy(struct rule_body *rule_body) amalloc(&ccarena, sizeof(*prereqs->buf) * prereqs->len); for (i = 0; i < prereqs->len; ++i) { - prereqdup(&ccarena, &prereqs->buf[i].str, - &rule_body->prereqs.buf[i].str); + prereqdup(&ccarena, &prereqs->buf[i], + &rule_body->prereqs.buf[i]); } /*printf(">>> Cur: %d\n", ccarena.cur - ccarena.start);*/ return tmp; @@ -2263,7 +2379,7 @@ static struct rule_body *suitable_patrule(struct world *world, int idx, tmp = construct_prereqs(world->pat_rules + idx, &wildcard); for (i = 0; i < tmp->prereqs.len; ++i) { - struct str *prereq = &tmp->prereqs.buf[i].str; + struct str *prereq = &tmp->prereqs.buf[i]; struct rule_body *pbody; if (exists(prereq->start)) continue; @@ -2349,7 +2465,7 @@ static int exec_prereqs(struct world *world, struct full_rule *rule, for (i = 0; i < rule->rest->prereqs.len; ++i) { int ret, is_oo; - struct str *prereq = &rule->rest->prereqs.buf[i].str; + struct str *prereq = &rule->rest->prereqs.buf[i]; tinfo_get(&pinfo, prereq); ret = exec_target(world, prereq, &pinfo); is_oo = i >= rule->rest->normal_prereq_count; @@ -2434,32 +2550,13 @@ static void exec(struct world *world) { struct target_info info; if (strempty(&world->target)) { - printf("nothing to be done"); + printf("nothing to be done\n"); hexit(0); } tinfo_get(&info, &world->target); exec_target(world, &world->target, &info); } -static int is_assignment(char *arg, char **equal_sign) -{ - char *tmp = strchr(arg, '='); - if (tmp == NULL) - return 0; - *equal_sign = tmp; - return 1; -} - -static void parse_cmdarg_assignment(struct world *world, char *arg, - char *equal_sign) -{ - struct buf buf = { arg, equal_sign, equal_sign }; - char *end = equal_sign + strzlen(equal_sign); - struct line line = { 0, { equal_sign, end } }; - - parse_assignment(world, NULL, &buf, &line, vs_cmdargs); -} - static void parse_cmdargs(struct world *world, char **argv) { char *makefile = "Makefile"; @@ -2494,8 +2591,8 @@ static void parse_cmdargs(struct world *world, char **argv) target = argv[0]; } } - world->makefile = mmap_makefile(makefile); world->target = target ? STR(target) : CSTR(""); + fstack_add(&world->fstack, makefile, NULL); } static void print_program_time(int debug) diff --git a/tools/sed.c b/tools/sed.c index 833e7d2..ea576c0 100644 --- a/tools/sed.c +++ b/tools/sed.c @@ -1,7 +1,9 @@ /* - * This file is part of musl-esp: modified version of Musl libc library. - * musl-esp in general and this file specifically are available under + * This file is part of musl-mod: modified version of Musl libc library. + * musl-mod in general and this file specifically are available under * MIT license. See COPYRIGHT file. + * + * Limited sed to generate 2 files. */ #include "common.h" |