summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladimir Azarov <avm@intermediate-node.net>2024-11-27 20:55:42 +0100
committerVladimir Azarov <avm@intermediate-node.net>2024-11-27 22:10:44 +0100
commit06e5eea08d5c06fcca00a469608b288696ae81d1 (patch)
tree2d48b0542d36104fbaa73be50f28953990e9f27b
parentf7789809675968b753f9b40e298d23b2f7ab4c61 (diff)
Include directive. Variable assignment from environment
-rw-r--r--.gitignore4
-rw-r--r--Makefile28
-rwxr-xr-xcompile_make.sh29
-rwxr-xr-xconfigure64
-rw-r--r--tools/TODO1
-rw-r--r--tools/common.c6
-rw-r--r--tools/common.h6
-rw-r--r--tools/musl-make.c (renamed from tools/make.c)465
-rw-r--r--tools/sed.c6
9 files changed, 387 insertions, 222 deletions
diff --git a/.gitignore b/.gitignore
index 5cf0a05..c412b01 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,8 @@
*.a
generated
tools/sed
-tools/make
+tools/musl-make
tools/Makefile
+tools/inc*
musl-*.tar.gz
+config.mk
diff --git a/Makefile b/Makefile
index 5c5c2aa..adaf1a6 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,11 @@
-AR = ar
+#
+# 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.
+#
+
CC = gcc
+AR = ar
CFLAGS = -g
arch = x86_64
@@ -12,11 +18,13 @@ cflags = -pipe -std=c99 -nostdinc -D_XOPEN_SOURCE=700 \
-Iarch/$(arch) -Iarch/generic -Isrc/include -Isrc/internal \
-Igenerated/include -Iinclude $(CFLAGS)
-prefix = /tmp/root
+bindir = $(prefix)/bin
includedir = $(prefix)/include
libdir = $(prefix)/lib
-src_dirs = crt src/* src/mallocng
+include config.mk
+
+src_dirs = crt src/* src/malloc/mallocng
common_src = $(wildcard $(addsuffix /*.c, $(src_dirs)))
arch_src = $(wildcard $(addsuffix /$(arch)/*.[csS], $(src_dirs)))
@@ -45,6 +53,8 @@ dirs = $(sort $(dir $(generated_headers)))
### Tools ###
+musl_make = tools/musl-make
+
gcc_prefix = $(dir $(shell gcc -print-libgcc-file-name))
tool_cflags = -Wall -nostdinc -Wno-main \
@@ -107,6 +117,10 @@ libc.a: $(all_obj)
rm -f $@
$(AR) rcs $@ $^
+$(DESTDIR)$(bindir)/%: tools/%
+ $(install_cmd)
+ chmod +x $@
+
$(DESTDIR)$(libdir)/%: %
$(install_cmd)
@@ -122,9 +136,10 @@ $(DESTDIR)$(includedir)/bits/%: generated/include/bits/%
$(DESTDIR)$(includedir)/%: include/%
$(install_cmd)
+install-progs: $(musl_make:tools/%=$(DESTDIR)$(bindir)/%)
install-libs: $(addprefix $(DESTDIR)$(libdir)/, $(lib_obj))
install-headers: $(all_inc:include/%=$(DESTDIR)$(includedir)/%)
-install: install-libs install-headers
+install: install-progs install-libs install-headers
musl-1.2.5-mod.tar.gz:
git archive --format=tar.gz --prefix=musl-1.2.5-mod/ -o $@ HEAD
@@ -132,5 +147,8 @@ musl-1.2.5-mod.tar.gz:
clean:
rm -rf generated
rm -f crt/*.o crt/*/*.o src/*/*.o src/*/*/*.o libc.a crt*.o
- rm -f tools/*.o tools/sed tools/make
+ rm -f tools/*.o tools/sed tools/musl-make
rm -f musl-*.tar.gz
+
+distclean: clean
+ rm -f config.mk
diff --git a/compile_make.sh b/compile_make.sh
deleted file mode 100755
index 78bc6c0..0000000
--- a/compile_make.sh
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/sh -e
-
-defined() {
- [ x"$2" = x ] && echo $1 is undefined && exit 1
- echo $1 = $2
-}
-
-pexec() {
- echo $@
- $@
-}
-
-defined CC "$CC"
-defined LD "$LD"
-
-arch=x86_64
-
-gcc_prefix=$(dirname $(gcc -print-libgcc-file-name))
-
-tool_cflags="-Wall -nostdinc -Wno-main \
- -ffreestanding -fno-pic -fno-stack-protector \
- -Igenerated/include -Iarch/$arch \
- -I${gcc_prefix}/include -Iarch/generic"
-
-cflags="$tool_cflags $CFLAGS"
-
-pexec $CC $cflags -c -o tools/common.o tools/common.c
-pexec $CC $cflags -c -o tools/make.o tools/make.c
-pexec $LD -nostdlib -o tools/make tools/make.o tools/common.o
diff --git a/configure b/configure
new file mode 100755
index 0000000..4fe0876
--- /dev/null
+++ b/configure
@@ -0,0 +1,64 @@
+#!/bin/sh -e
+
+#
+# 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.
+#
+
+defined() {
+ [ x"$2" = x ] && echo $1 is undefined && exit 1
+ echo $1 = $2
+}
+
+pexec() {
+ echo $@
+ $@
+}
+
+print_help() {
+ cat <<EOF
+$0: configuration script for compiling musl
+ --help print this help
+ --prefix=<dir> directory where to install musl
+EOF
+ exit 0
+}
+
+prefix=/tmp
+
+for arg; do
+ case $arg in
+ --prefix=*)
+ prefix=${arg#--prefix=}
+ ;;
+ --help)
+ print_help
+ ;;
+ *)
+ echo $args: unknown argument && exit 1
+ ;;
+ esac
+done
+
+: ${CC:=gcc}
+: ${LD:=ld}
+
+arch=x86_64
+
+gcc_prefix=$(dirname $(gcc -print-libgcc-file-name))
+
+tool_cflags="-Wall -nostdinc -Wno-main \
+ -ffreestanding -fno-pic -fno-stack-protector \
+ -Igenerated/include -Iarch/$arch \
+ -I${gcc_prefix}/include -Iarch/generic"
+
+cflags="$tool_cflags $CFLAGS"
+
+echo prefix = $prefix >config.mk
+
+[ -f tools/musl-make ] && exit 0
+
+pexec $CC $cflags -c -o tools/common.o tools/common.c
+pexec $CC $cflags -c -o tools/musl-make.o tools/musl-make.c
+pexec $LD -nostdlib -o tools/musl-make tools/musl-make.o tools/common.o
diff --git a/tools/TODO b/tools/TODO
index 0a21b70..6f21b0c 100644
--- a/tools/TODO
+++ b/tools/TODO
@@ -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"