summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/TODO1
-rw-r--r--tools/common.c2
-rw-r--r--tools/make.c238
-rw-r--r--tools/sed.c6
4 files changed, 162 insertions, 85 deletions
diff --git a/tools/TODO b/tools/TODO
index 6f21b0c..0a21b70 100644
--- a/tools/TODO
+++ b/tools/TODO
@@ -1,3 +1,4 @@
+* 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 8156bec..8f03978 100644
--- a/tools/common.c
+++ b/tools/common.c
@@ -280,7 +280,7 @@ void perror(char *s)
}
enum {
- buflen = 32 * 1024
+ buflen = 16 * 1024
};
struct iobuf {
diff --git a/tools/make.c b/tools/make.c
index 0b1f704..0b82cd0 100644
--- a/tools/make.c
+++ b/tools/make.c
@@ -1,3 +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
+ * MIT license. See COPYRIGHT file.
+ */
+
#include "common.h"
enum {
@@ -11,12 +17,6 @@ enum {
const char *debug_prx = ">>> ";
-struct conf {
- char *target;
- char *makefile;
- int debug_mode;
-};
-
struct line {
int linenum;
struct str str;
@@ -58,9 +58,15 @@ struct rule_details {
int lineno;
};
+enum {
+ vs_makefile,
+ vs_cmdargs
+};
+
struct vt_cell {
struct str vname;
struct str value;
+ char scope;
};
struct vtable {
@@ -180,21 +186,21 @@ static struct vt_cell *vtable_getcell(struct vtable *t, struct str *key)
}
static void vtable_update(struct vtable *vt, struct str *key,
- int alloc_name, struct str *value)
+ int alloc_name, struct str *value, char scope)
{
struct vt_cell *cell = vtable_getcell(vt, key);
if (cell->vname.start == NULL) {
++vt->cells_occupied;
if ((double)vt->cells_occupied / hash_table_size >= 0.7)
error("vtable: threshold reached");
- }
- if (cell->vname.start == NULL) {
+
if (alloc_name)
strdup(&cell->vname, key, 0);
else
cell->vname = *key;
}
cell->value = *value;
+ cell->scope = scope;
}
static struct str *vtable_find(struct vtable *vt, struct str *key)
@@ -233,37 +239,6 @@ static int rtable_find(struct rtable *rt, struct str *key,
return 1;
}
-static void parse_cmdargs(struct conf *conf, char **argv)
-{
- ++argv;
- for (; argv[0]; ++argv) {
- if (argv[0][0] == '-') {
- if (argv[0][1] == 'f' && argv[0][2] == 0) {
- if (argv[1] == NULL)
- error("-f: missing file name");
- conf->makefile = argv[1];
- ++argv;
- } else if (argv[0][1] == 'C' && argv[0][2] == 0) {
- if (argv[1] == NULL)
- error("-C: missing dir");
- if (chdir(argv[1]) == -1)
- syscall_error(argv[1]);
- ++argv;
- } else if (argv[0][1] == 'd' && argv[0][2] == 0) {
- conf->debug_mode = 1;
- } else {
- error("%s: unknown flag", argv[0]);
- }
- } else {
- if (conf->target)
- error("%s: target already provided");
- conf->target = argv[0];
- }
- }
- if (conf->makefile == NULL)
- conf->makefile = "Makefile";
-}
-
static char *mmap_makefile(char *fname)
{
int fd = open(fname, O_RDONLY, 0);
@@ -287,6 +262,15 @@ syserr:
return NULL; /* unreachable */
}
+static char *strchr(char *s, char c)
+{
+ for (; *s; ++s) {
+ if (*s == c)
+ return s;
+ }
+ return NULL;
+}
+
static int readline(char **makefile, struct line *line)
{
static int linenum = 1;
@@ -1724,45 +1708,73 @@ static void make_full_vname(struct buf *dest, struct str *prx,
buf_puts(dest, vname);
}
-static void set_single_var(struct vtable *vt, int mode, struct str *prefix,
- struct str *vname,struct str *value, int alloc_name)
+struct variable {
+ struct str name;
+ struct strbuf *goals;
+ struct str *value;
+ char scope;
+
+ int linenum;
+ 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;
+}
+
+static void set_single_var(struct variable *var, struct str *goal, int mode)
{
static char localbuf[buf_static_size];
struct buf buf;
- struct str tmp;
+ struct str fullname;
+ /* TODO: Why do we need to alloc for goal specific assignments */
+ int alloc = goal ? 1 : 0;
buf_static_init(buf, localbuf, buf_static_size);
- if (prefix != NULL) {
- make_full_vname(&buf, prefix, vname);
- tmp = (struct str) { buf.start, buf.cur };
+ if (goal != NULL) {
+ make_full_vname(&buf, goal, &var->name);
+ fullname = (struct str) { buf.start, buf.cur };
} else {
- tmp = *vname;
+ fullname = var->name;
}
+
if (mode == svmode_set) {
- vtable_update(vt, &tmp, alloc_name, value);
+ if (check_policy(var, &fullname) == 0)
+ return;
+ /* Double work, but I do not think we should even bother */
+ vtable_update(var->vt, &fullname, alloc, var->value, var->scope);
} else {
struct str newval;
- struct str *oldval = vtable_find(vt, &tmp);
+ struct str *oldval = vtable_find(var->vt, &fullname);
if (oldval == NULL)
- oldval = vtable_find(vt, vname);
- str_combine(&newval, oldval, value);
- vtable_update(vt, &tmp, alloc_name, &newval);
+ oldval = vtable_find(var->vt, &var->name);
+ str_combine(&newval, oldval, var->value);
+ vtable_update(var->vt, &fullname, alloc, &newval, var->scope);
}
}
-static void setvar(struct vtable *vt, int mode, struct strbuf *targets,
- struct str *vname, struct str *value)
+static void setvar(struct variable *var, int mode)
{
- trim(value);
+ trim(var->value);
- if (targets != NULL) {
+ if (var->goals != NULL) {
int i;
- for (i = 0; i < targets->len; ++i) {
- set_single_var(vt, mode, &targets->buf[i].str, vname, value, 1);
- }
+ for (i = 0; i < var->goals->len; ++i)
+ set_single_var(var, &var->goals->buf[i].str, mode);
} else {
- set_single_var(vt, mode, NULL, vname, value, 0);
+ set_single_var(var, NULL, mode);
}
}
@@ -1773,32 +1785,37 @@ static int is_followed(struct line *line, char c)
static void follows(struct line *line, char c)
{
- if (is_followed(line, c)) {
- line->str.start += 2;
+ if (is_followed(line, c))
return;
- }
lerror(line->linenum, "expected %c after %c", c,
line->str.start[0]);
}
-static void parse_assignment(struct world *world, struct strbuf *targets,
- struct buf *buf, struct line *line)
+static void parse_assignment(struct world *world, struct strbuf *goals,
+ struct buf *buf, struct line *line, char scope)
{
- struct str vname = { buf->start, buf->cur };
+ struct variable var = {
+ { buf->start, buf->cur },
+ goals,
+ &line->str,
+ scope,
+
+ line->linenum,
+ &world->vtable
+ };
- trim(&vname);
- if (!valid_var_name(&vname)) {
+ trim(&var.name);
+ if (!valid_var_name(&var.name)) {
lerror(line->linenum, "[%S]: invalid variable name",
- &vname);
+ &var.name);
}
- if (line->str.start[0] == '+') {
+ if (var.value->start[0] == '+') {
follows(line, '=');
- setvar(&world->vtable, svmode_append, targets, &vname,
- &line->str);
+ var.value->start += 2;
+ setvar(&var, svmode_append);
} else {
- ++line->str.start;
- setvar(&world->vtable, svmode_set, targets, &vname,
- &line->str);
+ ++var.value->start;
+ setvar(&var, svmode_set);
}
}
@@ -1975,7 +1992,7 @@ static void handle_target_spec(struct world *world, struct buf *buf,
if (*line->str.start == ':')
lerror(line->linenum, "expected target-specific var");
- parse_assignment(world, &rule->targets, buf, line);
+ parse_assignment(world, &rule->targets, buf, line, vs_makefile);
}
static void parse_rule(struct world *world, struct buf *buf,
@@ -2016,7 +2033,7 @@ static int parse_toplev(struct world *world)
} else if (*line.str.start == ':') {
parse_rule(world, buf, &line);
} else {
- parse_assignment(world, NULL, buf, &line);
+ parse_assignment(world, NULL, buf, &line, vs_makefile);
}
return 1;
}
@@ -2027,14 +2044,11 @@ static void parse(struct world *world)
;
}
-static void world_init(struct world *world, struct conf *conf, char **envp)
+static void world_init(struct world *world, char **envp)
{
- world->makefile = mmap_makefile(conf->makefile);
- world->target = conf->target ? STR(conf->target) : CSTR("");
world->envp = envp;
world->pat_rule_num = 0;
- world->debug_mode = conf->debug_mode;
vtable_init(&world->vtable);
rtable_init(&world->rtable);
@@ -2427,6 +2441,63 @@ static void exec(struct world *world)
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";
+ char *target = NULL;
+ char *equal_sign;
+
+ ++argv;
+ for (; argv[0]; ++argv) {
+ if (argv[0][0] == '-') {
+ if (argv[0][1] == 'f' && argv[0][2] == 0) {
+ if (argv[1] == NULL)
+ error("-f: missing file name");
+ makefile = argv[1];
+ ++argv;
+ } else if (argv[0][1] == 'C' && argv[0][2] == 0) {
+ if (argv[1] == NULL)
+ error("-C: missing dir");
+ if (chdir(argv[1]) == -1)
+ syscall_error(argv[1]);
+ ++argv;
+ } else if (argv[0][1] == 'd' && argv[0][2] == 0) {
+ world->debug_mode = 1;
+ } else {
+ error("%s: unknown flag", argv[0]);
+ }
+ } else if (is_assignment(argv[0], &equal_sign)) {
+ parse_cmdarg_assignment(world, argv[0],
+ equal_sign);
+ } else {
+ if (target)
+ error("%s: target already provided");
+ target = argv[0];
+ }
+ }
+ world->makefile = mmap_makefile(makefile);
+ world->target = target ? STR(target) : CSTR("");
+}
+
static void print_program_time(int debug)
{
struct rusage rusage;
@@ -2442,11 +2513,10 @@ static void print_program_time(int debug)
int main(int argc, char **argv, char **envp)
{
struct world world;
- struct conf conf = { NULL, NULL };
- parse_cmdargs(&conf, argv);
+ world_init(&world, envp);
+ parse_cmdargs(&world, argv);
- world_init(&world, &conf, envp);
parse(&world);
exec(&world);
diff --git a/tools/sed.c b/tools/sed.c
index c427acd..833e7d2 100644
--- a/tools/sed.c
+++ b/tools/sed.c
@@ -1,3 +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
+ * MIT license. See COPYRIGHT file.
+ */
+
#include "common.h"
enum {