#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 = 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');
}