ref: a1c3c34c70431447a89fbe08c3475dbfaee7b672
dir: /sys/src/cmd/mk/word.c/
#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'); }