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