Improve IFS expansion using code from NetBSD.
We now pass the ifs.sh testsuite. PR: standards/79067 Approved by: ed (mentor) (implicit) Obtained from: NetBSD
This commit is contained in:
parent
56ea66b4d9
commit
a02858661b
141
bin/sh/expand.c
141
bin/sh/expand.c
@ -82,7 +82,7 @@ struct ifsregion {
|
||||
struct ifsregion *next; /* next region in list */
|
||||
int begoff; /* offset of start of region */
|
||||
int endoff; /* offset of end of region */
|
||||
int nulonly; /* search for nul bytes only */
|
||||
int inquotes; /* search for nul bytes only */
|
||||
};
|
||||
|
||||
|
||||
@ -936,13 +936,19 @@ varvalue(char *name, int quoted, int subtype, int flag)
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
recordregion(int start, int end, int nulonly)
|
||||
recordregion(int start, int end, int inquotes)
|
||||
{
|
||||
struct ifsregion *ifsp;
|
||||
|
||||
if (ifslastp == NULL) {
|
||||
ifsp = &ifsfirst;
|
||||
} else {
|
||||
if (ifslastp->endoff == start
|
||||
&& ifslastp->inquotes == inquotes) {
|
||||
/* extend previous area */
|
||||
ifslastp->endoff = end;
|
||||
return;
|
||||
}
|
||||
ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
|
||||
ifslastp->next = ifsp;
|
||||
}
|
||||
@ -950,7 +956,7 @@ recordregion(int start, int end, int nulonly)
|
||||
ifslastp->next = NULL;
|
||||
ifslastp->begoff = start;
|
||||
ifslastp->endoff = end;
|
||||
ifslastp->nulonly = nulonly;
|
||||
ifslastp->inquotes = inquotes;
|
||||
}
|
||||
|
||||
|
||||
@ -969,75 +975,88 @@ ifsbreakup(char *string, struct arglist *arglist)
|
||||
char *p;
|
||||
char *q;
|
||||
char *ifs;
|
||||
int ifsspc;
|
||||
int nulonly;
|
||||
|
||||
const char *ifsspc;
|
||||
int had_param_ch = 0;
|
||||
|
||||
start = string;
|
||||
ifsspc = 0;
|
||||
nulonly = 0;
|
||||
if (ifslastp != NULL) {
|
||||
ifsp = &ifsfirst;
|
||||
do {
|
||||
p = string + ifsp->begoff;
|
||||
nulonly = ifsp->nulonly;
|
||||
ifs = nulonly ? nullstr :
|
||||
( ifsset() ? ifsval() : " \t\n" );
|
||||
ifsspc = 0;
|
||||
while (p < string + ifsp->endoff) {
|
||||
q = p;
|
||||
if (*p == CTLESC)
|
||||
|
||||
if (ifslastp == NULL) {
|
||||
/* Return entire argument, IFS doesn't apply to any of it */
|
||||
sp = (struct strlist *)stalloc(sizeof *sp);
|
||||
sp->text = start;
|
||||
*arglist->lastp = sp;
|
||||
arglist->lastp = &sp->next;
|
||||
return;
|
||||
}
|
||||
|
||||
ifs = ifsset() ? ifsval() : " \t\n";
|
||||
|
||||
for (ifsp = &ifsfirst; ifsp != NULL; ifsp = ifsp->next) {
|
||||
p = string + ifsp->begoff;
|
||||
while (p < string + ifsp->endoff) {
|
||||
had_param_ch = 1;
|
||||
q = p;
|
||||
if (*p == CTLESC)
|
||||
p++;
|
||||
if (ifsp->inquotes) {
|
||||
/* Only NULs (should be from "$@") end args */
|
||||
if (*p != 0) {
|
||||
p++;
|
||||
if (strchr(ifs, *p)) {
|
||||
if (!nulonly)
|
||||
ifsspc = (strchr(" \t\n", *p) != NULL);
|
||||
/* Ignore IFS whitespace at start */
|
||||
if (q == start && ifsspc) {
|
||||
p++;
|
||||
start = p;
|
||||
continue;
|
||||
}
|
||||
*q = '\0';
|
||||
sp = (struct strlist *)stalloc(sizeof *sp);
|
||||
sp->text = start;
|
||||
*arglist->lastp = sp;
|
||||
arglist->lastp = &sp->next;
|
||||
continue;
|
||||
}
|
||||
ifsspc = NULL;
|
||||
} else {
|
||||
if (!strchr(ifs, *p)) {
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
had_param_ch = 0;
|
||||
ifsspc = strchr(" \t\n", *p);
|
||||
|
||||
/* Ignore IFS whitespace at start */
|
||||
if (q == start && ifsspc != NULL) {
|
||||
p++;
|
||||
if (!nulonly) {
|
||||
for (;;) {
|
||||
if (p >= string + ifsp->endoff) {
|
||||
break;
|
||||
}
|
||||
q = p;
|
||||
if (*p == CTLESC)
|
||||
p++;
|
||||
if (strchr(ifs, *p) == NULL ) {
|
||||
p = q;
|
||||
break;
|
||||
} else if (strchr(" \t\n",*p) == NULL) {
|
||||
if (ifsspc) {
|
||||
p++;
|
||||
ifsspc = 0;
|
||||
} else {
|
||||
p = q;
|
||||
break;
|
||||
}
|
||||
} else
|
||||
p++;
|
||||
}
|
||||
}
|
||||
start = p;
|
||||
} else
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} while ((ifsp = ifsp->next) != NULL);
|
||||
if (*start || (!ifsspc && start > string)) {
|
||||
|
||||
/* Save this argument... */
|
||||
*q = '\0';
|
||||
sp = (struct strlist *)stalloc(sizeof *sp);
|
||||
sp->text = start;
|
||||
*arglist->lastp = sp;
|
||||
arglist->lastp = &sp->next;
|
||||
p++;
|
||||
|
||||
if (ifsspc != NULL) {
|
||||
/* Ignore further trailing IFS whitespace */
|
||||
for (; p < string + ifsp->endoff; p++) {
|
||||
q = p;
|
||||
if (*p == CTLESC)
|
||||
p++;
|
||||
if (strchr(ifs, *p) == NULL) {
|
||||
p = q;
|
||||
break;
|
||||
}
|
||||
if (strchr(" \t\n", *p) == NULL) {
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
start = p;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
/*
|
||||
* Save anything left as an argument.
|
||||
* Traditionally we have treated 'IFS=':'; set -- x$IFS' as
|
||||
* generating 2 arguments, the second of which is empty.
|
||||
* Some recent clarification of the Posix spec say that it
|
||||
* should only generate one....
|
||||
*/
|
||||
if (had_param_ch || *start != 0) {
|
||||
sp = (struct strlist *)stalloc(sizeof *sp);
|
||||
sp->text = start;
|
||||
*arglist->lastp = sp;
|
||||
|
Loading…
Reference in New Issue
Block a user