1 76193d7c 2003-09-30 devnull #include "mk.h"
3 76193d7c 2003-09-30 devnull static Word *subsub(Word*, char*, char*);
4 76193d7c 2003-09-30 devnull static Word *expandvar(char**);
5 76193d7c 2003-09-30 devnull static Bufblock *varname(char**);
6 76193d7c 2003-09-30 devnull static Word *extractpat(char*, char**, char*, char*);
7 76193d7c 2003-09-30 devnull static int submatch(char*, Word*, Word*, int*, char**);
8 76193d7c 2003-09-30 devnull static Word *varmatch(char *, char**);
11 76193d7c 2003-09-30 devnull varsub(char **s)
13 76193d7c 2003-09-30 devnull Bufblock *b;
16 76193d7c 2003-09-30 devnull if(**s == '{') /* either ${name} or ${name: A%B==C%D}*/
17 76193d7c 2003-09-30 devnull return expandvar(s);
19 76193d7c 2003-09-30 devnull b = varname(s);
20 76193d7c 2003-09-30 devnull if(b == 0)
21 76193d7c 2003-09-30 devnull return 0;
23 76193d7c 2003-09-30 devnull w = varmatch(b->start, s);
24 76193d7c 2003-09-30 devnull freebuf(b);
25 76193d7c 2003-09-30 devnull return w;
29 76193d7c 2003-09-30 devnull * extract a variable name
31 76193d7c 2003-09-30 devnull static Bufblock*
32 76193d7c 2003-09-30 devnull varname(char **s)
34 76193d7c 2003-09-30 devnull Bufblock *b;
35 76193d7c 2003-09-30 devnull char *cp;
39 76193d7c 2003-09-30 devnull b = newbuf();
42 76193d7c 2003-09-30 devnull n = chartorune(&r, cp);
43 76193d7c 2003-09-30 devnull if (!WORDCHR(r))
45 76193d7c 2003-09-30 devnull rinsert(b, r);
48 76193d7c 2003-09-30 devnull if (b->current == b->start){
49 76193d7c 2003-09-30 devnull SYNERR(-1);
50 76193d7c 2003-09-30 devnull fprint(2, "missing variable name <%s>\n", *s);
51 76193d7c 2003-09-30 devnull freebuf(b);
52 76193d7c 2003-09-30 devnull return 0;
55 76193d7c 2003-09-30 devnull insert(b, 0);
56 76193d7c 2003-09-30 devnull return b;
59 76193d7c 2003-09-30 devnull static Word*
60 76193d7c 2003-09-30 devnull varmatch(char *name, char **s)
63 76193d7c 2003-09-30 devnull Symtab *sym;
64 76193d7c 2003-09-30 devnull char *cp;
66 76193d7c 2003-09-30 devnull sym = symlook(name, S_VAR, 0);
68 76193d7c 2003-09-30 devnull /* check for at least one non-NULL value */
69 76193d7c 2003-09-30 devnull for (w = (Word*)sym->value; w; w = w->next)
70 76193d7c 2003-09-30 devnull if(w->s && *w->s)
71 76193d7c 2003-09-30 devnull return wdup(w);
73 76193d7c 2003-09-30 devnull for(cp = *s; *cp == ' ' || *cp == '\t'; cp++) /* skip trailing whitespace */
76 76193d7c 2003-09-30 devnull return 0;
79 76193d7c 2003-09-30 devnull static Word*
80 76193d7c 2003-09-30 devnull expandvar(char **s)
83 76193d7c 2003-09-30 devnull Bufblock *buf;
84 76193d7c 2003-09-30 devnull Symtab *sym;
85 76193d7c 2003-09-30 devnull char *cp, *begin, *end;
87 76193d7c 2003-09-30 devnull begin = *s;
88 76193d7c 2003-09-30 devnull (*s)++; /* skip the '{' */
89 76193d7c 2003-09-30 devnull buf = varname(s);
90 76193d7c 2003-09-30 devnull if (buf == 0)
91 76193d7c 2003-09-30 devnull return 0;
93 76193d7c 2003-09-30 devnull if (*cp == '}') { /* ${name} variant*/
94 76193d7c 2003-09-30 devnull (*s)++; /* skip the '}' */
95 76193d7c 2003-09-30 devnull w = varmatch(buf->start, s);
96 76193d7c 2003-09-30 devnull freebuf(buf);
97 76193d7c 2003-09-30 devnull return w;
99 76193d7c 2003-09-30 devnull if (*cp != ':') {
100 76193d7c 2003-09-30 devnull SYNERR(-1);
101 76193d7c 2003-09-30 devnull fprint(2, "bad variable name <%s>\n", buf->start);
102 76193d7c 2003-09-30 devnull freebuf(buf);
103 76193d7c 2003-09-30 devnull return 0;
106 76193d7c 2003-09-30 devnull end = charin(cp , "}");
107 76193d7c 2003-09-30 devnull if(end == 0){
108 76193d7c 2003-09-30 devnull SYNERR(-1);
109 76193d7c 2003-09-30 devnull fprint(2, "missing '}': %s\n", begin);
112 76193d7c 2003-09-30 devnull *end = 0;
113 76193d7c 2003-09-30 devnull *s = end+1;
115 76193d7c 2003-09-30 devnull sym = symlook(buf->start, S_VAR, 0);
116 76193d7c 2003-09-30 devnull if(sym == 0 || sym->value == 0)
117 76193d7c 2003-09-30 devnull w = newword(buf->start);
119 76193d7c 2003-09-30 devnull w = subsub((Word*) sym->value, cp, end);
120 76193d7c 2003-09-30 devnull freebuf(buf);
121 76193d7c 2003-09-30 devnull return w;
124 76193d7c 2003-09-30 devnull static Word*
125 76193d7c 2003-09-30 devnull extractpat(char *s, char **r, char *term, char *end)
127 76193d7c 2003-09-30 devnull int save;
128 76193d7c 2003-09-30 devnull char *cp;
129 76193d7c 2003-09-30 devnull Word *w;
131 76193d7c 2003-09-30 devnull cp = charin(s, term);
133 76193d7c 2003-09-30 devnull *r = cp;
134 76193d7c 2003-09-30 devnull if(cp == s)
135 76193d7c 2003-09-30 devnull return 0;
136 76193d7c 2003-09-30 devnull save = *cp;
137 76193d7c 2003-09-30 devnull *cp = 0;
138 76193d7c 2003-09-30 devnull w = stow(s);
139 76193d7c 2003-09-30 devnull *cp = save;
140 76193d7c 2003-09-30 devnull } else {
141 76193d7c 2003-09-30 devnull *r = end;
142 76193d7c 2003-09-30 devnull w = stow(s);
144 76193d7c 2003-09-30 devnull return w;
147 76193d7c 2003-09-30 devnull static Word*
148 76193d7c 2003-09-30 devnull subsub(Word *v, char *s, char *end)
150 76193d7c 2003-09-30 devnull int nmid;
151 76193d7c 2003-09-30 devnull Word *head, *tail, *w, *h;
152 76193d7c 2003-09-30 devnull Word *a, *b, *c, *d;
153 76193d7c 2003-09-30 devnull Bufblock *buf;
154 76193d7c 2003-09-30 devnull char *cp, *enda;
156 76193d7c 2003-09-30 devnull a = extractpat(s, &cp, "=%&", end);
157 76193d7c 2003-09-30 devnull b = c = d = 0;
158 76193d7c 2003-09-30 devnull if(PERCENT(*cp))
159 76193d7c 2003-09-30 devnull b = extractpat(cp+1, &cp, "=", end);
160 76193d7c 2003-09-30 devnull if(*cp == '=')
161 76193d7c 2003-09-30 devnull c = extractpat(cp+1, &cp, "&%", end);
162 76193d7c 2003-09-30 devnull if(PERCENT(*cp))
163 76193d7c 2003-09-30 devnull d = stow(cp+1);
164 76193d7c 2003-09-30 devnull else if(*cp)
165 76193d7c 2003-09-30 devnull d = stow(cp);
167 76193d7c 2003-09-30 devnull head = tail = 0;
168 76193d7c 2003-09-30 devnull buf = newbuf();
169 76193d7c 2003-09-30 devnull for(; v; v = v->next){
170 76193d7c 2003-09-30 devnull h = w = 0;
171 76193d7c 2003-09-30 devnull if(submatch(v->s, a, b, &nmid, &enda)){
172 76193d7c 2003-09-30 devnull /* enda points to end of A match in source;
173 76193d7c 2003-09-30 devnull * nmid = number of chars between end of A and start of B
176 76193d7c 2003-09-30 devnull h = w = wdup(c);
177 76193d7c 2003-09-30 devnull while(w->next)
178 76193d7c 2003-09-30 devnull w = w->next;
180 76193d7c 2003-09-30 devnull if(PERCENT(*cp) && nmid > 0){
182 76193d7c 2003-09-30 devnull bufcpy(buf, w->s, strlen(w->s));
183 76193d7c 2003-09-30 devnull bufcpy(buf, enda, nmid);
184 76193d7c 2003-09-30 devnull insert(buf, 0);
185 76193d7c 2003-09-30 devnull free(w->s);
186 76193d7c 2003-09-30 devnull w->s = strdup(buf->start);
187 76193d7c 2003-09-30 devnull } else {
188 76193d7c 2003-09-30 devnull bufcpy(buf, enda, nmid);
189 76193d7c 2003-09-30 devnull insert(buf, 0);
190 76193d7c 2003-09-30 devnull h = w = newword(buf->start);
192 76193d7c 2003-09-30 devnull buf->current = buf->start;
194 76193d7c 2003-09-30 devnull if(d && *d->s){
197 76193d7c 2003-09-30 devnull bufcpy(buf, w->s, strlen(w->s));
198 76193d7c 2003-09-30 devnull bufcpy(buf, d->s, strlen(d->s));
199 76193d7c 2003-09-30 devnull insert(buf, 0);
200 76193d7c 2003-09-30 devnull free(w->s);
201 76193d7c 2003-09-30 devnull w->s = strdup(buf->start);
202 76193d7c 2003-09-30 devnull w->next = wdup(d->next);
203 76193d7c 2003-09-30 devnull while(w->next)
204 76193d7c 2003-09-30 devnull w = w->next;
205 76193d7c 2003-09-30 devnull buf->current = buf->start;
207 76193d7c 2003-09-30 devnull h = w = wdup(d);
210 76193d7c 2003-09-30 devnull if(w == 0)
211 76193d7c 2003-09-30 devnull h = w = newword(v->s);
213 76193d7c 2003-09-30 devnull if(head == 0)
214 76193d7c 2003-09-30 devnull head = h;
216 76193d7c 2003-09-30 devnull tail->next = h;
217 76193d7c 2003-09-30 devnull tail = w;
219 76193d7c 2003-09-30 devnull freebuf(buf);
220 76193d7c 2003-09-30 devnull delword(a);
221 76193d7c 2003-09-30 devnull delword(b);
222 76193d7c 2003-09-30 devnull delword(c);
223 76193d7c 2003-09-30 devnull delword(d);
224 76193d7c 2003-09-30 devnull return head;
227 76193d7c 2003-09-30 devnull static int
228 76193d7c 2003-09-30 devnull submatch(char *s, Word *a, Word *b, int *nmid, char **enda)
230 76193d7c 2003-09-30 devnull Word *w;
232 76193d7c 2003-09-30 devnull char *end;
235 76193d7c 2003-09-30 devnull for(w = a; w; w = w->next){
236 76193d7c 2003-09-30 devnull n = strlen(w->s);
237 76193d7c 2003-09-30 devnull if(strncmp(s, w->s, n) == 0)
240 76193d7c 2003-09-30 devnull if(a && w == 0) /* a == NULL matches everything*/
241 76193d7c 2003-09-30 devnull return 0;
243 76193d7c 2003-09-30 devnull *enda = s+n; /* pointer to end a A part match */
244 76193d7c 2003-09-30 devnull *nmid = strlen(s)-n; /* size of remainder of source */
245 76193d7c 2003-09-30 devnull end = *enda+*nmid;
246 76193d7c 2003-09-30 devnull for(w = b; w; w = w->next){
247 76193d7c 2003-09-30 devnull n = strlen(w->s);
248 76193d7c 2003-09-30 devnull if(strcmp(w->s, end-n) == 0){
249 76193d7c 2003-09-30 devnull *nmid -= n;
253 76193d7c 2003-09-30 devnull if(b && w == 0) /* b == NULL matches everything */
254 76193d7c 2003-09-30 devnull return 0;
255 76193d7c 2003-09-30 devnull return 1;