tvarsub.c - plan9port - [fork] Plan 9 from user space | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
tvarsub.c (4307B) | |
--- | |
1 #include "mk.h" | |
2 | |
3 static Word *subsub(Word*, char*, char*); | |
4 static Word *expandvar(char**); | |
5 static Bufblock *varname(char**); | |
6 static Word *extractpat(char*, char**, char*, char… | |
7 static int submatch(char*, Word*, Word*, int*, cha… | |
8 static Word *varmatch(char *); | |
9 | |
10 Word * | |
11 varsub(char **s) | |
12 { | |
13 Bufblock *b; | |
14 Word *w; | |
15 | |
16 if(**s == '{') /* either ${name} or ${name: A%B==… | |
17 return expandvar(s); | |
18 | |
19 b = varname(s); | |
20 if(b == 0) | |
21 return 0; | |
22 | |
23 w = varmatch(b->start); | |
24 freebuf(b); | |
25 return w; | |
26 } | |
27 | |
28 /* | |
29 * extract a variable name | |
30 */ | |
31 static Bufblock* | |
32 varname(char **s) | |
33 { | |
34 Bufblock *b; | |
35 char *cp; | |
36 Rune r; | |
37 int n; | |
38 | |
39 b = newbuf(); | |
40 cp = *s; | |
41 for(;;){ | |
42 n = chartorune(&r, cp); | |
43 if (!WORDCHR(r)) | |
44 break; | |
45 rinsert(b, r); | |
46 cp += n; | |
47 } | |
48 if (b->current == b->start){ | |
49 SYNERR(-1); | |
50 fprint(2, "missing variable name <%s>\n", *s); | |
51 freebuf(b); | |
52 return 0; | |
53 } | |
54 *s = cp; | |
55 insert(b, 0); | |
56 return b; | |
57 } | |
58 | |
59 static Word* | |
60 varmatch(char *name) | |
61 { | |
62 Word *w; | |
63 Symtab *sym; | |
64 | |
65 sym = symlook(name, S_VAR, 0); | |
66 if(sym){ | |
67 /* check for at least one non-NULL value */ | |
68 for (w = sym->u.ptr; w; w = w->next) | |
69 if(w->s && *w->s) | |
70 return wdup(w); | |
71 } | |
72 return 0; | |
73 } | |
74 | |
75 static Word* | |
76 expandvar(char **s) | |
77 { | |
78 Word *w; | |
79 Bufblock *buf; | |
80 Symtab *sym; | |
81 char *cp, *begin, *end; | |
82 | |
83 begin = *s; | |
84 (*s)++; /* skip t… | |
85 buf = varname(s); | |
86 if (buf == 0) | |
87 return 0; | |
88 cp = *s; | |
89 if (*cp == '}') { /* ${name} vari… | |
90 (*s)++; /* skip t… | |
91 w = varmatch(buf->start); | |
92 freebuf(buf); | |
93 return w; | |
94 } | |
95 if (*cp != ':') { | |
96 SYNERR(-1); | |
97 fprint(2, "bad variable name <%s>\n", buf->start); | |
98 freebuf(buf); | |
99 return 0; | |
100 } | |
101 cp++; | |
102 end = shellt->charin(cp , "}"); | |
103 if(end == 0){ | |
104 SYNERR(-1); | |
105 fprint(2, "missing '}': %s\n", begin); | |
106 Exit(); | |
107 } | |
108 *end = 0; | |
109 *s = end+1; | |
110 | |
111 sym = symlook(buf->start, S_VAR, 0); | |
112 if(sym == 0 || sym->u.ptr == 0) | |
113 w = newword(buf->start); | |
114 else | |
115 w = subsub(sym->u.ptr, cp, end); | |
116 freebuf(buf); | |
117 return w; | |
118 } | |
119 | |
120 static Word* | |
121 extractpat(char *s, char **r, char *term, char *end) | |
122 { | |
123 int save; | |
124 char *cp; | |
125 Word *w; | |
126 | |
127 cp = shellt->charin(s, term); | |
128 if(cp){ | |
129 *r = cp; | |
130 if(cp == s) | |
131 return 0; | |
132 save = *cp; | |
133 *cp = 0; | |
134 w = stow(s); | |
135 *cp = save; | |
136 } else { | |
137 *r = end; | |
138 w = stow(s); | |
139 } | |
140 return w; | |
141 } | |
142 | |
143 static Word* | |
144 subsub(Word *v, char *s, char *end) | |
145 { | |
146 int nmid; | |
147 Word *head, *tail, *w, *h; | |
148 Word *a, *b, *c, *d; | |
149 Bufblock *buf; | |
150 char *cp, *enda; | |
151 | |
152 a = extractpat(s, &cp, "=%&", end); | |
153 b = c = d = 0; | |
154 if(PERCENT(*cp)) | |
155 b = extractpat(cp+1, &cp, "=", end); | |
156 if(*cp == '=') | |
157 c = extractpat(cp+1, &cp, "&%", end); | |
158 if(PERCENT(*cp)) | |
159 d = stow(cp+1); | |
160 else if(*cp) | |
161 d = stow(cp); | |
162 | |
163 head = tail = 0; | |
164 buf = newbuf(); | |
165 for(; v; v = v->next){ | |
166 h = w = 0; | |
167 if(submatch(v->s, a, b, &nmid, &enda)){ | |
168 /* enda points to end of A match in source; | |
169 * nmid = number of chars between end of A and s… | |
170 */ | |
171 if(c){ | |
172 h = w = wdup(c); | |
173 while(w->next) | |
174 w = w->next; | |
175 } | |
176 if(PERCENT(*cp) && nmid > 0){ | |
177 if(w){ | |
178 bufcpy(buf, w->s, strlen(w->s)); | |
179 bufcpy(buf, enda, nmid); | |
180 insert(buf, 0); | |
181 free(w->s); | |
182 w->s = strdup(buf->start); | |
183 } else { | |
184 bufcpy(buf, enda, nmid); | |
185 insert(buf, 0); | |
186 h = w = newword(buf->start); | |
187 } | |
188 buf->current = buf->start; | |
189 } | |
190 if(d && *d->s){ | |
191 if(w){ | |
192 | |
193 bufcpy(buf, w->s, strlen(w->s)); | |
194 bufcpy(buf, d->s, strlen(d->s)); | |
195 insert(buf, 0); | |
196 free(w->s); | |
197 w->s = strdup(buf->start); | |
198 w->next = wdup(d->next); | |
199 while(w->next) | |
200 w = w->next; | |
201 buf->current = buf->start; | |
202 } else | |
203 h = w = wdup(d); | |
204 } | |
205 } | |
206 if(w == 0) | |
207 h = w = newword(v->s); | |
208 | |
209 if(head == 0) | |
210 head = h; | |
211 else | |
212 tail->next = h; | |
213 tail = w; | |
214 } | |
215 freebuf(buf); | |
216 delword(a); | |
217 delword(b); | |
218 delword(c); | |
219 delword(d); | |
220 return head; | |
221 } | |
222 | |
223 static int | |
224 submatch(char *s, Word *a, Word *b, int *nmid, char **enda) | |
225 { | |
226 Word *w; | |
227 int n; | |
228 char *end; | |
229 | |
230 n = 0; | |
231 for(w = a; w; w = w->next){ | |
232 n = strlen(w->s); | |
233 if(strncmp(s, w->s, n) == 0) | |
234 break; | |
235 } | |
236 if(a && w == 0) /* a == NULL matches everything*/ | |
237 return 0; | |
238 | |
239 *enda = s+n; /* pointer to end a A part match */ | |
240 *nmid = strlen(s)-n; /* size of remainder of source */ | |
241 end = *enda+*nmid; | |
242 for(w = b; w; w = w->next){ | |
243 n = strlen(w->s); | |
244 if(strcmp(w->s, end-n) == 0){ | |
245 *nmid -= n; | |
246 break; | |
247 } | |
248 } | |
249 if(b && w == 0) /* b == NULL matches everything */ | |
250 return 0; | |
251 return 1; | |
252 } |