mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-02 22:11:54 +02:00
manual/9838
This commit is contained in:
parent
4d60fd3fea
commit
2b37049c22
20 changed files with 2440 additions and 2507 deletions
|
@ -1318,7 +1318,7 @@ pmjobdir(int job)
|
|||
{
|
||||
char *ret;
|
||||
|
||||
ret = dupstring(jobtab[job].pwd);
|
||||
ret = dupstring(jobtab[job].pwd ? jobtab[job].pwd : pwd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -2117,6 +2117,7 @@ static int
|
|||
bin_compquote(char *nam, char **args, char *ops, int func)
|
||||
{
|
||||
char *name;
|
||||
struct value vbuf;
|
||||
Value v;
|
||||
|
||||
/* Anything to do? */
|
||||
|
@ -2128,7 +2129,7 @@ bin_compquote(char *nam, char **args, char *ops, int func)
|
|||
|
||||
while ((name = *args++)) {
|
||||
name = dupstring(name);
|
||||
if ((v = getvalue(&name, 0))) {
|
||||
if ((v = getvalue(&vbuf, &name, 0))) {
|
||||
switch (PM_TYPE(v->pm->flags)) {
|
||||
case PM_SCALAR:
|
||||
{
|
||||
|
|
|
@ -732,6 +732,7 @@ static int
|
|||
bin_vared(char *name, char **args, char *ops, int func)
|
||||
{
|
||||
char *s, *t, *ova = varedarg;
|
||||
struct value vbuf;
|
||||
Value v;
|
||||
Param pm = 0;
|
||||
int create = 0, ifl;
|
||||
|
@ -809,7 +810,7 @@ bin_vared(char *name, char **args, char *ops, int func)
|
|||
}
|
||||
/* handle non-existent parameter */
|
||||
s = args[0];
|
||||
v = fetchvalue(&s, (!create || type == PM_SCALAR),
|
||||
v = fetchvalue(&vbuf, &s, (!create || type == PM_SCALAR),
|
||||
SCANPM_WANTKEYS|SCANPM_WANTVALS|SCANPM_MATCHMANY);
|
||||
if (!v && !create) {
|
||||
zwarnnam(name, "no such variable: %s", args[0], 0);
|
||||
|
|
|
@ -209,7 +209,7 @@ int
|
|||
execbuiltin(LinkList args, Builtin bn)
|
||||
{
|
||||
LinkNode n;
|
||||
char ops[MAX_OPS], *arg, *pp, *name, **argv, **oargv, *optstr;
|
||||
char ops[MAX_OPS], *arg, *pp, *name, *optstr;
|
||||
char *oxarg, *xarg = NULL;
|
||||
char typenumstr[] = TYPESET_OPTNUM;
|
||||
int flags, sense, argc = 0, execop, xtr = isset(XTRACE), lxarg = 0;
|
||||
|
@ -330,37 +330,42 @@ execbuiltin(LinkList args, Builtin bn)
|
|||
while (n)
|
||||
argc++, incnode(n);
|
||||
}
|
||||
/* Get the actual arguments, into argv. Oargv saves the *
|
||||
* beginning of the array for later reference. */
|
||||
oargv = argv = (char **)ncalloc(sizeof(char **) * (argc + 1));
|
||||
if ((*argv++ = arg))
|
||||
while ((*argv++ = (char *)ugetnode(args)));
|
||||
argv = oargv;
|
||||
if (errflag) {
|
||||
errflag = 0;
|
||||
return 1;
|
||||
}
|
||||
{
|
||||
VARARR(char *, argarr, (argc + 1));
|
||||
char **argv, **oargv;
|
||||
|
||||
/* check that the argument count lies within the specified bounds */
|
||||
if (argc < bn->minargs || (argc > bn->maxargs && bn->maxargs != -1)) {
|
||||
zwarnnam(name, (argc < bn->minargs)
|
||||
? "not enough arguments" : "too many arguments", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
/* Get the actual arguments, into argv. Oargv saves the *
|
||||
* beginning of the array for later reference. */
|
||||
oargv = argv = argarr;
|
||||
if ((*argv++ = arg))
|
||||
while ((*argv++ = (char *)ugetnode(args)));
|
||||
argv = oargv;
|
||||
if (errflag) {
|
||||
errflag = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* display execution trace information, if required */
|
||||
if (xtr) {
|
||||
printprompt4();
|
||||
fprintf(xtrerr, "%s", name);
|
||||
if (xarg)
|
||||
fprintf(xtrerr, " %s", xarg);
|
||||
while (*oargv)
|
||||
fprintf(xtrerr, " %s", *oargv++);
|
||||
fputc('\n', xtrerr);
|
||||
fflush(xtrerr);
|
||||
/* check that the argument count lies within the specified bounds */
|
||||
if (argc < bn->minargs || (argc > bn->maxargs && bn->maxargs != -1)) {
|
||||
zwarnnam(name, (argc < bn->minargs)
|
||||
? "not enough arguments" : "too many arguments", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* display execution trace information, if required */
|
||||
if (xtr) {
|
||||
printprompt4();
|
||||
fprintf(xtrerr, "%s", name);
|
||||
if (xarg)
|
||||
fprintf(xtrerr, " %s", xarg);
|
||||
while (*oargv)
|
||||
fprintf(xtrerr, " %s", *oargv++);
|
||||
fputc('\n', xtrerr);
|
||||
fflush(xtrerr);
|
||||
}
|
||||
/* call the handler function, and return its return value */
|
||||
return (*(bn->handlerfunc)) (name, argv, ops, bn->funcid);
|
||||
}
|
||||
/* call the handler function, and return its return value */
|
||||
return (*(bn->handlerfunc)) (name, argv, ops, bn->funcid);
|
||||
}
|
||||
|
||||
/* Enable/disable an element in one of the internal hash tables. *
|
||||
|
@ -704,12 +709,14 @@ bin_cd(char *nam, char **argv, char *ops, int func)
|
|||
cd_new_pwd(func, dir);
|
||||
|
||||
if (stat(unmeta(pwd), &st1) < 0) {
|
||||
setjobpwd();
|
||||
zsfree(pwd);
|
||||
pwd = metafy(zgetcwd(), -1, META_DUP);
|
||||
} else if (stat(".", &st2) < 0)
|
||||
chdir(unmeta(pwd));
|
||||
else if (st1.st_ino != st2.st_ino || st1.st_dev != st2.st_dev) {
|
||||
if (chasinglinks) {
|
||||
setjobpwd();
|
||||
zsfree(pwd);
|
||||
pwd = metafy(zgetcwd(), -1, META_DUP);
|
||||
} else {
|
||||
|
@ -1004,6 +1011,7 @@ cd_new_pwd(int func, LinkNode dir)
|
|||
current (i.e. new) pwd */
|
||||
zsfree(oldpwd);
|
||||
oldpwd = pwd;
|
||||
setjobpwd();
|
||||
pwd = new_pwd;
|
||||
set_pwd_env();
|
||||
|
||||
|
@ -2154,7 +2162,7 @@ mkautofn(Shfunc shf)
|
|||
p->pats = NULL;
|
||||
p->heap = 0;
|
||||
|
||||
p->prog[0] = WCB_LIST(Z_SYNC | Z_END);
|
||||
p->prog[0] = WCB_LIST((Z_SYNC | Z_END), 0);
|
||||
p->prog[1] = WCB_SUBLIST(WC_SUBLIST_END, 0, 3);
|
||||
p->prog[2] = WCB_PIPE(WC_PIPE_END, 0);
|
||||
p->prog[3] = WCB_AUTOFN();
|
||||
|
|
67
Src/cond.c
67
Src/cond.c
|
@ -42,10 +42,17 @@ int
|
|||
evalcond(Estate state)
|
||||
{
|
||||
struct stat *st;
|
||||
char *left, *right = NULL;
|
||||
Wordcode pcode = state->pc++;
|
||||
wordcode code = *pcode;
|
||||
int ctype = WC_COND_TYPE(code);
|
||||
char *left, *right;
|
||||
Wordcode pcode;
|
||||
wordcode code;
|
||||
int ctype, htok = 0;
|
||||
|
||||
rec:
|
||||
|
||||
left = right = NULL;
|
||||
pcode = state->pc++;
|
||||
code = *pcode;
|
||||
ctype = WC_COND_TYPE(code);
|
||||
|
||||
switch (ctype) {
|
||||
case COND_NOT:
|
||||
|
@ -56,7 +63,7 @@ evalcond(Estate state)
|
|||
if (evalcond(state)) {
|
||||
if (tracingcond)
|
||||
fprintf(xtrerr, " %s", condstr[ctype]);
|
||||
return evalcond(state);
|
||||
goto rec;
|
||||
} else {
|
||||
state->pc = pcode + (WC_COND_SKIP(code) + 1);
|
||||
return 0;
|
||||
|
@ -65,7 +72,7 @@ evalcond(Estate state)
|
|||
if (!evalcond(state)) {
|
||||
if (tracingcond)
|
||||
fprintf(xtrerr, " %s", condstr[ctype]);
|
||||
return evalcond(state);
|
||||
goto rec;
|
||||
} else {
|
||||
state->pc = pcode + (WC_COND_SKIP(code) + 1);
|
||||
return 1;
|
||||
|
@ -74,16 +81,16 @@ evalcond(Estate state)
|
|||
case COND_MODI:
|
||||
{
|
||||
Conddef cd;
|
||||
char *name = ecgetstr(state, 0), **strs;
|
||||
char *name = ecgetstr(state, EC_NODUP, NULL), **strs;
|
||||
int l = WC_COND_SKIP(code);
|
||||
|
||||
if (ctype == COND_MOD)
|
||||
strs = ecgetarr(state, l, 1);
|
||||
strs = ecgetarr(state, l, EC_DUP, NULL);
|
||||
else {
|
||||
char *sbuf[3];
|
||||
|
||||
sbuf[0] = ecgetstr(state, 0);
|
||||
sbuf[1] = ecgetstr(state, 0);
|
||||
sbuf[0] = ecgetstr(state, EC_NODUP, NULL);
|
||||
sbuf[1] = ecgetstr(state, EC_NODUP, NULL);
|
||||
sbuf[2] = NULL;
|
||||
|
||||
strs = arrdup(sbuf);
|
||||
|
@ -120,19 +127,23 @@ evalcond(Estate state)
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
left = ecgetstr(state, 1);
|
||||
singsub(&left);
|
||||
untokenize(left);
|
||||
left = ecgetstr(state, EC_DUPTOK, &htok);
|
||||
if (htok) {
|
||||
singsub(&left);
|
||||
untokenize(left);
|
||||
}
|
||||
if (ctype <= COND_GE && ctype != COND_STREQ && ctype != COND_STRNEQ) {
|
||||
right = ecgetstr(state, 1);
|
||||
singsub(&right);
|
||||
untokenize(right);
|
||||
right = ecgetstr(state, EC_DUPTOK, &htok);
|
||||
if (htok) {
|
||||
singsub(&right);
|
||||
untokenize(right);
|
||||
}
|
||||
}
|
||||
if (tracingcond) {
|
||||
if (ctype < COND_MOD) {
|
||||
char *rt = (char *) right;
|
||||
if (ctype == COND_STREQ || ctype == COND_STRNEQ) {
|
||||
rt = dupstring(ecrawstr(state->prog, state->pc));
|
||||
rt = dupstring(ecrawstr(state->prog, state->pc, NULL));
|
||||
singsub(&rt);
|
||||
untokenize(rt);
|
||||
}
|
||||
|
@ -191,8 +202,10 @@ evalcond(Estate state)
|
|||
char *opat;
|
||||
int save;
|
||||
|
||||
right = opat = dupstring(ecrawstr(state->prog, state->pc));
|
||||
singsub(&right);
|
||||
right = opat = dupstring(ecrawstr(state->prog, state->pc,
|
||||
&htok));
|
||||
if (htok)
|
||||
singsub(&right);
|
||||
save = (!state->prog->heap &&
|
||||
!strcmp(opat, right) && pprog != dummy_patprog2);
|
||||
|
||||
|
@ -370,10 +383,11 @@ cond_str(char **args, int num, int raw)
|
|||
{
|
||||
char *s = args[num];
|
||||
|
||||
singsub(&s);
|
||||
if (!raw)
|
||||
untokenize(s);
|
||||
|
||||
if (has_token(s)) {
|
||||
singsub(&s);
|
||||
if (!raw)
|
||||
untokenize(s);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
@ -383,9 +397,10 @@ cond_val(char **args, int num)
|
|||
{
|
||||
char *s = args[num];
|
||||
|
||||
singsub(&s);
|
||||
untokenize(s);
|
||||
|
||||
if (has_token(s)) {
|
||||
singsub(&s);
|
||||
untokenize(s);
|
||||
}
|
||||
return mathevali(s);
|
||||
}
|
||||
|
||||
|
|
164
Src/exec.c
164
Src/exec.c
|
@ -134,6 +134,14 @@ mod_export Funcstack funcstack;
|
|||
static LinkList args;
|
||||
static int doneps4;
|
||||
|
||||
/* Execution functions. */
|
||||
|
||||
static int (*execfuncs[]) _((Estate, int)) = {
|
||||
execcursh, exectime, execfuncdef, execfor, execselect,
|
||||
execwhile, execrepeat, execcase, execif, execcond,
|
||||
execarith, execautofn
|
||||
};
|
||||
|
||||
/* parse string into a list */
|
||||
|
||||
/**/
|
||||
|
@ -713,6 +721,33 @@ execode(Eprog p, int dont_change_job, int exiting)
|
|||
execlist(&s, dont_change_job, exiting);
|
||||
}
|
||||
|
||||
/* Execute a simplified command. This is used to execute things that
|
||||
* will run completely in the shell, so that we can by-pass all that
|
||||
* nasty job-handling and redirection stuff in execpline and execcmd. */
|
||||
|
||||
/**/
|
||||
static int
|
||||
execsimple(Estate state)
|
||||
{
|
||||
wordcode code = *state->pc++;
|
||||
|
||||
if (code)
|
||||
lineno = code - 1;
|
||||
|
||||
code = wc_code(*state->pc++);
|
||||
|
||||
if (code == WC_ASSIGN) {
|
||||
cmdoutval = 0;
|
||||
addvars(state, state->pc - 1, 0);
|
||||
if (isset(XTRACE)) {
|
||||
fputc('\n', xtrerr);
|
||||
fflush(xtrerr);
|
||||
}
|
||||
return (lastval = (errflag ? errflag : cmdoutval));
|
||||
} else
|
||||
return (lastval = (execfuncs[code - WC_CURSH])(state, 0));
|
||||
}
|
||||
|
||||
/* Main routine for executing a list. *
|
||||
* exiting means that the (sub)shell we are in is a definite goner *
|
||||
* after the current list is finished, so we may be able to exec the *
|
||||
|
@ -749,11 +784,18 @@ execlist(Estate state, int dont_change_job, int exiting)
|
|||
* semi-colon or ampersand (`sublists'). */
|
||||
code = *state->pc++;
|
||||
while (wc_code(code) == WC_LIST && !breaks && !retflag) {
|
||||
ltype = WC_LIST_TYPE(code);
|
||||
csp = cmdsp;
|
||||
|
||||
if (ltype & Z_SIMPLE) {
|
||||
next = state->pc + WC_LIST_SKIP(code);
|
||||
execsimple(state);
|
||||
state->pc = next;
|
||||
goto sublist_done;
|
||||
}
|
||||
/* Reset donetrap: this ensures that a trap is only *
|
||||
* called once for each sublist that fails. */
|
||||
donetrap = 0;
|
||||
csp = cmdsp;
|
||||
ltype = WC_LIST_TYPE(code);
|
||||
|
||||
/* Loop through code followed by &&, ||, or end of sublist. */
|
||||
code = *state->pc++;
|
||||
|
@ -764,14 +806,19 @@ execlist(Estate state, int dont_change_job, int exiting)
|
|||
switch (WC_SUBLIST_TYPE(code)) {
|
||||
case WC_SUBLIST_END:
|
||||
/* End of sublist; just execute, ignoring status. */
|
||||
execpline(state, code, ltype, (ltype & Z_END) && exiting);
|
||||
if (WC_SUBLIST_FLAGS(code) & WC_SUBLIST_SIMPLE)
|
||||
execsimple(state);
|
||||
else
|
||||
execpline(state, code, ltype, (ltype & Z_END) && exiting);
|
||||
state->pc = next;
|
||||
goto sublist_done;
|
||||
break;
|
||||
case WC_SUBLIST_AND:
|
||||
/* If the return code is non-zero, we skip pipelines until *
|
||||
* we find a sublist followed by ORNEXT. */
|
||||
if ((ret = execpline(state, code, Z_SYNC, 0))) {
|
||||
if ((ret = ((WC_SUBLIST_FLAGS(code) & WC_SUBLIST_SIMPLE) ?
|
||||
execsimple(state) :
|
||||
execpline(state, code, Z_SYNC, 0)))) {
|
||||
state->pc = next;
|
||||
code = *state->pc++;
|
||||
next = state->pc + WC_SUBLIST_SKIP(code);
|
||||
|
@ -794,7 +841,9 @@ execlist(Estate state, int dont_change_job, int exiting)
|
|||
case WC_SUBLIST_OR:
|
||||
/* If the return code is zero, we skip pipelines until *
|
||||
* we find a sublist followed by ANDNEXT. */
|
||||
if (!(ret = execpline(state, code, Z_SYNC, 0))) {
|
||||
if (!(ret = ((WC_SUBLIST_FLAGS(code) & WC_SUBLIST_SIMPLE) ?
|
||||
execsimple(state) :
|
||||
execpline(state, code, Z_SYNC, 0)))) {
|
||||
state->pc = next;
|
||||
code = *state->pc++;
|
||||
next = state->pc + WC_SUBLIST_SKIP(code);
|
||||
|
@ -1190,6 +1239,7 @@ makecline(LinkList list)
|
|||
/* A bigger argv is necessary for executing scripts */
|
||||
ptr = argv = 2 + (char **) ncalloc((countlinknodes(list) + 4) *
|
||||
sizeof(char *));
|
||||
|
||||
if (isset(XTRACE)) {
|
||||
if (!doneps4)
|
||||
printprompt4();
|
||||
|
@ -1390,10 +1440,11 @@ static void
|
|||
addvars(Estate state, Wordcode pc, int export)
|
||||
{
|
||||
LinkList vl;
|
||||
int xtr, isstr;
|
||||
int xtr, isstr, htok = 0;
|
||||
char **arr, **ptr, *name;
|
||||
Wordcode opc = state->pc;
|
||||
wordcode ac;
|
||||
local_list1(svl);
|
||||
|
||||
xtr = isset(XTRACE);
|
||||
if (xtr) {
|
||||
|
@ -1402,17 +1453,18 @@ addvars(Estate state, Wordcode pc, int export)
|
|||
}
|
||||
state->pc = pc;
|
||||
while (wc_code(ac = *state->pc++) == WC_ASSIGN) {
|
||||
name = ecgetstr(state, 1);
|
||||
untokenize(name);
|
||||
name = ecgetstr(state, EC_DUPTOK, &htok);
|
||||
if (htok)
|
||||
untokenize(name);
|
||||
if (xtr)
|
||||
fprintf(xtrerr, "%s=", name);
|
||||
if ((isstr = (WC_ASSIGN_TYPE(ac) == WC_ASSIGN_SCALAR))) {
|
||||
vl = newlinklist();
|
||||
addlinknode(vl, ecgetstr(state, 1));
|
||||
init_list1(svl, ecgetstr(state, EC_DUPTOK, &htok));
|
||||
vl = &svl;
|
||||
} else
|
||||
vl = ecgetlist(state, WC_ASSIGN_NUM(ac), 1);
|
||||
vl = ecgetlist(state, WC_ASSIGN_NUM(ac), EC_DUPTOK, &htok);
|
||||
|
||||
if (vl) {
|
||||
if (vl && htok) {
|
||||
prefork(vl, (isstr ? (PF_SINGLE|PF_ASSIGN) :
|
||||
PF_ASSIGN));
|
||||
if (errflag) {
|
||||
|
@ -1490,17 +1542,19 @@ void
|
|||
setunderscore(char *str)
|
||||
{
|
||||
if (str && *str) {
|
||||
int l = strlen(str) + 1;
|
||||
int l = strlen(str) + 1, nl = (l + 31) & ~31;
|
||||
|
||||
if (l > underscorelen || l < (underscorelen >> 2)) {
|
||||
if (nl > underscorelen || (underscorelen - nl) > 64) {
|
||||
zfree(underscore, underscorelen);
|
||||
underscore = (char *) zalloc(underscorelen = l);
|
||||
underscore = (char *) zalloc(underscorelen = nl);
|
||||
}
|
||||
strcpy(underscore, str);
|
||||
underscoreused = l;
|
||||
} else {
|
||||
zfree(underscore, underscorelen);
|
||||
underscore = (char *) zalloc(underscorelen = 32);
|
||||
if (underscorelen > 128) {
|
||||
zfree(underscore, underscorelen);
|
||||
underscore = (char *) zalloc(underscorelen = 32);
|
||||
}
|
||||
*underscore = '\0';
|
||||
underscoreused = 1;
|
||||
}
|
||||
|
@ -1537,7 +1591,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
|
|||
struct multio *mfds[10];
|
||||
char *text;
|
||||
int save[10];
|
||||
int fil, dfil, is_cursh, type, do_exec = 0, i;
|
||||
int fil, dfil, is_cursh, type, do_exec = 0, i, htok = 0;
|
||||
int nullexec = 0, assign = 0, forked = 0;
|
||||
int is_shfunc = 0, is_builtin = 0, is_exec = 0;
|
||||
/* Various flags to the command. */
|
||||
|
@ -1560,8 +1614,11 @@ execcmd(Estate state, int input, int output, int how, int last1)
|
|||
|
||||
type = wc_code(code);
|
||||
|
||||
/* It would be nice if we could use EC_DUPTOK instead of EC_DUP here.
|
||||
* But for that we would need to check/change all builtins so that
|
||||
* they don't modify their argument strings. */
|
||||
args = (type == WC_SIMPLE ?
|
||||
ecgetlist(state, WC_SIMPLE_ARGC(code), 1) : NULL);
|
||||
ecgetlist(state, WC_SIMPLE_ARGC(code), EC_DUP, &htok) : NULL);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
save[i] = -2;
|
||||
|
@ -1633,7 +1690,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
|
|||
|
||||
/* Do prefork substitutions */
|
||||
esprefork = (assign || isset(MAGICEQUALSUBST)) ? PF_TYPESET : 0;
|
||||
if (args)
|
||||
if (args && htok)
|
||||
prefork(args, esprefork);
|
||||
|
||||
if (type == WC_SIMPLE) {
|
||||
|
@ -1890,7 +1947,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
|
|||
wordcode ac;
|
||||
|
||||
while (wc_code(ac = *p) == WC_ASSIGN) {
|
||||
if (!strcmp(ecrawstr(state->prog, p + 1), "STTY")) {
|
||||
if (!strcmp(ecrawstr(state->prog, p + 1, NULL), "STTY")) {
|
||||
jobtab[thisjob].stty_in_env = 1;
|
||||
break;
|
||||
}
|
||||
|
@ -1926,7 +1983,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
|
|||
is_exec = 1;
|
||||
}
|
||||
|
||||
if ((esglob = !(cflags & BINF_NOGLOB)) && args) {
|
||||
if ((esglob = !(cflags & BINF_NOGLOB)) && args && htok) {
|
||||
LinkList oargs = args;
|
||||
globlist(args, 0);
|
||||
args = oargs;
|
||||
|
@ -2087,7 +2144,8 @@ execcmd(Estate state, int input, int output, int how, int last1)
|
|||
/* We are done with redirection. close the mnodes, *
|
||||
* spawning tee/cat processes as necessary. */
|
||||
for (i = 0; i < 10; i++)
|
||||
closemn(mfds, i);
|
||||
if (mfds[i] && mfds[i]->ct >= 2)
|
||||
closemn(mfds, i);
|
||||
|
||||
if (nullexec) {
|
||||
if (nullexec == 1) {
|
||||
|
@ -2120,15 +2178,9 @@ execcmd(Estate state, int input, int output, int how, int last1)
|
|||
if (is_exec)
|
||||
entersubsh(how, (type != WC_SUBSH) ? 2 : 1, 1);
|
||||
if (type >= WC_CURSH) {
|
||||
static int (*func[]) _((Estate, int)) = {
|
||||
execcursh, exectime, execfuncdef, execfor, execselect,
|
||||
execwhile, execrepeat, execcase, execif, execcond,
|
||||
execarith, execautofn
|
||||
};
|
||||
|
||||
if (last1 == 1)
|
||||
do_exec = 1;
|
||||
lastval = (func[type - WC_CURSH])(state, do_exec);
|
||||
lastval = (execfuncs[type - WC_CURSH])(state, do_exec);
|
||||
} else if (is_builtin || is_shfunc) {
|
||||
LinkList restorelist = 0, removelist = 0;
|
||||
/* builtin or shell function */
|
||||
|
@ -2136,16 +2188,20 @@ execcmd(Estate state, int input, int output, int how, int last1)
|
|||
if (!forked && ((cflags & BINF_COMMAND) ||
|
||||
(unset(POSIXBUILTINS) && !assign) ||
|
||||
(isset(POSIXBUILTINS) && !is_shfunc &&
|
||||
!(hn->flags & BINF_PSPECIAL))))
|
||||
save_params(state, varspc, &restorelist, &removelist);
|
||||
|
||||
!(hn->flags & BINF_PSPECIAL)))) {
|
||||
if (varspc)
|
||||
save_params(state, varspc, &restorelist, &removelist);
|
||||
else
|
||||
restorelist = removelist = NULL;
|
||||
}
|
||||
if (varspc) {
|
||||
/* Export this if the command is a shell function,
|
||||
* but not if it's a builtin.
|
||||
*/
|
||||
addvars(state, varspc, is_shfunc);
|
||||
if (errflag) {
|
||||
restore_params(restorelist, removelist);
|
||||
if (restorelist)
|
||||
restore_params(restorelist, removelist);
|
||||
lastval = 1;
|
||||
fixfds(save);
|
||||
goto done;
|
||||
|
@ -2204,7 +2260,8 @@ execcmd(Estate state, int input, int output, int how, int last1)
|
|||
savehistfile(NULL, 1, HFILE_USE_OPTIONS);
|
||||
exit(lastval);
|
||||
}
|
||||
restore_params(restorelist, removelist);
|
||||
if (restorelist)
|
||||
restore_params(restorelist, removelist);
|
||||
|
||||
} else {
|
||||
if (!forked)
|
||||
|
@ -2271,15 +2328,11 @@ save_params(Estate state, Wordcode pc, LinkList *restore_p, LinkList *remove_p)
|
|||
|
||||
MUSTUSEHEAP("save_params()");
|
||||
|
||||
if (!pc) {
|
||||
*restore_p = *remove_p = NULL;
|
||||
return;
|
||||
}
|
||||
*restore_p = newlinklist();
|
||||
*remove_p = newlinklist();
|
||||
|
||||
while (wc_code(ac = *pc) == WC_ASSIGN) {
|
||||
s = ecrawstr(state->prog, pc + 1);
|
||||
s = ecrawstr(state->prog, pc + 1, NULL);
|
||||
if ((pm = (Param) paramtab->getnode(paramtab, s))) {
|
||||
if (!(pm->flags & PM_SPECIAL)) {
|
||||
paramtab->removenode(paramtab, s);
|
||||
|
@ -2309,14 +2362,12 @@ restore_params(LinkList restorelist, LinkList removelist)
|
|||
Param pm;
|
||||
char *s;
|
||||
|
||||
if (removelist) {
|
||||
/* remove temporary parameters */
|
||||
while ((s = (char *) ugetnode(removelist))) {
|
||||
if ((pm = (Param) paramtab->getnode(paramtab, s)) &&
|
||||
!(pm->flags & PM_SPECIAL)) {
|
||||
pm->flags &= ~PM_READONLY;
|
||||
unsetparam_pm(pm, 0, 0);
|
||||
}
|
||||
/* remove temporary parameters */
|
||||
while ((s = (char *) ugetnode(removelist))) {
|
||||
if ((pm = (Param) paramtab->getnode(paramtab, s)) &&
|
||||
!(pm->flags & PM_SPECIAL)) {
|
||||
pm->flags &= ~PM_READONLY;
|
||||
unsetparam_pm(pm, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2560,7 +2611,7 @@ getoutput(char *cmd, int qt)
|
|||
wc_code(pc[6]) == WC_SIMPLE && !WC_SIMPLE_ARGC(pc[6])) {
|
||||
/* $(< word) */
|
||||
int stream;
|
||||
char *s = dupstring(ecrawstr(prog, pc + 5));
|
||||
char *s = dupstring(ecrawstr(prog, pc + 5, NULL));
|
||||
|
||||
singsub(&s);
|
||||
if (errflag)
|
||||
|
@ -2908,13 +2959,15 @@ execarith(Estate state, int do_exec)
|
|||
{
|
||||
char *e;
|
||||
zlong val = 0;
|
||||
int htok = 0;
|
||||
|
||||
if (isset(XTRACE)) {
|
||||
printprompt4();
|
||||
fprintf(xtrerr, "((");
|
||||
}
|
||||
e = ecgetstr(state, 1);
|
||||
singsub(&e);
|
||||
e = ecgetstr(state, EC_DUPTOK, &htok);
|
||||
if (htok)
|
||||
singsub(&e);
|
||||
if (isset(XTRACE))
|
||||
fprintf(xtrerr, " %s", e);
|
||||
|
||||
|
@ -2954,21 +3007,22 @@ execfuncdef(Estate state, int do_exec)
|
|||
{
|
||||
Shfunc shf;
|
||||
char *s;
|
||||
int signum, nprg, npats, len, plen, i;
|
||||
int signum, nprg, npats, len, plen, i, htok = 0;
|
||||
Wordcode beg = state->pc, end;
|
||||
Eprog prog;
|
||||
Patprog *pp;
|
||||
LinkList names;
|
||||
|
||||
end = beg + WC_FUNCDEF_SKIP(state->pc[-1]);
|
||||
names = ecgetlist(state, *state->pc++, 1);
|
||||
names = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok);
|
||||
nprg = *state->pc++ - 4;
|
||||
npats = *state->pc++;
|
||||
|
||||
plen = (end - state->pc) * sizeof(wordcode);
|
||||
len = plen + (npats * sizeof(Patprog));
|
||||
|
||||
execsubst(names);
|
||||
if (htok)
|
||||
execsubst(names);
|
||||
|
||||
PERMALLOC {
|
||||
while ((s = (char *) ugetnode(names))) {
|
||||
|
@ -3346,7 +3400,7 @@ stripkshdef(Eprog prog, char *name)
|
|||
return prog;
|
||||
code = *pc++;
|
||||
if (wc_code(code) != WC_FUNCDEF ||
|
||||
*pc != 1 || strcmp(name, ecrawstr(prog, pc + 1)))
|
||||
*pc != 1 || strcmp(name, ecrawstr(prog, pc + 1, NULL)))
|
||||
return prog;
|
||||
|
||||
{
|
||||
|
|
23
Src/glob.c
23
Src/glob.c
|
@ -1482,15 +1482,15 @@ hasbraces(char *str)
|
|||
if (isset(BRACECCL)) {
|
||||
/* In this case, any properly formed brace expression *
|
||||
* will match and expand to the characters in between. */
|
||||
int bc;
|
||||
int bc, c;
|
||||
|
||||
for (bc = 0; *str; ++str)
|
||||
if (*str == Inbrace) {
|
||||
for (bc = 0; (c = *str); ++str)
|
||||
if (c == Inbrace) {
|
||||
if (!bc && str[1] == Outbrace)
|
||||
*str++ = '{', *str = '}';
|
||||
else
|
||||
bc++;
|
||||
} else if (*str == Outbrace) {
|
||||
} else if (c == Outbrace) {
|
||||
if (!bc)
|
||||
*str = '}';
|
||||
else if (!--bc)
|
||||
|
@ -1568,24 +1568,23 @@ hasbraces(char *str)
|
|||
int
|
||||
xpandredir(struct redir *fn, LinkList tab)
|
||||
{
|
||||
LinkList fake;
|
||||
char *nam;
|
||||
struct redir *ff;
|
||||
int ret = 0;
|
||||
local_list1(fake);
|
||||
|
||||
/* Stick the name in a list... */
|
||||
fake = newlinklist();
|
||||
addlinknode(fake, fn->name);
|
||||
init_list1(fake, fn->name);
|
||||
/* ...which undergoes all the usual shell expansions */
|
||||
prefork(fake, isset(MULTIOS) ? 0 : PF_SINGLE);
|
||||
prefork(&fake, isset(MULTIOS) ? 0 : PF_SINGLE);
|
||||
/* Globbing is only done for multios. */
|
||||
if (!errflag && isset(MULTIOS))
|
||||
globlist(fake, 0);
|
||||
globlist(&fake, 0);
|
||||
if (errflag)
|
||||
return 0;
|
||||
if (nonempty(fake) && !nextnode(firstnode(fake))) {
|
||||
if (nonempty(&fake) && !nextnode(firstnode(&fake))) {
|
||||
/* Just one match, the usual case. */
|
||||
char *s = peekfirst(fake);
|
||||
char *s = peekfirst(&fake);
|
||||
fn->name = s;
|
||||
untokenize(s);
|
||||
if (fn->type == MERGEIN || fn->type == MERGEOUT) {
|
||||
|
@ -1609,7 +1608,7 @@ xpandredir(struct redir *fn, LinkList tab)
|
|||
else {
|
||||
if (fn->type == MERGEOUT)
|
||||
fn->type = ERRWRITE;
|
||||
while ((nam = (char *)ugetnode(fake))) {
|
||||
while ((nam = (char *)ugetnode(&fake))) {
|
||||
/* Loop over matches, duplicating the *
|
||||
* redirection for each file found. */
|
||||
ff = (struct redir *)alloc(sizeof *ff);
|
||||
|
|
|
@ -80,10 +80,10 @@ static HashTable firstht, lastht;
|
|||
mod_export unsigned
|
||||
hasher(char *str)
|
||||
{
|
||||
unsigned hashval = 0;
|
||||
unsigned hashval = 0, c;
|
||||
|
||||
while (*str)
|
||||
hashval += (hashval << 5) + *(unsigned char *)str++;
|
||||
while ((c = *((unsigned char *) str++)))
|
||||
hashval += (hashval << 5) + c;
|
||||
|
||||
return hashval;
|
||||
}
|
||||
|
|
|
@ -82,6 +82,11 @@ mod_export int hasam;
|
|||
/**/
|
||||
mod_export int (*getkeyptr) _((int));
|
||||
|
||||
/* SIGCHLD mask */
|
||||
|
||||
/**/
|
||||
mod_export sigset_t sigchld_mask;
|
||||
|
||||
#ifdef DEBUG
|
||||
/* depth of allocation type stack */
|
||||
|
||||
|
@ -761,6 +766,8 @@ setupvals(void)
|
|||
void
|
||||
init_signals(void)
|
||||
{
|
||||
sigchld_mask = signal_mask(SIGCHLD);
|
||||
|
||||
intr();
|
||||
|
||||
#ifndef QDEBUG
|
||||
|
|
37
Src/jobs.c
37
Src/jobs.c
|
@ -54,7 +54,7 @@ int prevjob;
|
|||
|
||||
/**/
|
||||
mod_export struct job jobtab[MAXJOB];
|
||||
|
||||
|
||||
/* shell timings */
|
||||
|
||||
/**/
|
||||
|
@ -556,6 +556,7 @@ dumptime(Job jn)
|
|||
static int
|
||||
should_report_time(Job j)
|
||||
{
|
||||
struct value vbuf;
|
||||
Value v;
|
||||
char *s = "REPORTTIME";
|
||||
int reporttime;
|
||||
|
@ -565,7 +566,8 @@ should_report_time(Job j)
|
|||
return 1;
|
||||
|
||||
HEAPALLOC {
|
||||
if (!(v = getvalue(&s, 0)) || (reporttime = getintvalue(v)) < 0) {
|
||||
if (!(v = getvalue(&vbuf, &s, 0)) ||
|
||||
(reporttime = getintvalue(v)) < 0) {
|
||||
LASTALLOC_RETURN 0;
|
||||
}
|
||||
} LASTALLOC;
|
||||
|
@ -717,7 +719,8 @@ printjob(Job jn, int lng, int synch)
|
|||
* the directory where the job is running, otherwise the current directory
|
||||
*/
|
||||
|
||||
if ((lng & 4) || (interact && job == thisjob && strcmp(jn->pwd, pwd))) {
|
||||
if ((lng & 4) || (interact && job == thisjob &&
|
||||
jn->pwd && strcmp(jn->pwd, pwd))) {
|
||||
fprintf(shout, "(pwd %s: ", (lng & 4) ? "" : "now");
|
||||
fprintdir((lng & 4) ? jn->pwd : pwd, shout);
|
||||
fprintf(shout, ")\n");
|
||||
|
@ -774,7 +777,9 @@ deletejob(Job jn)
|
|||
|
||||
if (jn->ty)
|
||||
zfree(jn->ty, sizeof(struct ttyinfo));
|
||||
|
||||
if (jn->pwd)
|
||||
zsfree(jn->pwd);
|
||||
jn->pwd = NULL;
|
||||
if (jn->stat & STAT_WASSUPER)
|
||||
deletejob(jobtab + jn->other);
|
||||
jn->gleader = jn->other = 0;
|
||||
|
@ -945,11 +950,8 @@ initjob(void)
|
|||
for (i = 1; i < MAXJOB; i++)
|
||||
if (!jobtab[i].stat) {
|
||||
jobtab[i].stat = STAT_INUSE;
|
||||
if (strlen(pwd) >= PATH_MAX) {
|
||||
memcpy(jobtab[i].pwd, pwd, PATH_MAX);
|
||||
jobtab[i].pwd[PATH_MAX] = '\0';
|
||||
} else
|
||||
strcpy(jobtab[i].pwd, pwd);
|
||||
if (jobtab[i].pwd)
|
||||
zsfree(jobtab[i].pwd);
|
||||
jobtab[i].gleader = 0;
|
||||
return i;
|
||||
}
|
||||
|
@ -958,6 +960,21 @@ initjob(void)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/**/
|
||||
void
|
||||
setjobpwd(void)
|
||||
{
|
||||
int i, l;
|
||||
|
||||
for (i = 1; i < MAXJOB; i++)
|
||||
if (jobtab[i].stat && !jobtab[i].pwd) {
|
||||
if ((l = strlen(pwd)) >= PATH_MAX)
|
||||
jobtab[i].pwd = ztrdup(pwd + l - PATH_MAX);
|
||||
else
|
||||
jobtab[i].pwd = ztrdup(pwd);
|
||||
}
|
||||
}
|
||||
|
||||
/* print pids for & */
|
||||
|
||||
/**/
|
||||
|
@ -1302,7 +1319,7 @@ bin_fg(char *name, char **argv, char *ops, int func)
|
|||
/* for bg and fg -- show the job we are operating on */
|
||||
printjob(jobtab + job, (stopped) ? -1 : 0, 1);
|
||||
if (func != BIN_BG) { /* fg or wait */
|
||||
if (strcmp(jobtab[job].pwd, pwd)) {
|
||||
if (jobtab[job].pwd && strcmp(jobtab[job].pwd, pwd)) {
|
||||
fprintf(shout, "(pwd : ");
|
||||
fprintdir(jobtab[job].pwd, shout);
|
||||
fprintf(shout, ")\n");
|
||||
|
|
115
Src/lex.c
115
Src/lex.c
|
@ -191,6 +191,11 @@ struct lexstack {
|
|||
void (*hwend) _((void));
|
||||
void (*addtoline) _((int));
|
||||
|
||||
int eclen, ecused, ecfree, ecnpats;
|
||||
Wordcode ecbuf;
|
||||
Eccstr ecstrs;
|
||||
int ecsoffs;
|
||||
|
||||
unsigned char *cstack;
|
||||
int csp;
|
||||
};
|
||||
|
@ -243,6 +248,13 @@ lexsave(void)
|
|||
ls->hwbegin = hwbegin;
|
||||
ls->hwend = hwend;
|
||||
ls->addtoline = addtoline;
|
||||
ls->eclen = eclen;
|
||||
ls->ecused = ecused;
|
||||
ls->ecfree = ecfree;
|
||||
ls->ecnpats = ecnpats;
|
||||
ls->ecbuf = ecbuf;
|
||||
ls->ecstrs = ecstrs;
|
||||
ls->ecsoffs = ecsoffs;
|
||||
cmdsp = 0;
|
||||
inredir = 0;
|
||||
hdocs = NULL;
|
||||
|
@ -295,6 +307,13 @@ lexrestore(void)
|
|||
hwbegin = lstack->hwbegin;
|
||||
hwend = lstack->hwend;
|
||||
addtoline = lstack->addtoline;
|
||||
eclen = lstack->eclen;
|
||||
ecused = lstack->ecused;
|
||||
ecfree = lstack->ecfree;
|
||||
ecnpats = lstack->ecnpats;
|
||||
ecbuf = lstack->ecbuf;
|
||||
ecstrs = lstack->ecstrs;
|
||||
ecsoffs = lstack->ecsoffs;
|
||||
hlinesz = lstack->hlinesz;
|
||||
errflag = 0;
|
||||
|
||||
|
@ -315,15 +334,17 @@ yylex(void)
|
|||
if (tok == NEWLIN || tok == ENDINPUT) {
|
||||
while (hdocs) {
|
||||
struct heredocs *next = hdocs->next;
|
||||
char *name;
|
||||
|
||||
hwbegin(0);
|
||||
cmdpush(hdocs->rd->type == HEREDOC ? CS_HEREDOC : CS_HEREDOCD);
|
||||
cmdpush(WC_REDIR_TYPE(*(hdocs->pc)) == HEREDOC ?
|
||||
CS_HEREDOC : CS_HEREDOCD);
|
||||
STOPHIST
|
||||
hdocs->rd->name = gethere(hdocs->rd->name, hdocs->rd->type);
|
||||
name = gethere(hdocs->str, WC_REDIR_TYPE(*hdocs->pc));
|
||||
ALLOWHIST
|
||||
cmdpop();
|
||||
hwend();
|
||||
hdocs->rd->type = HERESTR;
|
||||
setheredoc(hdocs->pc, HERESTR, name);
|
||||
zfree(hdocs, sizeof(struct heredocs));
|
||||
hdocs = next;
|
||||
}
|
||||
|
@ -1458,52 +1479,62 @@ exalias(void)
|
|||
yytext = tokstrings[tok];
|
||||
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
VARARR(char, copy, (strlen(tokstr) + 1));
|
||||
|
||||
if (has_token(tokstr)) {
|
||||
char *p, *t;
|
||||
if (has_token(tokstr)) {
|
||||
char *p, *t;
|
||||
|
||||
yytext = p = ncalloc(strlen(tokstr) + 1);
|
||||
for (t = tokstr; (*p++ = itok(*t) ? ztokens[*t++ - Pound] : *t++););
|
||||
} else
|
||||
yytext = tokstr;
|
||||
yytext = p = copy;
|
||||
for (t = tokstr;
|
||||
(*p++ = itok(*t) ? ztokens[*t++ - Pound] : *t++););
|
||||
} else
|
||||
yytext = tokstr;
|
||||
|
||||
if (zleparse && !(inbufflags & INP_ALIAS)) {
|
||||
int zp = zleparse;
|
||||
if (zleparse && !(inbufflags & INP_ALIAS)) {
|
||||
int zp = zleparse;
|
||||
|
||||
gotword();
|
||||
if (zp == 1 && !zleparse) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (tok == STRING) {
|
||||
/* Check for an alias */
|
||||
an = noaliases ? NULL : (Alias) aliastab->getnode(aliastab, yytext);
|
||||
if (an && !an->inuse && ((an->flags & ALIAS_GLOBAL) || incmdpos ||
|
||||
inalmore)) {
|
||||
inpush(an->text, INP_ALIAS, an);
|
||||
/* remove from history if it begins with space */
|
||||
if (isset(HISTIGNORESPACE) && an->text[0] == ' ')
|
||||
remhist();
|
||||
lexstop = 0;
|
||||
return 1;
|
||||
gotword();
|
||||
if (zp == 1 && !zleparse) {
|
||||
if (yytext == copy)
|
||||
yytext = tokstr;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Then check for a reserved word */
|
||||
if ((incmdpos ||
|
||||
(unset(IGNOREBRACES) && yytext[0] == '}' && !yytext[1])) &&
|
||||
(rw = (Reswd) reswdtab->getnode(reswdtab, yytext))) {
|
||||
tok = rw->token;
|
||||
if (tok == DINBRACK)
|
||||
incond = 1;
|
||||
} else if (incond && !strcmp(yytext, "]]")) {
|
||||
tok = DOUTBRACK;
|
||||
incond = 0;
|
||||
} else if (incond && yytext[0] == '!' && !yytext[1])
|
||||
tok = BANG;
|
||||
if (tok == STRING) {
|
||||
/* Check for an alias */
|
||||
an = noaliases ? NULL :
|
||||
(Alias) aliastab->getnode(aliastab, yytext);
|
||||
if (an && !an->inuse && ((an->flags & ALIAS_GLOBAL) || incmdpos ||
|
||||
inalmore)) {
|
||||
inpush(an->text, INP_ALIAS, an);
|
||||
/* remove from history if it begins with space */
|
||||
if (isset(HISTIGNORESPACE) && an->text[0] == ' ')
|
||||
remhist();
|
||||
lexstop = 0;
|
||||
if (yytext == copy)
|
||||
yytext = tokstr;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Then check for a reserved word */
|
||||
if ((incmdpos ||
|
||||
(unset(IGNOREBRACES) && yytext[0] == '}' && !yytext[1])) &&
|
||||
(rw = (Reswd) reswdtab->getnode(reswdtab, yytext))) {
|
||||
tok = rw->token;
|
||||
if (tok == DINBRACK)
|
||||
incond = 1;
|
||||
} else if (incond && !strcmp(yytext, "]]")) {
|
||||
tok = DOUTBRACK;
|
||||
incond = 0;
|
||||
} else if (incond && yytext[0] == '!' && !yytext[1])
|
||||
tok = BANG;
|
||||
}
|
||||
inalmore = 0;
|
||||
if (yytext == copy)
|
||||
yytext = tokstr;
|
||||
}
|
||||
inalmore = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -220,3 +220,26 @@ rolllist(LinkList l, LinkNode nd)
|
|||
l->last->next = 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
LinkList
|
||||
newsizedlist(int size)
|
||||
{
|
||||
LinkList list;
|
||||
LinkNode node;
|
||||
|
||||
MUSTUSEHEAP("newsizedlist()");
|
||||
|
||||
list = (LinkList) zhalloc(sizeof(struct linklist) +
|
||||
(size * sizeof(struct linknode)));
|
||||
|
||||
list->first = (LinkNode) (list + 1);
|
||||
for (node = list->first; size; size--, node++) {
|
||||
node->last = node - 1;
|
||||
node->next = node + 1;
|
||||
}
|
||||
list->last = node - 1;
|
||||
list->first->last = (LinkNode) list;
|
||||
node[-1].next = NULL;
|
||||
|
||||
return list;
|
||||
}
|
||||
|
|
56
Src/loop.c
56
Src/loop.c
|
@ -51,12 +51,12 @@ execfor(Estate state, int do_exec)
|
|||
{
|
||||
Wordcode end, loop;
|
||||
wordcode code = state->pc[-1];
|
||||
int iscond = (WC_FOR_TYPE(code) == WC_FOR_COND);
|
||||
int iscond = (WC_FOR_TYPE(code) == WC_FOR_COND), ctok = 0, atok = 0;
|
||||
char *name, *str, *cond = NULL, *advance = NULL;
|
||||
zlong val = 0;
|
||||
LinkList args = NULL;
|
||||
|
||||
name = ecgetstr(state, 0);
|
||||
name = ecgetstr(state, EC_NODUP, NULL);
|
||||
end = state->pc + WC_FOR_SKIP(code);
|
||||
|
||||
if (iscond) {
|
||||
|
@ -75,14 +75,17 @@ execfor(Estate state, int do_exec)
|
|||
state->pc = end;
|
||||
return lastval = errflag;
|
||||
}
|
||||
cond = ecgetstr(state, 0);
|
||||
advance = ecgetstr(state, 0);
|
||||
cond = ecgetstr(state, EC_NODUP, &ctok);
|
||||
advance = ecgetstr(state, EC_NODUP, &atok);
|
||||
} else if (WC_FOR_TYPE(code) == WC_FOR_LIST) {
|
||||
if (!(args = ecgetlist(state, *state->pc++, 1))) {
|
||||
int htok = 0;
|
||||
|
||||
if (!(args = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok))) {
|
||||
state->pc = end;
|
||||
return 0;
|
||||
}
|
||||
execsubst(args);
|
||||
if (htok)
|
||||
execsubst(args);
|
||||
} else {
|
||||
char **x;
|
||||
|
||||
|
@ -97,8 +100,11 @@ execfor(Estate state, int do_exec)
|
|||
loop = state->pc;
|
||||
for (;;) {
|
||||
if (iscond) {
|
||||
str = dupstring(cond);
|
||||
singsub(&str);
|
||||
if (ctok) {
|
||||
str = dupstring(cond);
|
||||
singsub(&str);
|
||||
} else
|
||||
str = cond;
|
||||
if (!errflag) {
|
||||
while (iblank(*str))
|
||||
str++;
|
||||
|
@ -141,13 +147,16 @@ execfor(Estate state, int do_exec)
|
|||
if (retflag)
|
||||
break;
|
||||
if (iscond && !errflag) {
|
||||
str = dupstring(advance);
|
||||
if (atok) {
|
||||
str = dupstring(advance);
|
||||
singsub(&str);
|
||||
} else
|
||||
str = advance;
|
||||
if (isset(XTRACE)) {
|
||||
printprompt4();
|
||||
fprintf(xtrerr, "%s\n", str);
|
||||
fflush(xtrerr);
|
||||
}
|
||||
singsub(&str);
|
||||
if (!errflag)
|
||||
matheval(str);
|
||||
}
|
||||
|
@ -179,7 +188,7 @@ execselect(Estate state, int do_exec)
|
|||
LinkList args;
|
||||
|
||||
end = state->pc + WC_FOR_SKIP(code);
|
||||
name = ecgetstr(state, 0);
|
||||
name = ecgetstr(state, EC_NODUP, NULL);
|
||||
|
||||
if (WC_SELECT_TYPE(code) == WC_SELECT_PPARAM) {
|
||||
char **x;
|
||||
|
@ -188,11 +197,14 @@ execselect(Estate state, int do_exec)
|
|||
for (x = pparams; *x; x++)
|
||||
addlinknode(args, dupstring(*x));
|
||||
} else {
|
||||
if (!(args = ecgetlist(state, *state->pc++, 1))) {
|
||||
int htok = 0;
|
||||
|
||||
if (!(args = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok))) {
|
||||
state->pc = end;
|
||||
return 0;
|
||||
}
|
||||
execsubst(args);
|
||||
if (htok)
|
||||
execsubst(args);
|
||||
}
|
||||
if (!args || empty(args)) {
|
||||
state->pc = end;
|
||||
|
@ -391,14 +403,15 @@ execrepeat(Estate state, int do_exec)
|
|||
{
|
||||
Wordcode end, loop;
|
||||
wordcode code = state->pc[-1];
|
||||
int count;
|
||||
int count, htok = 0;
|
||||
char *tmp;
|
||||
|
||||
end = state->pc + WC_REPEAT_SKIP(code);
|
||||
|
||||
lastval = 0;
|
||||
tmp = ecgetstr(state, 1);
|
||||
singsub(&tmp);
|
||||
tmp = ecgetstr(state, EC_DUPTOK, &htok);
|
||||
if (htok)
|
||||
singsub(&tmp);
|
||||
count = atoi(tmp);
|
||||
pushheap();
|
||||
cmdpush(CS_REPEAT);
|
||||
|
@ -487,7 +500,7 @@ execcase(Estate state, int do_exec)
|
|||
|
||||
end = state->pc + WC_CASE_SKIP(code);
|
||||
|
||||
word = ecgetstr(state, 1);
|
||||
word = ecgetstr(state, EC_DUP, NULL);
|
||||
singsub(&word);
|
||||
untokenize(word);
|
||||
lastval = 0;
|
||||
|
@ -509,7 +522,7 @@ execcase(Estate state, int do_exec)
|
|||
if (isset(XTRACE)) {
|
||||
char *pat2, *opat;
|
||||
|
||||
opat = pat = ecgetstr(state, 1);
|
||||
opat = pat = ecgetstr(state, EC_DUP, NULL);
|
||||
singsub(&pat);
|
||||
save = (!state->prog->heap &&
|
||||
!strcmp(pat, opat) && *spprog != dummy_patprog2);
|
||||
|
@ -529,9 +542,12 @@ execcase(Estate state, int do_exec)
|
|||
if (!pprog) {
|
||||
if (!pat) {
|
||||
char *opat;
|
||||
int htok = 0;
|
||||
|
||||
opat = pat = dupstring(ecrawstr(state->prog, state->pc - 2));
|
||||
singsub(&pat);
|
||||
opat = pat = dupstring(ecrawstr(state->prog,
|
||||
state->pc - 2, &htok));
|
||||
if (htok)
|
||||
singsub(&pat);
|
||||
save = (!state->prog->heap &&
|
||||
!strcmp(pat, opat) && *spprog != dummy_patprog2);
|
||||
}
|
||||
|
|
108
Src/params.c
108
Src/params.c
|
@ -747,8 +747,8 @@ static zlong
|
|||
getarg(char **str, int *inv, Value v, int a2, zlong *w)
|
||||
{
|
||||
int hasbeg = 0, word = 0, rev = 0, ind = 0, down = 0, l, i, ishash;
|
||||
int keymatch = 0;
|
||||
char *s = *str, *sep = NULL, *t, sav, *d, **ta, **p, *tt;
|
||||
int keymatch = 0, needtok = 0;
|
||||
char *s = *str, *sep = NULL, *t, sav, *d, **ta, **p, *tt, c;
|
||||
zlong num = 1, beg = 0, r = 0;
|
||||
Patprog pprog = NULL;
|
||||
|
||||
|
@ -870,21 +870,25 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w)
|
|||
*inv = ind;
|
||||
}
|
||||
|
||||
for (t=s, i=0;
|
||||
*t && ((*t != ']' && *t != Outbrack && (ishash || *t != ',')) || i); t++)
|
||||
if (*t == '[' || *t == Inbrack)
|
||||
for (t = s, i = 0;
|
||||
(c = *t) && ((c != ']' && c != Outbrack &&
|
||||
(ishash || c != ',')) || i); t++) {
|
||||
if (c == '[' || c == Inbrack)
|
||||
i++;
|
||||
else if (*t == ']' || *t == Outbrack)
|
||||
else if (c == ']' || c == Outbrack)
|
||||
i--;
|
||||
|
||||
if (!*t)
|
||||
if (ispecial(c))
|
||||
needtok = 1;
|
||||
}
|
||||
if (!c)
|
||||
return 0;
|
||||
s = dupstrpfx(s, t - s);
|
||||
*str = tt = t;
|
||||
if (parsestr(s))
|
||||
return 0;
|
||||
singsub(&s);
|
||||
|
||||
if (needtok) {
|
||||
if (parsestr(s))
|
||||
return 0;
|
||||
singsub(&s);
|
||||
}
|
||||
if (!rev) {
|
||||
if (ishash) {
|
||||
HashTable ht = v->pm->gets.hfn(v->pm);
|
||||
|
@ -1177,43 +1181,42 @@ getindex(char **pptr, Value v)
|
|||
|
||||
/**/
|
||||
mod_export Value
|
||||
getvalue(char **pptr, int bracks)
|
||||
getvalue(Value v, char **pptr, int bracks)
|
||||
{
|
||||
return fetchvalue(pptr, bracks, 0);
|
||||
return fetchvalue(v, pptr, bracks, 0);
|
||||
}
|
||||
|
||||
/**/
|
||||
mod_export Value
|
||||
fetchvalue(char **pptr, int bracks, int flags)
|
||||
fetchvalue(Value v, char **pptr, int bracks, int flags)
|
||||
{
|
||||
char *s, *t;
|
||||
char sav;
|
||||
Value v;
|
||||
char sav, c;
|
||||
int ppar = 0;
|
||||
|
||||
s = t = *pptr;
|
||||
|
||||
if (idigit(*s)) {
|
||||
if (idigit(c = *s)) {
|
||||
if (bracks >= 0)
|
||||
ppar = zstrtol(s, &s, 10);
|
||||
else
|
||||
ppar = *s++ - '0';
|
||||
}
|
||||
else if (iident(*s))
|
||||
else if (iident(c))
|
||||
while (iident(*s))
|
||||
s++;
|
||||
else if (*s == Quest)
|
||||
else if (c == Quest)
|
||||
*s++ = '?';
|
||||
else if (*s == Pound)
|
||||
else if (c == Pound)
|
||||
*s++ = '#';
|
||||
else if (*s == String)
|
||||
else if (c == String)
|
||||
*s++ = '$';
|
||||
else if (*s == Qstring)
|
||||
else if (c == Qstring)
|
||||
*s++ = '$';
|
||||
else if (*s == Star)
|
||||
else if (c == Star)
|
||||
*s++ = '*';
|
||||
else if (*s == '#' || *s == '-' || *s == '?' || *s == '$' ||
|
||||
*s == '_' || *s == '!' || *s == '@' || *s == '*')
|
||||
else if (c == '#' || c == '-' || c == '?' || c == '$' ||
|
||||
c == '!' || c == '@' || c == '*')
|
||||
s++;
|
||||
else
|
||||
return NULL;
|
||||
|
@ -1221,7 +1224,10 @@ fetchvalue(char **pptr, int bracks, int flags)
|
|||
if ((sav = *s))
|
||||
*s = '\0';
|
||||
if (ppar) {
|
||||
v = (Value) hcalloc(sizeof *v);
|
||||
if (v)
|
||||
memset(v, 0, sizeof(*v));
|
||||
else
|
||||
v = (Value) hcalloc(sizeof *v);
|
||||
v->pm = argvparam;
|
||||
v->inv = 0;
|
||||
v->a = v->b = ppar - 1;
|
||||
|
@ -1231,14 +1237,17 @@ fetchvalue(char **pptr, int bracks, int flags)
|
|||
Param pm;
|
||||
int isvarat;
|
||||
|
||||
isvarat = !strcmp(t, "@");
|
||||
isvarat = (t[0] == '@' && !t[1]);
|
||||
pm = (Param) paramtab->getnode(paramtab, *t == '0' ? "0" : t);
|
||||
if (sav)
|
||||
*s = sav;
|
||||
*pptr = s;
|
||||
if (!pm || (pm->flags & PM_UNSET))
|
||||
return NULL;
|
||||
v = (Value) hcalloc(sizeof *v);
|
||||
if (v)
|
||||
memset(v, 0, sizeof(*v));
|
||||
else
|
||||
v = (Value) hcalloc(sizeof *v);
|
||||
if (PM_TYPE(pm->flags) & (PM_ARRAY|PM_HASHED)) {
|
||||
/* Overload v->isarr as the flag bits for hashed arrays. */
|
||||
v->isarr = flags | (isvarat ? SCANPM_ISVAR_AT : 0);
|
||||
|
@ -1628,9 +1637,10 @@ setarrvalue(Value v, char **val)
|
|||
mod_export zlong
|
||||
getiparam(char *s)
|
||||
{
|
||||
struct value vbuf;
|
||||
Value v;
|
||||
|
||||
if (!(v = getvalue(&s, 1)))
|
||||
if (!(v = getvalue(&vbuf, &s, 1)))
|
||||
return 0;
|
||||
return getintvalue(v);
|
||||
}
|
||||
|
@ -1641,8 +1651,10 @@ getiparam(char *s)
|
|||
mnumber
|
||||
getnparam(char *s)
|
||||
{
|
||||
struct value vbuf;
|
||||
Value v;
|
||||
if (!(v = getvalue(&s, 1))) {
|
||||
|
||||
if (!(v = getvalue(&vbuf, &s, 1))) {
|
||||
mnumber mn;
|
||||
mn.type = MN_INTEGER;
|
||||
mn.u.l = 0;
|
||||
|
@ -1657,9 +1669,10 @@ getnparam(char *s)
|
|||
mod_export char *
|
||||
getsparam(char *s)
|
||||
{
|
||||
struct value vbuf;
|
||||
Value v;
|
||||
|
||||
if (!(v = getvalue(&s, 0)))
|
||||
if (!(v = getvalue(&vbuf, &s, 0)))
|
||||
return NULL;
|
||||
return getstrvalue(v);
|
||||
}
|
||||
|
@ -1670,9 +1683,10 @@ getsparam(char *s)
|
|||
mod_export char **
|
||||
getaparam(char *s)
|
||||
{
|
||||
struct value vbuf;
|
||||
Value v;
|
||||
|
||||
if (!idigit(*s) && (v = getvalue(&s, 0)) &&
|
||||
if (!idigit(*s) && (v = getvalue(&vbuf, &s, 0)) &&
|
||||
PM_TYPE(v->pm->flags) == PM_ARRAY)
|
||||
return v->pm->gets.afn(v->pm);
|
||||
return NULL;
|
||||
|
@ -1684,9 +1698,10 @@ getaparam(char *s)
|
|||
mod_export char **
|
||||
gethparam(char *s)
|
||||
{
|
||||
struct value vbuf;
|
||||
Value v;
|
||||
|
||||
if (!idigit(*s) && (v = getvalue(&s, 0)) &&
|
||||
if (!idigit(*s) && (v = getvalue(&vbuf, &s, 0)) &&
|
||||
PM_TYPE(v->pm->flags) == PM_HASHED)
|
||||
return paramvalarr(v->pm->gets.hfn(v->pm), SCANPM_WANTVALS);
|
||||
return NULL;
|
||||
|
@ -1696,6 +1711,7 @@ gethparam(char *s)
|
|||
mod_export Param
|
||||
setsparam(char *s, char *val)
|
||||
{
|
||||
struct value vbuf;
|
||||
Value v;
|
||||
char *t = s;
|
||||
char *ss;
|
||||
|
@ -1708,12 +1724,12 @@ setsparam(char *s, char *val)
|
|||
}
|
||||
if ((ss = strchr(s, '['))) {
|
||||
*ss = '\0';
|
||||
if (!(v = getvalue(&s, 1)))
|
||||
if (!(v = getvalue(&vbuf, &s, 1)))
|
||||
createparam(t, PM_ARRAY);
|
||||
*ss = '[';
|
||||
v = NULL;
|
||||
} else {
|
||||
if (!(v = getvalue(&s, 1)))
|
||||
if (!(v = getvalue(&vbuf, &s, 1)))
|
||||
createparam(t, PM_SCALAR);
|
||||
else if ((PM_TYPE(v->pm->flags) & (PM_ARRAY|PM_HASHED)) &&
|
||||
!(v->pm->flags & (PM_SPECIAL|PM_TIED)) && unset(KSHARRAYS)) {
|
||||
|
@ -1722,7 +1738,7 @@ setsparam(char *s, char *val)
|
|||
v = NULL;
|
||||
}
|
||||
}
|
||||
if (!v && !(v = getvalue(&t, 1))) {
|
||||
if (!v && !(v = getvalue(&vbuf, &t, 1))) {
|
||||
zsfree(val);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1734,6 +1750,7 @@ setsparam(char *s, char *val)
|
|||
mod_export Param
|
||||
setaparam(char *s, char **val)
|
||||
{
|
||||
struct value vbuf;
|
||||
Value v;
|
||||
char *t = s;
|
||||
char *ss;
|
||||
|
@ -1746,7 +1763,7 @@ setaparam(char *s, char **val)
|
|||
}
|
||||
if ((ss = strchr(s, '['))) {
|
||||
*ss = '\0';
|
||||
if (!(v = getvalue(&s, 1)))
|
||||
if (!(v = getvalue(&vbuf, &s, 1)))
|
||||
createparam(t, PM_ARRAY);
|
||||
*ss = '[';
|
||||
if (v && PM_TYPE(v->pm->flags) == PM_HASHED) {
|
||||
|
@ -1757,7 +1774,7 @@ setaparam(char *s, char **val)
|
|||
}
|
||||
v = NULL;
|
||||
} else {
|
||||
if (!(v = fetchvalue(&s, 1, SCANPM_ASSIGNING)))
|
||||
if (!(v = fetchvalue(&vbuf, &s, 1, SCANPM_ASSIGNING)))
|
||||
createparam(t, PM_ARRAY);
|
||||
else if (!(PM_TYPE(v->pm->flags) & (PM_ARRAY|PM_HASHED)) &&
|
||||
!(v->pm->flags & (PM_SPECIAL|PM_TIED))) {
|
||||
|
@ -1768,7 +1785,7 @@ setaparam(char *s, char **val)
|
|||
}
|
||||
}
|
||||
if (!v)
|
||||
if (!(v = fetchvalue(&t, 1, SCANPM_ASSIGNING)))
|
||||
if (!(v = fetchvalue(&vbuf, &t, 1, SCANPM_ASSIGNING)))
|
||||
return NULL;
|
||||
setarrvalue(v, val);
|
||||
return v->pm;
|
||||
|
@ -1778,6 +1795,7 @@ setaparam(char *s, char **val)
|
|||
mod_export Param
|
||||
sethparam(char *s, char **val)
|
||||
{
|
||||
struct value vbuf;
|
||||
Value v;
|
||||
char *t = s;
|
||||
|
||||
|
@ -1793,7 +1811,7 @@ sethparam(char *s, char **val)
|
|||
errflag = 1;
|
||||
return NULL;
|
||||
} else {
|
||||
if (!(v = fetchvalue(&s, 1, SCANPM_ASSIGNING)))
|
||||
if (!(v = fetchvalue(&vbuf, &s, 1, SCANPM_ASSIGNING)))
|
||||
createparam(t, PM_HASHED);
|
||||
else if (!(PM_TYPE(v->pm->flags) & PM_HASHED) &&
|
||||
!(v->pm->flags & PM_SPECIAL)) {
|
||||
|
@ -1803,7 +1821,7 @@ sethparam(char *s, char **val)
|
|||
}
|
||||
}
|
||||
if (!v)
|
||||
if (!(v = fetchvalue(&t, 1, SCANPM_ASSIGNING)))
|
||||
if (!(v = fetchvalue(&vbuf, &t, 1, SCANPM_ASSIGNING)))
|
||||
return NULL;
|
||||
setarrvalue(v, val);
|
||||
return v->pm;
|
||||
|
@ -1813,6 +1831,7 @@ sethparam(char *s, char **val)
|
|||
mod_export Param
|
||||
setiparam(char *s, zlong val)
|
||||
{
|
||||
struct value vbuf;
|
||||
Value v;
|
||||
char *t = s;
|
||||
Param pm;
|
||||
|
@ -1823,7 +1842,7 @@ setiparam(char *s, zlong val)
|
|||
errflag = 1;
|
||||
return NULL;
|
||||
}
|
||||
if (!(v = getvalue(&s, 1))) {
|
||||
if (!(v = getvalue(&vbuf, &s, 1))) {
|
||||
pm = createparam(t, PM_INTEGER);
|
||||
DPUTS(!pm, "BUG: parameter not created");
|
||||
pm->u.val = val;
|
||||
|
@ -1844,6 +1863,7 @@ setiparam(char *s, zlong val)
|
|||
Param
|
||||
setnparam(char *s, mnumber val)
|
||||
{
|
||||
struct value vbuf;
|
||||
Value v;
|
||||
char *t = s;
|
||||
Param pm;
|
||||
|
@ -1853,7 +1873,7 @@ setnparam(char *s, mnumber val)
|
|||
errflag = 1;
|
||||
return NULL;
|
||||
}
|
||||
if (!(v = getvalue(&s, 1))) {
|
||||
if (!(v = getvalue(&vbuf, &s, 1))) {
|
||||
pm = createparam(t, (val.type & MN_INTEGER) ? PM_INTEGER
|
||||
: PM_FFLOAT);
|
||||
DPUTS(!pm, "BUG: parameter not created");
|
||||
|
|
3855
Src/parse.c
3855
Src/parse.c
File diff suppressed because it is too large
Load diff
|
@ -177,20 +177,25 @@ signal_mask(int sig)
|
|||
|
||||
/* Block the signals in the given signal *
|
||||
* set. Return the old signal set. */
|
||||
|
||||
|
||||
/**/
|
||||
#ifdef POSIX_SIGNALS
|
||||
|
||||
/**/
|
||||
mod_export sigset_t dummy_sigset1, dummy_sigset2;
|
||||
|
||||
/**/
|
||||
#else
|
||||
|
||||
/**/
|
||||
#ifndef BSD_SIGNALS
|
||||
|
||||
sigset_t
|
||||
signal_block(sigset_t set)
|
||||
{
|
||||
sigset_t oset;
|
||||
|
||||
#ifdef POSIX_SIGNALS
|
||||
sigprocmask(SIG_BLOCK, &set, &oset);
|
||||
#else
|
||||
# ifdef BSD_SIGNALS
|
||||
oset = sigblock(set);
|
||||
# else
|
||||
# ifdef SYSV_SIGNALS
|
||||
#ifdef SYSV_SIGNALS
|
||||
int i;
|
||||
|
||||
oset = blocked_set;
|
||||
|
@ -200,7 +205,7 @@ signal_block(sigset_t set)
|
|||
sighold(i);
|
||||
}
|
||||
}
|
||||
# else /* NO_SIGNAL_BLOCKING */
|
||||
#else /* NO_SIGNAL_BLOCKING */
|
||||
/* We will just ignore signals if the system doesn't have *
|
||||
* the ability to block them. */
|
||||
int i;
|
||||
|
@ -212,25 +217,27 @@ signal_block(sigset_t set)
|
|||
signal_ignore(i);
|
||||
}
|
||||
}
|
||||
# endif /* SYSV_SIGNALS */
|
||||
# endif /* BSD_SIGNALS */
|
||||
#endif /* POSIX_SIGNALS */
|
||||
#endif /* SYSV_SIGNALS */
|
||||
|
||||
return oset;
|
||||
}
|
||||
|
||||
/**/
|
||||
#endif /* BSD_SIGNALS */
|
||||
|
||||
/**/
|
||||
#endif /* POSIX_SIGNALS */
|
||||
|
||||
/* Unblock the signals in the given signal *
|
||||
* set. Return the old signal set. */
|
||||
|
||||
/**/
|
||||
#ifndef POSIX_SIGNALS
|
||||
|
||||
sigset_t
|
||||
signal_unblock(sigset_t set)
|
||||
{
|
||||
sigset_t oset;
|
||||
|
||||
#ifdef POSIX_SIGNALS
|
||||
sigprocmask(SIG_UNBLOCK, &set, &oset);
|
||||
#else
|
||||
# ifdef BSD_SIGNALS
|
||||
sigfillset(&oset);
|
||||
oset = sigsetmask(oset);
|
||||
|
@ -260,11 +267,12 @@ signal_unblock(sigset_t set)
|
|||
}
|
||||
# endif /* SYSV_SIGNALS */
|
||||
# endif /* BSD_SIGNALS */
|
||||
#endif /* POSIX_SIGNALS */
|
||||
|
||||
return oset;
|
||||
}
|
||||
|
||||
#endif /* POSIX_SIGNALS */
|
||||
|
||||
/* set the process signal mask to *
|
||||
* be the given signal mask */
|
||||
|
||||
|
|
|
@ -56,8 +56,8 @@
|
|||
# define sigismember(s,n) ((*(s) & (1 << ((n) - 1))) != 0)
|
||||
#endif /* ifndef POSIX_SIGNALS */
|
||||
|
||||
#define child_block() signal_block(signal_mask(SIGCHLD))
|
||||
#define child_unblock() signal_unblock(signal_mask(SIGCHLD))
|
||||
#define child_block() signal_block(sigchld_mask)
|
||||
#define child_unblock() signal_unblock(sigchld_mask)
|
||||
#define child_suspend(S) signal_suspend(SIGCHLD, S)
|
||||
|
||||
/* ignore a signal */
|
||||
|
@ -92,3 +92,29 @@
|
|||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* Make some signal functions faster. */
|
||||
|
||||
#ifdef POSIX_SIGNALS
|
||||
#define signal_block(S) \
|
||||
((dummy_sigset1 = (S)), \
|
||||
sigprocmask(SIG_BLOCK, &dummy_sigset1, &dummy_sigset2), \
|
||||
dummy_sigset2)
|
||||
#else
|
||||
# ifdef BSD_SIGNALS
|
||||
#define signal_block(S) sigblock(S)
|
||||
# else
|
||||
extern sigset_t signal_block _((sigset_t));
|
||||
# endif /* BSD_SIGNALS */
|
||||
#endif /* POSIX_SIGNALS */
|
||||
|
||||
#ifdef POSIX_SIGNALS
|
||||
#define signal_unblock(S) \
|
||||
((dummy_sigset1 = (S)), \
|
||||
sigprocmask(SIG_UNBLOCK, &dummy_sigset1, &dummy_sigset2), \
|
||||
dummy_sigset2)
|
||||
#else
|
||||
extern sigset_t signal_unblock _((sigset_t));
|
||||
#endif /* POSIX_SIGNALS */
|
||||
|
||||
|
|
221
Src/subst.c
221
Src/subst.c
|
@ -53,12 +53,12 @@ prefork(LinkList list, int flags)
|
|||
|
||||
MUSTUSEHEAP("prefork");
|
||||
for (node = firstnode(list); node; incnode(node)) {
|
||||
char *str;
|
||||
char *str, c;
|
||||
|
||||
str = (char *)getdata(node);
|
||||
if ((*str == Inang || *str == Outang || *str == Equals) &&
|
||||
if (((c = *str) == Inang || c == Outang || c == Equals) &&
|
||||
str[1] == Inpar) {
|
||||
if (*str == Inang || *str == Outang)
|
||||
if (c == Inang || c == Outang)
|
||||
setdata(node, (void *) getproc(str)); /* <(...) or >(...) */
|
||||
else
|
||||
setdata(node, (void *) getoutputfile(str)); /* =(...) */
|
||||
|
@ -94,16 +94,16 @@ stringsubst(LinkList list, LinkNode node, int ssub)
|
|||
{
|
||||
int qt;
|
||||
char *str3 = (char *)getdata(node);
|
||||
char *str = str3;
|
||||
char *str = str3, c;
|
||||
|
||||
while (!errflag && *str) {
|
||||
if ((qt = *str == Qstring) || *str == String) {
|
||||
if (str[1] == Inpar) {
|
||||
while (!errflag && (c = *str)) {
|
||||
if ((qt = c == Qstring) || c == String) {
|
||||
if ((c = str[1]) == Inpar) {
|
||||
if (!qt)
|
||||
mult_isarr = 1;
|
||||
str++;
|
||||
goto comsub;
|
||||
} else if (str[1] == Inbrack) {
|
||||
} else if (c == Inbrack) {
|
||||
/* $[...] */
|
||||
char *str2 = str;
|
||||
str2++;
|
||||
|
@ -115,7 +115,7 @@ stringsubst(LinkList list, LinkNode node, int ssub)
|
|||
str = arithsubst(str + 2, &str3, str2);
|
||||
setdata(node, (void *) str3);
|
||||
continue;
|
||||
} else if (str[1] == Snull) {
|
||||
} else if (c == Snull) {
|
||||
str = getkeystring(str, NULL, 4, NULL);
|
||||
continue;
|
||||
} else {
|
||||
|
@ -125,14 +125,14 @@ stringsubst(LinkList list, LinkNode node, int ssub)
|
|||
str3 = (char *)getdata(node);
|
||||
continue;
|
||||
}
|
||||
} else if ((qt = *str == Qtick) || *str == Tick)
|
||||
} else if ((qt = c == Qtick) || c == Tick)
|
||||
comsub: {
|
||||
LinkList pl;
|
||||
char *s, *str2 = str;
|
||||
char endchar;
|
||||
int l1, l2;
|
||||
|
||||
if (*str == Inpar) {
|
||||
if (c == Inpar) {
|
||||
endchar = Outpar;
|
||||
str[-1] = '\0';
|
||||
#ifdef DEBUG
|
||||
|
@ -143,7 +143,7 @@ stringsubst(LinkList list, LinkNode node, int ssub)
|
|||
#endif
|
||||
str--;
|
||||
} else {
|
||||
endchar = *str;
|
||||
endchar = c;
|
||||
*str = '\0';
|
||||
|
||||
while (*++str != endchar)
|
||||
|
@ -164,12 +164,12 @@ stringsubst(LinkList list, LinkNode node, int ssub)
|
|||
* be left unchanged. Note that the lexer doesn't tokenize *
|
||||
* the body of a command substitution so if there are some *
|
||||
* tokens here they are from a ${(e)~...} substitution. */
|
||||
for (str = str2; *++str; )
|
||||
if (itok(*str) && *str != Nularg &&
|
||||
!(endchar != Outpar && *str == Bnull &&
|
||||
for (str = str2; (c = *++str); )
|
||||
if (itok(c) && c != Nularg &&
|
||||
!(endchar != Outpar && c == Bnull &&
|
||||
(str[1] == '$' || str[1] == '\\' || str[1] == '`' ||
|
||||
(qt && str[1] == '"'))))
|
||||
*str = ztokens[*str - Pound];
|
||||
*str = ztokens[c - Pound];
|
||||
str++;
|
||||
if (!(pl = getoutput(str2 + 1, qt || ssub))) {
|
||||
zerr("parse error in command substitution", NULL, 0);
|
||||
|
@ -231,15 +231,15 @@ globlist(LinkList list, int nountok)
|
|||
mod_export void
|
||||
singsub(char **s)
|
||||
{
|
||||
LinkList foo;
|
||||
local_list1(foo);
|
||||
|
||||
foo = newlinklist();
|
||||
addlinknode(foo, *s);
|
||||
prefork(foo, PF_SINGLE);
|
||||
init_list1(foo, *s);
|
||||
|
||||
prefork(&foo, PF_SINGLE);
|
||||
if (errflag)
|
||||
return;
|
||||
*s = (char *) ugetnode(foo);
|
||||
DPUTS(nonempty(foo), "BUG: singsub() produced more than one word!");
|
||||
*s = (char *) ugetnode(&foo);
|
||||
DPUTS(nonempty(&foo), "BUG: singsub() produced more than one word!");
|
||||
}
|
||||
|
||||
/* Perform substitution on a single word. Unlike with singsub, the *
|
||||
|
@ -259,24 +259,23 @@ static int mult_isarr;
|
|||
static int
|
||||
multsub(char **s, char ***a, int *isarr, char *sep)
|
||||
{
|
||||
LinkList foo;
|
||||
int l, omi = mult_isarr;
|
||||
char **r, **p;
|
||||
local_list1(foo);
|
||||
|
||||
mult_isarr = 0;
|
||||
foo = newlinklist();
|
||||
addlinknode(foo, *s);
|
||||
prefork(foo, 0);
|
||||
init_list1(foo, *s);
|
||||
prefork(&foo, 0);
|
||||
if (errflag) {
|
||||
if (isarr)
|
||||
*isarr = 0;
|
||||
mult_isarr = omi;
|
||||
return 0;
|
||||
}
|
||||
if ((l = countlinknodes(foo))) {
|
||||
if ((l = countlinknodes(&foo))) {
|
||||
p = r = ncalloc((l + 1) * sizeof(char*));
|
||||
while (nonempty(foo))
|
||||
*p++ = (char *)ugetnode(foo);
|
||||
while (nonempty(&foo))
|
||||
*p++ = (char *)ugetnode(&foo);
|
||||
*p = NULL;
|
||||
if (a && mult_isarr) {
|
||||
*a = r;
|
||||
|
@ -291,7 +290,7 @@ multsub(char **s, char ***a, int *isarr, char *sep)
|
|||
return 0;
|
||||
}
|
||||
if (l)
|
||||
*s = (char *) ugetnode(foo);
|
||||
*s = (char *) ugetnode(&foo);
|
||||
else
|
||||
*s = dupstring("");
|
||||
if (isarr)
|
||||
|
@ -423,20 +422,27 @@ filesubstr(char **namptr, int assign)
|
|||
|
||||
/**/
|
||||
static char *
|
||||
strcatsub(char **d, char *pb, char *pe, char *src, int l, char *s, int glbsub)
|
||||
strcatsub(char **d, char *pb, char *pe, char *src, int l, char *s, int glbsub,
|
||||
int copied)
|
||||
{
|
||||
char *dest;
|
||||
int pl = pe - pb;
|
||||
char *dest = ncalloc(pl + l + (s ? strlen(s) : 0) + 1);
|
||||
|
||||
*d = dest;
|
||||
strncpy(dest, pb, pl);
|
||||
dest += pl;
|
||||
strcpy(dest, src);
|
||||
if (glbsub)
|
||||
tokenize(dest);
|
||||
dest += l;
|
||||
if (s)
|
||||
strcpy(dest, s);
|
||||
if (!pl && (!s || !*s)) {
|
||||
dest = (*d = (copied ? src : dupstring(src)));
|
||||
if (glbsub)
|
||||
tokenize(dest);
|
||||
} else {
|
||||
*d = dest = ncalloc(pl + l + (s ? strlen(s) : 0) + 1);
|
||||
strncpy(dest, pb, pl);
|
||||
dest += pl;
|
||||
strcpy(dest, src);
|
||||
if (glbsub)
|
||||
tokenize(dest);
|
||||
dest += l;
|
||||
if (s)
|
||||
strcpy(dest, s);
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
@ -719,7 +725,7 @@ subst_parse_str(char *s, int single)
|
|||
LinkNode
|
||||
paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
||||
{
|
||||
char *aptr = *str;
|
||||
char *aptr = *str, c, cc;
|
||||
char *s = aptr, *fstr, *idbeg, *idend, *ostr = (char *) getdata(n);
|
||||
int colf; /* != 0 means we found a colon after the name */
|
||||
int isarr = 0;
|
||||
|
@ -733,6 +739,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
int spbreak = isset(SHWORDSPLIT) && !ssub && !qt;
|
||||
char *val = NULL, **aval = NULL;
|
||||
unsigned int fwidth = 0;
|
||||
struct value vbuf;
|
||||
Value v = NULL;
|
||||
int flags = 0;
|
||||
int flnum = 0;
|
||||
|
@ -756,24 +763,24 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
int subexp;
|
||||
|
||||
*s++ = '\0';
|
||||
if (!ialnum(*s) && *s != '#' && *s != Pound && *s != '-' &&
|
||||
*s != '!' && *s != '$' && *s != String && *s != Qstring &&
|
||||
*s != '?' && *s != Quest && *s != '_' &&
|
||||
*s != '*' && *s != Star && *s != '@' && *s != '{' &&
|
||||
*s != Inbrace && *s != '=' && *s != Equals && *s != Hat &&
|
||||
*s != '^' && *s != '~' && *s != Tilde && *s != '+') {
|
||||
if (!ialnum(c = *s) && c != '#' && c != Pound && c != '-' &&
|
||||
c != '!' && c != '$' && c != String && c != Qstring &&
|
||||
c != '?' && c != Quest && c != '_' &&
|
||||
c != '*' && c != Star && c != '@' && c != '{' &&
|
||||
c != Inbrace && c != '=' && c != Equals && c != Hat &&
|
||||
c != '^' && c != '~' && c != Tilde && c != '+') {
|
||||
s[-1] = '$';
|
||||
*str = s;
|
||||
return n;
|
||||
}
|
||||
DPUTS(*s == '{', "BUG: inbrace == '{' in paramsubst()");
|
||||
if (*s == Inbrace) {
|
||||
DPUTS(c == '{', "BUG: inbrace == '{' in paramsubst()");
|
||||
if (c == Inbrace) {
|
||||
inbrace = 1;
|
||||
s++;
|
||||
if (*s == '!' && s[1] != Outbrace && emulation == EMULATE_KSH) {
|
||||
if ((c = *s) == '!' && s[1] != Outbrace && emulation == EMULATE_KSH) {
|
||||
hkeys = SCANPM_WANTKEYS;
|
||||
s++;
|
||||
} else if (*s == '(' || *s == Inpar) {
|
||||
} else if (c == '(' || c == Inpar) {
|
||||
char *t, sav;
|
||||
int tt = 0;
|
||||
zlong num;
|
||||
|
@ -788,8 +795,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
}\
|
||||
}
|
||||
|
||||
for (s++; *s != ')' && *s != Outpar; s++, tt = 0) {
|
||||
switch (*s) {
|
||||
for (s++; (c = *s) != ')' && c != Outpar; s++, tt = 0) {
|
||||
switch (c) {
|
||||
case ')':
|
||||
case Outpar:
|
||||
break;
|
||||
|
@ -979,31 +986,31 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
postmul = " ";
|
||||
|
||||
for (;;) {
|
||||
if (*s == '^' || *s == Hat) {
|
||||
if (*++s == '^' || *s == Hat) {
|
||||
if ((c = *s) == '^' || c == Hat) {
|
||||
if ((c = *++s) == '^' || c == Hat) {
|
||||
plan9 = 0;
|
||||
s++;
|
||||
} else
|
||||
plan9 = 1;
|
||||
} else if (*s == '=' || *s == Equals) {
|
||||
if (*++s == '=' || *s == Equals) {
|
||||
} else if ((c = *s) == '=' || c == Equals) {
|
||||
if ((c = *++s) == '=' || c == Equals) {
|
||||
spbreak = 0;
|
||||
s++;
|
||||
} else
|
||||
spbreak = 1;
|
||||
} else if ((*s == '#' || *s == Pound) &&
|
||||
(iident(s[1])
|
||||
|| s[1] == '*' || s[1] == Star || s[1] == '@'
|
||||
|| s[1] == '-' || (s[1] == ':' && s[2] == '-')
|
||||
|| (isstring(s[1]) && (s[2] == Inbrace || s[2] == Inpar))))
|
||||
} else if ((c == '#' || c == Pound) &&
|
||||
(iident(cc = s[1])
|
||||
|| cc == '*' || cc == Star || cc == '@'
|
||||
|| cc == '-' || (cc == ':' && s[2] == '-')
|
||||
|| (isstring(cc) && (s[2] == Inbrace || s[2] == Inpar))))
|
||||
getlen = 1 + whichlen, s++;
|
||||
else if (*s == '~' || *s == Tilde) {
|
||||
if (*++s == '~' || *s == Tilde) {
|
||||
else if (c == '~' || c == Tilde) {
|
||||
if ((c = *++s) == '~' || c == Tilde) {
|
||||
globsubst = 0;
|
||||
s++;
|
||||
} else
|
||||
globsubst = 1;
|
||||
} else if (*s == '+') {
|
||||
} else if (c == '+') {
|
||||
if (iident(s[1]) || (aspar && isstring(s[1]) &&
|
||||
(s[2] == Inbrace || s[2] == Inpar)))
|
||||
chkset = 1, s++;
|
||||
|
@ -1043,7 +1050,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
s++;
|
||||
v = (Value) NULL;
|
||||
} else if (aspar) {
|
||||
if ((v = getvalue(&s, 1))) {
|
||||
if ((v = getvalue(&vbuf, &s, 1))) {
|
||||
val = idbeg = getstrvalue(v);
|
||||
subexp = 1;
|
||||
} else
|
||||
|
@ -1052,8 +1059,9 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
if (!subexp || aspar) {
|
||||
char *ov = val;
|
||||
|
||||
if (!(v = fetchvalue((subexp ? &ov : &s), (wantt ? -1 :
|
||||
((unset(KSHARRAYS) || inbrace) ? 1 : -1)),
|
||||
if (!(v = fetchvalue(&vbuf, (subexp ? &ov : &s),
|
||||
(wantt ? -1 :
|
||||
((unset(KSHARRAYS) || inbrace) ? 1 : -1)),
|
||||
hkeys|hvals|(arrasg ? SCANPM_ASSIGNING : 0))) ||
|
||||
(v->pm && (v->pm->flags & PM_UNSET)))
|
||||
vunset = 1;
|
||||
|
@ -1199,13 +1207,13 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
|
||||
case PM_LOWER:
|
||||
t = val;
|
||||
for (; *t; t++)
|
||||
*t = tulower(*t);
|
||||
for (; (c = *t); t++)
|
||||
*t = tulower(c);
|
||||
break;
|
||||
case PM_UPPER:
|
||||
t = val;
|
||||
for (; *t; t++)
|
||||
*t = tuupper(*t);
|
||||
for (; (c = *t); t++)
|
||||
*t = tuupper(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1236,12 +1244,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
fstr = s;
|
||||
if (inbrace) {
|
||||
int bct;
|
||||
for (bct = 1;; fstr++) {
|
||||
if (!*fstr)
|
||||
break;
|
||||
else if (*fstr == Inbrace)
|
||||
for (bct = 1; (c = *fstr); fstr++) {
|
||||
if (c == Inbrace)
|
||||
bct++;
|
||||
else if (*fstr == Outbrace && !--bct)
|
||||
else if (c == Outbrace && !--bct)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1250,29 +1256,29 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
zerr("closing brace expected", NULL, 0);
|
||||
return NULL;
|
||||
}
|
||||
if (*fstr)
|
||||
if (c)
|
||||
*fstr++ = '\0';
|
||||
}
|
||||
|
||||
/* Check for ${..?..} or ${..=..} or one of those. *
|
||||
* Only works if the name is in braces. */
|
||||
|
||||
if (inbrace && (*s == '-' ||
|
||||
*s == '+' ||
|
||||
*s == ':' ||
|
||||
*s == '=' || *s == Equals ||
|
||||
*s == '%' ||
|
||||
*s == '#' || *s == Pound ||
|
||||
*s == '?' || *s == Quest ||
|
||||
*s == '/')) {
|
||||
if (inbrace && ((c = *s) == '-' ||
|
||||
c == '+' ||
|
||||
c == ':' ||
|
||||
c == '=' || c == Equals ||
|
||||
c == '%' ||
|
||||
c == '#' || c == Pound ||
|
||||
c == '?' || c == Quest ||
|
||||
c == '/')) {
|
||||
|
||||
if (!flnum)
|
||||
flnum++;
|
||||
if (*s == '%')
|
||||
if (c == '%')
|
||||
flags |= SUB_END;
|
||||
|
||||
/* Check for ${..%%..} or ${..##..} */
|
||||
if ((*s == '%' || *s == '#' || *s == Pound) && *s == s[1]) {
|
||||
if ((c == '%' || c == '#' || c == Pound) && c == s[1]) {
|
||||
s++;
|
||||
/* we have %%, not %, or ##, not # */
|
||||
flags |= SUB_LONG;
|
||||
|
@ -1285,17 +1291,17 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
* indicates shortest substring; else look for longest.
|
||||
*/
|
||||
flags = (flags & SUB_SUBSTR) ? 0 : SUB_LONG;
|
||||
if (*s == '/') {
|
||||
if ((c = *s) == '/') {
|
||||
/* doubled, so replace all occurrences */
|
||||
flags |= SUB_GLOBAL;
|
||||
s++;
|
||||
}
|
||||
/* Check for anchored substitution */
|
||||
if (*s == '%') {
|
||||
if (c == '%') {
|
||||
/* anchor at tail */
|
||||
flags |= SUB_END;
|
||||
s++;
|
||||
} else if (*s == '#' || *s == Pound) {
|
||||
} else if (c == '#' || c == Pound) {
|
||||
/* anchor at head: this is the `normal' case in getmatch */
|
||||
s++;
|
||||
} else
|
||||
|
@ -1311,8 +1317,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
* double quotes the Bnull isn't there, so it's not
|
||||
* consistent.
|
||||
*/
|
||||
for (ptr = s; *ptr && *ptr != '/'; ptr++)
|
||||
if (*ptr == '\\' && ptr[1] == '/')
|
||||
for (ptr = s; (c = *ptr) && c != '/'; ptr++)
|
||||
if (c == '\\' && ptr[1] == '/')
|
||||
chuck(ptr);
|
||||
replstr = (*ptr && ptr[1]) ? ptr+1 : "";
|
||||
*ptr = '\0';
|
||||
|
@ -1453,12 +1459,12 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
|
||||
singsub(&s);
|
||||
if (t == '/' && (flags & SUB_SUBSTR)) {
|
||||
if (*s == '#' || *s == '%') {
|
||||
if ((c = *s) == '#' || c == '%') {
|
||||
flags &= ~SUB_SUBSTR;
|
||||
if (*s == '%')
|
||||
if (c == '%')
|
||||
flags |= SUB_END;
|
||||
s++;
|
||||
} else if (*s == '\\') {
|
||||
} else if (c == '\\') {
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
@ -1508,6 +1514,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
}
|
||||
s = ss;
|
||||
}
|
||||
copied = 1;
|
||||
if (inbrace && *s) {
|
||||
if (*s == ':' && !imeta(s[1]))
|
||||
zerr("unrecognized modifier `%c'", NULL, s[1]);
|
||||
|
@ -1696,7 +1703,6 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
int pre = quotetype != 3 ? 1 : 2;
|
||||
int sl;
|
||||
char *tmp;
|
||||
|
||||
tmp = bslashquote(val, NULL, quotetype);
|
||||
sl = strlen(tmp);
|
||||
val = (char *) zhalloc(pre + sl + 2);
|
||||
|
@ -1769,15 +1775,15 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
qsort(aval, i, sizeof(char *), sortfn[sortit-1]);
|
||||
}
|
||||
if (plan9) {
|
||||
LinkList tl = newlinklist();
|
||||
LinkNode tn;
|
||||
local_list1(tl);
|
||||
|
||||
*--fstr = Marker;
|
||||
addlinknode(tl, fstr);
|
||||
if (!eval && !stringsubst(tl, firstnode(tl), ssub))
|
||||
init_list1(tl, fstr);
|
||||
if (!eval && !stringsubst(&tl, firstnode(&tl), ssub))
|
||||
return NULL;
|
||||
*str = aptr;
|
||||
tn = firstnode(tl);
|
||||
tn = firstnode(&tl);
|
||||
while ((x = *aval++)) {
|
||||
if (prenum || postnum)
|
||||
x = dopadding(x, prenum, postnum, preone, postone,
|
||||
|
@ -1785,10 +1791,11 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
if (eval && subst_parse_str(x, (qt && !nojoin)))
|
||||
return NULL;
|
||||
xlen = strlen(x);
|
||||
for (tn = firstnode(tl);
|
||||
for (tn = firstnode(&tl);
|
||||
tn && *(y = (char *) getdata(tn)) == Marker;
|
||||
incnode(tn)) {
|
||||
strcatsub(&y, ostr, aptr, x, xlen, y + 1, globsubst);
|
||||
strcatsub(&y, ostr, aptr, x, xlen, y + 1, globsubst,
|
||||
copied);
|
||||
if (qt && !*y && isarr != 2)
|
||||
y = dupstring(nulstring);
|
||||
if (plan9)
|
||||
|
@ -1820,7 +1827,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
if (eval && subst_parse_str(x, (qt && !nojoin)))
|
||||
return NULL;
|
||||
xlen = strlen(x);
|
||||
strcatsub(&y, ostr, aptr, x, xlen, NULL, globsubst);
|
||||
strcatsub(&y, ostr, aptr, x, xlen, NULL, globsubst, copied);
|
||||
if (qt && !*y && isarr != 2)
|
||||
y = dupstring(nulstring);
|
||||
setdata(n, (void *) y);
|
||||
|
@ -1851,7 +1858,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
if (eval && subst_parse_str(x, (qt && !nojoin)))
|
||||
return NULL;
|
||||
xlen = strlen(x);
|
||||
*str = strcatsub(&y, aptr, aptr, x, xlen, fstr, globsubst);
|
||||
*str = strcatsub(&y, aptr, aptr, x, xlen, fstr, globsubst, copied);
|
||||
if (qt && !*y && isarr != 2)
|
||||
y = dupstring(nulstring);
|
||||
insertlinknode(l, n, (void *) y), incnode(n);
|
||||
|
@ -1870,7 +1877,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
if (eval && subst_parse_str(x, (qt && !nojoin)))
|
||||
return NULL;
|
||||
xlen = strlen(x);
|
||||
*str = strcatsub(&y, ostr, aptr, x, xlen, fstr, globsubst);
|
||||
*str = strcatsub(&y, ostr, aptr, x, xlen, fstr, globsubst, copied);
|
||||
if (qt && !*y)
|
||||
y = dupstring(nulstring);
|
||||
setdata(n, (void *) y);
|
||||
|
|
44
Src/text.c
44
Src/text.c
|
@ -78,7 +78,7 @@ taddlist(Estate state, int num)
|
|||
{
|
||||
if (num) {
|
||||
while (num--) {
|
||||
taddstr(ecgetstr(state, 0));
|
||||
taddstr(ecgetstr(state, EC_NODUP, NULL));
|
||||
taddchr(' ');
|
||||
}
|
||||
tptr--;
|
||||
|
@ -243,7 +243,7 @@ gettext2(Estate state)
|
|||
switch (wc_code(code)) {
|
||||
case WC_LIST:
|
||||
if (!s) {
|
||||
tpush(code, (WC_LIST_TYPE(code) & Z_END));
|
||||
s = tpush(code, (WC_LIST_TYPE(code) & Z_END));
|
||||
stack = 0;
|
||||
} else {
|
||||
if (WC_LIST_TYPE(code) & Z_ASYNC) {
|
||||
|
@ -260,6 +260,8 @@ gettext2(Estate state)
|
|||
s->pop = (WC_LIST_TYPE(s->code) & Z_END);
|
||||
}
|
||||
}
|
||||
if (!stack && (WC_LIST_TYPE(s->code) & Z_SIMPLE))
|
||||
state->pc++;
|
||||
break;
|
||||
case WC_SUBLIST:
|
||||
if (!s) {
|
||||
|
@ -306,14 +308,14 @@ gettext2(Estate state)
|
|||
}
|
||||
break;
|
||||
case WC_ASSIGN:
|
||||
taddstr(ecgetstr(state, 0));
|
||||
taddstr(ecgetstr(state, EC_NODUP, NULL));
|
||||
taddchr('=');
|
||||
if (WC_ASSIGN_TYPE(code) == WC_ASSIGN_ARRAY) {
|
||||
taddchr('(');
|
||||
taddlist(state, WC_ASSIGN_NUM(code));
|
||||
taddstr(") ");
|
||||
} else {
|
||||
taddstr(ecgetstr(state, 0));
|
||||
taddstr(ecgetstr(state, EC_NODUP, NULL));
|
||||
taddchr(' ');
|
||||
}
|
||||
break;
|
||||
|
@ -391,14 +393,14 @@ gettext2(Estate state)
|
|||
taddstr("for ");
|
||||
if (WC_FOR_TYPE(code) == WC_FOR_COND) {
|
||||
taddstr("((");
|
||||
taddstr(ecgetstr(state, 0));
|
||||
taddstr(ecgetstr(state, EC_NODUP, NULL));
|
||||
taddstr("; ");
|
||||
taddstr(ecgetstr(state, 0));
|
||||
taddstr(ecgetstr(state, EC_NODUP, NULL));
|
||||
taddstr("; ");
|
||||
taddstr(ecgetstr(state, 0));
|
||||
taddstr(ecgetstr(state, EC_NODUP, NULL));
|
||||
taddstr(")) do");
|
||||
} else {
|
||||
taddstr(ecgetstr(state, 0));
|
||||
taddstr(ecgetstr(state, EC_NODUP, NULL));
|
||||
if (WC_FOR_TYPE(code) == WC_FOR_LIST) {
|
||||
taddstr(" in ");
|
||||
taddlist(state, *state->pc++);
|
||||
|
@ -419,7 +421,7 @@ gettext2(Estate state)
|
|||
case WC_SELECT:
|
||||
if (!s) {
|
||||
taddstr("select ");
|
||||
taddstr(ecgetstr(state, 0));
|
||||
taddstr(ecgetstr(state, EC_NODUP, NULL));
|
||||
if (WC_SELECT_TYPE(code) == WC_SELECT_LIST) {
|
||||
taddstr(" in ");
|
||||
taddlist(state, *state->pc++);
|
||||
|
@ -457,7 +459,7 @@ gettext2(Estate state)
|
|||
case WC_REPEAT:
|
||||
if (!s) {
|
||||
taddstr("repeat ");
|
||||
taddstr(ecgetstr(state, 0));
|
||||
taddstr(ecgetstr(state, EC_NODUP, NULL));
|
||||
taddnl();
|
||||
taddstr("do");
|
||||
tindent++;
|
||||
|
@ -475,7 +477,7 @@ gettext2(Estate state)
|
|||
Wordcode end = state->pc + WC_CASE_SKIP(code);
|
||||
|
||||
taddstr("case ");
|
||||
taddstr(ecgetstr(state, 0));
|
||||
taddstr(ecgetstr(state, EC_NODUP, NULL));
|
||||
taddstr(" in");
|
||||
|
||||
if (state->pc >= end) {
|
||||
|
@ -492,7 +494,7 @@ gettext2(Estate state)
|
|||
else
|
||||
taddchr(' ');
|
||||
code = *state->pc++;
|
||||
taddstr(ecgetstr(state, 0));
|
||||
taddstr(ecgetstr(state, EC_NODUP, NULL));
|
||||
state->pc++;
|
||||
taddstr(") ");
|
||||
tindent++;
|
||||
|
@ -508,7 +510,7 @@ gettext2(Estate state)
|
|||
else
|
||||
taddchr(' ');
|
||||
code = *state->pc++;
|
||||
taddstr(ecgetstr(state, 0));
|
||||
taddstr(ecgetstr(state, EC_NODUP, NULL));
|
||||
state->pc++;
|
||||
taddstr(") ");
|
||||
tindent++;
|
||||
|
@ -638,31 +640,31 @@ gettext2(Estate state)
|
|||
}
|
||||
break;
|
||||
case COND_MOD:
|
||||
taddstr(ecgetstr(state, 0));
|
||||
taddstr(ecgetstr(state, EC_NODUP, NULL));
|
||||
taddchr(' ');
|
||||
taddlist(state, WC_COND_SKIP(code));
|
||||
stack = 1;
|
||||
break;
|
||||
case COND_MODI:
|
||||
{
|
||||
char *name = ecgetstr(state, 0);
|
||||
char *name = ecgetstr(state, EC_NODUP, NULL);
|
||||
|
||||
taddstr(ecgetstr(state, 0));
|
||||
taddstr(ecgetstr(state, EC_NODUP, NULL));
|
||||
taddchr(' ');
|
||||
taddstr(name);
|
||||
taddchr(' ');
|
||||
taddstr(ecgetstr(state, 0));
|
||||
taddstr(ecgetstr(state, EC_NODUP, NULL));
|
||||
stack = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (ctype <= COND_GE) {
|
||||
/* Binary test: `a = b' etc. */
|
||||
taddstr(ecgetstr(state, 0));
|
||||
taddstr(ecgetstr(state, EC_NODUP, NULL));
|
||||
taddstr(" ");
|
||||
taddstr(c1[ctype - COND_STREQ]);
|
||||
taddstr(" ");
|
||||
taddstr(ecgetstr(state, 0));
|
||||
taddstr(ecgetstr(state, EC_NODUP, NULL));
|
||||
if (ctype == COND_STREQ ||
|
||||
ctype == COND_STRNEQ)
|
||||
state->pc++;
|
||||
|
@ -675,7 +677,7 @@ gettext2(Estate state)
|
|||
c2[2] = ' ';
|
||||
c2[3] = '\0';
|
||||
taddstr(c2);
|
||||
taddstr(ecgetstr(state, 0));
|
||||
taddstr(ecgetstr(state, EC_NODUP, NULL));
|
||||
}
|
||||
stack = 1;
|
||||
break;
|
||||
|
@ -685,7 +687,7 @@ gettext2(Estate state)
|
|||
break;
|
||||
case WC_ARITH:
|
||||
taddstr("((");
|
||||
taddstr(ecgetstr(state, 0));
|
||||
taddstr(ecgetstr(state, EC_NODUP, NULL));
|
||||
taddstr("))");
|
||||
stack = 1;
|
||||
break;
|
||||
|
|
73
Src/zsh.h
73
Src/zsh.h
|
@ -352,7 +352,25 @@ struct linklist {
|
|||
#define pushnode(X,Y) insertlinknode(X,(LinkNode) X,Y)
|
||||
#define incnode(X) (X = nextnode(X))
|
||||
#define firsthist() (hist_ring? hist_ring->down->histnum : curhist)
|
||||
#define setsizednode(X,Y,Z) ((X)->first[(Y)].dat = (void *) (Z))
|
||||
|
||||
/* stack allocated linked lists */
|
||||
|
||||
#define local_list0(N) struct linklist N
|
||||
#define init_list0(N) \
|
||||
do { \
|
||||
(N).first = NULL; \
|
||||
(N).last = (LinkNode) &(N); \
|
||||
} while (0)
|
||||
#define local_list1(N) struct linklist N; struct linknode __n0
|
||||
#define init_list1(N,V0) \
|
||||
do { \
|
||||
(N).first = &__n0; \
|
||||
(N).last = &__n0; \
|
||||
__n0.next = NULL; \
|
||||
__n0.last = (LinkNode) &(N); \
|
||||
__n0.dat = (void *) (V0); \
|
||||
} while (0)
|
||||
|
||||
/********************************/
|
||||
/* Definitions for syntax trees */
|
||||
|
@ -364,9 +382,10 @@ struct linklist {
|
|||
#define Z_SYNC (1<<1) /* run this sublist synchronously (;) */
|
||||
#define Z_ASYNC (1<<2) /* run this sublist asynchronously (&) */
|
||||
#define Z_DISOWN (1<<3) /* run this sublist without job control (&|) */
|
||||
/* (1<<4) is used for Z_END, see the wordcode definitions */
|
||||
/* (1<<5) is used for Z_SIMPLE, see the wordcode definitions */
|
||||
|
||||
/* flags for command modifiers */
|
||||
#define CFLAG_EXEC (1<<0) /* exec ... */
|
||||
/* Condition types. */
|
||||
|
||||
#define COND_NOT 0
|
||||
#define COND_AND 1
|
||||
|
@ -481,11 +500,24 @@ struct estate {
|
|||
char *strs; /* strings from prog */
|
||||
};
|
||||
|
||||
typedef struct eccstr *Eccstr;
|
||||
|
||||
struct eccstr {
|
||||
Eccstr next;
|
||||
char *str;
|
||||
wordcode offs;
|
||||
};
|
||||
|
||||
#define EC_NODUP 0
|
||||
#define EC_DUP 1
|
||||
#define EC_DUPTOK 2
|
||||
|
||||
#define WC_CODEBITS 5
|
||||
|
||||
#define wc_code(C) ((C) & ((wordcode) ((1 << WC_CODEBITS) - 1)))
|
||||
#define wc_data(C) ((C) >> WC_CODEBITS)
|
||||
#define wc_bld(C, D) (((wordcode) (C)) | (((wordcode) (D)) << WC_CODEBITS))
|
||||
#define wc_bdata(D) ((D) << WC_CODEBITS)
|
||||
#define wc_bld(C,D) (((wordcode) (C)) | (((wordcode) (D)) << WC_CODEBITS))
|
||||
|
||||
#define WC_END 0
|
||||
#define WC_LIST 1
|
||||
|
@ -512,17 +544,20 @@ struct estate {
|
|||
|
||||
#define WC_LIST_TYPE(C) wc_data(C)
|
||||
#define Z_END (1<<4)
|
||||
#define WCB_LIST(T) wc_bld(WC_LIST, (T))
|
||||
#define Z_SIMPLE (1<<5)
|
||||
#define WC_LIST_SKIP(C) (wc_data(C) >> 6)
|
||||
#define WCB_LIST(T,O) wc_bld(WC_LIST, ((T) | ((O) << 6)))
|
||||
|
||||
#define WC_SUBLIST_TYPE(C) (wc_data(C) & ((wordcode) 3))
|
||||
#define WC_SUBLIST_END 0
|
||||
#define WC_SUBLIST_AND 1
|
||||
#define WC_SUBLIST_OR 2
|
||||
#define WC_SUBLIST_FLAGS(C) (wc_data(C) & ((wordcode) 12))
|
||||
#define WC_SUBLIST_FLAGS(C) (wc_data(C) & ((wordcode) 0x1c))
|
||||
#define WC_SUBLIST_COPROC 4
|
||||
#define WC_SUBLIST_NOT 8
|
||||
#define WC_SUBLIST_SKIP(C) (wc_data(C) >> 4)
|
||||
#define WCB_SUBLIST(T,F,O) wc_bld(WC_SUBLIST, ((T) | (F) | ((O) << 4)))
|
||||
#define WC_SUBLIST_SIMPLE 16
|
||||
#define WC_SUBLIST_SKIP(C) (wc_data(C) >> 5)
|
||||
#define WCB_SUBLIST(T,F,O) wc_bld(WC_SUBLIST, ((T) | (F) | ((O) << 5)))
|
||||
|
||||
#define WC_PIPE_TYPE(C) (wc_data(C) & ((wordcode) 1))
|
||||
#define WC_PIPE_END 0
|
||||
|
@ -612,7 +647,7 @@ struct job {
|
|||
pid_t gleader; /* process group leader of this job */
|
||||
pid_t other; /* subjob id or subshell pid */
|
||||
int stat; /* see STATs below */
|
||||
char pwd[PATH_MAX + 1]; /* current working dir of shell when *
|
||||
char *pwd; /* current working dir of shell when *
|
||||
* this job was spawned */
|
||||
struct process *procs; /* list of processes */
|
||||
LinkList filelist; /* list of files to delete when done */
|
||||
|
@ -683,7 +718,8 @@ struct execstack {
|
|||
|
||||
struct heredocs {
|
||||
struct heredocs *next;
|
||||
Redir rd;
|
||||
Wordcode pc;
|
||||
char *str;
|
||||
};
|
||||
|
||||
struct dirsav {
|
||||
|
@ -968,7 +1004,7 @@ struct patprog {
|
|||
#define GF_BACKREF 0x0400
|
||||
#define GF_MATCHREF 0x0800
|
||||
|
||||
/* Dummy Patprog pointers. Used mainly in executions trees, but the
|
||||
/* Dummy Patprog pointers. Used mainly in executable code, but the
|
||||
* pattern code needs to know about it, too. */
|
||||
|
||||
#define dummy_patprog1 ((Patprog) 1)
|
||||
|
@ -1475,14 +1511,19 @@ struct ttyinfo {
|
|||
/****************************************/
|
||||
|
||||
#define CMDSTACKSZ 256
|
||||
#define cmdpush(X) if (!(cmdsp >= 0 && cmdsp < CMDSTACKSZ)) {;} else cmdstack[cmdsp++]=(X)
|
||||
#define cmdpush(X) do { \
|
||||
if (cmdsp >= 0 && cmdsp < CMDSTACKSZ) \
|
||||
cmdstack[cmdsp++]=(X); \
|
||||
} while (0)
|
||||
#ifdef DEBUG
|
||||
# define cmdpop() if (cmdsp <= 0) { \
|
||||
fputs("BUG: cmdstack empty\n", stderr); \
|
||||
fflush(stderr); \
|
||||
} else cmdsp--
|
||||
# define cmdpop() do { \
|
||||
if (cmdsp <= 0) { \
|
||||
fputs("BUG: cmdstack empty\n", stderr); \
|
||||
fflush(stderr); \
|
||||
} else cmdsp--; \
|
||||
} while (0)
|
||||
#else
|
||||
# define cmdpop() if (cmdsp <= 0) {;} else cmdsp--
|
||||
# define cmdpop() do { if (cmdsp > 0) cmdsp--; } while (0)
|
||||
#endif
|
||||
|
||||
#define CS_FOR 0
|
||||
|
|
Loading…
Reference in a new issue