word.c (2717B)
1 #include "mk.h" 2 3 static Word *nextword(char**); 4 5 Word* 6 newword(char *s) 7 { 8 Word *w; 9 10 w = (Word *)Malloc(sizeof(Word)); 11 w->s = strdup(s); 12 w->next = 0; 13 return(w); 14 } 15 16 Word * 17 stow(char *s) 18 { 19 Word *head, *w, *new; 20 21 w = head = 0; 22 while(*s){ 23 new = nextword(&s); 24 if(new == 0) 25 break; 26 if (w) 27 w->next = new; 28 else 29 head = w = new; 30 while(w->next) 31 w = w->next; 32 33 } 34 if (!head) 35 head = newword(""); 36 return(head); 37 } 38 39 char * 40 wtos(Word *w, int sep) 41 { 42 Bufblock *buf; 43 char *cp; 44 45 buf = newbuf(); 46 for(; w; w = w->next){ 47 for(cp = w->s; *cp; cp++) 48 insert(buf, *cp); 49 if(w->next) 50 insert(buf, sep); 51 } 52 insert(buf, 0); 53 cp = strdup(buf->start); 54 freebuf(buf); 55 return(cp); 56 } 57 58 Word* 59 wdup(Word *w) 60 { 61 Word *v, *new, *base; 62 63 v = base = 0; 64 while(w){ 65 new = newword(w->s); 66 if(v) 67 v->next = new; 68 else 69 base = new; 70 v = new; 71 w = w->next; 72 } 73 return base; 74 } 75 76 void 77 delword(Word *w) 78 { 79 Word *v; 80 81 while(v = w){ 82 w = w->next; 83 if(v->s) 84 free(v->s); 85 free(v); 86 } 87 } 88 89 /* 90 * break out a word from a string handling quotes, executions, 91 * and variable expansions. 92 */ 93 static Word* 94 nextword(char **s) 95 { 96 Bufblock *b; 97 Word *head, *tail, *w; 98 Rune r; 99 char *cp; 100 int empty; 101 102 cp = *s; 103 b = newbuf(); 104 restart: 105 head = tail = 0; 106 while(*cp == ' ' || *cp == '\t') /* leading white space */ 107 cp++; 108 empty = 1; 109 while(*cp){ 110 cp += chartorune(&r, cp); 111 switch(r) 112 { 113 case ' ': 114 case '\t': 115 case '\n': 116 goto out; 117 case '\\': 118 case '\'': 119 case '"': 120 empty = 0; 121 cp = shellt->expandquote(cp, r, b); 122 if(cp == 0){ 123 fprint(2, "missing closing quote: %s\n", *s); 124 Exit(); 125 } 126 break; 127 case '$': 128 w = varsub(&cp); 129 if(w == 0){ 130 if(empty) 131 goto restart; 132 break; 133 } 134 empty = 0; 135 if(b->current != b->start){ 136 bufcpy(b, w->s, strlen(w->s)); 137 insert(b, 0); 138 free(w->s); 139 w->s = strdup(b->start); 140 b->current = b->start; 141 } 142 if(head){ 143 bufcpy(b, tail->s, strlen(tail->s)); 144 bufcpy(b, w->s, strlen(w->s)); 145 insert(b, 0); 146 free(tail->s); 147 tail->s = strdup(b->start); 148 tail->next = w->next; 149 free(w->s); 150 free(w); 151 b->current = b->start; 152 } else 153 tail = head = w; 154 while(tail->next) 155 tail = tail->next; 156 break; 157 default: 158 empty = 0; 159 rinsert(b, r); 160 break; 161 } 162 } 163 out: 164 *s = cp; 165 if(b->current != b->start){ 166 if(head){ 167 cp = b->current; 168 bufcpy(b, tail->s, strlen(tail->s)); 169 bufcpy(b, b->start, cp-b->start); 170 insert(b, 0); 171 free(tail->s); 172 tail->s = strdup(cp); 173 } else { 174 insert(b, 0); 175 head = newword(b->start); 176 } 177 } 178 freebuf(b); 179 return head; 180 } 181 182 void 183 dumpw(char *s, Word *w) 184 { 185 Bprint(&bout, "%s", s); 186 for(; w; w = w->next) 187 Bprint(&bout, " '%s'", w->s); 188 Bputc(&bout, '\n'); 189 }