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:
cinap_lenrek 2023-12-28 18:10:41 +00:00
parent 6b0150764c
commit 94b1d3f0ad
23 changed files with 754 additions and 826 deletions

View file

@ -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))

View file

@ -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;
}

View file

@ -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;

View file

@ -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&REGEXP)
@ -109,10 +103,10 @@ buildenv(Job *j, int slot)
else
envupd("stem", newword(j->stem));
envupd("prereq", wdup(j->p));
snprint(buf, sizeof buf, "%d", getpid());
envupd("pid", newword(buf));
snprint(buf, sizeof buf, "%d", slot);
envupd("nproc", newword(buf));
snprint(num, sizeof num, "%d", getpid());
envupd("pid", newword(num));
snprint(num, sizeof num, "%d", slot);
envupd("nproc", newword(num));
envupd("newprereq", wdup(j->np));
envupd("alltarget", wdup(j->at));
l = &v;
@ -129,10 +123,7 @@ buildenv(Job *j, int slot)
continue;
}
}
*l = w->next;
free(w->s);
free(w);
w = *l;
*l = w = popword(w);
}
envupd("newmember", v);
/* update stem0 -> stem9 */

View file

@ -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){

View file

@ -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*);

View file

@ -41,7 +41,6 @@ applyrules(char *target, char *cnt)
sym = symlook(target, S_NODE, 0);
if(sym)
return sym->u.ptr;
target = strdup(target);
node = newnode(target);
head.n = 0;
head.next = 0;
@ -49,8 +48,7 @@ applyrules(char *target, char *cnt)
memset((char*)rmatch, 0, sizeof(rmatch));
for(r = sym? sym->u.ptr:0; r; r = r->chain){
if(r->attr&META) continue;
if(strcmp(target, r->target)) continue;
if((!r->recipe || !*r->recipe) && (!r->tail || !r->tail->s || !*r->tail->s)) continue; /* no effect; ignore */
if((!r->recipe || !*r->recipe) && empty(r->tail)) continue; /* no effect; ignore */
if(cnt[r->rule] >= nreps) continue;
cnt[r->rule]++;
node->flags |= PROBABLE;
@ -62,19 +60,20 @@ applyrules(char *target, char *cnt)
* if(r->attr&DEL)
* node->flags |= DELETE;
*/
if(!r->tail || !r->tail->s || !*r->tail->s) {
if(empty(r->tail)) {
a->next = newarc((Node *)0, r, "", rmatch);
a = a->next;
} else
} else {
for(w = r->tail; w; w = w->next){
a->next = newarc(applyrules(w->s, cnt), r, "", rmatch);
a = a->next;
}
}
cnt[r->rule]--;
head.n = node;
}
for(r = metarules; r; r = r->next){
if((!r->recipe || !*r->recipe) && (!r->tail || !r->tail->s || !*r->tail->s)) continue; /* no effect; ignore */
if((!r->recipe || !*r->recipe) && empty(r->tail)) continue; /* no effect; ignore */
if ((r->attr&NOVIRT) && a != &head && (a->r->attr&VIR))
continue;
if(r->attr&REGEXP){
@ -84,7 +83,7 @@ applyrules(char *target, char *cnt)
if(regexec(r->pat, node->name, rmatch, NREGEXP) == 0)
continue;
} else {
if(!match(node->name, r->target, stem)) continue;
if(!match(node->name, r->target->name, stem)) continue;
}
if(cnt[r->rule] >= nreps) continue;
cnt[r->rule]++;
@ -96,7 +95,7 @@ applyrules(char *target, char *cnt)
* if(r->attr&DEL)
* node->flags |= DELETE;
*/
if(!r->tail || !r->tail->s || !*r->tail->s) {
if(empty(r->tail)){
a->next = newarc((Node *)0, r, stem, rmatch);
a = a->next;
} else
@ -118,20 +117,20 @@ applyrules(char *target, char *cnt)
static void
togo(Node *node)
{
Arc *la, *a;
Arc **l, *a;
/* delete them now */
la = 0;
for(a = node->prereqs; a; la = a, a = a->next)
l = &node->prereqs;
while(a = *l){
if(a->flag&TOGO){
if(a == node->prereqs)
node->prereqs = a->next;
else
la->next = a->next, a = la;
}
*l = a->next;
freearc(a);
} else
l = &a->next;
}
}
static
static int
vacuous(Node *node)
{
Arc *la, *a;
@ -149,9 +148,8 @@ vacuous(Node *node)
for(a = node->prereqs; a; a = a->next)
if((a->flag&TOGO) == 0)
for(la = node->prereqs; la; la = la->next)
if((la->flag&TOGO) && (la->r == a->r)){
if((la->flag&TOGO) && (la->r == a->r))
la->flag &= ~TOGO;
}
togo(node);
if(vac)
node->flags |= VACUOUS;
@ -161,15 +159,17 @@ vacuous(Node *node)
static Node *
newnode(char *name)
{
register Node *node;
Symtab *sym;
Node *node;
sym = symlook(name, S_NODE, 1);
node = (Node *)Malloc(sizeof(Node));
symlook(name, S_NODE, (void *)node);
node->name = name;
node->name = sym->name;
node->time = timeof(name, 0);
node->prereqs = 0;
node->flags = node->time? PROBABLE : 0;
node->next = 0;
sym->u.ptr = node;
return(node);
}

View file

@ -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;
}
}

View file

@ -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')

View file

@ -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();
}

View file

@ -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;

View file

@ -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

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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, '\'');
}

View file

@ -9,7 +9,7 @@ dorecipe(Node *node)
Node *n;
Rule *r = 0;
Symtab *s;
Word head, ahead, lp, ln, *w, *ww, *aw;
Word *head, *ahead, *lp, *ln, *w, **ww, **aw;
aa = 0;
/*
@ -45,24 +45,21 @@ dorecipe(Node *node)
build the node list
*/
node->next = 0;
head.next = 0;
ww = &head;
ahead.next = 0;
aw = &ahead;
head = 0, ww = &head;
ahead = 0, aw = &ahead;
if(r->attr&REGEXP){
ww->next = newword(node->name);
aw->next = newword(node->name);
*ww = newword(node->name);
*aw = newword(node->name);
} else {
for(w = r->alltargets; w; w = w->next){
if(r->attr&META)
subst(aa->stem, w->s, buf, sizeof(buf));
else
strecpy(buf, buf + sizeof buf - 1, w->s);
aw->next = newword(buf);
aw = aw->next;
*aw = newword(buf), aw = &(*aw)->next;
if((s = symlook(buf, S_NODE, 0)) == 0)
continue; /* not a node we are interested in */
n = s->u.ptr;
n = (Node*)s->u.ptr;
if(aflag == 0 && n->time) {
for(a = n->prereqs; a; a = a->next)
if(a->n && outofdate(n, a, 0))
@ -70,8 +67,7 @@ dorecipe(Node *node)
if(a == 0)
continue;
}
ww->next = newword(buf);
ww = ww->next;
*ww = newword(buf), ww = &(*ww)->next;
if(n == node) continue;
n->next = node->next;
node->next = n;
@ -83,38 +79,24 @@ dorecipe(Node *node)
/*
gather the params for the job
*/
lp.next = ln.next = 0;
lp = ln = 0;
for(n = node; n; n = n->next){
for(a = n->prereqs; a; a = a->next){
if(a->n){
addw(&lp, a->n->name);
wadd(&lp, a->n->name);
if(outofdate(n, a, 0)){
addw(&ln, a->n->name);
wadd(&ln, a->n->name);
if(explain)
fprint(1, "%s(%ld) < %s(%ld)\n",
n->name, n->time, a->n->name, a->n->time);
}
} else {
if(explain)
fprint(1, "%s has no prerequisites\n",
n->name);
fprint(1, "%s has no prerequisites\n", n->name);
}
}
MADESET(n, BEINGMADE);
}
/* print("lt=%s ln=%s lp=%s\n",wtos(head.next, ' '),wtos(ln.next, ' '),wtos(lp.next, ' '));/**/
run(newjob(r, node, aa->stem, aa->match, lp.next, ln.next, head.next, ahead.next));
run(newjob(r, node, aa->stem, aa->match, lp, ln, head, ahead));
return(1);
}
void
addw(Word *w, char *s)
{
Word *lw;
for(lw = w; w = w->next; lw = w){
if(strcmp(s, w->s) == 0)
return;
}
lw->next = newword(s);
}

View file

@ -1,48 +1,52 @@
#include "mk.h"
static Rule *lr, *lmr;
static rcmp(Rule *r, char *target, Word *tail);
static int nrules = 0;
void
addrule(char *head, Word *tail, char *body, Word *ahead, int attr, int hline, char *prog)
addrule(char *head, Word *tail, char *body, Word *ahead, int attr, int line, char *prog)
{
Rule *r;
Rule *rr;
Rule *r, *rr;
Symtab *sym;
int reuse;
r = 0;
reuse = 0;
if(sym = symlook(head, S_TARGET, 0)){
for(r = sym->u.ptr; r; r = r->chain)
if(rcmp(r, head, tail) == 0){
sym = symlook(head, S_TARGET, 0);
if(sym){
for(r = sym->u.ptr; r; r = r->chain){
if(wcmp(r->tail, tail) == 0){
reuse = 1;
break;
}
}
}
if(r == 0)
r = (Rule *)Malloc(sizeof(Rule));
r->target = head;
r->tail = tail;
r->recipe = body;
r->line = hline;
r->file = infile;
r->line = line;
r->file = mkinfile;
r->attr = attr;
r->alltargets = ahead;
r->prog = prog;
r->rule = nrules++;
if(!reuse){
rr = symlook(head, S_TARGET, r)->u.ptr;
if(rr != r){
r->next = 0;
r->chain = 0;
if(sym == 0){
sym = symlook(head, S_TARGET, 1);
sym->u.ptr = r;
} else {
rr = sym->u.ptr;
r->chain = rr->chain;
rr->chain = r;
} else
r->chain = 0;
}
}
if(!reuse)
r->next = 0;
r->target = sym;
if((attr&REGEXP) || charin(head, "%&")){
r->attr |= META;
if(reuse)
@ -73,30 +77,21 @@ addrule(char *head, Word *tail, char *body, Word *ahead, int attr, int hline, ch
void
dumpr(char *s, Rule *r)
{
char *t;
Bprint(&bout, "%s: start=%p\n", s, r);
for(; r; r = r->next){
Bprint(&bout, "\tRule %p: %s:%d attr=%x next=%p chain=%p alltarget='%s'",
r, r->file, r->line, r->attr, r->next, r->chain, wtos(r->alltargets, ' '));
r, r->file, r->line, r->attr, r->next, r->chain,
t = wtos(r->alltargets)), free(t);
if(r->prog)
Bprint(&bout, " prog='%s'", r->prog);
Bprint(&bout, "\n\ttarget=%s: %s\n", r->target, wtos(r->tail,' '));
Bprint(&bout, "\n\ttarget=%s: %s\n", r->target->name,
t = wtos(r->tail)), free(t);
Bprint(&bout, "\trecipe@%p='%s'\n", r->recipe, r->recipe);
}
}
static int
rcmp(Rule *r, char *target, Word *tail)
{
Word *w;
if(strcmp(r->target, target))
return 1;
for(w = r->tail; w && tail; w = w->next, tail = tail->next)
if(strcmp(w->s, tail->s))
return 1;
return(w || tail);
}
char *
rulecnt(void)
{

View file

@ -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]);
}

View file

@ -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];

View file

@ -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

View file

@ -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

View file

@ -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){

View file

@ -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;