summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2023-12-28 18:10:41 +0000
committercinap_lenrek <cinap_lenrek@felloff.net>2023-12-28 18:10:41 +0000
commit94b1d3f0ad587b6e507ff872eb8562466e3af21a (patch)
tree9815cba818e688481fcb60a08244f8c20d1f56ea
parent6b0150764cc579c3764e6ed2a6db1237f11577de (diff)
mk: Various improvements
Variables are lists, just as in rc, so preserve emptry strings ('') in variables properly: FOO='' bar baz should result in FOO=('' bar baz) in the environment, while FOO= becomes a emptry list FOO=(). Get rid of the Evy struct, the environment can be represented as just an array of Symtab pointers, also meaning the value can never be out of sync. Embedd the name string in Symtab struct. It is immutable and dont require the caller to strdup() the name. Make Word's immutable, embedding the string value in the Word struct. This avoids alot of extra allocations. Provide a Strdup() function that handles allocation error. Handle variable overrides from the command line internally, avoiding the maketmp() file. When executing a recipe, pass the body using the -c flag to rc, avoiding a pipe() and fork(). This also has the advntage that rc can optimize the script as it sees it in its entirety and avoid fork() down the line. Make sure not to leak file-descriptors into sub-processes. Do an attempt at freeing memory (mostly for Arc's and environment values).
-rw-r--r--sys/src/cmd/mk/arc.c18
-rw-r--r--sys/src/cmd/mk/archive.c12
-rw-r--r--sys/src/cmd/mk/bufblock.c15
-rw-r--r--sys/src/cmd/mk/env.c75
-rw-r--r--sys/src/cmd/mk/file.c6
-rw-r--r--sys/src/cmd/mk/fns.h36
-rw-r--r--sys/src/cmd/mk/graph.c44
-rw-r--r--sys/src/cmd/mk/job.c20
-rw-r--r--sys/src/cmd/mk/lex.c3
-rw-r--r--sys/src/cmd/mk/main.c164
-rw-r--r--sys/src/cmd/mk/mk.c39
-rw-r--r--sys/src/cmd/mk/mk.h77
-rw-r--r--sys/src/cmd/mk/parse.c172
-rw-r--r--sys/src/cmd/mk/plan9.c341
-rw-r--r--sys/src/cmd/mk/rc.c41
-rw-r--r--sys/src/cmd/mk/recipe.c44
-rw-r--r--sys/src/cmd/mk/rule.c57
-rw-r--r--sys/src/cmd/mk/run.c49
-rw-r--r--sys/src/cmd/mk/shprint.c46
-rw-r--r--sys/src/cmd/mk/symtab.c16
-rw-r--r--sys/src/cmd/mk/var.c16
-rw-r--r--sys/src/cmd/mk/varsub.c97
-rw-r--r--sys/src/cmd/mk/word.c178
23 files changed, 747 insertions, 819 deletions
diff --git a/sys/src/cmd/mk/arc.c b/sys/src/cmd/mk/arc.c
index 5e0267ff8..8f98ec932 100644
--- a/sys/src/cmd/mk/arc.c
+++ b/sys/src/cmd/mk/arc.c
@@ -8,7 +8,7 @@ newarc(Node *n, Rule *r, char *stem, Resub *match)
a = (Arc *)Malloc(sizeof(Arc));
a->n = n;
a->r = r;
- a->stem = strdup(stem);
+ a->stem = Strdup(stem);
rcopy(a->match, match, NREGEXP);
a->next = 0;
a->flag = 0;
@@ -17,6 +17,13 @@ newarc(Node *n, Rule *r, char *stem, Resub *match)
}
void
+freearc(Arc *a)
+{
+ free(a->stem);
+ free(a);
+}
+
+void
dumpa(char *s, Arc *a)
{
char buf[1024];
@@ -36,15 +43,10 @@ dumpa(char *s, Arc *a)
void
nrep(void)
{
- Symtab *sym;
Word *w;
- sym = symlook("NREP", S_VAR, 0);
- if(sym){
- w = sym->u.ptr;
- if (w && w->s && *w->s)
- nreps = atoi(w->s);
- }
+ if(!empty(w = getvar("NREP")))
+ nreps = atoi(w->s);
if(nreps < 1)
nreps = 1;
if(DEBUG(D_GRAPH))
diff --git a/sys/src/cmd/mk/archive.c b/sys/src/cmd/mk/archive.c
index d7bf27edc..3746e4ccd 100644
--- a/sys/src/cmd/mk/archive.c
+++ b/sys/src/cmd/mk/archive.c
@@ -7,9 +7,9 @@ static char *split(char*, char**);
long
atimeof(int force, char *name)
{
+ char buf[512], *archive, *member;
Symtab *sym;
long t;
- char *archive, *member, buf[512];
archive = split(name, &member);
if(archive == 0)
@@ -26,7 +26,7 @@ atimeof(int force, char *name)
else{
atimes(archive);
/* mark the aggegate as having been done */
- symlook(strdup(archive), S_AGG, "")->u.value = t;
+ symlook(archive, S_AGG, 1)->u.value = t;
}
/* truncate long member name to sizeof of name field in archive header */
snprint(buf, sizeof(buf), "%s(%.*s)", archive, utfnlen(member, SARNAME), member);
@@ -113,7 +113,7 @@ atimes(char *ar)
i--;
h.name[i+1]=0; /* can stomp on date field */
snprint(buf, sizeof buf, "%s(%s)", ar, h.name);
- symlook(strdup(buf), S_TIME, (void*)t)->u.value = t;
+ symlook(buf, S_TIME, 1)->u.value = t;
t = atol(h.size);
if(t&01) t++;
LSEEK(fd, t, 1);
@@ -131,7 +131,7 @@ type(char *file)
if(fd < 0){
if(symlook(file, S_BITCH, 0) == 0){
Bprint(&bout, "%s doesn't exist: assuming it will be an archive\n", file);
- symlook(file, S_BITCH, (void *)file);
+ symlook(file, S_BITCH, 1);
}
return 1;
}
@@ -148,7 +148,7 @@ split(char *name, char **member)
{
char *p, *q;
- p = strdup(name);
+ p = Strdup(name);
q = utfrune(p, '(');
if(q){
*q++ = 0;
@@ -159,8 +159,8 @@ split(char *name, char **member)
*q = 0;
if(type(p))
return p;
- free(p);
fprint(2, "mk: '%s' is not an archive\n", name);
}
+ free(p);
return 0;
}
diff --git a/sys/src/cmd/mk/bufblock.c b/sys/src/cmd/mk/bufblock.c
index 979403bca..f10bff0d6 100644
--- a/sys/src/cmd/mk/bufblock.c
+++ b/sys/src/cmd/mk/bufblock.c
@@ -25,6 +25,8 @@ newbuf(void)
void
freebuf(Bufblock *p)
{
+ assert(p->current >= p->start);
+ p->current = 0;
p->next = freelist;
freelist = p;
}
@@ -39,6 +41,7 @@ growbuf(Bufblock *p)
n = p->end-p->start+QUANTA;
/* search the free list for a big buffer */
for (f = freelist; f; f = f->next) {
+ assert(f->current == 0);
if (f->end-f->start >= n) {
memcpy(f->start, p->start, p->end-p->start);
cp = f->start;
@@ -47,7 +50,6 @@ growbuf(Bufblock *p)
cp = f->end;
f->end = p->end;
p->end = cp;
- f->current = f->start;
break;
}
}
@@ -59,9 +61,17 @@ growbuf(Bufblock *p)
}
void
-bufcpy(Bufblock *buf, char *cp, int n)
+bufcpy(Bufblock *buf, char *cp)
{
+ int c;
+ while (c = *cp++)
+ insert(buf, c);
+}
+
+void
+bufncpy(Bufblock *buf, char *cp, int n)
+{
while (n--)
insert(buf, *cp++);
}
@@ -69,7 +79,6 @@ bufcpy(Bufblock *buf, char *cp, int n)
void
insert(Bufblock *buf, int c)
{
-
if (buf->current >= buf->end)
growbuf(buf);
*buf->current++ = c;
diff --git a/sys/src/cmd/mk/env.c b/sys/src/cmd/mk/env.c
index 767621229..611a87742 100644
--- a/sys/src/cmd/mk/env.c
+++ b/sys/src/cmd/mk/env.c
@@ -1,10 +1,10 @@
#include "mk.h"
enum {
- ENVQUANTA=10
+ ENVQUANTA=64
};
-Envy *envy;
+static Symtab **envy;
static int nextv;
static char *myenv[] =
@@ -36,72 +36,66 @@ initenv(void)
char **p;
for(p = myenv; *p; p++)
- symlook(*p, S_INTERNAL, (void *)"");
+ symlook(*p, S_INTERNAL, 1)->u.ptr = 0;
readenv(); /* o.s. dependent */
}
static void
-envinsert(char *name, Word *value)
+envupd(char *name, Word *value)
+{
+ Symtab *sym = symlook(name, S_INTERNAL, 0);
+ assert(sym != 0);
+ delword(sym->u.ptr);
+ sym->u.ptr = value;
+}
+
+static void
+envinsert(Symtab *sym)
{
static int envsize;
if (nextv >= envsize) {
envsize += ENVQUANTA;
- envy = (Envy *) Realloc((char *) envy, envsize*sizeof(Envy));
+ envy = (Symtab **) Realloc(envy, envsize*sizeof(Symtab*));
}
- envy[nextv].name = name;
- envy[nextv++].values = value;
+ envy[nextv++] = sym;
}
static void
-envupd(char *name, Word *value)
+ereset(Symtab *s)
{
- Envy *e;
-
- for(e = envy; e->name; e++)
- if(strcmp(name, e->name) == 0){
- delword(e->values);
- e->values = value;
- return;
- }
- e->name = name;
- e->values = value;
- envinsert(0,0);
+ delword(s->u.ptr);
+ s->u.ptr = 0;
+ envinsert(s);
}
static void
ecopy(Symtab *s)
{
- char **p;
-
if(symlook(s->name, S_NOEXPORT, 0))
return;
- for(p = myenv; *p; p++)
- if(strcmp(*p, s->name) == 0)
- return;
- envinsert(s->name, s->u.ptr);
+ if(symlook(s->name, S_INTERNAL, 0))
+ return;
+ envinsert(s);
}
-void
+Symtab**
execinit(void)
{
- char **p;
-
nextv = 0;
- for(p = myenv; *p; p++)
- envinsert(*p, stow(""));
-
+ symtraverse(S_INTERNAL, ereset);
symtraverse(S_VAR, ecopy);
- envinsert(0, 0);
+ envinsert(0);
+ return envy;
}
-Envy*
+Symtab**
buildenv(Job *j, int slot)
{
char **p, *cp, *qp;
Word *w, *v, **l;
+ char num[16];
int i;
- char buf[256];
envupd("target", wdup(j->t));
if(j->r->attr&REGEXP)
@@ -109,10 +103,10 @@ buildenv(Job *j, int slot)
else
envupd("stem", newword(j->stem));
envupd("prereq", wdup(j->p));
- snprint(buf, sizeof buf, "%d", getpid());
- envupd("pid", newword(buf));
- snprint(buf, sizeof buf, "%d", slot);
- envupd("nproc", newword(buf));
+ snprint(num, sizeof num, "%d", getpid());
+ envupd("pid", newword(num));
+ snprint(num, sizeof num, "%d", slot);
+ envupd("nproc", newword(num));
envupd("newprereq", wdup(j->np));
envupd("alltarget", wdup(j->at));
l = &v;
@@ -129,10 +123,7 @@ buildenv(Job *j, int slot)
continue;
}
}
- *l = w->next;
- free(w->s);
- free(w);
- w = *l;
+ *l = w = popword(w);
}
envupd("newmember", v);
/* update stem0 -> stem9 */
diff --git a/sys/src/cmd/mk/file.c b/sys/src/cmd/mk/file.c
index 5ddebba43..3cabdc6aa 100644
--- a/sys/src/cmd/mk/file.c
+++ b/sys/src/cmd/mk/file.c
@@ -21,14 +21,14 @@ timeof(char *name, int force)
return mtime(name);
sym = symlook(name, S_TIME, 0);
- if (sym)
+ if(sym)
return sym->u.value; /* uggh */
t = mkmtime(name, 0);
if(t == 0)
return 0;
- symlook(name, S_TIME, (void*)t); /* install time in cache */
+ symlook(name, S_TIME, 1)->u.value = t; /* install time in cache */
return t;
}
@@ -76,7 +76,7 @@ timeinit(char *s)
} while(*s);
c = *s;
*s = 0;
- symlook(strdup(cp), S_TIME, (void *)t)->u.value = t;
+ symlook(cp, S_TIME, 1)->u.value = t;
if (c)
*s++ = c;
while(*s){
diff --git a/sys/src/cmd/mk/fns.h b/sys/src/cmd/mk/fns.h
index f16475042..b61ec21ca 100644
--- a/sys/src/cmd/mk/fns.h
+++ b/sys/src/cmd/mk/fns.h
@@ -1,11 +1,13 @@
void addrule(char*, Word*, char*, Word*, int, int, char*);
void addrules(Word*, Word*, char*, int, int, char*);
-void addw(Word*, char*);
int assline(Biobuf *, Bufblock *);
long atimeof(int,char*);
void atouch(char*);
-void bufcpy(Bufblock *, char *, int);
-Envy *buildenv(Job*, int);
+void bufcpy(Bufblock *, char *);
+void bufcpyq(Bufblock *, char *);
+void bufcpyw(Bufblock *, Word *);
+void bufncpy(Bufblock *, char *, int);
+Symtab **buildenv(Job*, int);
void catchnotes(void);
char *charin(char *, char *);
int chgtime(char*);
@@ -20,23 +22,24 @@ void dumpn(char*, Node*);
void dumpr(char*, Rule*);
void dumpv(char*);
void dumpw(char*, Word*);
+int empty(Word*);
int escapetoken(Biobuf*, Bufblock*, int, int);
-void execinit(void);
-int execsh(char*, char*, Bufblock*, Envy*);
+Symtab **execinit(void);
+int execsh(char*, char*, Symtab**, Bufblock*);
void Exit(void);
char *expandquote(char*, Rune, Bufblock*);
void expunge(int, char*);
+void freearc(Arc*);
void freebuf(Bufblock*);
+void freejob(Job*);
void front(char*);
+Word *getvar(char*);
Node *graph(char*);
void growbuf(Bufblock *);
void initenv(void);
void insert(Bufblock *, int);
-void ipop(void);
-void ipush(void);
void killchildren(char*);
void *Malloc(int);
-char *maketmp(void);
int match(char*, char*, char*);
void mk(char*);
ulong mkmtime(char*, int);
@@ -50,8 +53,9 @@ int nextslot(void);
void nproc(void);
void nrep(void);
int outofdate(Node*, Arc*, int);
-void parse(char*, int, int);
-int pipecmd(char*, Envy*, int*);
+void parse(char*, int);
+int pipecmd(char*, char*, Symtab**, int*);
+Word *popword(Word*);
void prusage(void);
void rcopy(char**, Resub*, int);
void readenv(void);
@@ -59,21 +63,25 @@ void *Realloc(void*, int);
void rinsert(Bufblock *, Rune);
char *rulecnt(void);
void run(Job*);
-void setvar(char*, void*);
+void setvar(char*, Word*);
char *shname(char*);
-void shprint(char*, Envy*, Bufblock*);
+void shprint(char*, Bufblock*);
Word *stow(char*);
+char *Strdup(char*);
void subst(char*, char*, char*, int);
-Symtab *symlook(char*, int, void*);
+Symtab *symlook(char*, int, int);
void symtraverse(int, void(*)(Symtab*));
void timeinit(char*);
long timeof(char*, int);
void touch(char*);
void update(int, Node*);
void usage(void);
+void varoverride(char*);
Word *varsub(char**);
+int wadd(Word**, char*);
int waitfor(char*);
int waitup(int, int*);
+int wcmp(Word*, Word*);
Word *wdup(Word*);
int work(Node*, Node*, Arc*);
-char *wtos(Word*, int);
+char *wtos(Word*);
diff --git a/sys/src/cmd/mk/graph.c b/sys/src/cmd/mk/graph.c
index 87217afc6..dc119679f 100644
--- a/sys/src/cmd/mk/graph.c
+++ b/sys/src/cmd/mk/graph.c
@@ -41,7 +41,6 @@ applyrules(char *target, char *cnt)
sym = symlook(target, S_NODE, 0);
if(sym)
return sym->u.ptr;
- target = strdup(target);
node = newnode(target);
head.n = 0;
head.next = 0;
@@ -49,8 +48,7 @@ applyrules(char *target, char *cnt)
memset((char*)rmatch, 0, sizeof(rmatch));
for(r = sym? sym->u.ptr:0; r; r = r->chain){
if(r->attr&META) continue;
- if(strcmp(target, r->target)) continue;
- if((!r->recipe || !*r->recipe) && (!r->tail || !r->tail->s || !*r->tail->s)) continue; /* no effect; ignore */
+ if((!r->recipe || !*r->recipe) && empty(r->tail)) continue; /* no effect; ignore */
if(cnt[r->rule] >= nreps) continue;
cnt[r->rule]++;
node->flags |= PROBABLE;
@@ -62,19 +60,20 @@ applyrules(char *target, char *cnt)
* if(r->attr&DEL)
* node->flags |= DELETE;
*/
- if(!r->tail || !r->tail->s || !*r->tail->s) {
+ if(empty(r->tail)) {
a->next = newarc((Node *)0, r, "", rmatch);
a = a->next;
- } else
+ } else {
for(w = r->tail; w; w = w->next){
a->next = newarc(applyrules(w->s, cnt), r, "", rmatch);
a = a->next;
+ }
}
cnt[r->rule]--;
head.n = node;
}
for(r = metarules; r; r = r->next){
- if((!r->recipe || !*r->recipe) && (!r->tail || !r->tail->s || !*r->tail->s)) continue; /* no effect; ignore */
+ if((!r->recipe || !*r->recipe) && empty(r->tail)) continue; /* no effect; ignore */
if ((r->attr&NOVIRT) && a != &head && (a->r->attr&VIR))
continue;
if(r->attr&REGEXP){
@@ -84,7 +83,7 @@ applyrules(char *target, char *cnt)
if(regexec(r->pat, node->name, rmatch, NREGEXP) == 0)
continue;
} else {
- if(!match(node->name, r->target, stem)) continue;
+ if(!match(node->name, r->target->name, stem)) continue;
}
if(cnt[r->rule] >= nreps) continue;
cnt[r->rule]++;
@@ -96,7 +95,7 @@ applyrules(char *target, char *cnt)
* if(r->attr&DEL)
* node->flags |= DELETE;
*/
- if(!r->tail || !r->tail->s || !*r->tail->s) {
+ if(empty(r->tail)){
a->next = newarc((Node *)0, r, stem, rmatch);
a = a->next;
} else
@@ -118,20 +117,20 @@ applyrules(char *target, char *cnt)
static void
togo(Node *node)
{
- Arc *la, *a;
+ Arc **l, *a;
/* delete them now */
- la = 0;
- for(a = node->prereqs; a; la = a, a = a->next)
+ l = &node->prereqs;
+ while(a = *l){
if(a->flag&TOGO){
- if(a == node->prereqs)
- node->prereqs = a->next;
- else
- la->next = a->next, a = la;
- }
+ *l = a->next;
+ freearc(a);
+ } else
+ l = &a->next;
+ }
}
-static
+static int
vacuous(Node *node)
{
Arc *la, *a;
@@ -149,9 +148,8 @@ vacuous(Node *node)
for(a = node->prereqs; a; a = a->next)
if((a->flag&TOGO) == 0)
for(la = node->prereqs; la; la = la->next)
- if((la->flag&TOGO) && (la->r == a->r)){
+ if((la->flag&TOGO) && (la->r == a->r))
la->flag &= ~TOGO;
- }
togo(node);
if(vac)
node->flags |= VACUOUS;
@@ -161,15 +159,17 @@ vacuous(Node *node)
static Node *
newnode(char *name)
{
- register Node *node;
+ Symtab *sym;
+ Node *node;
+ sym = symlook(name, S_NODE, 1);
node = (Node *)Malloc(sizeof(Node));
- symlook(name, S_NODE, (void *)node);
- node->name = name;
+ node->name = sym->name;
node->time = timeof(name, 0);
node->prereqs = 0;
node->flags = node->time? PROBABLE : 0;
node->next = 0;
+ sym->u.ptr = node;
return(node);
}
diff --git a/sys/src/cmd/mk/job.c b/sys/src/cmd/mk/job.c
index a8266667f..1b47110df 100644
--- a/sys/src/cmd/mk/job.c
+++ b/sys/src/cmd/mk/job.c
@@ -3,7 +3,7 @@
Job *
newjob(Rule *r, Node *nlist, char *stem, char **match, Word *pre, Word *npre, Word *tar, Word *atar)
{
- register Job *j;
+ Job *j;
j = (Job *)Malloc(sizeof(Job));
j->r = r;
@@ -20,14 +20,28 @@ newjob(Rule *r, Node *nlist, char *stem, char **match, Word *pre, Word *npre, Wo
}
void
+freejob(Job *j)
+{
+ delword(j->p);
+ delword(j->np);
+ delword(j->t);
+ delword(j->at);
+ free(j);
+}
+
+void
dumpj(char *s, Job *j, int all)
{
+ char *t;
+
Bprint(&bout, "%s\n", s);
while(j){
Bprint(&bout, "job@%p: r=%p n=%p stem='%s' nproc=%d\n",
j, j->r, j->n, j->stem, j->nproc);
- Bprint(&bout, "\ttarget='%s' alltarget='%s' prereq='%s' nprereq='%s'\n",
- wtos(j->t, ' '), wtos(j->at, ' '), wtos(j->p, ' '), wtos(j->np, ' '));
+ Bprint(&bout, "\ttarget=%s", t = wtos(j->t)), free(t);
+ Bprint(&bout, " alltarget=%s", t = wtos(j->at)), free(t);
+ Bprint(&bout, " prereq=%s", t = wtos(j->p)), free(t);
+ Bprint(&bout, " nprereq=%s\n", t = wtos(j->np)), free(t);
j = all? j->next : 0;
}
}
diff --git a/sys/src/cmd/mk/lex.c b/sys/src/cmd/mk/lex.c
index 5c4bc99be..1ea3c2912 100644
--- a/sys/src/cmd/mk/lex.c
+++ b/sys/src/cmd/mk/lex.c
@@ -89,8 +89,7 @@ bquote(Biobuf *bp, Bufblock *buf)
insert(buf, '\n');
insert(buf,0);
buf->current = buf->start+start;
- execinit();
- execsh(0, buf->current, buf, envy);
+ execsh(buf->current, 0, execinit(), buf);
return 1;
}
if(c == '\n')
diff --git a/sys/src/cmd/mk/main.c b/sys/src/cmd/mk/main.c
index e4a98d4f2..a834f307b 100644
--- a/sys/src/cmd/mk/main.c
+++ b/sys/src/cmd/mk/main.c
@@ -3,36 +3,29 @@
#define MKFILE "mkfile"
int debug;
-Rule *rules, *metarules;
int nflag = 0;
+int sflag = 0;
int tflag = 0;
int iflag = 0;
int kflag = 0;
int aflag = 0;
int uflag = 0;
+int nreps = 1;
char *explain = 0;
Word *target1;
-int nreps = 1;
Job *jobs;
+Rule *rules, *patrule, *metarules;
Biobuf bout;
-Rule *patrule;
+
void badusage(void);
-#ifdef PROF
-short buf[10000];
-#endif
void
main(int argc, char **argv)
{
- Word *w;
- char *s, *temp;
- char *files[256], **f = files, **ff;
- int sflag = 0;
- int i;
- int tfd = -1;
- Biobuf tb;
- Bufblock *buf;
+ Word **link, *flags, *files, *args;
Bufblock *whatif;
+ char *s;
+ int i;
/*
* start with a copy of the current environment variables
@@ -40,13 +33,14 @@ main(int argc, char **argv)
*/
Binit(&bout, 1, OWRITE);
- buf = newbuf();
whatif = 0;
USED(argc);
- for(argv++; *argv && (**argv == '-'); argv++)
+
+ flags = 0;
+ link = &flags;
+ for(argv++; *argv && (**argv == '-'); argv++, link = &(*link)->next)
{
- bufcpy(buf, argv[0], strlen(argv[0]));
- insert(buf, ' ');
+ *link = newword(*argv);
switch(argv[0][1])
{
case 'a':
@@ -67,11 +61,12 @@ main(int argc, char **argv)
explain = &argv[0][2];
break;
case 'f':
- if(*++argv == 0)
+ argv++;
+ if(*argv == 0 || **argv == 0)
badusage();
- *f++ = *argv;
- bufcpy(buf, argv[0], strlen(argv[0]));
- insert(buf, ' ');
+ link = &(*link)->next;
+ *link = newword(*argv);
+ wadd(&files, *argv);
break;
case 'i':
iflag = 1;
@@ -97,23 +92,19 @@ main(int argc, char **argv)
else
insert(whatif, ' ');
if(argv[0][2])
- bufcpy(whatif, &argv[0][2], strlen(&argv[0][2]));
+ bufcpy(whatif, &argv[0][2]);
else {
if(*++argv == 0)
badusage();
- bufcpy(whatif, &argv[0][0], strlen(&argv[0][0]));
+ bufcpy(whatif, &argv[0][0]);
+ link = &(*link)->next;
+ *link = newword(*argv);
}
break;
default:
badusage();
}
}
-#ifdef PROF
- {
- extern etext();
- monitor(main, etext, buf, sizeof buf, 300);
- }
-#endif
if(aflag)
iflag = 1;
@@ -124,54 +115,30 @@ main(int argc, char **argv)
/*
assignment args become null strings
*/
- temp = 0;
+ mkinfile = "command line args";
for(i = 0; argv[i]; i++) if(utfrune(argv[i], '=')){
- bufcpy(buf, argv[i], strlen(argv[i]));
- insert(buf, ' ');
- if(tfd < 0){
- temp = maketmp();
- if(temp == 0) {
- perror("temp file");
- Exit();
- }
- if((tfd = create(temp, ORDWR, 0600)) < 0){
- perror(temp);
- Exit();
- }
- Binit(&tb, tfd, OWRITE);
- }
- Bprint(&tb, "%s\n", argv[i]);
+ if(!wadd(&flags, argv[i]))
+ varoverride(argv[i]);
*argv[i] = 0;
}
- if(tfd >= 0){
- Bflush(&tb);
- LSEEK(tfd, 0L, 0);
- parse("command line args", tfd, 1);
- remove(temp);
- }
+ setvar("MKFLAGS", flags);
- if (buf->current != buf->start) {
- buf->current--;
- insert(buf, 0);
- }
- symlook("MKFLAGS", S_VAR, (void *) stow(buf->start));
- buf->current = buf->start;
+ args = 0;
+ link = &args;
for(i = 0; argv[i]; i++){
if(*argv[i] == 0) continue;
- if(i)
- insert(buf, ' ');
- bufcpy(buf, argv[i], strlen(argv[i]));
+ *link = newword(argv[i]);
+ link = &(*link)->next;
}
- insert(buf, 0);
- symlook("MKARGS", S_VAR, (void *) stow(buf->start));
- freebuf(buf);
+ setvar("MKARGS", args);
- if(f == files){
- if(access(MKFILE, 4) == 0)
- parse(MKFILE, open(MKFILE, 0), 0);
- } else
- for(ff = files; ff < f; ff++)
- parse(*ff, open(*ff, 0), 0);
+ if(files == 0){
+ if(access(MKFILE, AEXIST) == 0)
+ parse(MKFILE, open(MKFILE, OREAD|OCEXEC));
+ } else {
+ for(; files; files = popword(files))
+ parse(files->s, open(files->s, OREAD|OCEXEC));
+ }
if(DEBUG(D_PARSE)){
dumpw("default targets", target1);
dumpr("rules", rules);
@@ -184,44 +151,26 @@ main(int argc, char **argv)
freebuf(whatif);
}
execinit();
- /* skip assignment args */
- while(*argv && (**argv == 0))
- argv++;
catchnotes();
- if(*argv == 0){
- if(target1)
- for(w = target1; w; w = w->next)
- mk(w->s);
- else {
+ if(args == 0){
+ if(target1 == 0){
fprint(2, "mk: nothing to mk\n");
Exit();
}
+ for(; target1; target1 = popword(target1))
+ mk(target1->s);
} else {
+ args = wdup(args);
if(sflag){
- for(; *argv; argv++)
- if(**argv)
- mk(*argv);
+ for(; args; args = popword(args))
+ mk(args->s);
} else {
- Word *head, *tail, *t;
-
- /* fake a new rule with all the args as prereqs */
- tail = 0;
- t = 0;
- for(; *argv; argv++)
- if(**argv){
- if(tail == 0)
- tail = t = newword(*argv);
- else {
- t->next = newword(*argv);
- t = t->next;
- }
- }
- if(tail->next == 0)
- mk(tail->s);
+ if(args->next == 0)
+ mk(args->s);
else {
- head = newword("command line arguments");
- addrules(head, tail, strdup(""), VIR, mkinline, 0);
+ Word *head = newword(mkinfile);
+ addrules(head, args, Strdup(""), VIR, 0, 0);
mk(head->s);
}
}
@@ -234,7 +183,6 @@ main(int argc, char **argv)
void
badusage(void)
{
-
fprint(2, "usage: mk [-f file] [-n] [-a] [-e] [-t] [-k] [-i] [-d[egp]] [targets ...]\n");
Exit();
}
@@ -242,13 +190,14 @@ badusage(void)
void *
Malloc(int n)
{
- register void *s;
+ void *s;
s = malloc(n);
if(!s) {
fprint(2, "mk: cannot alloc %d bytes\n", n);
Exit();
}
+ setmalloctag(s, getcallerpc(&n));
return(s);
}
@@ -263,9 +212,20 @@ Realloc(void *s, int n)
fprint(2, "mk: cannot alloc %d bytes\n", n);
Exit();
}
+ setrealloctag(s, getcallerpc(&s));
return(s);
}
+char *
+Strdup(char *s)
+{
+ int n = strlen(s)+1;
+ char *d = Malloc(n);
+ memcpy(d, s, n);
+ setmalloctag(d, getcallerpc(&s));
+ return d;
+}
+
void
regerror(char *s)
{
@@ -274,6 +234,6 @@ regerror(char *s)
patrule->file, patrule->line, s);
else
fprint(2, "mk: %s:%d: regular expression error; %s\n",
- infile, mkinline, s);
+ mkinfile, mkinline, s);
Exit();
}
diff --git a/sys/src/cmd/mk/mk.c b/sys/src/cmd/mk/mk.c
index a7a95a510..be0dc1d12 100644
--- a/sys/src/cmd/mk/mk.c
+++ b/sys/src/cmd/mk/mk.c
@@ -172,7 +172,7 @@ update(int fake, Node *node)
Arc *a;
MADESET(node, fake? BEINGMADE : MADE);
- if(((node->flags&VIRTUAL) == 0) && (access(node->name, 0) == 0)){
+ if(((node->flags&VIRTUAL) == 0) && (access(node->name, AEXIST) == 0)){
node->time = timeof(node->name, 1);
node->flags &= ~(CANPRETEND|PRETENDING);
for(a = node->prereqs; a; a = a->next)
@@ -188,14 +188,12 @@ update(int fake, Node *node)
}
static
-pcmp(char *prog, char *p, char *q)
+pcmp(char *cmd)
{
- char buf[3*NAMEBLOCK];
int pid;
Bflush(&bout);
- snprint(buf, sizeof buf, "%s '%s' '%s'\n", prog, p, q);
- pid = pipecmd(buf, 0, 0);
+ pid = pipecmd(cmd, 0, 0, 0);
while(waitup(-3, &pid) >= 0)
;
return(pid? 2:1);
@@ -204,25 +202,28 @@ pcmp(char *prog, char *p, char *q)
int
outofdate(Node *node, Arc *arc, int eval)
{
- char buf[3*NAMEBLOCK], *str;
- Symtab *sym;
- int ret;
-
- str = 0;
if(arc->prog){
- snprint(buf, sizeof buf, "%s%c%s", node->name, 0377,
- arc->n->name);
- sym = symlook(buf, S_OUTOFDATE, 0);
+ Bufblock *cmd;
+ Symtab *sym;
+ int ret;
+
+ cmd = newbuf();
+ bufcpy(cmd, arc->prog);
+ insert(cmd, ' ');
+ bufcpyq(cmd, node->name);
+ insert(cmd, ' ');
+ bufcpyq(cmd, arc->n->name);
+ insert(cmd, '\n');
+ insert(cmd, 0);
+ sym = symlook(cmd->start, S_OUTOFDATE, 0);
if(sym == 0 || eval){
+ ret = pcmp(cmd->start);
if(sym == 0)
- str = strdup(buf);
- ret = pcmp(arc->prog, node->name, arc->n->name);
- if(sym)
- sym->u.value = ret;
- else
- symlook(str, S_OUTOFDATE, (void *)ret);
+ sym = symlook(cmd->start, S_OUTOFDATE, 1);
+ sym->u.value = ret;
} else
ret = sym->u.value;
+ freebuf(cmd);
return(ret-1);
} else if(strchr(arc->n->name, '(') && arc->n->time == 0) /* missing archive member */
return 1;
diff --git a/sys/src/cmd/mk/mk.h b/sys/src/cmd/mk/mk.h
index fd48e71de..ef845eb35 100644
--- a/sys/src/cmd/mk/mk.h
+++ b/sys/src/cmd/mk/mk.h
@@ -15,21 +15,39 @@ typedef struct Bufblock
typedef struct Word
{
- char *s;
struct Word *next;
+ char s[1];
} Word;
-typedef struct Envy
+typedef struct Symtab
{
- char *name;
- Word *values;
-} Envy;
+ union{
+ void *ptr;
+ uintptr value;
+ } u;
+ struct Symtab *next;
+ unsigned char space;
+ char name[1];
+} Symtab;
-extern Envy *envy;
+enum {
+ S_VAR, /* variable -> value */
+ S_TARGET, /* target -> rule */
+ S_TIME, /* file -> time */
+ S_NODE, /* target name -> node */
+ S_AGG, /* aggregate -> time */
+ S_BITCH, /* bitched about aggregate not there */
+ S_NOEXPORT, /* var -> noexport */
+ S_OVERRIDE, /* can't override */
+ S_OUTOFDATE, /* "cmp 'file1' 'file2'\n" -> 2(outofdate) or 1(not outofdate) */
+ S_BULKED, /* directory; we have bulked */
+ S_WESET, /* variable; we set in the mkfile */
+ S_INTERNAL, /* variable -> value; an internal mk variable (e.g., stem, target) */
+};
typedef struct Rule
{
- char *target; /* one target */
+ Symtab *target; /* one target */
Word *tail; /* constituents of targets */
char *recipe; /* do it ! */
short attr; /* attributes */
@@ -112,50 +130,17 @@ typedef struct Job
} Job;
extern Job *jobs;
-typedef struct Symtab
-{
- short space;
- char *name;
- union{
- void *ptr;
- uintptr value;
- } u;
- struct Symtab *next;
-} Symtab;
-
-enum {
- S_VAR, /* variable -> value */
- S_TARGET, /* target -> rule */
- S_TIME, /* file -> time */
- S_PID, /* pid -> products */
- S_NODE, /* target name -> node */
- S_AGG, /* aggregate -> time */
- S_BITCH, /* bitched about aggregate not there */
- S_NOEXPORT, /* var -> noexport */
- S_OVERRIDE, /* can't override */
- S_OUTOFDATE, /* n1\377n2 -> 2(outofdate) or 1(not outofdate) */
- S_MAKEFILE, /* target -> node */
- S_MAKEVAR, /* dumpable mk variable */
- S_EXPORTED, /* var -> current exported value */
- S_BULKED, /* we have bulked this dir */
- S_WESET, /* variable; we set in the mkfile */
- S_INTERNAL, /* an internal mk variable (e.g., stem, target) */
-};
-
extern int debug;
extern int nflag, tflag, iflag, kflag, aflag, mflag;
extern int mkinline;
-extern char *infile;
+extern char *mkinfile;
extern int nreps;
extern char *explain;
-extern char *termchars;
-extern char *shell;
-extern char *shellname;
-extern char *shflags;
-extern int IWS;
-
-#define SYNERR(l) (fprint(2, "mk: %s:%d: syntax error; ", infile, ((l)>=0)?(l):mkinline))
-#define RERR(r) (fprint(2, "mk: %s:%d: rule error; ", (r)->file, (r)->line))
+extern char termchars[];
+extern char shell[];
+extern char shellname[];
+
+#define SYNERR(l) (fprint(2, "mk: %s:%d: syntax error; ", mkinfile, ((l)>=0)?(l):mkinline))
#define NAMEBLOCK 1000
#define BIGBLOCK 20000
diff --git a/sys/src/cmd/mk/parse.c b/sys/src/cmd/mk/parse.c
index ac3f01faf..67be5c4ed 100644
--- a/sys/src/cmd/mk/parse.c
+++ b/sys/src/cmd/mk/parse.c
@@ -1,110 +1,133 @@
#include "mk.h"
-char *infile;
+char *mkinfile;
int mkinline;
+
+static void ipush(char *file);
+static void ipop(void);
+static void doassign(Word *, Word *, int, int);
static int rhead(char *, Word **, Word **, int *, char **);
static char *rbody(Biobuf*);
extern Word *target1;
void
-parse(char *f, int fd, int varoverride)
+parse(char *f, int fd)
{
- int hline;
- char *body;
+ int hline, attr, pid, newfd;
Word *head, *tail;
- int attr, set, pid;
char *prog, *p;
- int newfd;
- Biobuf in;
Bufblock *buf;
+ Biobuf in;
if(fd < 0){
perror(f);
Exit();
}
- ipush();
- infile = strdup(f);
- mkinline = 1;
Binit(&in, fd, OREAD);
+ ipush(f);
buf = newbuf();
while(assline(&in, buf)){
hline = mkinline;
switch(rhead(buf->start, &head, &tail, &attr, &prog))
{
case '<':
- p = wtos(tail, ' ');
+ p = wtos(tail);
if(*p == 0){
SYNERR(-1);
fprint(2, "missing include file name\n");
Exit();
}
- newfd = open(p, OREAD);
+ newfd = open(p, OREAD|OCEXEC);
if(newfd < 0){
fprint(2, "warning: skipping missing include file: ");
perror(p);
} else
- parse(p, newfd, 0);
+ parse(p, newfd);
+ free(p);
break;
case '|':
- p = wtos(tail, ' ');
+ p = wtos(tail);
if(*p == 0){
SYNERR(-1);
fprint(2, "missing include program name\n");
Exit();
}
- execinit();
- pid=pipecmd(p, envy, &newfd);
+ pid=pipecmd(p, 0, execinit(), &newfd);
if(newfd < 0){
fprint(2, "warning: skipping missing program file: ");
perror(p);
} else
- parse(p, newfd, 0);
+ parse(p, newfd);
while(waitup(-3, &pid) >= 0)
;
if(pid != 0){
fprint(2, "bad include program status\n");
Exit();
}
+ free(p);
break;
case ':':
- body = rbody(&in);
- addrules(head, tail, body, attr, hline, prog);
- break;
+ addrules(head, tail, rbody(&in), attr, hline, prog);
+ continue; /* don't free head and tail */
case '=':
- if(head->next){
- SYNERR(-1);
- fprint(2, "multiple vars on left side of assignment\n");
- Exit();
- }
- if(symlook(head->s, S_OVERRIDE, 0)){
- set = varoverride;
- } else {
- set = 1;
- if(varoverride)
- symlook(head->s, S_OVERRIDE, (void *)"");
- }
- if(set){
-/*
-char *cp;
-dumpw("tail", tail);
-cp = wtos(tail, ' '); print("assign %s to %s\n", head->s, cp); free(cp);
-*/
- setvar(head->s, (void *) tail);
- symlook(head->s, S_WESET, (void *)"");
- }
- if(attr)
- symlook(head->s, S_NOEXPORT, (void *)"");
- break;
+ doassign(head, tail, attr, 0);
+ continue;
default:
SYNERR(hline);
fprint(2, "expected one of :<=\n");
Exit();
break;
}
+ delword(head);
+ delword(tail);
}
- close(fd);
freebuf(buf);
ipop();
+ close(fd);
+}
+
+static void
+doassign(Word *head, Word *tail, int attr, int override)
+{
+ int set;
+
+ if(head->next){
+ SYNERR(-1);
+ fprint(2, "multiple vars on left side of assignment\n");
+ Exit();
+ }
+ if(symlook(head->s, S_OVERRIDE, 0)){
+ set = override;
+ } else {
+ set = 1;
+ if(override)
+ symlook(head->s, S_OVERRIDE, 1);
+ }
+ if(set){
+ setvar(head->s, tail);
+ symlook(head->s, S_WESET, 1);
+ tail = 0; /* don't free */
+ }
+ if(attr)
+ symlook(head->s, S_NOEXPORT, 1);
+ delword(head);
+ delword(tail);
+}
+
+void
+varoverride(char *line)
+{
+ Word *head, *tail;
+ char *dummy;
+ int attr;
+
+ head = tail = 0;
+ if(rhead(line, &head, &tail, &attr, &dummy) == '='){
+ doassign(head, tail, attr, 1);
+ return;
+ }
+ delword(head);
+ delword(tail);
}
void
@@ -135,6 +158,10 @@ rhead(char *line, Word **h, Word **t, int *attr, char **prog)
int n;
Word *w;
+ *h = *t = 0;
+ *attr = 0;
+ *prog = 0;
+
p = charin(line,":=<");
if(p == 0)
return('?');
@@ -144,8 +171,6 @@ rhead(char *line, Word **h, Word **t, int *attr, char **prog)
sep = '|';
p++;
}
- *attr = 0;
- *prog = 0;
if(sep == '='){
pp = charin(p, termchars); /* termchars is shell-dependent */
if (pp && *pp == '=') {
@@ -195,7 +220,7 @@ rhead(char *line, Word **h, Word **t, int *attr, char **prog)
if (pp == 0 || *pp == 0)
goto eos;
*pp = 0;
- *prog = strdup(p);
+ *prog = Strdup(p);
*pp = ':';
p = pp;
break;
@@ -221,7 +246,7 @@ rhead(char *line, Word **h, Word **t, int *attr, char **prog)
}
}
*h = w = stow(line);
- if(*w->s == 0 && sep != '<' && sep != '|') {
+ if(empty(w) && sep != '<' && sep != '|') {
SYNERR(mkinline-1);
fprint(2, "no var on left side of assignment/rule\n");
Exit();
@@ -257,7 +282,7 @@ rbody(Biobuf *in)
mkinline++;
}
insert(buf, 0);
- p = strdup(buf->start);
+ p = Strdup(buf->start);
freebuf(buf);
return p;
}
@@ -270,40 +295,29 @@ struct input
};
static struct input *inputs = 0;
-void
-ipush(void)
+static void
+ipush(char *file)
{
- struct input *in, *me;
+ struct input *i;
- me = (struct input *)Malloc(sizeof(*me));
- me->file = infile;
- me->line = mkinline;
- me->next = 0;
- if(inputs == 0)
- inputs = me;
- else {
- for(in = inputs; in->next; )
- in = in->next;
- in->next = me;
- }
+ i = (struct input *)Malloc(sizeof(*i));
+ i->file = mkinfile;
+ i->line = mkinline;
+ i->next = inputs;
+ inputs = i;
+
+ mkinfile = Strdup(file);
+ mkinline = 1;
}
-void
+static void
ipop(void)
{
- struct input *in, *me;
+ struct input *i;
- assert(/*pop input list*/ inputs != 0);
- if(inputs->next == 0){
- me = inputs;
- inputs = 0;
- } else {
- for(in = inputs; in->next->next; )
- in = in->next;
- me = in->next;
- in->next = 0;
- }
- infile = me->file;
- mkinline = me->line;
- free((char *)me);
+ i = inputs;
+ inputs = i->next;
+ mkinfile = i->file;
+ mkinline = i->line;
+ free(i);
}
diff --git a/sys/src/cmd/mk/plan9.c b/sys/src/cmd/mk/plan9.c
index 485537c84..b91c4694b 100644
--- a/sys/src/cmd/mk/plan9.c
+++ b/sys/src/cmd/mk/plan9.c
@@ -1,7 +1,8 @@
#include "mk.h"
-char *shell = "/bin/rc";
-char *shellname = "rc";
+char shell[] = "/bin/rc";
+char shellname[] = "rc";
+char envdir[] = "/env/";
static Word *encodenulls(char*, int);
@@ -11,128 +12,119 @@ readenv(void)
char *p;
int envf, f;
Dir *e;
- char nam[1024];
- int i, n, len;
+ Bufblock *path;
+ int i, n, len, npath;
Word *w;
rfork(RFENVG); /* use copy of the current environment variables */
- envf = open("/env", OREAD);
+ envf = open(envdir, OREAD);
if(envf < 0)
return;
+
+ path = newbuf();
+ bufcpy(path, envdir);
+ npath = path->current - path->start;
+
while((n = dirread(envf, &e)) > 0){
for(i = 0; i < n; i++){
- len = e[i].length;
/* don't import funny names, NULL values,
* or internal mk variables
*/
+ len = e[i].length;
if(len <= 0 || *shname(e[i].name) != '\0')
continue;
if (symlook(e[i].name, S_INTERNAL, 0))
continue;
- snprint(nam, sizeof nam, "/env/%s", e[i].name);
- f = open(nam, OREAD);
+
+ path->current = path->start + npath;
+ bufcpy(path, e[i].name);
+ insert(path, 0);
+ f = open(path->start, OREAD);
if(f < 0)
continue;
p = Malloc(len+1);
if(read(f, p, len) != len){
- perror(nam);
+ perror(path->start);
close(f);
continue;
}
+ p[len] = '\0';
close(f);
- if (p[len-1] == 0)
- len--;
- else
- p[len] = 0;
w = encodenulls(p, len);
free(p);
- p = strdup(e[i].name);
- setvar(p, (void *) w);
- symlook(p, S_EXPORTED, (void*)"")->u.ptr = "";
+ setvar(e[i].name, w);
}
free(e);
}
+ freebuf(path);
close(envf);
}
-/* break string of values into words at 01's or nulls*/
static Word *
encodenulls(char *s, int n)
{
- Word *w, *head;
- char *cp;
-
- head = w = 0;
- while (n-- > 0) {
- for (cp = s; *cp && *cp != '\0'; cp++)
- n--;
- *cp = 0;
- if (w) {
- w->next = newword(s);
- w = w->next;
- } else
- head = w = newword(s);
- s = cp+1;
+ Word *head, **link;
+ int m;
+
+ head = 0;
+ link = &head;
+ while(n > 0){
+ m = strlen(s)+1;
+ n -= m;
+ *link = newword(s);
+ s += m;
+ link = &(*link)->next;
}
- if (!head)
- head = newword("");
return head;
}
-/* as well as 01's, change blanks to nulls, so that rc will
- * treat the words as separate arguments
- */
void
-exportenv(Envy *e)
+exportenv(Symtab **e)
{
- int f, n, hasvalue, first;
+ int f, n, npath;
+ Bufblock *path;
Word *w;
- Symtab *sy;
- char nam[256];
- for(;e->name; e++){
- sy = symlook(e->name, S_VAR, 0);
- if (e->values == 0 || e->values->s == 0 || e->values->s[0] == 0)
- hasvalue = 0;
- else
- hasvalue = 1;
- if(sy == 0 && !hasvalue) /* non-existant null symbol */
- continue;
- snprint(nam, sizeof nam, "/env/%s", e->name);
- if (sy != 0 && !hasvalue) { /* Remove from environment */
- /* we could remove it from the symbol table
- * too, but we're in the child copy, and it
- * would still remain in the parent's table.
- */
- remove(nam);
- delword(e->values);
- e->values = 0; /* memory leak */
+ path = newbuf();
+ bufcpy(path, envdir);
+ npath = path->current - path->start;
+
+ for(;*e; e++){
+ w = (*e)->u.ptr;
+ path->current = path->start + npath;
+ bufcpy(path, (*e)->name);
+ insert(path, 0);
+ if(w == 0){
+ remove(path->start);
continue;
}
-
- f = create(nam, OWRITE, 0666L);
+ f = create(path->start, OWRITE, 0666L);
if(f < 0) {
- fprint(2, "can't create %s, f=%d\n", nam, f);
- perror(nam);
+ fprint(2, "can't create %s\n", path->start);
+ perror(path->start);
continue;
}
- first = 1;
- for (w = e->values; w; w = w->next) {
+ if(w->next == 0){
n = strlen(w->s);
- if (n) {
- if(first)
- first = 0;
- else{
- if (write (f, "\0", 1) != 1)
- perror(nam);
- }
- if (write(f, w->s, n) != n)
- perror(nam);
- }
+ if(n == 0) n = 1;
+ if(write(f, w->s, n) != n)
+ perror(path->start);
+ } else {
+ Bufblock *buf = newbuf();
+ do {
+ bufcpy(buf, w->s);
+ insert(buf, 0);
+ w = w->next;
+ } while(w);
+ n = buf->current - buf->start;
+ if(write(f, buf->start, n) != n)
+ perror(path->start);
+ freebuf(buf);
}
close(f);
}
+ freebuf(path);
}
int
@@ -156,83 +148,31 @@ expunge(int pid, char *msg)
}
int
-execsh(char *args, char *cmd, Bufblock *buf, Envy *e)
+execsh(char *cmd, char *args, Symtab **env, Bufblock *buf)
{
- char *p;
- int tot, n, pid, in[2], out[2];
+ int fd, tot, n, pid;
- if(buf && pipe(out) < 0){
- perror("pipe");
- Exit();
- }
- pid = rfork(RFPROC|RFFDG|RFENVG);
- if(pid < 0){
- perror("mk rfork");
- Exit();
- }
- if(pid == 0){
- if(buf)
- close(out[0]);
- if(pipe(in) < 0){
- perror("pipe");
- Exit();
- }
- pid = fork();
- if(pid < 0){
- perror("mk fork");
- Exit();
- }
- if(pid != 0){
- dup(in[0], 0);
- if(buf){
- dup(out[1], 1);
- close(out[1]);
- }
- close(in[0]);
- close(in[1]);
- if (e)
- exportenv(e);
- if(shflags)
- execl(shell, shellname, shflags, args, nil);
- else
- execl(shell, shellname, args, nil);
- perror(shell);
- _exits("exec");
- }
- if(buf)
- close(out[1]);
- close(in[0]);
- p = cmd+strlen(cmd);
- while(cmd < p){
- n = write(in[1], cmd, p-cmd);
- if(n < 0)
- break;
- cmd += n;
- }
- close(in[1]);
- _exits(0);
- }
+ pid = pipecmd(cmd, args, env, buf? &fd: 0);
if(buf){
- close(out[1]);
tot = 0;
for(;;){
- if (buf->current >= buf->end)
+ if(buf->current >= buf->end)
growbuf(buf);
- n = read(out[0], buf->current, buf->end-buf->current);
+ n = read(fd, buf->current, buf->end-buf->current);
if(n <= 0)
break;
buf->current += n;
tot += n;
}
- if (tot && buf->current[-1] == '\n')
+ if(tot && buf->current[-1] == '\n')
buf->current--;
- close(out[0]);
+ close(fd);
}
return pid;
}
int
-pipecmd(char *cmd, Envy *e, int *fd)
+pipecmd(char *cmd, char *args, Symtab **env, int *fd)
{
int pid, pfd[2];
@@ -254,18 +194,22 @@ pipecmd(char *cmd, Envy *e, int *fd)
dup(pfd[1], 1);
close(pfd[1]);
}
- if(e)
- exportenv(e);
- if(shflags)
- execl(shell, shellname, shflags, "-c", cmd, nil);
+ if(env)
+ exportenv(env);
+ if(args)
+ execl(shell, shellname, args, "-Ic", cmd, nil);
else
- execl(shell, shellname, "-c", cmd, nil);
+ execl(shell, shellname, "-Ic", cmd, nil);
perror(shell);
_exits("exec");
}
if(fd){
+ char name[32];
+
close(pfd[1]);
- *fd = pfd[0];
+ snprint(name, sizeof(name), "/fd/%d", pfd[0]);
+ *fd = open(name, OREAD|OCEXEC);
+ close(pfd[0]);
}
return pid;
}
@@ -301,15 +245,6 @@ catchnotes()
atnotify(notifyf, 1);
}
-char*
-maketmp(void)
-{
- static char temp[] = "/tmp/mkargXXXXXX";
-
- mktemp(temp);
- return temp;
-}
-
int
chgtime(char *name)
{
@@ -335,7 +270,7 @@ rcopy(char **to, Resub *match, int n)
p = match->ep;
c = *p;
*p = 0;
- *to = strdup(match->sp);
+ *to = Strdup(match->sp);
*p = c;
}
else
@@ -344,95 +279,75 @@ rcopy(char **to, Resub *match, int n)
}
void
-dirtime(char *dir, char *path)
+dirtime(char *dir)
{
- int i, fd, n;
- long mtime;
+ int i, fd, n, npath;
+ Bufblock *path;
+ ulong t;
Dir *d;
- char buf[4096];
- fd = open(dir, OREAD);
+ if(symlook(dir, S_BULKED, 0))
+ return;
+ symlook(dir, S_BULKED, 1);
+
+ path = newbuf();
+ bufcpy(path, dir);
+ if(strcmp(dir, ".") == 0)
+ npath = 0;
+ else {
+ insert(path, '/');
+ npath = path->current - path->start;
+ }
+ insert(path, 0);
+ fd = open(path->start, OREAD);
if(fd >= 0){
while((n = dirread(fd, &d)) > 0){
for(i=0; i<n; i++){
- mtime = d[i].mtime;
+ t = d[i].mtime;
/* defensive driving: this does happen */
- if(mtime == 0)
- mtime = 1;
- snprint(buf, sizeof buf, "%s%s", path,
- d[i].name);
- if(symlook(buf, S_TIME, 0) == nil)
- symlook(strdup(buf), S_TIME,
- (void*)mtime)->u.value = mtime;
+ if(t == 0) t = 1;
+ path->current = path->start + npath;
+ bufcpy(path, d[i].name);
+ insert(path, 0);
+ symlook(path->start, S_TIME, 1)->u.value = t;
}
free(d);
}
close(fd);
}
-}
-
-void
-bulkmtime(char *dir)
-{
- char buf[4096];
- char *ss, *s, *sym;
-
- if(dir){
- sym = dir;
- s = dir;
- if(strcmp(dir, "/") == 0)
- strecpy(buf, buf + sizeof buf - 1, dir);
- else
- snprint(buf, sizeof buf, "%s/", dir);
- }else{
- s = ".";
- sym = "";
- buf[0] = 0;
- }
- if(symlook(sym, S_BULKED, 0))
- return;
- ss = strdup(sym);
- symlook(ss, S_BULKED, (void*)ss);
- dirtime(s, buf);
+ freebuf(path);
}
ulong
mkmtime(char *name, int force)
{
- Dir *d;
- char *s, *ss, carry;
+ char *a, *s;
ulong t;
- Symtab *sym;
- char buf[4096];
- strecpy(buf, buf + sizeof buf - 1, name);
- cleanname(buf);
- name = buf;
-
- s = utfrrune(name, '/');
- if(s == name)
- s++;
+ t = 0;
+ /* cleanname() needs at least 2 characters */
+ a = Malloc(strlen(name)+2+1);
+ strcpy(a, name);
+ cleanname(a);
+ s = utfrrune(a, '/');
if(s){
- ss = name;
- carry = *s;
*s = 0;
+ dirtime(a);
+ *s = '/';
}else{
- ss = 0;
- carry = 0;
+ dirtime(".");
}
- bulkmtime(ss);
- if(carry)
- *s = carry;
if(!force){
- sym = symlook(name, S_TIME, 0);
+ Symtab *sym = symlook(a, S_TIME, 0);
if(sym)
- return sym->u.value;
- return 0;
+ t = sym->u.value;
+ } else {
+ Dir *d = dirstat(a);
+ if(d){
+ t = d->mtime;
+ free(d);
+ }
}
- if((d = dirstat(name)) == nil)
- return 0;
- t = d->mtime;
- free(d);
+ free(a);
return t;
}
-
diff --git a/sys/src/cmd/mk/rc.c b/sys/src/cmd/mk/rc.c
index 657ddf278..30856f3bf 100644
--- a/sys/src/cmd/mk/rc.c
+++ b/sys/src/cmd/mk/rc.c
@@ -1,8 +1,6 @@
#include "mk.h"
-char *termchars = "'= \t"; /*used in parse.c to isolate assignment attribute*/
-char *shflags = "-I"; /* rc flag to force non-interactive mode */
-int IWS = '\1'; /* inter-word separator in env - not used in plan 9 */
+char termchars[] = "'= \t"; /*used in parse.c to isolate assignment attribute*/
/*
* This file contains functions that depend on rc's syntax. Most
@@ -173,3 +171,40 @@ copyq(char *s, Rune q, Bufblock *buf)
}
return s;
}
+
+static int
+needquotes(char *s)
+{
+ Rune r;
+
+ if(*s == 0)
+ return 1;
+ while(*s){
+ s += chartorune(&r, s);
+ if(needsrcquote(r))
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * append string s into buffer buf with rc quoting as neccessary.
+ */
+void
+bufcpyq(Bufblock *buf, char *s)
+{
+ Rune r;
+
+ if(!needquotes(s)){
+ bufcpy(buf, s);
+ return;
+ }
+ insert(buf, '\'');
+ while(*s){
+ s += chartorune(&r, s);
+ if(r == '\'')
+ rinsert(buf, r);
+ rinsert(buf, r);
+ }
+ insert(buf, '\'');
+}
diff --git a/sys/src/cmd/mk/recipe.c b/sys/src/cmd/mk/recipe.c
index 93a6f56f2..d88422951 100644
--- a/sys/src/cmd/mk/recipe.c
+++ b/sys/src/cmd/mk/recipe.c
@@ -9,7 +9,7 @@ dorecipe(Node *node)
Node *n;
Rule *r = 0;
Symtab *s;
- Word head, ahead, lp, ln, *w, *ww, *aw;
+ Word *head, *ahead, *lp, *ln, *w, **ww, **aw;
aa = 0;
/*
@@ -45,24 +45,21 @@ dorecipe(Node *node)
build the node list
*/
node->next = 0;
- head.next = 0;
- ww = &head;
- ahead.next = 0;
- aw = &ahead;
+ head = 0, ww = &head;
+ ahead = 0, aw = &ahead;
if(r->attr&REGEXP){
- ww->next = newword(node->name);
- aw->next = newword(node->name);
+ *ww = newword(node->name);
+ *aw = newword(node->name);
} else {
for(w = r->alltargets; w; w = w->next){
if(r->attr&META)
subst(aa->stem, w->s, buf, sizeof(buf));
else
strecpy(buf, buf + sizeof buf - 1, w->s);
- aw->next = newword(buf);
- aw = aw->next;
+ *aw = newword(buf), aw = &(*aw)->next;
if((s = symlook(buf, S_NODE, 0)) == 0)
continue; /* not a node we are interested in */
- n = s->u.ptr;
+ n = (Node*)s->u.ptr;
if(aflag == 0 && n->time) {
for(a = n->prereqs; a; a = a->next)
if(a->n && outofdate(n, a, 0))
@@ -70,8 +67,7 @@ dorecipe(Node *node)
if(a == 0)
continue;
}
- ww->next = newword(buf);
- ww = ww->next;
+ *ww = newword(buf), ww = &(*ww)->next;
if(n == node) continue;
n->next = node->next;
node->next = n;
@@ -83,38 +79,24 @@ dorecipe(Node *node)
/*
gather the params for the job
*/
- lp.next = ln.next = 0;
+ lp = ln = 0;
for(n = node; n; n = n->next){
for(a = n->prereqs; a; a = a->next){
if(a->n){
- addw(&lp, a->n->name);
+ wadd(&lp, a->n->name);
if(outofdate(n, a, 0)){
- addw(&ln, a->n->name);
+ wadd(&ln, a->n->name);
if(explain)
fprint(1, "%s(%ld) < %s(%ld)\n",
n->name, n->time, a->n->name, a->n->time);
}
} else {
if(explain)
- fprint(1, "%s has no prerequisites\n",
- n->name);
+ fprint(1, "%s has no prerequisites\n", n->name);
}
}
MADESET(n, BEINGMADE);
}
-/* print("lt=%s ln=%s lp=%s\n",wtos(head.next, ' '),wtos(ln.next, ' '),wtos(lp.next, ' '));/**/
- run(newjob(r, node, aa->stem, aa->match, lp.next, ln.next, head.next, ahead.next));
+ run(newjob(r, node, aa->stem, aa->match, lp, ln, head, ahead));
return(1);
}
-
-void
-addw(Word *w, char *s)
-{
- Word *lw;
-
- for(lw = w; w = w->next; lw = w){
- if(strcmp(s, w->s) == 0)
- return;
- }
- lw->next = newword(s);
-}
diff --git a/sys/src/cmd/mk/rule.c b/sys/src/cmd/mk/rule.c
index 8d4b493b7..d0562d3af 100644
--- a/sys/src/cmd/mk/rule.c
+++ b/sys/src/cmd/mk/rule.c
@@ -1,48 +1,52 @@
#include "mk.h"
static Rule *lr, *lmr;
-static rcmp(Rule *r, char *target, Word *tail);
static int nrules = 0;
void
-addrule(char *head, Word *tail, char *body, Word *ahead, int attr, int hline, char *prog)
+addrule(char *head, Word *tail, char *body, Word *ahead, int attr, int line, char *prog)
{
- Rule *r;
- Rule *rr;
+ Rule *r, *rr;
Symtab *sym;
int reuse;
r = 0;
reuse = 0;
- if(sym = symlook(head, S_TARGET, 0)){
- for(r = sym->u.ptr; r; r = r->chain)
- if(rcmp(r, head, tail) == 0){
+ sym = symlook(head, S_TARGET, 0);
+ if(sym){
+ for(r = sym->u.ptr; r; r = r->chain){
+ if(wcmp(r->tail, tail) == 0){
reuse = 1;
break;
}
+ }
}
if(r == 0)
r = (Rule *)Malloc(sizeof(Rule));
- r->target = head;
+
r->tail = tail;
r->recipe = body;
- r->line = hline;
- r->file = infile;
+ r->line = line;
+ r->file = mkinfile;
r->attr = attr;
r->alltargets = ahead;
r->prog = prog;
r->rule = nrules++;
if(!reuse){
- rr = symlook(head, S_TARGET, r)->u.ptr;
- if(rr != r){
+ r->next = 0;
+ r->chain = 0;
+ if(sym == 0){
+ sym = symlook(head, S_TARGET, 1);
+ sym->u.ptr = r;
+ } else {
+ rr = sym->u.ptr;
r->chain = rr->chain;
rr->chain = r;
- } else
- r->chain = 0;
+ }
}
- if(!reuse)
- r->next = 0;
+ r->target = sym;
+
if((attr&REGEXP) || charin(head, "%&")){
r->attr |= META;
if(reuse)
@@ -73,30 +77,21 @@ addrule(char *head, Word *tail, char *body, Word *ahead, int attr, int hline, ch
void
dumpr(char *s, Rule *r)
{
+ char *t;
+
Bprint(&bout, "%s: start=%p\n", s, r);
for(; r; r = r->next){
Bprint(&bout, "\tRule %p: %s:%d attr=%x next=%p chain=%p alltarget='%s'",
- r, r->file, r->line, r->attr, r->next, r->chain, wtos(r->alltargets, ' '));
+ r, r->file, r->line, r->attr, r->next, r->chain,
+ t = wtos(r->alltargets)), free(t);
if(r->prog)
Bprint(&bout, " prog='%s'", r->prog);
- Bprint(&bout, "\n\ttarget=%s: %s\n", r->target, wtos(r->tail,' '));
+ Bprint(&bout, "\n\ttarget=%s: %s\n", r->target->name,
+ t = wtos(r->tail)), free(t);
Bprint(&bout, "\trecipe@%p='%s'\n", r->recipe, r->recipe);
}
}
-static int
-rcmp(Rule *r, char *target, Word *tail)
-{
- Word *w;
-
- if(strcmp(r->target, target))
- return 1;
- for(w = r->tail; w && tail; w = w->next, tail = tail->next)
- if(strcmp(w->s, tail->s))
- return 1;
- return(w || tail);
-}
-
char *
rulecnt(void)
{
diff --git a/sys/src/cmd/mk/run.c b/sys/src/cmd/mk/run.c
index c01b519fd..bc5d3c19f 100644
--- a/sys/src/cmd/mk/run.c
+++ b/sys/src/cmd/mk/run.c
@@ -40,12 +40,12 @@ run(Job *j)
static void
sched(void)
{
- char *flags;
- Job *j;
+ char *t, *flags;
Bufblock *buf;
- int slot;
+ Symtab **env;
Node *n;
- Envy *e;
+ Job *j;
+ int slot;
if(jobs == 0){
usage();
@@ -54,14 +54,16 @@ sched(void)
j = jobs;
jobs = j->next;
if(DEBUG(D_EXEC))
- fprint(1, "firing up job for target %s\n", wtos(j->t, ' '));
+ fprint(1, "firing up job for target %s\n",
+ t = wtos(j->t)),
+ free(t);
slot = nextslot();
events[slot].job = j;
buf = newbuf();
- e = buildenv(j, slot);
- shprint(j->r->recipe, e, buf);
+ env = buildenv(j, slot);
+ shprint(j->r->recipe, buf);
if(!tflag && (nflag || !(j->r->attr&QUIET)))
- Bwrite(&bout, buf->start, (long)strlen(buf->start));
+ Bwrite(&bout, buf->start, strlen(buf->start));
freebuf(buf);
if(nflag||tflag){
for(n = j->n; n; n = n->next){
@@ -82,18 +84,19 @@ sched(void)
flags = 0;
else
flags = "-e";
- events[slot].pid = execsh(flags, j->r->recipe, 0, e);
+ events[slot].pid = execsh(j->r->recipe, flags, env, 0);
usage();
nrunning++;
if(DEBUG(D_EXEC))
- fprint(1, "pid for target %s = %d\n", wtos(j->t, ' '), events[slot].pid);
+ fprint(1, "pid for target %s = %d\n",
+ t = wtos(j->t), events[slot].pid),
+ free(t);
}
}
int
waitup(int echildok, int *retstatus)
{
- Envy *e;
int pid;
int slot;
Symtab *s;
@@ -140,13 +143,14 @@ again: /* rogue processes */
goto again;
}
j = events[slot].job;
+ events[slot].job = 0;
+ events[slot].pid = -1;
usage();
nrunning--;
- events[slot].pid = -1;
if(buf[0]){
- e = buildenv(j, slot);
+ buildenv(j, slot);
bp = newbuf();
- shprint(j->r->recipe, e, bp);
+ shprint(j->r->recipe, bp);
front(bp->start);
fprint(2, "mk: %s: exit status=%s", bp->start, buf);
freebuf(bp);
@@ -169,8 +173,9 @@ again: /* rogue processes */
for(w = j->t; w; w = w->next){
if((s = symlook(w->s, S_NODE, 0)) == 0)
continue; /* not interested in this node */
- update(uarg, s->u.ptr);
+ update(uarg, (Node*)s->u.ptr);
}
+ freejob(j);
if(nrunning < nproclimit)
sched();
return(0);
@@ -179,21 +184,17 @@ again: /* rogue processes */
void
nproc(void)
{
- Symtab *sym;
Word *w;
- if(sym = symlook("NPROC", S_VAR, 0)) {
- w = sym->u.ptr;
- if (w && w->s && w->s[0])
- nproclimit = atoi(w->s);
- }
+ if(!empty(w = getvar("NPROC")))
+ nproclimit = atoi(w->s);
if(nproclimit < 1)
nproclimit = 1;
if(DEBUG(D_EXEC))
fprint(1, "nprocs = %d\n", nproclimit);
if(nproclimit > nevents){
if(nevents)
- events = (Event *)Realloc((char *)events, nproclimit*sizeof(Event));
+ events = (Event *)Realloc(events, nproclimit*sizeof(Event));
else
events = (Event *)Malloc(nproclimit*sizeof(Event));
while(nevents < nproclimit)
@@ -281,7 +282,7 @@ usage(void)
long t;
time(&t);
- if(tick)
+ if(tick && nrunning < nelem(tslot))
tslot[nrunning] += (t-tick);
tick = t;
}
@@ -292,6 +293,6 @@ prusage(void)
int i;
usage();
- for(i = 0; i <= nevents; i++)
+ for(i = 0; i <= nevents && i < nelem(tslot); i++)
fprint(1, "%d: %ld\n", i, tslot[i]);
}
diff --git a/sys/src/cmd/mk/shprint.c b/sys/src/cmd/mk/shprint.c
index 1481cf8cc..3807ef50b 100644
--- a/sys/src/cmd/mk/shprint.c
+++ b/sys/src/cmd/mk/shprint.c
@@ -1,9 +1,9 @@
#include "mk.h"
-static char *vexpand(char*, Envy*, Bufblock*);
+static char *vexpand(char*, Bufblock*);
void
-shprint(char *s, Envy *env, Bufblock *buf)
+shprint(char *s, Bufblock *buf)
{
int n;
Rune r;
@@ -11,7 +11,7 @@ shprint(char *s, Envy *env, Bufblock *buf)
while(*s) {
n = chartorune(&r, s);
if (r == '$')
- s = vexpand(s, env, buf);
+ s = vexpand(s, buf);
else {
rinsert(buf, r);
s += n;
@@ -21,25 +21,26 @@ shprint(char *s, Envy *env, Bufblock *buf)
insert(buf, 0);
}
-static char *
-mygetenv(char *name, Envy *env)
+static Symtab*
+mygetenv(char *name)
{
- if (!env)
- return 0;
- if (symlook(name, S_WESET, 0) == 0 && symlook(name, S_INTERNAL, 0) == 0)
- return 0;
- /* only resolve internal variables and variables we've set */
- for(; env->name; env++){
- if (strcmp(env->name, name) == 0)
- return wtos(env->values, ' ');
+ Symtab *s;
+
+ /* only resolve internal variables and variables we've set */
+ s = symlook(name, S_INTERNAL, 0);
+ if(s == 0){
+ s = symlook(name, S_VAR, 0);
+ if(s == 0 || !symlook(name, S_WESET, 0))
+ return 0;
}
- return 0;
+ return s;
}
static char *
-vexpand(char *w, Envy *env, Bufblock *buf)
+vexpand(char *w, Bufblock *buf)
{
- char *s, carry, *p, *q;
+ char carry, *p, *q;
+ Symtab *s;
assert(/*vexpand no $*/ *w == '$');
p = w+1; /* skip dollar sign */
@@ -52,15 +53,14 @@ vexpand(char *w, Envy *env, Bufblock *buf)
q = shname(p);
carry = *q;
*q = 0;
- s = mygetenv(p, env);
+ s = mygetenv(p);
*q = carry;
if (carry == '}')
q++;
- if (s) {
- bufcpy(buf, s, strlen(s));
- free(s);
- } else /* copy name intact*/
- bufcpy(buf, w, q-w);
+ if(s)
+ bufcpyw(buf, s->u.ptr);
+ else /* copy $name intact */
+ bufncpy(buf, w, q-w);
return(q);
}
@@ -71,7 +71,7 @@ front(char *s)
int i, j;
char *flds[512];
- q = strdup(s);
+ q = Strdup(s);
i = getfields(q, flds, nelem(flds), 0, " \t\n");
if(i > 5){
flds[4] = flds[i-1];
diff --git a/sys/src/cmd/mk/symtab.c b/sys/src/cmd/mk/symtab.c
index 0e2a64881..9e4768ee9 100644
--- a/sys/src/cmd/mk/symtab.c
+++ b/sys/src/cmd/mk/symtab.c
@@ -5,7 +5,7 @@
static Symtab *hash[NHASH];
Symtab *
-symlook(char *sym, int space, void *install)
+symlook(char *sym, int space, int install)
{
long h;
char *p;
@@ -17,17 +17,17 @@ symlook(char *sym, int space, void *install)
h = ~h;
h %= NHASH;
for(s = hash[h]; s; s = s->next)
- if((s->space == space) && (strcmp(s->name, sym) == 0))
- return(s);
+ if(s->space == space && strcmp(s->name, sym) == 0)
+ return s;
if(install == 0)
- return(0);
- s = (Symtab *)Malloc(sizeof(Symtab));
+ return 0;
+ s = (Symtab *)Malloc(sizeof(Symtab) + (++p - sym));
s->space = space;
- s->name = sym;
- s->u.ptr = install;
+ s->u.ptr = 0;
+ memcpy(s->name, sym, p - sym);
s->next = hash[h];
hash[h] = s;
- return(s);
+ return s;
}
void
diff --git a/sys/src/cmd/mk/var.c b/sys/src/cmd/mk/var.c
index 94e813f5f..4fdac3d0f 100644
--- a/sys/src/cmd/mk/var.c
+++ b/sys/src/cmd/mk/var.c
@@ -1,10 +1,20 @@
#include "mk.h"
+Word*
+getvar(char *name)
+{
+ Symtab *sym = symlook(name, S_VAR, 0);
+ if(sym)
+ return sym->u.ptr;
+ return 0;
+}
+
void
-setvar(char *name, void *value)
+setvar(char *name, Word *value)
{
- symlook(name, S_VAR, value)->u.ptr = value;
- symlook(name, S_MAKEVAR, (void*)"");
+ Symtab *sym = symlook(name, S_VAR, 1);
+ delword(sym->u.ptr);
+ sym->u.ptr = value;
}
static void
diff --git a/sys/src/cmd/mk/varsub.c b/sys/src/cmd/mk/varsub.c
index aaf9c512b..3ba686785 100644
--- a/sys/src/cmd/mk/varsub.c
+++ b/sys/src/cmd/mk/varsub.c
@@ -5,7 +5,6 @@ static Word *expandvar(char**);
static Bufblock *varname(char**);
static Word *extractpat(char*, char**, char*, char*);
static int submatch(char*, Word*, Word*, int*, char**);
-static Word *varmatch(char *);
Word *
varsub(char **s)
@@ -15,14 +14,12 @@ varsub(char **s)
if(**s == '{') /* either ${name} or ${name: A%B==C%D}*/
return expandvar(s);
-
b = varname(s);
if(b == 0)
return 0;
-
- w = varmatch(b->start);
+ w = getvar(b->start);
freebuf(b);
- return w;
+ return wdup(w);
}
/*
@@ -45,7 +42,7 @@ varname(char **s)
rinsert(b, r);
cp += n;
}
- if (b->current == b->start){
+ if(b->current == b->start){
SYNERR(-1);
fprint(2, "missing variable name <%s>\n", *s);
freebuf(b);
@@ -57,49 +54,32 @@ varname(char **s)
}
static Word*
-varmatch(char *name)
-{
- Word *w;
- Symtab *sym;
-
- sym = symlook(name, S_VAR, 0);
- if(sym){
- /* check for at least one non-NULL value */
- for (w = sym->u.ptr; w; w = w->next)
- if(w->s && *w->s)
- return wdup(w);
- }
- return 0;
-}
-
-static Word*
expandvar(char **s)
{
Word *w;
Bufblock *buf;
- Symtab *sym;
char *cp, *begin, *end;
begin = *s;
(*s)++; /* skip the '{' */
buf = varname(s);
- if (buf == 0)
+ if(buf == 0)
return 0;
cp = *s;
- if (*cp == '}') { /* ${name} variant*/
+ if(*cp == '}') { /* ${name} variant*/
(*s)++; /* skip the '}' */
- w = varmatch(buf->start);
+ w = getvar(buf->start);
freebuf(buf);
- return w;
+ return wdup(w);
}
- if (*cp != ':') {
+ if(*cp != ':') {
SYNERR(-1);
fprint(2, "bad variable name <%s>\n", buf->start);
freebuf(buf);
return 0;
}
cp++;
- end = charin(cp , "}");
+ end = charin(cp, "}");
if(end == 0){
SYNERR(-1);
fprint(2, "missing '}': %s\n", begin);
@@ -107,21 +87,17 @@ expandvar(char **s)
}
*end = 0;
*s = end+1;
-
- sym = symlook(buf->start, S_VAR, 0);
- if(sym == 0 || sym->u.value == 0)
- w = newword(buf->start);
- else
- w = subsub(sym->u.ptr, cp, end);
+ w = getvar(buf->start);
freebuf(buf);
+ if(w)
+ w = subsub(w, cp, end);
return w;
}
static Word*
extractpat(char *s, char **r, char *term, char *end)
{
- int save;
- char *cp;
+ char save, *cp;
Word *w;
cp = charin(s, term);
@@ -144,7 +120,7 @@ static Word*
subsub(Word *v, char *s, char *end)
{
int nmid;
- Word *head, *tail, *w, *h;
+ Word *head, *tail, *w, *h, **l;
Word *a, *b, *c, *d;
Bufblock *buf;
char *cp, *enda;
@@ -164,47 +140,52 @@ subsub(Word *v, char *s, char *end)
buf = newbuf();
for(; v; v = v->next){
h = w = 0;
+ l = &h;
if(submatch(v->s, a, b, &nmid, &enda)){
/* enda points to end of A match in source;
* nmid = number of chars between end of A and start of B
*/
if(c){
- h = w = wdup(c);
- while(w->next)
+ *l = w = wdup(c);
+ while(w->next){
+ l = &w->next;
w = w->next;
+ }
}
if(PERCENT(*cp) && nmid > 0){
if(w){
- bufcpy(buf, w->s, strlen(w->s));
- bufcpy(buf, enda, nmid);
+ bufcpy(buf, w->s);
+ bufncpy(buf, enda, nmid);
insert(buf, 0);
- free(w->s);
- w->s = strdup(buf->start);
+ delword(w);
+ *l = w = newword(buf->start);
} else {
- bufcpy(buf, enda, nmid);
+ bufncpy(buf, enda, nmid);
insert(buf, 0);
- h = w = newword(buf->start);
+ *l = w = newword(buf->start);
}
buf->current = buf->start;
}
- if(d && *d->s){
+ if(!empty(d)){
if(w){
-
- bufcpy(buf, w->s, strlen(w->s));
- bufcpy(buf, d->s, strlen(d->s));
+ bufcpy(buf, w->s);
+ bufcpy(buf, d->s);
insert(buf, 0);
- free(w->s);
- w->s = strdup(buf->start);
+ delword(w);
+ *l = w = newword(buf->start);
w->next = wdup(d->next);
- while(w->next)
- w = w->next;
buf->current = buf->start;
- } else
- h = w = wdup(d);
+ } else {
+ *l = w = wdup(d);
+ }
+ while(w->next){
+ l = &w->next;
+ w = w->next;
+ }
}
}
if(w == 0)
- h = w = newword(v->s);
+ *l = w = newword(v->s);
if(head == 0)
head = h;
@@ -223,9 +204,9 @@ subsub(Word *v, char *s, char *end)
static int
submatch(char *s, Word *a, Word *b, int *nmid, char **enda)
{
+ char *end;
Word *w;
int n;
- char *end;
n = 0;
for(w = a; w; w = w->next){
diff --git a/sys/src/cmd/mk/word.c b/sys/src/cmd/mk/word.c
index ac92cacaf..760490258 100644
--- a/sys/src/cmd/mk/word.c
+++ b/sys/src/cmd/mk/word.c
@@ -5,85 +5,109 @@ static Word *nextword(char**);
Word*
newword(char *s)
{
- Word *w;
-
- w = (Word *)Malloc(sizeof(Word));
- w->s = strdup(s);
+ int n = strlen(s)+1;
+ Word *w = (Word *)Malloc(sizeof(Word) + n);
+ memcpy(w->s, s, n);
w->next = 0;
- return(w);
+ return w;
+}
+
+Word*
+popword(Word *w)
+{
+ Word *x = w->next;
+ free(w);
+ return x;
}
Word *
stow(char *s)
{
- Word *head, *w, *new;
+ Word *w, *h, **l;
- w = head = 0;
- while(*s){
- new = nextword(&s);
- if(new == 0)
- break;
- if (w)
- w->next = new;
- else
- head = w = new;
+ h = 0;
+ l = &h;
+ while(*s && (*l = w = nextword(&s))){
while(w->next)
w = w->next;
-
+ l = &w->next;
}
- if (!head)
- head = newword("");
- return(head);
+ return h;
}
char *
-wtos(Word *w, int sep)
+wtos(Word *w)
{
Bufblock *buf;
- char *cp;
+ char *s;
buf = newbuf();
+ bufcpyw(buf, w);
+ insert(buf, 0);
+ s = Strdup(buf->start);
+ freebuf(buf);
+ return s;
+}
+
+void
+bufcpyw(Bufblock *buf, Word *w)
+{
for(; w; w = w->next){
- for(cp = w->s; *cp; cp++)
- insert(buf, *cp);
+ bufcpyq(buf, w->s);
if(w->next)
- insert(buf, sep);
+ insert(buf, ' ');
}
- insert(buf, 0);
- cp = strdup(buf->start);
- freebuf(buf);
- return(cp);
+}
+
+int
+empty(Word *w)
+{
+ return w == 0 || w->s[0] == 0;
+}
+
+int
+wadd(Word **l, char *s)
+{
+ Word *w;
+
+ while(w = *l){
+ if(strcmp(w->s, s) == 0)
+ return 1;
+ l = &w->next;
+ }
+ *l = newword(s);
+ return 0;
+}
+
+int
+wcmp(Word *a, Word *b)
+{
+ for(; a && b; a = a->next, b = b->next)
+ if(strcmp(a->s, b->s))
+ return 1;
+ return(a || b);
}
Word*
wdup(Word *w)
{
- Word *v, *new, *base;
+ Word *h, **l;
- v = base = 0;
+ h = 0;
+ l = &h;
while(w){
- new = newword(w->s);
- if(v)
- v->next = new;
- else
- base = new;
- v = new;
+ *l = newword(w->s);
+ l = &(*l)->next;
w = w->next;
}
- return base;
+ return h;
}
void
delword(Word *w)
{
- Word *v;
-
- while(v = w){
- w = w->next;
- if(v->s)
- free(v->s);
- free(v);
- }
+ while(w)
+ w = popword(w);
}
/*
@@ -93,19 +117,20 @@ delword(Word *w)
static Word*
nextword(char **s)
{
+ Word *head, *tail, **link, *w, *t;
Bufblock *b;
- Word *head, *tail, *w;
- Rune r;
- char *cp;
int empty;
+ char *cp;
+ Rune r;
cp = *s;
b = newbuf();
-restart:
+ empty = 1;
head = tail = 0;
+ link = &head;
+restart:
while(*cp == ' ' || *cp == '\t') /* leading white space */
cp++;
- empty = 1;
while(*cp){
cp += chartorune(&r, cp);
switch(r)
@@ -117,12 +142,12 @@ restart:
case '\\':
case '\'':
case '"':
- empty = 0;
cp = expandquote(cp, r, b);
if(cp == 0){
fprint(2, "missing closing quote: %s\n", *s);
Exit();
}
+ empty = 0;
break;
case '$':
w = varsub(&cp);
@@ -133,47 +158,48 @@ restart:
}
empty = 0;
if(b->current != b->start){
- bufcpy(b, w->s, strlen(w->s));
+ bufcpy(b, w->s);
insert(b, 0);
- free(w->s);
- w->s = strdup(b->start);
+ t = popword(w);
+ w = newword(b->start);
+ w->next = t;
b->current = b->start;
}
- if(head){
- bufcpy(b, tail->s, strlen(tail->s));
- bufcpy(b, w->s, strlen(w->s));
+ if(tail){
+ bufcpy(b, tail->s);
+ bufcpy(b, w->s);
insert(b, 0);
- free(tail->s);
- tail->s = strdup(b->start);
- tail->next = w->next;
- free(w->s);
- free(w);
+ delword(tail);
+ *link = tail = newword(b->start);
+ tail->next = popword(w);
b->current = b->start;
} else
- tail = head = w;
- while(tail->next)
+ *link = tail = w;
+ while(tail->next){
+ link = &tail->next;
tail = tail->next;
+ }
break;
default:
- empty = 0;
rinsert(b, r);
break;
}
}
out:
*s = cp;
- if(b->current != b->start){
- if(head){
- cp = b->current;
- bufcpy(b, tail->s, strlen(tail->s));
- bufcpy(b, b->start, cp-b->start);
+ if(b->current != b->start || !empty){
+ insert(b, 0);
+ if(tail){
+ cp = Strdup(b->start);
+ b->current = b->start;
+ bufcpy(b, tail->s);
+ bufcpy(b, cp);
+ free(cp);
insert(b, 0);
- free(tail->s);
- tail->s = strdup(cp);
- } else {
- insert(b, 0);
- head = newword(b->start);
- }
+ delword(tail);
+ *link = newword(b->start);
+ } else
+ *link = newword(b->start);
}
freebuf(b);
return head;