diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2023-12-28 18:10:41 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2023-12-28 18:10:41 +0000 |
commit | 94b1d3f0ad587b6e507ff872eb8562466e3af21a (patch) | |
tree | 9815cba818e688481fcb60a08244f8c20d1f56ea | |
parent | 6b0150764cc579c3764e6ed2a6db1237f11577de (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.c | 18 | ||||
-rw-r--r-- | sys/src/cmd/mk/archive.c | 12 | ||||
-rw-r--r-- | sys/src/cmd/mk/bufblock.c | 15 | ||||
-rw-r--r-- | sys/src/cmd/mk/env.c | 75 | ||||
-rw-r--r-- | sys/src/cmd/mk/file.c | 6 | ||||
-rw-r--r-- | sys/src/cmd/mk/fns.h | 36 | ||||
-rw-r--r-- | sys/src/cmd/mk/graph.c | 44 | ||||
-rw-r--r-- | sys/src/cmd/mk/job.c | 20 | ||||
-rw-r--r-- | sys/src/cmd/mk/lex.c | 3 | ||||
-rw-r--r-- | sys/src/cmd/mk/main.c | 164 | ||||
-rw-r--r-- | sys/src/cmd/mk/mk.c | 39 | ||||
-rw-r--r-- | sys/src/cmd/mk/mk.h | 77 | ||||
-rw-r--r-- | sys/src/cmd/mk/parse.c | 172 | ||||
-rw-r--r-- | sys/src/cmd/mk/plan9.c | 341 | ||||
-rw-r--r-- | sys/src/cmd/mk/rc.c | 41 | ||||
-rw-r--r-- | sys/src/cmd/mk/recipe.c | 44 | ||||
-rw-r--r-- | sys/src/cmd/mk/rule.c | 57 | ||||
-rw-r--r-- | sys/src/cmd/mk/run.c | 49 | ||||
-rw-r--r-- | sys/src/cmd/mk/shprint.c | 46 | ||||
-rw-r--r-- | sys/src/cmd/mk/symtab.c | 16 | ||||
-rw-r--r-- | sys/src/cmd/mk/var.c | 16 | ||||
-rw-r--r-- | sys/src/cmd/mk/varsub.c | 97 | ||||
-rw-r--r-- | sys/src/cmd/mk/word.c | 178 |
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®EXP) @@ -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®EXP){ @@ -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®EXP){ - 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®EXP) || 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; |