sh: Solve the alias recursion problem in a less hackish way.
Add the space to avoid alias recursion when the alias is expanded, not when it is added. As a result, displaying an alias via command -v, command -V or type no longer erroneously appends a space. Adjust the tests so they now require this bug to be absent.
This commit is contained in:
parent
51fcfa2666
commit
4b489a60e1
@ -68,18 +68,7 @@ setalias(const char *name, const char *val)
|
||||
if (equal(name, ap->name)) {
|
||||
INTOFF;
|
||||
ckfree(ap->val);
|
||||
/* See HACK below. */
|
||||
#ifdef notyet
|
||||
ap->val = savestr(val);
|
||||
#else
|
||||
{
|
||||
size_t len = strlen(val);
|
||||
ap->val = ckmalloc(len + 2);
|
||||
memcpy(ap->val, val, len);
|
||||
ap->val[len] = ' ';
|
||||
ap->val[len+1] = '\0';
|
||||
}
|
||||
#endif
|
||||
INTON;
|
||||
return;
|
||||
}
|
||||
@ -88,34 +77,7 @@ setalias(const char *name, const char *val)
|
||||
INTOFF;
|
||||
ap = ckmalloc(sizeof (struct alias));
|
||||
ap->name = savestr(name);
|
||||
/*
|
||||
* XXX - HACK: in order that the parser will not finish reading the
|
||||
* alias value off the input before processing the next alias, we
|
||||
* dummy up an extra space at the end of the alias. This is a crock
|
||||
* and should be re-thought. The idea (if you feel inclined to help)
|
||||
* is to avoid alias recursions. The mechanism used is: when
|
||||
* expanding an alias, the value of the alias is pushed back on the
|
||||
* input as a string and a pointer to the alias is stored with the
|
||||
* string. The alias is marked as being in use. When the input
|
||||
* routine finishes reading the string, it marks the alias not
|
||||
* in use. The problem is synchronization with the parser. Since
|
||||
* it reads ahead, the alias is marked not in use before the
|
||||
* resulting token(s) is next checked for further alias sub. The
|
||||
* H A C K is that we add a little fluff after the alias value
|
||||
* so that the string will not be exhausted. This is a good
|
||||
* idea ------- ***NOT***
|
||||
*/
|
||||
#ifdef notyet
|
||||
ap->val = savestr(val);
|
||||
#else /* hack */
|
||||
{
|
||||
size_t len = strlen(val);
|
||||
ap->val = ckmalloc(len + 2);
|
||||
memcpy(ap->val, val, len);
|
||||
ap->val[len] = ' '; /* fluff */
|
||||
ap->val[len+1] = '\0';
|
||||
}
|
||||
#endif
|
||||
ap->flag = 0;
|
||||
ap->next = *app;
|
||||
*app = ap;
|
||||
@ -207,14 +169,8 @@ comparealiases(const void *p1, const void *p2)
|
||||
static void
|
||||
printalias(const struct alias *a)
|
||||
{
|
||||
char *p;
|
||||
|
||||
out1fmt("%s=", a->name);
|
||||
/* Don't print the space added above. */
|
||||
p = a->val + strlen(a->val) - 1;
|
||||
*p = '\0';
|
||||
out1qstr(a->val);
|
||||
*p = ' ';
|
||||
out1c('\n');
|
||||
}
|
||||
|
||||
|
@ -226,7 +226,14 @@ preadbuffer(void)
|
||||
int more;
|
||||
char savec;
|
||||
|
||||
if (parsefile->strpush) {
|
||||
while (parsefile->strpush) {
|
||||
/*
|
||||
* Add a space to the end of an alias to ensure that the
|
||||
* alias remains in use while parsing its last word.
|
||||
* This avoids alias recursions.
|
||||
*/
|
||||
if (parsenleft == -1 && parsefile->strpush->ap != NULL)
|
||||
return ' ';
|
||||
popstring();
|
||||
if (--parsenleft >= 0)
|
||||
return (*parsenextc++);
|
||||
|
@ -4,4 +4,4 @@ true
|
||||
fun
|
||||
break
|
||||
if
|
||||
alias foo='bar '
|
||||
alias foo=bar
|
||||
|
@ -5,4 +5,4 @@ fun is a shell function
|
||||
break is a special shell builtin
|
||||
if is a shell keyword
|
||||
{ is a shell keyword
|
||||
foo is an alias for bar
|
||||
foo is an alias for bar
|
||||
|
@ -4,4 +4,4 @@ fun is a shell function
|
||||
break is a special shell builtin
|
||||
if is a shell keyword
|
||||
{ is a shell keyword
|
||||
foo is an alias for bar
|
||||
foo is an alias for bar
|
||||
|
Loading…
x
Reference in New Issue
Block a user