Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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*, char**);
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==C%D}*/
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 the '{' */
85
	buf = varname(s);
86
	if (buf == 0)
87
		return 0;
88
	cp = *s;
89
	if (*cp == '}') {				/* ${name} variant*/
90
		(*s)++;					/* skip the '}' */
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 = 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.value == 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 = 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 start of B
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
}