rc: fix slow Xqdol(), avoid recursion in conclist(), estrdup(), avoid copying
Xqdol() used to take quadratic time because of strcat(), the code isnt really needed as list2str() aready does the same thing in linear time without the strcat(). add estrdup() which uses emalloc() so allocation error are catched. move strdups() of name from callers into newvar(). avoid recursion of conclist(), and avoid copying of word strings by providing Newword() function which doesnt copy the word string.
This commit is contained in:
parent
2bdd2663db
commit
a2f7d03d4e
11 changed files with 64 additions and 53 deletions
|
@ -56,7 +56,7 @@ void
|
||||||
cleanhere(char *f)
|
cleanhere(char *f)
|
||||||
{
|
{
|
||||||
emitf(Xdelhere);
|
emitf(Xdelhere);
|
||||||
emits(strdup(f));
|
emits(estrdup(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
char*
|
char*
|
||||||
|
@ -258,7 +258,7 @@ outcode(tree *t, int eflag)
|
||||||
else{
|
else{
|
||||||
emitf(Xmark);
|
emitf(Xmark);
|
||||||
emitf(Xword);
|
emitf(Xword);
|
||||||
emits(strdup("*"));
|
emits(estrdup("*"));
|
||||||
emitf(Xdol);
|
emitf(Xdol);
|
||||||
}
|
}
|
||||||
emitf(Xmark); /* dummy value for Xlocal */
|
emitf(Xmark); /* dummy value for Xlocal */
|
||||||
|
@ -275,7 +275,7 @@ outcode(tree *t, int eflag)
|
||||||
break;
|
break;
|
||||||
case WORD:
|
case WORD:
|
||||||
emitf(Xword);
|
emitf(Xword);
|
||||||
emits(strdup(t->str));
|
emits(estrdup(t->str));
|
||||||
break;
|
break;
|
||||||
case DUP:
|
case DUP:
|
||||||
if(t->rtype==DUPFD){
|
if(t->rtype==DUPFD){
|
||||||
|
|
|
@ -28,20 +28,30 @@ start(code *c, int pc, var *local)
|
||||||
}
|
}
|
||||||
|
|
||||||
word*
|
word*
|
||||||
newword(char *wd, word *next)
|
Newword(char *wd, word *next)
|
||||||
{
|
{
|
||||||
word *p = new(word);
|
word *p = new(word);
|
||||||
p->word = strdup(wd);
|
p->word = wd;
|
||||||
p->next = next;
|
p->next = next;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pushword(char *wd)
|
Pushword(char *wd)
|
||||||
{
|
{
|
||||||
if(runq->argv==0)
|
if(runq->argv==0)
|
||||||
panic("pushword but no argv!", 0);
|
panic("pushword but no argv!", 0);
|
||||||
runq->argv->words = newword(wd, runq->argv->words);
|
runq->argv->words = Newword(wd, runq->argv->words);
|
||||||
|
}
|
||||||
|
|
||||||
|
word*
|
||||||
|
newword(char *wd, word *next)
|
||||||
|
{
|
||||||
|
return Newword(estrdup(wd), next);
|
||||||
|
}
|
||||||
|
void
|
||||||
|
pushword(char *wd)
|
||||||
|
{
|
||||||
|
Pushword(estrdup(wd));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -113,7 +123,7 @@ var*
|
||||||
newvar(char *name, var *next)
|
newvar(char *name, var *next)
|
||||||
{
|
{
|
||||||
var *v = new(var);
|
var *v = new(var);
|
||||||
v->name = name;
|
v->name = estrdup(name);
|
||||||
v->val = 0;
|
v->val = 0;
|
||||||
v->fn = 0;
|
v->fn = 0;
|
||||||
v->changed = 0;
|
v->changed = 0;
|
||||||
|
@ -174,7 +184,7 @@ main(int argc, char *argv[])
|
||||||
start(bootstrap, 1, (var *)0);
|
start(bootstrap, 1, (var *)0);
|
||||||
/* prime bootstrap argv */
|
/* prime bootstrap argv */
|
||||||
pushlist();
|
pushlist();
|
||||||
argv0 = strdup(argv[0]);
|
argv0 = estrdup(argv[0]);
|
||||||
for(i = argc-1;i!=0;--i) pushword(argv[i]);
|
for(i = argc-1;i!=0;--i) pushword(argv[i]);
|
||||||
for(;;){
|
for(;;){
|
||||||
if(flag['r'])
|
if(flag['r'])
|
||||||
|
@ -304,7 +314,7 @@ Xexit(void)
|
||||||
--runq->pc;
|
--runq->pc;
|
||||||
starval = vlook("*")->val;
|
starval = vlook("*")->val;
|
||||||
start(trapreq->fn, trapreq->pc, (struct var *)0);
|
start(trapreq->fn, trapreq->pc, (struct var *)0);
|
||||||
runq->local = newvar(strdup("*"), runq->local);
|
runq->local = newvar("*", runq->local);
|
||||||
runq->local->val = copywords(starval, (struct word *)0);
|
runq->local->val = copywords(starval, (struct word *)0);
|
||||||
runq->local->changed = 1;
|
runq->local->changed = 1;
|
||||||
runq->redir = runq->startredir = 0;
|
runq->redir = runq->startredir = 0;
|
||||||
|
@ -548,16 +558,21 @@ Xcase(void)
|
||||||
word*
|
word*
|
||||||
conclist(word *lp, word *rp, word *tail)
|
conclist(word *lp, word *rp, word *tail)
|
||||||
{
|
{
|
||||||
char *buf;
|
word *v, *p, **end;
|
||||||
word *v;
|
int ln, rn;
|
||||||
if(lp->next || rp->next)
|
|
||||||
tail = conclist(lp->next==0? lp: lp->next,
|
for(end = &v;;){
|
||||||
rp->next==0? rp: rp->next, tail);
|
ln = strlen(lp->word), rn = strlen(rp->word);
|
||||||
buf = emalloc(strlen(lp->word)+strlen((char *)rp->word)+1);
|
p = Newword(emalloc(ln+rn+1), (word *)0);
|
||||||
strcpy(buf, lp->word);
|
Memcpy(p->word, lp->word, ln);
|
||||||
strcat(buf, rp->word);
|
Memcpy(p->word+ln, rp->word, rn+1);
|
||||||
v = newword(buf, tail);
|
*end = p, end = &p->next;
|
||||||
efree(buf);
|
if(lp->next == 0 && rp->next == 0)
|
||||||
|
break;
|
||||||
|
if(lp->next) lp = lp->next;
|
||||||
|
if(rp->next) rp = rp->next;
|
||||||
|
}
|
||||||
|
*end = tail;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -647,9 +662,8 @@ Xdol(void)
|
||||||
void
|
void
|
||||||
Xqdol(void)
|
Xqdol(void)
|
||||||
{
|
{
|
||||||
word *a, *p;
|
|
||||||
char *s;
|
char *s;
|
||||||
int n;
|
word *a;
|
||||||
if(count(runq->argv->words)!=1){
|
if(count(runq->argv->words)!=1){
|
||||||
Xerror1("variable name not singleton!");
|
Xerror1("variable name not singleton!");
|
||||||
return;
|
return;
|
||||||
|
@ -658,24 +672,7 @@ Xqdol(void)
|
||||||
deglob(s);
|
deglob(s);
|
||||||
a = vlook(s)->val;
|
a = vlook(s)->val;
|
||||||
poplist();
|
poplist();
|
||||||
n = count(a);
|
Pushword(list2str(a));
|
||||||
if(n==0){
|
|
||||||
pushword("");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for(p = a;p;p = p->next) n+=strlen(p->word);
|
|
||||||
s = emalloc(n);
|
|
||||||
if(a){
|
|
||||||
strcpy(s, a->word);
|
|
||||||
for(p = a->next;p;p = p->next){
|
|
||||||
strcat(s, " ");
|
|
||||||
strcat(s, p->word);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
s[0]='\0';
|
|
||||||
pushword(s);
|
|
||||||
efree(s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
word*
|
word*
|
||||||
|
@ -780,7 +777,7 @@ Xlocal(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
deglob(runq->argv->words->word);
|
deglob(runq->argv->words->word);
|
||||||
runq->local = newvar(strdup(runq->argv->words->word), runq->local);
|
runq->local = newvar(runq->argv->words->word, runq->local);
|
||||||
poplist();
|
poplist();
|
||||||
globlist();
|
globlist();
|
||||||
runq->local->val = runq->argv->words;
|
runq->local->val = runq->argv->words;
|
||||||
|
|
|
@ -14,7 +14,7 @@ rcargv(char *s)
|
||||||
word *p;
|
word *p;
|
||||||
|
|
||||||
p = vlook("*")->val;
|
p = vlook("*")->val;
|
||||||
argv = malloc((count(p)+6)*sizeof(char*));
|
argv = emalloc((count(p)+6)*sizeof(char*));
|
||||||
argc = 0;
|
argc = 0;
|
||||||
argv[argc++] = argv0;
|
argv[argc++] = argv0;
|
||||||
if(flag['e'])
|
if(flag['e'])
|
||||||
|
|
|
@ -34,7 +34,7 @@ heredoc(tree *tag)
|
||||||
h->tag = tag;
|
h->tag = tag;
|
||||||
hexnum(&tmp[9], getpid());
|
hexnum(&tmp[9], getpid());
|
||||||
hexnum(&tmp[14], ser++);
|
hexnum(&tmp[14], ser++);
|
||||||
h->name = strdup(tmp);
|
h->name = estrdup(tmp);
|
||||||
return token(tmp, WORD);
|
return token(tmp, WORD);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -103,6 +103,7 @@ void *Realloc(void *, ulong);
|
||||||
void *emalloc(long);
|
void *emalloc(long);
|
||||||
void *erealloc(void *, long);
|
void *erealloc(void *, long);
|
||||||
void efree(void *);
|
void efree(void *);
|
||||||
|
char *estrdup(char*);
|
||||||
|
|
||||||
#define NOFILE 128 /* should come from <param.h> */
|
#define NOFILE 128 /* should come from <param.h> */
|
||||||
|
|
||||||
|
|
|
@ -131,7 +131,7 @@ execfunc(var *func)
|
||||||
runq->argv->words = 0;
|
runq->argv->words = 0;
|
||||||
poplist();
|
poplist();
|
||||||
start(func->fn, func->pc, runq->local);
|
start(func->fn, func->pc, runq->local);
|
||||||
runq->local = newvar(strdup("*"), runq->local);
|
runq->local = newvar("*", runq->local);
|
||||||
runq->local->val = starval;
|
runq->local->val = starval;
|
||||||
runq->local->changed = 1;
|
runq->local->changed = 1;
|
||||||
}
|
}
|
||||||
|
@ -172,7 +172,7 @@ execcd(void)
|
||||||
dir = smprint("%s/%s", cdpath->word,
|
dir = smprint("%s/%s", cdpath->word,
|
||||||
a->next->word);
|
a->next->word);
|
||||||
else
|
else
|
||||||
dir = strdup(a->next->word);
|
dir = estrdup(a->next->word);
|
||||||
|
|
||||||
if(dochdir(dir) >= 0){
|
if(dochdir(dir) >= 0){
|
||||||
if(cdpath->word[0] != '\0' &&
|
if(cdpath->word[0] != '\0' &&
|
||||||
|
@ -355,14 +355,14 @@ execdot(void)
|
||||||
Xerror1("Usage: . [-i] file [arg ...]");
|
Xerror1("Usage: . [-i] file [arg ...]");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
zero = strdup(p->argv->words->word);
|
zero = estrdup(p->argv->words->word);
|
||||||
popword();
|
popword();
|
||||||
fd = -1;
|
fd = -1;
|
||||||
for(path = searchpath(zero); path; path = path->next){
|
for(path = searchpath(zero); path; path = path->next){
|
||||||
if(path->word[0] != '\0')
|
if(path->word[0] != '\0')
|
||||||
file = smprint("%s/%s", path->word, zero);
|
file = smprint("%s/%s", path->word, zero);
|
||||||
else
|
else
|
||||||
file = strdup(zero);
|
file = estrdup(zero);
|
||||||
|
|
||||||
fd = open(file, 0);
|
fd = open(file, 0);
|
||||||
free(file);
|
free(file);
|
||||||
|
@ -480,7 +480,7 @@ execwhatis(void){ /* mildly wrong -- should fork before writing */
|
||||||
file = smprint("%s/%s",
|
file = smprint("%s/%s",
|
||||||
path->word, a->word);
|
path->word, a->word);
|
||||||
else
|
else
|
||||||
file = strdup(a->word);
|
file = estrdup(a->word);
|
||||||
if(Executable(file)){
|
if(Executable(file)){
|
||||||
pfmt(out, "%s\n", file);
|
pfmt(out, "%s\n", file);
|
||||||
free(file);
|
free(file);
|
||||||
|
|
|
@ -30,6 +30,19 @@ efree(void *p)
|
||||||
free(p);
|
free(p);
|
||||||
else pfmt(err, "free 0\n");
|
else pfmt(err, "free 0\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
estrdup(char *s)
|
||||||
|
{
|
||||||
|
char *d;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
n = strlen(s)+1;
|
||||||
|
d = emalloc(n);
|
||||||
|
Memcpy(d, s, n);
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
extern int lastword, lastdol;
|
extern int lastword, lastdol;
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -18,7 +18,7 @@ dotrap(void)
|
||||||
trapreq = vlook(Signame[i]);
|
trapreq = vlook(Signame[i]);
|
||||||
if(trapreq->fn){
|
if(trapreq->fn){
|
||||||
start(trapreq->fn, trapreq->pc, (struct var *)0);
|
start(trapreq->fn, trapreq->pc, (struct var *)0);
|
||||||
runq->local = newvar(strdup("*"), runq->local);
|
runq->local = newvar("*", runq->local);
|
||||||
runq->local->val = copywords(starval, (struct word *)0);
|
runq->local->val = copywords(starval, (struct word *)0);
|
||||||
runq->local->changed = 1;
|
runq->local->changed = 1;
|
||||||
runq->redir = runq->startredir = 0;
|
runq->redir = runq->startredir = 0;
|
||||||
|
|
|
@ -111,7 +111,7 @@ simplemung(tree *t)
|
||||||
t = tree1(SIMPLE, t);
|
t = tree1(SIMPLE, t);
|
||||||
s = openstr();
|
s = openstr();
|
||||||
pfmt(s, "%t", t);
|
pfmt(s, "%t", t);
|
||||||
t->str = strdup((char *)s->strp);
|
t->str = estrdup((char *)s->strp);
|
||||||
closeio(s);
|
closeio(s);
|
||||||
for(u = t->child[0];u->type==ARGLIST;u = u->child[0]){
|
for(u = t->child[0];u->type==ARGLIST;u = u->child[0]){
|
||||||
if(u->child[1]->type==DUP
|
if(u->child[1]->type==DUP
|
||||||
|
|
|
@ -256,7 +256,7 @@ register struct word *args, *path;
|
||||||
case ENOEXEC:
|
case ENOEXEC:
|
||||||
pfmt(err, "%s: Bourne again\n", argv[1]);
|
pfmt(err, "%s: Bourne again\n", argv[1]);
|
||||||
argv[0]="sh";
|
argv[0]="sh";
|
||||||
argv[1] = strdup(file);
|
argv[1] = estrdup(file);
|
||||||
execve("/bin/sh", argv, env);
|
execve("/bin/sh", argv, env);
|
||||||
goto Bad;
|
goto Bad;
|
||||||
case ETXTBSY:
|
case ETXTBSY:
|
||||||
|
|
|
@ -63,7 +63,7 @@ gvlook(char *name)
|
||||||
int h = hash(name, NVAR);
|
int h = hash(name, NVAR);
|
||||||
var *v;
|
var *v;
|
||||||
for(v = gvar[h];v;v = v->next) if(strcmp(v->name, name)==0) return v;
|
for(v = gvar[h];v;v = v->next) if(strcmp(v->name, name)==0) return v;
|
||||||
return gvar[h] = newvar(strdup(name), gvar[h]);
|
return gvar[h] = newvar(name, gvar[h]);
|
||||||
}
|
}
|
||||||
|
|
||||||
var*
|
var*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue