Initial revision
This commit is contained in:
parent
ed7c8e8d02
commit
76193d7cb0
223 changed files with 32479 additions and 0 deletions
256
src/cmd/mk/varsub.c
Normal file
256
src/cmd/mk/varsub.c
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
#include "mk.h"
|
||||
|
||||
static Word *subsub(Word*, char*, char*);
|
||||
static Word *expandvar(char**);
|
||||
static Bufblock *varname(char**);
|
||||
static Word *extractpat(char*, char**, char*, char*);
|
||||
static int submatch(char*, Word*, Word*, int*, char**);
|
||||
static Word *varmatch(char *, char**);
|
||||
|
||||
Word *
|
||||
varsub(char **s)
|
||||
{
|
||||
Bufblock *b;
|
||||
Word *w;
|
||||
|
||||
if(**s == '{') /* either ${name} or ${name: A%B==C%D}*/
|
||||
return expandvar(s);
|
||||
|
||||
b = varname(s);
|
||||
if(b == 0)
|
||||
return 0;
|
||||
|
||||
w = varmatch(b->start, s);
|
||||
freebuf(b);
|
||||
return w;
|
||||
}
|
||||
|
||||
/*
|
||||
* extract a variable name
|
||||
*/
|
||||
static Bufblock*
|
||||
varname(char **s)
|
||||
{
|
||||
Bufblock *b;
|
||||
char *cp;
|
||||
Rune r;
|
||||
int n;
|
||||
|
||||
b = newbuf();
|
||||
cp = *s;
|
||||
for(;;){
|
||||
n = chartorune(&r, cp);
|
||||
if (!WORDCHR(r))
|
||||
break;
|
||||
rinsert(b, r);
|
||||
cp += n;
|
||||
}
|
||||
if (b->current == b->start){
|
||||
SYNERR(-1);
|
||||
fprint(2, "missing variable name <%s>\n", *s);
|
||||
freebuf(b);
|
||||
return 0;
|
||||
}
|
||||
*s = cp;
|
||||
insert(b, 0);
|
||||
return b;
|
||||
}
|
||||
|
||||
static Word*
|
||||
varmatch(char *name, char **s)
|
||||
{
|
||||
Word *w;
|
||||
Symtab *sym;
|
||||
char *cp;
|
||||
|
||||
sym = symlook(name, S_VAR, 0);
|
||||
if(sym){
|
||||
/* check for at least one non-NULL value */
|
||||
for (w = (Word*)sym->value; w; w = w->next)
|
||||
if(w->s && *w->s)
|
||||
return wdup(w);
|
||||
}
|
||||
for(cp = *s; *cp == ' ' || *cp == '\t'; cp++) /* skip trailing whitespace */
|
||||
;
|
||||
*s = cp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Word*
|
||||
expandvar(char **s)
|
||||
{
|
||||
Word *w;
|
||||
Bufblock *buf;
|
||||
Symtab *sym;
|
||||
char *cp, *begin, *end;
|
||||
|
||||
begin = *s;
|
||||
(*s)++; /* skip the '{' */
|
||||
buf = varname(s);
|
||||
if (buf == 0)
|
||||
return 0;
|
||||
cp = *s;
|
||||
if (*cp == '}') { /* ${name} variant*/
|
||||
(*s)++; /* skip the '}' */
|
||||
w = varmatch(buf->start, s);
|
||||
freebuf(buf);
|
||||
return w;
|
||||
}
|
||||
if (*cp != ':') {
|
||||
SYNERR(-1);
|
||||
fprint(2, "bad variable name <%s>\n", buf->start);
|
||||
freebuf(buf);
|
||||
return 0;
|
||||
}
|
||||
cp++;
|
||||
end = charin(cp , "}");
|
||||
if(end == 0){
|
||||
SYNERR(-1);
|
||||
fprint(2, "missing '}': %s\n", begin);
|
||||
Exit();
|
||||
}
|
||||
*end = 0;
|
||||
*s = end+1;
|
||||
|
||||
sym = symlook(buf->start, S_VAR, 0);
|
||||
if(sym == 0 || sym->value == 0)
|
||||
w = newword(buf->start);
|
||||
else
|
||||
w = subsub((Word*) sym->value, cp, end);
|
||||
freebuf(buf);
|
||||
return w;
|
||||
}
|
||||
|
||||
static Word*
|
||||
extractpat(char *s, char **r, char *term, char *end)
|
||||
{
|
||||
int save;
|
||||
char *cp;
|
||||
Word *w;
|
||||
|
||||
cp = charin(s, term);
|
||||
if(cp){
|
||||
*r = cp;
|
||||
if(cp == s)
|
||||
return 0;
|
||||
save = *cp;
|
||||
*cp = 0;
|
||||
w = stow(s);
|
||||
*cp = save;
|
||||
} else {
|
||||
*r = end;
|
||||
w = stow(s);
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
static Word*
|
||||
subsub(Word *v, char *s, char *end)
|
||||
{
|
||||
int nmid;
|
||||
Word *head, *tail, *w, *h;
|
||||
Word *a, *b, *c, *d;
|
||||
Bufblock *buf;
|
||||
char *cp, *enda;
|
||||
|
||||
a = extractpat(s, &cp, "=%&", end);
|
||||
b = c = d = 0;
|
||||
if(PERCENT(*cp))
|
||||
b = extractpat(cp+1, &cp, "=", end);
|
||||
if(*cp == '=')
|
||||
c = extractpat(cp+1, &cp, "&%", end);
|
||||
if(PERCENT(*cp))
|
||||
d = stow(cp+1);
|
||||
else if(*cp)
|
||||
d = stow(cp);
|
||||
|
||||
head = tail = 0;
|
||||
buf = newbuf();
|
||||
for(; v; v = v->next){
|
||||
h = w = 0;
|
||||
if(submatch(v->s, a, b, &nmid, &enda)){
|
||||
/* enda points to end of A match in source;
|
||||
* nmid = number of chars between end of A and start of B
|
||||
*/
|
||||
if(c){
|
||||
h = w = wdup(c);
|
||||
while(w->next)
|
||||
w = w->next;
|
||||
}
|
||||
if(PERCENT(*cp) && nmid > 0){
|
||||
if(w){
|
||||
bufcpy(buf, w->s, strlen(w->s));
|
||||
bufcpy(buf, enda, nmid);
|
||||
insert(buf, 0);
|
||||
free(w->s);
|
||||
w->s = strdup(buf->start);
|
||||
} else {
|
||||
bufcpy(buf, enda, nmid);
|
||||
insert(buf, 0);
|
||||
h = w = newword(buf->start);
|
||||
}
|
||||
buf->current = buf->start;
|
||||
}
|
||||
if(d && *d->s){
|
||||
if(w){
|
||||
|
||||
bufcpy(buf, w->s, strlen(w->s));
|
||||
bufcpy(buf, d->s, strlen(d->s));
|
||||
insert(buf, 0);
|
||||
free(w->s);
|
||||
w->s = strdup(buf->start);
|
||||
w->next = wdup(d->next);
|
||||
while(w->next)
|
||||
w = w->next;
|
||||
buf->current = buf->start;
|
||||
} else
|
||||
h = w = wdup(d);
|
||||
}
|
||||
}
|
||||
if(w == 0)
|
||||
h = w = newword(v->s);
|
||||
|
||||
if(head == 0)
|
||||
head = h;
|
||||
else
|
||||
tail->next = h;
|
||||
tail = w;
|
||||
}
|
||||
freebuf(buf);
|
||||
delword(a);
|
||||
delword(b);
|
||||
delword(c);
|
||||
delword(d);
|
||||
return head;
|
||||
}
|
||||
|
||||
static int
|
||||
submatch(char *s, Word *a, Word *b, int *nmid, char **enda)
|
||||
{
|
||||
Word *w;
|
||||
int n;
|
||||
char *end;
|
||||
|
||||
n = 0;
|
||||
for(w = a; w; w = w->next){
|
||||
n = strlen(w->s);
|
||||
if(strncmp(s, w->s, n) == 0)
|
||||
break;
|
||||
}
|
||||
if(a && w == 0) /* a == NULL matches everything*/
|
||||
return 0;
|
||||
|
||||
*enda = s+n; /* pointer to end a A part match */
|
||||
*nmid = strlen(s)-n; /* size of remainder of source */
|
||||
end = *enda+*nmid;
|
||||
for(w = b; w; w = w->next){
|
||||
n = strlen(w->s);
|
||||
if(strcmp(w->s, end-n) == 0){
|
||||
*nmid -= n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(b && w == 0) /* b == NULL matches everything */
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue