blob: f94c4fd7960931595d31bbc412354485bf88f4ce [file] [log] [blame]
#include "mk.h"
static Word *nextword(char**);
Word*
newword(char *s)
{
Word *w;
w = (Word *)Malloc(sizeof(Word));
w->s = strdup(s);
w->next = 0;
return(w);
}
Word *
stow(char *s)
{
Word *head, *w, *new;
w = head = 0;
while(*s){
new = nextword(&s);
if(new == 0)
break;
if (w)
w->next = new;
else
head = w = new;
while(w->next)
w = w->next;
}
if (!head)
head = newword("");
return(head);
}
char *
wtos(Word *w, int sep)
{
Bufblock *buf;
char *cp;
buf = newbuf();
for(; w; w = w->next){
for(cp = w->s; *cp; cp++)
insert(buf, *cp);
if(w->next)
insert(buf, sep);
}
insert(buf, 0);
cp = strdup(buf->start);
freebuf(buf);
return(cp);
}
Word*
wdup(Word *w)
{
Word *v, *new, *base;
v = base = 0;
while(w){
new = newword(w->s);
if(v)
v->next = new;
else
base = new;
v = new;
w = w->next;
}
return base;
}
void
delword(Word *w)
{
Word *v;
while(v = w){
w = w->next;
if(v->s)
free(v->s);
free(v);
}
}
/*
* break out a word from a string handling quotes, executions,
* and variable expansions.
*/
static Word*
nextword(char **s)
{
Bufblock *b;
Word *head, *tail, *w;
Rune r;
char *cp;
int empty;
cp = *s;
b = newbuf();
restart:
head = tail = 0;
while(*cp == ' ' || *cp == '\t') /* leading white space */
cp++;
empty = 1;
while(*cp){
cp += chartorune(&r, cp);
switch(r)
{
case ' ':
case '\t':
case '\n':
goto out;
case '\\':
case '\'':
case '"':
empty = 0;
cp = shellt->expandquote(cp, r, b);
if(cp == 0){
fprint(2, "missing closing quote: %s\n", *s);
Exit();
}
break;
case '$':
w = varsub(&cp);
if(w == 0){
if(empty)
goto restart;
break;
}
empty = 0;
if(b->current != b->start){
bufcpy(b, w->s, strlen(w->s));
insert(b, 0);
free(w->s);
w->s = strdup(b->start);
b->current = b->start;
}
if(head){
bufcpy(b, tail->s, strlen(tail->s));
bufcpy(b, w->s, strlen(w->s));
insert(b, 0);
free(tail->s);
tail->s = strdup(b->start);
tail->next = w->next;
free(w->s);
free(w);
b->current = b->start;
} else
tail = head = w;
while(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);
insert(b, 0);
free(tail->s);
tail->s = strdup(cp);
} else {
insert(b, 0);
head = newword(b->start);
}
}
freebuf(b);
return head;
}
void
dumpw(char *s, Word *w)
{
Bprint(&bout, "%s", s);
for(; w; w = w->next)
Bprint(&bout, " '%s'", w->s);
Bputc(&bout, '\n');
}