No functional changes (intended).
Rename some variables, add some comments, and restructure a little. In preparation for fixing "set ${x-a b c}" and friends.
This commit is contained in:
parent
b0cddc5f0d
commit
e4a2a056d2
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: eval.c,v 1.76 2004/04/30 06:27:59 dsl Exp $ */
|
/* $NetBSD: eval.c,v 1.77 2004/06/26 14:09:58 dsl Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1993
|
* Copyright (c) 1993
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
#if 0
|
#if 0
|
||||||
static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95";
|
static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95";
|
||||||
#else
|
#else
|
||||||
__RCSID("$NetBSD: eval.c,v 1.76 2004/04/30 06:27:59 dsl Exp $");
|
__RCSID("$NetBSD: eval.c,v 1.77 2004/06/26 14:09:58 dsl Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
|
@ -354,7 +354,7 @@ evalfor(union node *n, int flags)
|
||||||
setstackmark(&smark);
|
setstackmark(&smark);
|
||||||
arglist.lastp = &arglist.list;
|
arglist.lastp = &arglist.list;
|
||||||
for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
|
for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
|
||||||
expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
|
expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_IFS_SPLIT);
|
||||||
if (evalskip)
|
if (evalskip)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
215
bin/sh/expand.c
215
bin/sh/expand.c
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: expand.c,v 1.62 2004/06/09 12:17:36 christos Exp $ */
|
/* $NetBSD: expand.c,v 1.63 2004/06/26 14:09:58 dsl Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
#if 0
|
#if 0
|
||||||
static char sccsid[] = "@(#)expand.c 8.5 (Berkeley) 5/15/95";
|
static char sccsid[] = "@(#)expand.c 8.5 (Berkeley) 5/15/95";
|
||||||
#else
|
#else
|
||||||
__RCSID("$NetBSD: expand.c,v 1.62 2004/06/09 12:17:36 christos Exp $");
|
__RCSID("$NetBSD: expand.c,v 1.63 2004/06/26 14:09:58 dsl Exp $");
|
||||||
#endif
|
#endif
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ struct ifsregion {
|
||||||
struct ifsregion *next; /* next region in list */
|
struct ifsregion *next; /* next region in list */
|
||||||
int begoff; /* offset of start of region */
|
int begoff; /* offset of start of region */
|
||||||
int endoff; /* offset of end of region */
|
int endoff; /* offset of end of region */
|
||||||
int nulonly; /* search for nul bytes only */
|
int inquotes; /* search for nul bytes only */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -192,8 +192,8 @@ argstr(char *p, int flag)
|
||||||
for (;;) {
|
for (;;) {
|
||||||
switch (c = *p++) {
|
switch (c = *p++) {
|
||||||
case '\0':
|
case '\0':
|
||||||
case CTLENDVAR: /* ??? */
|
case CTLENDVAR: /* end of expanding yyy in ${xxx-yyy} */
|
||||||
goto breakloop;
|
return;
|
||||||
case CTLQUOTEMARK:
|
case CTLQUOTEMARK:
|
||||||
/* "$@" syntax adherence hack */
|
/* "$@" syntax adherence hack */
|
||||||
if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=')
|
if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=')
|
||||||
|
@ -237,10 +237,9 @@ argstr(char *p, int flag)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
STPUTC(c, expdest);
|
STPUTC(c, expdest);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
breakloop:;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC char *
|
STATIC char *
|
||||||
|
@ -605,7 +604,7 @@ evalvar(char *p, int flag)
|
||||||
int special;
|
int special;
|
||||||
int startloc;
|
int startloc;
|
||||||
int varlen;
|
int varlen;
|
||||||
int easy;
|
int apply_ifs;
|
||||||
int quotes = flag & (EXP_FULL | EXP_CASE);
|
int quotes = flag & (EXP_FULL | EXP_CASE);
|
||||||
|
|
||||||
varflags = (unsigned char)*p++;
|
varflags = (unsigned char)*p++;
|
||||||
|
@ -613,6 +612,7 @@ evalvar(char *p, int flag)
|
||||||
var = p;
|
var = p;
|
||||||
special = !is_name(*p);
|
special = !is_name(*p);
|
||||||
p = strchr(p, '=') + 1;
|
p = strchr(p, '=') + 1;
|
||||||
|
|
||||||
again: /* jump here after setting a variable with ${var=text} */
|
again: /* jump here after setting a variable with ${var=text} */
|
||||||
if (special) {
|
if (special) {
|
||||||
set = varisset(var, varflags & VSNUL);
|
set = varisset(var, varflags & VSNUL);
|
||||||
|
@ -625,9 +625,11 @@ again: /* jump here after setting a variable with ${var=text} */
|
||||||
} else
|
} else
|
||||||
set = 1;
|
set = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
varlen = 0;
|
varlen = 0;
|
||||||
startloc = expdest - stackblock();
|
startloc = expdest - stackblock();
|
||||||
if (!set && uflag)
|
|
||||||
|
if (!set && uflag) {
|
||||||
switch (subtype) {
|
switch (subtype) {
|
||||||
case VSNORMAL:
|
case VSNORMAL:
|
||||||
case VSTRIMLEFT:
|
case VSTRIMLEFT:
|
||||||
|
@ -638,6 +640,8 @@ again: /* jump here after setting a variable with ${var=text} */
|
||||||
error("%.*s: parameter not set", p - var - 1, var);
|
error("%.*s: parameter not set", p - var - 1, var);
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (set && subtype != VSPLUS) {
|
if (set && subtype != VSPLUS) {
|
||||||
/* insert the value of the variable */
|
/* insert the value of the variable */
|
||||||
if (special) {
|
if (special) {
|
||||||
|
@ -653,8 +657,7 @@ again: /* jump here after setting a variable with ${var=text} */
|
||||||
if (subtype == VSLENGTH) {
|
if (subtype == VSLENGTH) {
|
||||||
for (;*val; val++)
|
for (;*val; val++)
|
||||||
varlen++;
|
varlen++;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
while (*val) {
|
while (*val) {
|
||||||
if (quotes && syntax[(int)*val] == CCTL)
|
if (quotes && syntax[(int)*val] == CCTL)
|
||||||
STPUTC(CTLESC, expdest);
|
STPUTC(CTLESC, expdest);
|
||||||
|
@ -665,34 +668,33 @@ again: /* jump here after setting a variable with ${var=text} */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subtype == VSPLUS)
|
|
||||||
set = ! set;
|
|
||||||
|
|
||||||
easy = ((varflags & VSQUOTE) == 0 ||
|
apply_ifs = ((varflags & VSQUOTE) == 0 ||
|
||||||
(*var == '@' && shellparam.nparam != 1));
|
(*var == '@' && shellparam.nparam != 1));
|
||||||
|
|
||||||
|
|
||||||
switch (subtype) {
|
switch (subtype) {
|
||||||
case VSLENGTH:
|
case VSLENGTH:
|
||||||
expdest = cvtnum(varlen, expdest);
|
expdest = cvtnum(varlen, expdest);
|
||||||
goto record;
|
break;
|
||||||
|
|
||||||
case VSNORMAL:
|
case VSNORMAL:
|
||||||
if (!easy)
|
|
||||||
break;
|
|
||||||
record:
|
|
||||||
recordregion(startloc, expdest - stackblock(),
|
|
||||||
varflags & VSQUOTE);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VSPLUS:
|
case VSPLUS:
|
||||||
|
set = !set;
|
||||||
|
/* FALLTHROUGH */
|
||||||
case VSMINUS:
|
case VSMINUS:
|
||||||
if (!set) {
|
if (!set) {
|
||||||
|
printf("VSMINUS: flag %x\n", flag);
|
||||||
argstr(p, flag);
|
argstr(p, flag);
|
||||||
break;
|
/*
|
||||||
|
* ${x-a b c} doesn't get split, but removing the
|
||||||
|
* 'apply_ifs = 0' apparantly breaks ${1+"$@"}..
|
||||||
|
* ${x-'a b' c} should generate 2 args.
|
||||||
|
*/
|
||||||
|
/* We should have marked stuff already */
|
||||||
|
apply_ifs = 0;
|
||||||
}
|
}
|
||||||
if (easy)
|
|
||||||
goto record;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VSTRIMLEFT:
|
case VSTRIMLEFT:
|
||||||
|
@ -714,31 +716,33 @@ record:
|
||||||
}
|
}
|
||||||
/* Remove any recorded regions beyond start of variable */
|
/* Remove any recorded regions beyond start of variable */
|
||||||
removerecordregions(startloc);
|
removerecordregions(startloc);
|
||||||
goto record;
|
apply_ifs = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case VSASSIGN:
|
case VSASSIGN:
|
||||||
case VSQUESTION:
|
case VSQUESTION:
|
||||||
if (!set) {
|
if (set)
|
||||||
if (subevalvar(p, var, 0, subtype, startloc,
|
|
||||||
varflags)) {
|
|
||||||
varflags &= ~VSNUL;
|
|
||||||
/*
|
|
||||||
* Remove any recorded regions beyond
|
|
||||||
* start of variable
|
|
||||||
*/
|
|
||||||
removerecordregions(startloc);
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
if (subevalvar(p, var, 0, subtype, startloc, varflags)) {
|
||||||
|
varflags &= ~VSNUL;
|
||||||
|
/*
|
||||||
|
* Remove any recorded regions beyond
|
||||||
|
* start of variable
|
||||||
|
*/
|
||||||
|
removerecordregions(startloc);
|
||||||
|
goto again;
|
||||||
}
|
}
|
||||||
if (easy)
|
apply_ifs = 0;
|
||||||
goto record;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (apply_ifs)
|
||||||
|
recordregion(startloc, expdest - stackblock(),
|
||||||
|
varflags & VSQUOTE);
|
||||||
|
|
||||||
if (subtype != VSNORMAL) { /* skip to end of alternative */
|
if (subtype != VSNORMAL) { /* skip to end of alternative */
|
||||||
int nesting = 1;
|
int nesting = 1;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -897,10 +901,13 @@ numvar:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
STATIC void
|
STATIC void
|
||||||
recordregion(int start, int end, int nulonly)
|
recordregion(int start, int end, int inquotes)
|
||||||
{
|
{
|
||||||
struct ifsregion *ifsp;
|
struct ifsregion *ifsp;
|
||||||
|
|
||||||
|
if (start == end)
|
||||||
|
return;
|
||||||
|
|
||||||
if (ifslastp == NULL) {
|
if (ifslastp == NULL) {
|
||||||
ifsp = &ifsfirst;
|
ifsp = &ifsfirst;
|
||||||
} else {
|
} else {
|
||||||
|
@ -911,7 +918,7 @@ recordregion(int start, int end, int nulonly)
|
||||||
ifslastp->next = NULL;
|
ifslastp->next = NULL;
|
||||||
ifslastp->begoff = start;
|
ifslastp->begoff = start;
|
||||||
ifslastp->endoff = end;
|
ifslastp->endoff = end;
|
||||||
ifslastp->nulonly = nulonly;
|
ifslastp->inquotes = inquotes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -930,76 +937,86 @@ ifsbreakup(char *string, struct arglist *arglist)
|
||||||
char *p;
|
char *p;
|
||||||
char *q;
|
char *q;
|
||||||
const char *ifs;
|
const char *ifs;
|
||||||
int ifsspc;
|
const char *ifsspc;
|
||||||
int nulonly;
|
int inquotes;
|
||||||
|
|
||||||
|
|
||||||
start = string;
|
start = string;
|
||||||
ifsspc = 0;
|
ifsspc = NULL;
|
||||||
nulonly = 0;
|
inquotes = 0;
|
||||||
if (ifslastp != NULL) {
|
|
||||||
ifsp = &ifsfirst;
|
if (ifslastp == NULL) {
|
||||||
do {
|
/* Return entire argument, IFS doesn't apply to any of it */
|
||||||
p = string + ifsp->begoff;
|
sp = (struct strlist *)stalloc(sizeof *sp);
|
||||||
nulonly = ifsp->nulonly;
|
sp->text = start;
|
||||||
ifs = nulonly ? nullstr :
|
*arglist->lastp = sp;
|
||||||
( ifsset() ? ifsval() : " \t\n" );
|
arglist->lastp = &sp->next;
|
||||||
ifsspc = 0;
|
return;
|
||||||
while (p < string + ifsp->endoff) {
|
}
|
||||||
q = p;
|
|
||||||
if (*p == CTLESC)
|
ifs = ifsset() ? ifsval() : " \t\n";
|
||||||
|
|
||||||
|
for (ifsp = &ifsfirst; ifsp != NULL; ifsp = ifsp->next) {
|
||||||
|
p = string + ifsp->begoff;
|
||||||
|
inquotes = ifsp->inquotes;
|
||||||
|
ifsspc = NULL;
|
||||||
|
while (p < string + ifsp->endoff) {
|
||||||
|
q = p;
|
||||||
|
if (*p == CTLESC)
|
||||||
|
p++;
|
||||||
|
if (inquotes) {
|
||||||
|
/* Only NULs (probably from "$@") end args */
|
||||||
|
if (*p != 0) {
|
||||||
p++;
|
p++;
|
||||||
if (strchr(ifs, *p)) {
|
continue;
|
||||||
if (!nulonly)
|
}
|
||||||
ifsspc = (strchr(" \t\n", *p) != NULL);
|
} else {
|
||||||
/* Ignore IFS whitespace at start */
|
if (!strchr(ifs, *p)) {
|
||||||
if (q == start && ifsspc) {
|
p++;
|
||||||
p++;
|
continue;
|
||||||
start = p;
|
}
|
||||||
continue;
|
ifsspc = strchr(" \t\n", *p);
|
||||||
}
|
|
||||||
*q = '\0';
|
/* Ignore IFS whitespace at start */
|
||||||
sp = (struct strlist *)stalloc(sizeof *sp);
|
if (q == start && ifsspc != NULL) {
|
||||||
sp->text = start;
|
|
||||||
*arglist->lastp = sp;
|
|
||||||
arglist->lastp = &sp->next;
|
|
||||||
p++;
|
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;
|
start = p;
|
||||||
} else
|
continue;
|
||||||
p++;
|
}
|
||||||
}
|
}
|
||||||
} while ((ifsp = ifsp->next) != NULL);
|
|
||||||
if (*start || (!ifsspc && start > string &&
|
/* Save this argument... */
|
||||||
(nulonly || 1))) {
|
*q = '\0';
|
||||||
sp = (struct strlist *)stalloc(sizeof *sp);
|
sp = (struct strlist *)stalloc(sizeof *sp);
|
||||||
sp->text = start;
|
sp->text = start;
|
||||||
*arglist->lastp = sp;
|
*arglist->lastp = sp;
|
||||||
arglist->lastp = &sp->next;
|
arglist->lastp = &sp->next;
|
||||||
|
p++;
|
||||||
|
|
||||||
|
if (!inquotes) {
|
||||||
|
/* Ignore trailing IFS writespace */
|
||||||
|
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) {
|
||||||
|
if (ifsspc == NULL) {
|
||||||
|
p = q;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ifsspc = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
start = p;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
/* Save anything left as an argument */
|
||||||
|
if (*start || (!ifsspc && start > string)) {
|
||||||
sp = (struct strlist *)stalloc(sizeof *sp);
|
sp = (struct strlist *)stalloc(sizeof *sp);
|
||||||
sp->text = start;
|
sp->text = start;
|
||||||
*arglist->lastp = sp;
|
*arglist->lastp = sp;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: expand.h,v 1.14 2003/08/07 09:05:32 agc Exp $ */
|
/* $NetBSD: expand.h,v 1.15 2004/06/26 14:09:58 dsl Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1991, 1993
|
* Copyright (c) 1991, 1993
|
||||||
|
@ -53,7 +53,7 @@ struct arglist {
|
||||||
#define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
|
#define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
|
||||||
#define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
|
#define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
|
||||||
#define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
|
#define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
|
||||||
#define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
|
#define EXP_IFS_SPLIT 0x20 /* need to record arguments for ifs breakup */
|
||||||
|
|
||||||
|
|
||||||
union node;
|
union node;
|
||||||
|
|
Loading…
Reference in New Issue