mirror of
git://git.9front.org/plan9front/plan9front
synced 2025-01-12 11:10:06 +00:00
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).
This commit is contained in:
parent
6b0150764c
commit
94b1d3f0ad
23 changed files with 754 additions and 826 deletions
|
@ -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;
|
||||
|
@ -16,6 +16,13 @@ newarc(Node *n, Rule *r, char *stem, Resub *match)
|
|||
return(a);
|
||||
}
|
||||
|
||||
void
|
||||
freearc(Arc *a)
|
||||
{
|
||||
free(a->stem);
|
||||
free(a);
|
||||
}
|
||||
|
||||
void
|
||||
dumpa(char *s, Arc *a)
|
||||
{
|
||||
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
static int envsize;
|
||||
|
||||
if (nextv >= envsize) {
|
||||
envsize += ENVQUANTA;
|
||||
envy = (Envy *) Realloc((char *) envy, envsize*sizeof(Envy));
|
||||
}
|
||||
envy[nextv].name = name;
|
||||
envy[nextv++].values = value;
|
||||
}
|
||||
|
||||
static void
|
||||
envupd(char *name, Word *value)
|
||||
{
|
||||
Envy *e;
|
||||
Symtab *sym = symlook(name, S_INTERNAL, 0);
|
||||
assert(sym != 0);
|
||||
delword(sym->u.ptr);
|
||||
sym->u.ptr = value;
|
||||
}
|
||||
|
||||
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);
|
||||
static void
|
||||
envinsert(Symtab *sym)
|
||||
{
|
||||
static int envsize;
|
||||
|
||||
if (nextv >= envsize) {
|
||||
envsize += ENVQUANTA;
|
||||
envy = (Symtab **) Realloc(envy, envsize*sizeof(Symtab*));
|
||||
}
|
||||
envy[nextv++] = sym;
|
||||
}
|
||||
|
||||
static void
|
||||
ereset(Symtab *s)
|
||||
{
|
||||
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 */
|
||||
|
|
|
@ -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){
|
||||
|
|
|
@ -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*);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
@ -19,15 +19,29 @@ newjob(Rule *r, Node *nlist, char *stem, char **match, Word *pre, Word *npre, Wo
|
|||
return(j);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
extern char termchars[];
|
||||
extern char shell[];
|
||||
extern char shellname[];
|
||||
|
||||
#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))
|
||||
#define SYNERR(l) (fprint(2, "mk: %s:%d: syntax error; ", mkinfile, ((l)>=0)?(l):mkinline))
|
||||
#define NAMEBLOCK 1000
|
||||
#define BIGBLOCK 20000
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
Word *head, **link;
|
||||
int m;
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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, '\'');
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,10 +1,20 @@
|
|||
#include "mk.h"
|
||||
|
||||
void
|
||||
setvar(char *name, void *value)
|
||||
Word*
|
||||
getvar(char *name)
|
||||
{
|
||||
symlook(name, S_VAR, value)->u.ptr = value;
|
||||
symlook(name, S_MAKEVAR, (void*)"");
|
||||
Symtab *sym = symlook(name, S_VAR, 0);
|
||||
if(sym)
|
||||
return sym->u.ptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
setvar(char *name, Word *value)
|
||||
{
|
||||
Symtab *sym = symlook(name, S_VAR, 1);
|
||||
delword(sym->u.ptr);
|
||||
sym->u.ptr = value;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -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);
|
||||
|
@ -56,50 +53,33 @@ varname(char **s)
|
|||
return b;
|
||||
}
|
||||
|
||||
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){
|
||||
|
|
|
@ -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();
|
||||
for(; w; w = w->next){
|
||||
for(cp = w->s; *cp; cp++)
|
||||
insert(buf, *cp);
|
||||
if(w->next)
|
||||
insert(buf, sep);
|
||||
}
|
||||
bufcpyw(buf, w);
|
||||
insert(buf, 0);
|
||||
cp = strdup(buf->start);
|
||||
s = Strdup(buf->start);
|
||||
freebuf(buf);
|
||||
return(cp);
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
bufcpyw(Bufblock *buf, Word *w)
|
||||
{
|
||||
for(; w; w = w->next){
|
||||
bufcpyq(buf, w->s);
|
||||
if(w->next)
|
||||
insert(buf, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
Loading…
Reference in a new issue