1
0
Fork 0
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:
Tanaka Akira 2000-02-23 15:13:27 +00:00
parent 4d60fd3fea
commit 2b37049c22
20 changed files with 2440 additions and 2507 deletions

View file

@ -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;
}

View file

@ -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:
{

View file

@ -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);

View file

@ -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();

View file

@ -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);
}

View file

@ -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;
{

View file

@ -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);

View file

@ -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;
}

View file

@ -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

View file

@ -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
View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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");

File diff suppressed because it is too large Load diff

View file

@ -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 */

View file

@ -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 */

View file

@ -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);

View file

@ -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;

View file

@ -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