Unfold parsing of single letter modifiers from multi-letter ones.
Patch: 7.125 Submitted by: Max Okumoto <okumoto@ucsd.edu>
This commit is contained in:
parent
2ae8b5b5f6
commit
af0b17b173
@ -1248,218 +1248,291 @@ ParseModifier(const char input[], const char tstr[],
|
||||
tstr++;
|
||||
while (*tstr != endc) {
|
||||
char *newStr; /* New value to return */
|
||||
char termc; /* Character which terminated scan */
|
||||
Boolean readonly = FALSE;
|
||||
size_t consumed = 0;
|
||||
|
||||
DEBUGF(VAR, ("Applying :%c to \"%s\"\n", *tstr, value));
|
||||
switch (*tstr) {
|
||||
case 'N':
|
||||
case 'M':
|
||||
readonly = TRUE;
|
||||
newStr = modifier_M(tstr, value, endc, &consumed);
|
||||
tstr += consumed;
|
||||
break;
|
||||
case 'S':
|
||||
readonly = TRUE;
|
||||
newStr = modifier_S(tstr, value, v, vp, &consumed);
|
||||
tstr += consumed;
|
||||
break;
|
||||
case 'C':
|
||||
readonly = TRUE;
|
||||
newStr = modifier_C(tstr, value, v, vp, &consumed);
|
||||
tstr += consumed;
|
||||
break;
|
||||
case 'L':
|
||||
if (tstr[1] == endc || tstr[1] == ':') {
|
||||
Buffer *buf;
|
||||
buf = Buf_Init(MAKE_BSIZE);
|
||||
for (cp = value; *cp; cp++)
|
||||
Buf_AddByte(buf, (Byte)tolower(*cp));
|
||||
|
||||
Buf_AddByte(buf, (Byte)'\0');
|
||||
newStr = (char *)Buf_GetAll(buf, (size_t *)NULL);
|
||||
Buf_Destroy(buf, FALSE);
|
||||
|
||||
cp = tstr + 1;
|
||||
termc = *cp;
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case 'O':
|
||||
if (tstr[1] == endc || tstr[1] == ':') {
|
||||
newStr = VarSortWords(value, SortIncreasing);
|
||||
cp = tstr + 1;
|
||||
termc = *cp;
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case 'Q':
|
||||
if (tstr[1] == endc || tstr[1] == ':') {
|
||||
newStr = Var_Quote(value);
|
||||
cp = tstr + 1;
|
||||
termc = *cp;
|
||||
break;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
case 'T':
|
||||
if (tstr[1] == endc || tstr[1] == ':') {
|
||||
newStr = VarModify(value, VarTail, (void *)NULL);
|
||||
cp = tstr + 1;
|
||||
termc = *cp;
|
||||
break;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
case 'U':
|
||||
if (tstr[1] == endc || tstr[1] == ':') {
|
||||
Buffer *buf;
|
||||
buf = Buf_Init(MAKE_BSIZE);
|
||||
for (cp = value; *cp; cp++)
|
||||
Buf_AddByte(buf, (Byte)toupper(*cp));
|
||||
|
||||
Buf_AddByte(buf, (Byte)'\0');
|
||||
newStr = (char *)Buf_GetAll(buf, (size_t *)NULL);
|
||||
Buf_Destroy(buf, FALSE);
|
||||
|
||||
cp = tstr + 1;
|
||||
termc = *cp;
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case 'H':
|
||||
if (tstr[1] == endc || tstr[1] == ':') {
|
||||
newStr = VarModify(value, VarHead, (void *)NULL);
|
||||
cp = tstr + 1;
|
||||
termc = *cp;
|
||||
break;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
case 'E':
|
||||
if (tstr[1] == endc || tstr[1] == ':') {
|
||||
newStr = VarModify(value, VarSuffix, (void *)NULL);
|
||||
cp = tstr + 1;
|
||||
termc = *cp;
|
||||
break;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
case 'R':
|
||||
if (tstr[1] == endc || tstr[1] == ':') {
|
||||
newStr = VarModify(value, VarRoot, (void *)NULL);
|
||||
cp = tstr + 1;
|
||||
termc = *cp;
|
||||
break;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
#ifdef SUNSHCMD
|
||||
case 's':
|
||||
if (tstr[1] == 'h' && (tstr[2] == endc || tstr[2] == ':')) {
|
||||
const char *error;
|
||||
Buffer *buf;
|
||||
|
||||
buf = Cmd_Exec(value, &error);
|
||||
newStr = Buf_GetAll(buf, NULL);
|
||||
Buf_Destroy(buf, FALSE);
|
||||
|
||||
if (error)
|
||||
Error(error, value);
|
||||
cp = tstr + 2;
|
||||
termc = *cp;
|
||||
break;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
#endif
|
||||
default:
|
||||
{
|
||||
if (tstr[1] == endc || tstr[1] == ':') {
|
||||
char termc;
|
||||
Buffer *buf;
|
||||
|
||||
switch (*tstr) {
|
||||
case 'L':
|
||||
buf = Buf_Init(MAKE_BSIZE);
|
||||
for (cp = value; *cp; cp++)
|
||||
Buf_AddByte(buf, (Byte)tolower(*cp));
|
||||
|
||||
newStr = (char *)Buf_GetAll(buf, (size_t *)NULL);
|
||||
Buf_Destroy(buf, FALSE);
|
||||
|
||||
cp = tstr + 1;
|
||||
termc = *cp;
|
||||
break;
|
||||
case 'O':
|
||||
newStr = VarSortWords(value, SortIncreasing);
|
||||
cp = tstr + 1;
|
||||
termc = *cp;
|
||||
break;
|
||||
case 'Q':
|
||||
newStr = Var_Quote(value);
|
||||
cp = tstr + 1;
|
||||
termc = *cp;
|
||||
break;
|
||||
case 'T':
|
||||
newStr = VarModify(value, VarTail, (void *)NULL);
|
||||
cp = tstr + 1;
|
||||
termc = *cp;
|
||||
break;
|
||||
case 'U':
|
||||
buf = Buf_Init(MAKE_BSIZE);
|
||||
for (cp = value; *cp; cp++)
|
||||
Buf_AddByte(buf, (Byte)toupper(*cp));
|
||||
|
||||
newStr = (char *)Buf_GetAll(buf, (size_t *)NULL);
|
||||
Buf_Destroy(buf, FALSE);
|
||||
|
||||
cp = tstr + 1;
|
||||
termc = *cp;
|
||||
break;
|
||||
case 'H':
|
||||
newStr = VarModify(value, VarHead, (void *)NULL);
|
||||
cp = tstr + 1;
|
||||
termc = *cp;
|
||||
break;
|
||||
case 'E':
|
||||
newStr = VarModify(value, VarSuffix, (void *)NULL);
|
||||
cp = tstr + 1;
|
||||
termc = *cp;
|
||||
break;
|
||||
case 'R':
|
||||
newStr = VarModify(value, VarRoot, (void *)NULL);
|
||||
cp = tstr + 1;
|
||||
termc = *cp;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
#ifdef SYSVVARSUB
|
||||
/*
|
||||
* This can either be a bogus modifier or a
|
||||
* System-V substitution command.
|
||||
*/
|
||||
VarPattern pattern;
|
||||
Boolean eqFound;
|
||||
int cnt;
|
||||
/*
|
||||
* This can either be a bogus modifier or a
|
||||
* System-V substitution command.
|
||||
*/
|
||||
VarPattern pattern;
|
||||
Boolean eqFound;
|
||||
int cnt;
|
||||
|
||||
pattern.flags = 0;
|
||||
eqFound = FALSE;
|
||||
/*
|
||||
* First we make a pass through the string
|
||||
* trying to verify it is a SYSV-make-style
|
||||
* translation: it must be:
|
||||
* <string1>=<string2>)
|
||||
*/
|
||||
cp = tstr;
|
||||
cnt = 1;
|
||||
while (*cp != '\0' && cnt) {
|
||||
if (*cp == '=') {
|
||||
eqFound = TRUE;
|
||||
/* continue looking for endc */
|
||||
} else if (*cp == endc)
|
||||
cnt--;
|
||||
else if (*cp == startc)
|
||||
cnt++;
|
||||
if (cnt)
|
||||
cp++;
|
||||
}
|
||||
if (*cp == endc && eqFound) {
|
||||
int delim;
|
||||
pattern.flags = 0;
|
||||
eqFound = FALSE;
|
||||
/*
|
||||
* First we make a pass through the string
|
||||
* trying to verify it is a SYSV-make-style
|
||||
* translation: it must be:
|
||||
* <string1>=<string2>)
|
||||
*/
|
||||
cp = tstr;
|
||||
cnt = 1;
|
||||
while (*cp != '\0' && cnt) {
|
||||
if (*cp == '=') {
|
||||
eqFound = TRUE;
|
||||
/* continue looking for endc */
|
||||
} else if (*cp == endc)
|
||||
cnt--;
|
||||
else if (*cp == startc)
|
||||
cnt++;
|
||||
if (cnt)
|
||||
cp++;
|
||||
}
|
||||
if (*cp == endc && eqFound) {
|
||||
int delim;
|
||||
|
||||
/*
|
||||
* Now we break this sucker into the
|
||||
* lhs and rhs. We must null
|
||||
* terminate them of course.
|
||||
*/
|
||||
cp = tstr;
|
||||
/*
|
||||
* Now we break this sucker into the
|
||||
* lhs and rhs. We must null
|
||||
* terminate them of course.
|
||||
*/
|
||||
cp = tstr;
|
||||
|
||||
delim = '=';
|
||||
if ((pattern.lhs = VarGetPattern(vp,
|
||||
&cp, delim, &pattern.flags, &pattern.leftLen,
|
||||
NULL)) == NULL) {
|
||||
*lengthPtr = cp - input + 1;
|
||||
if (*freePtr)
|
||||
free(value);
|
||||
if (delim != '\0')
|
||||
Fatal("Unclosed substitution for %s (%c missing)",
|
||||
v->name, delim);
|
||||
return (var_Error);
|
||||
}
|
||||
delim = endc;
|
||||
delim = '=';
|
||||
if ((pattern.lhs = VarGetPattern(vp, &cp, delim, &pattern.flags, &pattern.leftLen, NULL)) == NULL) {
|
||||
*lengthPtr = cp - input + 1;
|
||||
if (*freePtr)
|
||||
free(value);
|
||||
if (delim != '\0')
|
||||
Fatal("Unclosed substitution for %s (%c missing)",
|
||||
v->name, delim);
|
||||
return (var_Error);
|
||||
}
|
||||
delim = endc;
|
||||
|
||||
pattern.rhs = VarGetPattern(vp, &cp,
|
||||
delim, NULL, &pattern.rightLen, &pattern);
|
||||
if (pattern.rhs == NULL) {
|
||||
*lengthPtr = cp - input + 1;
|
||||
if (*freePtr)
|
||||
free(value);
|
||||
if (delim != '\0')
|
||||
Fatal("Unclosed substitution for %s (%c missing)",
|
||||
v->name, delim);
|
||||
return (var_Error);
|
||||
}
|
||||
/*
|
||||
* SYSV modifications happen through
|
||||
* the whole string. Note the pattern
|
||||
* is anchored at the end.
|
||||
*/
|
||||
termc = *--cp;
|
||||
delim = '\0';
|
||||
newStr = VarModify(value, VarSYSVMatch, &pattern);
|
||||
pattern.rhs = VarGetPattern(vp, &cp, delim, NULL, &pattern.rightLen, &pattern);
|
||||
if (pattern.rhs == NULL) {
|
||||
*lengthPtr = cp - input + 1;
|
||||
if (*freePtr)
|
||||
free(value);
|
||||
if (delim != '\0')
|
||||
Fatal("Unclosed substitution for %s (%c missing)",
|
||||
v->name, delim);
|
||||
return (var_Error);
|
||||
}
|
||||
/*
|
||||
* SYSV modifications happen through
|
||||
* the whole string. Note the pattern
|
||||
* is anchored at the end.
|
||||
*/
|
||||
termc = *--cp;
|
||||
delim = '\0';
|
||||
newStr = VarModify(value, VarSYSVMatch, &pattern);
|
||||
|
||||
free(pattern.lhs);
|
||||
free(pattern.rhs);
|
||||
free(pattern.lhs);
|
||||
free(pattern.rhs);
|
||||
|
||||
termc = endc;
|
||||
} else
|
||||
termc = endc;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
Error("Unknown modifier '%c'\n", *tstr);
|
||||
for (cp = tstr + 1;
|
||||
*cp != ':' && *cp != endc && *cp != '\0';
|
||||
cp++)
|
||||
continue;
|
||||
termc = *cp;
|
||||
newStr = var_Error;
|
||||
{
|
||||
Error("Unknown modifier '%c'\n", *tstr);
|
||||
for (cp = tstr + 1;
|
||||
*cp != ':' && *cp != endc && *cp != '\0';
|
||||
cp++)
|
||||
continue;
|
||||
termc = *cp;
|
||||
newStr = var_Error;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (termc == '\0') {
|
||||
Error("Unclosed variable specification for %s",
|
||||
v->name);
|
||||
}
|
||||
tstr = (termc == ':') ? (cp + 1) : cp;
|
||||
} else {
|
||||
char termc;
|
||||
#ifdef SUNSHCMD
|
||||
if ((tstr[0] == 's') &&
|
||||
(tstr[1] == 'h') &&
|
||||
(tstr[2] == endc || tstr[2] == ':')) {
|
||||
const char *error;
|
||||
Buffer *buf;
|
||||
|
||||
buf = Cmd_Exec(value, &error);
|
||||
newStr = Buf_GetAll(buf, NULL);
|
||||
Buf_Destroy(buf, FALSE);
|
||||
|
||||
if (error)
|
||||
Error(error, value);
|
||||
cp = tstr + 2;
|
||||
termc = *cp;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
#ifdef SYSVVARSUB
|
||||
/*
|
||||
* This can either be a bogus modifier or a
|
||||
* System-V substitution command.
|
||||
*/
|
||||
VarPattern pattern;
|
||||
Boolean eqFound;
|
||||
int cnt;
|
||||
|
||||
pattern.flags = 0;
|
||||
eqFound = FALSE;
|
||||
/*
|
||||
* First we make a pass through the string
|
||||
* trying to verify it is a SYSV-make-style
|
||||
* translation: it must be:
|
||||
* <string1>=<string2>)
|
||||
*/
|
||||
cp = tstr;
|
||||
cnt = 1;
|
||||
while (*cp != '\0' && cnt) {
|
||||
if (*cp == '=') {
|
||||
eqFound = TRUE;
|
||||
/* continue looking for endc */
|
||||
} else if (*cp == endc)
|
||||
cnt--;
|
||||
else if (*cp == startc)
|
||||
cnt++;
|
||||
if (cnt)
|
||||
cp++;
|
||||
}
|
||||
if (*cp == endc && eqFound) {
|
||||
int delim;
|
||||
|
||||
/*
|
||||
* Now we break this sucker into the
|
||||
* lhs and rhs. We must null
|
||||
* terminate them of course.
|
||||
*/
|
||||
cp = tstr;
|
||||
|
||||
delim = '=';
|
||||
if ((pattern.lhs = VarGetPattern(vp, &cp, delim, &pattern.flags, &pattern.leftLen, NULL)) == NULL) {
|
||||
*lengthPtr = cp - input + 1;
|
||||
if (*freePtr)
|
||||
free(value);
|
||||
if (delim != '\0')
|
||||
Fatal("Unclosed substitution for %s (%c missing)",
|
||||
v->name, delim);
|
||||
return (var_Error);
|
||||
}
|
||||
delim = endc;
|
||||
|
||||
pattern.rhs = VarGetPattern(vp, &cp, delim, NULL, &pattern.rightLen, &pattern);
|
||||
if (pattern.rhs == NULL) {
|
||||
*lengthPtr = cp - input + 1;
|
||||
if (*freePtr)
|
||||
free(value);
|
||||
if (delim != '\0')
|
||||
Fatal("Unclosed substitution for %s (%c missing)",
|
||||
v->name, delim);
|
||||
return (var_Error);
|
||||
}
|
||||
/*
|
||||
* SYSV modifications happen through
|
||||
* the whole string. Note the pattern
|
||||
* is anchored at the end.
|
||||
*/
|
||||
termc = *--cp;
|
||||
delim = '\0';
|
||||
newStr = VarModify(value, VarSYSVMatch, &pattern);
|
||||
|
||||
free(pattern.lhs);
|
||||
free(pattern.rhs);
|
||||
|
||||
termc = endc;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
Error("Unknown modifier '%c'\n", *tstr);
|
||||
for (cp = tstr + 1;
|
||||
*cp != ':' && *cp != endc && *cp != '\0';
|
||||
cp++)
|
||||
continue;
|
||||
termc = *cp;
|
||||
newStr = var_Error;
|
||||
}
|
||||
}
|
||||
if (termc == '\0') {
|
||||
Error("Unclosed variable specification for %s",
|
||||
v->name);
|
||||
}
|
||||
tstr = (termc == ':') ? (cp + 1) : cp;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
DEBUGF(VAR, ("Result is \"%s\"\n", newStr));
|
||||
@ -1472,17 +1545,6 @@ ParseModifier(const char input[], const char tstr[],
|
||||
} else {
|
||||
*freePtr = FALSE;
|
||||
}
|
||||
|
||||
if (readonly == FALSE) {
|
||||
if (termc == '\0') {
|
||||
Error("Unclosed variable specification for %s",
|
||||
v->name);
|
||||
} else if (termc == ':') {
|
||||
cp++;
|
||||
} else {
|
||||
}
|
||||
tstr = cp;
|
||||
}
|
||||
}
|
||||
|
||||
used = tstr - input + 1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user