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:
cinap_lenrek 2014-07-23 15:28:37 +02:00
parent 2bdd2663db
commit a2f7d03d4e
11 changed files with 64 additions and 53 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View 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

View file

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

View file

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

View file

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

View file

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