summaryrefslogtreecommitdiff
path: root/Src
diff options
context:
space:
mode:
Diffstat (limited to 'Src')
-rw-r--r--Src/Modules/pcre.c68
-rw-r--r--Src/exec.c59
-rw-r--r--Src/init.c4
-rw-r--r--Src/lex.c6
-rw-r--r--Src/loop.c9
-rw-r--r--Src/module.c15
-rw-r--r--Src/parse.c48
-rw-r--r--Src/signals.c2
-rw-r--r--Src/zsh.h23
9 files changed, 172 insertions, 62 deletions
diff --git a/Src/Modules/pcre.c b/Src/Modules/pcre.c
index 27191d709..659fd22d5 100644
--- a/Src/Modules/pcre.c
+++ b/Src/Modules/pcre.c
@@ -148,7 +148,7 @@ bin_pcre_study(char *nam, UNUSED(char **args), UNUSED(Options ops), UNUSED(int f
/**/
static int
-zpcre_get_substrings(char *arg, int *ovec, int ret, char *matchvar,
+zpcre_get_substrings(char *arg, int *ovec, int captured_count, char *matchvar,
char *substravar, int want_offset_pair, int matchedinarr,
int want_begin_end)
{
@@ -156,15 +156,13 @@ zpcre_get_substrings(char *arg, int *ovec, int ret, char *matchvar,
char offset_all[50];
int capture_start = 1;
- if (matchedinarr)
+ if (matchedinarr) {
+ /* bash-style captures[0] entire-matched string in the array */
capture_start = 0;
- if (matchvar == NULL)
- matchvar = "MATCH";
- if (substravar == NULL)
- substravar = "match";
-
+ }
+
/* captures[0] will be entire matched string, [1] first substring */
- if (!pcre_get_substring_list(arg, ovec, ret, (const char ***)&captures)) {
+ if (!pcre_get_substring_list(arg, ovec, captured_count, (const char ***)&captures)) {
int nelem = arrlen(captures)-1;
/* Set to the offsets of the complete match */
if (want_offset_pair) {
@@ -176,30 +174,43 @@ zpcre_get_substrings(char *arg, int *ovec, int ret, char *matchvar,
* difference between the two values in each paired entry in ovec.
* ovec is length 2*(1+capture_list_length)
*/
- match_all = metafy(captures[0], ovec[1] - ovec[0], META_DUP);
- setsparam(matchvar, match_all);
+ if (matchvar) {
+ match_all = metafy(captures[0], ovec[1] - ovec[0], META_DUP);
+ setsparam(matchvar, match_all);
+ }
/*
* If we're setting match, mbegin, mend we only do
* so if there were parenthesised matches, for consistency
- * (c.f. regex.c).
+ * (c.f. regex.c). That's the next block after this one.
+ * Here we handle the simpler case where we don't worry about
+ * Unicode lengths, etc.
+ * Either !want_begin_end (ie, this is bash) or nelem; if bash
+ * then we're invoked always, even without nelem results, to
+ * set the array variable with one element in it, the complete match.
*/
- if (!want_begin_end || nelem) {
+ if (substravar &&
+ (!want_begin_end || nelem)) {
char **x, **y;
- int vec_off;
+ int vec_off, i;
y = &captures[capture_start];
- matches = x = (char **) zalloc(sizeof(char *) * (arrlen(y) + 1));
- vec_off = 2;
- do {
+ matches = x = (char **) zalloc(sizeof(char *) * (captured_count+1-capture_start));
+ for (i = capture_start; i < captured_count; i++, y++) {
+ vec_off = 2*i;
if (*y)
*x++ = metafy(*y, ovec[vec_off+1]-ovec[vec_off], META_DUP);
else
*x++ = NULL;
- vec_off += 2;
- } while (*y++);
+ }
+ *x = NULL;
setaparam(substravar, matches);
}
if (want_begin_end) {
+ /*
+ * cond-infix rather than builtin; also not bash; so we set a bunch
+ * of variables and arrays to values which require handling Unicode
+ * lengths
+ */
char *ptr = arg;
zlong offs = 0;
int clen, leftlen;
@@ -306,7 +317,9 @@ bin_pcre_match(char *nam, char **args, Options ops, UNUSED(int func))
zwarnnam(nam, "no pattern has been compiled");
return 1;
}
-
+
+ matched_portion = "MATCH";
+ receptacle = "match";
if(OPT_HASARG(ops,c='a')) {
receptacle = OPT_ARG(ops,c);
}
@@ -318,8 +331,8 @@ bin_pcre_match(char *nam, char **args, Options ops, UNUSED(int func))
return 1;
}
/* For the entire match, 'Return' the offset byte positions instead of the matched string */
- if(OPT_ISSET(ops,'b')) want_offset_pair = 1;
-
+ if(OPT_ISSET(ops,'b')) want_offset_pair = 1;
+
if ((ret = pcre_fullinfo(pcre_pattern, pcre_hints, PCRE_INFO_CAPTURECOUNT, &capcount)))
{
zwarnnam(nam, "error %d in fullinfo", ret);
@@ -360,7 +373,7 @@ cond_pcre_match(char **a, int id)
{
pcre *pcre_pat;
const char *pcre_err;
- char *lhstr, *rhre, *lhstr_plain, *rhre_plain, *avar=NULL;
+ char *lhstr, *rhre, *lhstr_plain, *rhre_plain, *avar, *svar;
int r = 0, pcre_opts = 0, pcre_errptr, capcnt, *ov, ovsize;
int lhstr_plain_len, rhre_plain_len;
int return_value = 0;
@@ -380,8 +393,13 @@ cond_pcre_match(char **a, int id)
ov = NULL;
ovsize = 0;
- if (isset(BASHREMATCH))
- avar="BASH_REMATCH";
+ if (isset(BASHREMATCH)) {
+ svar = NULL;
+ avar = "BASH_REMATCH";
+ } else {
+ svar = "MATCH";
+ avar = "match";
+ }
switch(id) {
case CPCRE_PLAIN:
@@ -414,7 +432,7 @@ cond_pcre_match(char **a, int id)
break;
}
else if (r>0) {
- zpcre_get_substrings(lhstr_plain, ov, r, NULL, avar, 0,
+ zpcre_get_substrings(lhstr_plain, ov, r, svar, avar, 0,
isset(BASHREMATCH),
!isset(BASHREMATCH));
return_value = 1;
diff --git a/Src/exec.c b/Src/exec.c
index f339dd6d0..cd99733f1 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -41,12 +41,15 @@ enum {
ADDVAR_RESTORE = 1 << 2
};
-/* used to suppress ERREXIT and trapping of SIGZERR, SIGEXIT. */
+/*
+ * used to suppress ERREXIT and trapping of SIGZERR, SIGEXIT.
+ * Bits from noerrexit_bits.
+ */
/**/
int noerrexit;
-/* used to suppress ERREXIT for one occurrence */
+/* used to suppress ERREXIT or ERRRETURN for one occurrence: 0 or 1 */
/**/
int this_noerrexit;
@@ -972,7 +975,7 @@ enum {
static void
entersubsh(int flags)
{
- int sig, monitor, job_control_ok;
+ int i, sig, monitor, job_control_ok;
if (!(flags & ESUB_KEEPTRAP))
for (sig = 0; sig < SIGCOUNT; sig++)
@@ -1083,6 +1086,14 @@ entersubsh(int flags)
opts[MONITOR] = 0;
opts[USEZLE] = 0;
zleactive = 0;
+ /*
+ * If we've saved fd's for later restoring, we're never going
+ * to restore them now, so just close them.
+ */
+ for (i = 10; i <= max_zsh_fd; i++) {
+ if (fdtable[i] & FDT_SAVED_MASK)
+ zclose(i);
+ }
if (flags & ESUB_PGRP)
clearjobtab(monitor);
get_usage();
@@ -1291,7 +1302,7 @@ execlist(Estate state, int dont_change_job, int exiting)
int oerrexit_opt = opts[ERREXIT];
Param pm;
opts[ERREXIT] = 0;
- noerrexit = 1;
+ noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN;
if (ltype & Z_SIMPLE) /* skip the line number */
pc2++;
pm = setsparam("ZSH_DEBUG_CMD", getpermtext(state->prog, pc2, 0));
@@ -1343,13 +1354,13 @@ execlist(Estate state, int dont_change_job, int exiting)
int isend = (WC_SUBLIST_TYPE(code) == WC_SUBLIST_END);
next = state->pc + WC_SUBLIST_SKIP(code);
if (!oldnoerrexit)
- noerrexit = !isend;
+ noerrexit = isend ? 0 : NOERREXIT_EXIT | NOERREXIT_RETURN;
if (WC_SUBLIST_FLAGS(code) & WC_SUBLIST_NOT) {
/* suppress errexit for "! this_command" */
if (isend)
this_noerrexit = 1;
/* suppress errexit for ! <list-of-shell-commands> */
- noerrexit = 1;
+ noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN;
}
switch (WC_SUBLIST_TYPE(code)) {
case WC_SUBLIST_END:
@@ -1436,11 +1447,11 @@ sublist_done:
/*
* See hairy code near the end of execif() for the
- * following. "noerrexit == 2" only applies until
+ * following. "noerrexit " only applies until
* we hit execcmd on the way down. We're now
* on the way back up, so don't restore it.
*/
- if (oldnoerrexit != 2)
+ if (!(oldnoerrexit & NOERREXIT_UNTIL_EXEC))
noerrexit = oldnoerrexit;
if (sigtrapped[SIGDEBUG] && !isset(DEBUGBEFORECMD) && !donedebug) {
@@ -1450,7 +1461,7 @@ sublist_done:
*/
int oerrexit_opt = opts[ERREXIT];
opts[ERREXIT] = 0;
- noerrexit = 1;
+ noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN;
exiting = donetrap;
ret = lastval;
dotrap(SIGDEBUG);
@@ -1466,16 +1477,19 @@ sublist_done:
/* Check whether we are suppressing traps/errexit *
* (typically in init scripts) and if we haven't *
* already performed them for this sublist. */
- if (!noerrexit && !this_noerrexit && !donetrap && !this_donetrap) {
- if (sigtrapped[SIGZERR] && lastval) {
+ if (!this_noerrexit && !donetrap && !this_donetrap) {
+ if (sigtrapped[SIGZERR] && lastval &&
+ !(noerrexit & NOERREXIT_EXIT)) {
dotrap(SIGZERR);
donetrap = 1;
}
if (lastval) {
int errreturn = isset(ERRRETURN) &&
- (isset(INTERACTIVE) || locallevel || sourcelevel);
- int errexit = isset(ERREXIT) ||
- (isset(ERRRETURN) && !errreturn);
+ (isset(INTERACTIVE) || locallevel || sourcelevel) &&
+ !(noerrexit & NOERREXIT_RETURN);
+ int errexit = (isset(ERREXIT) ||
+ (isset(ERRRETURN) && !errreturn)) &&
+ !(noerrexit & NOERREXIT_EXIT);
if (errexit) {
if (sigtrapped[SIGEXIT])
dotrap(SIGEXIT);
@@ -2318,6 +2332,9 @@ addfd(int forked, int *save, struct multio **mfds, int fd1, int fd2, int rflag,
return;
}
save[fd1] = fdN;
+ DPUTS(fdtable[fdN] != FDT_INTERNAL,
+ "Saved file descriptor not marked as internal");
+ fdtable[fdN] |= FDT_SAVED_MASK;
}
}
}
@@ -3008,7 +3025,7 @@ execcmd_exec(Estate state, Execcmd_params eparams,
preargs = NULL;
/* if we get this far, it is OK to pay attention to lastval again */
- if (noerrexit == 2 && !is_shfunc)
+ if ((noerrexit & NOERREXIT_UNTIL_EXEC) && !is_shfunc)
noerrexit = 0;
/* Do prefork substitutions.
@@ -3575,7 +3592,8 @@ execcmd_exec(Estate state, Execcmd_params eparams,
}
if (!bad && fn->fd1 <= max_zsh_fd) {
if (fn->fd1 >= 10 &&
- fdtable[fn->fd1] == FDT_INTERNAL)
+ (fdtable[fn->fd1] & FDT_TYPE_MASK) ==
+ FDT_INTERNAL)
bad = 3;
}
}
@@ -4270,7 +4288,7 @@ closem(int how)
for (i = 10; i <= max_zsh_fd; i++)
if (fdtable[i] != FDT_UNUSED &&
- (how == FDT_UNUSED || fdtable[i] == how)) {
+ (how == FDT_UNUSED || (fdtable[i] & FDT_TYPE_MASK) == how)) {
if (i == SHTTY)
SHTTY = -1;
zclose(i);
@@ -5450,6 +5468,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
char saveopts[OPT_SIZE], *oldscriptname = scriptname;
char *name = shfunc->node.nam;
int flags = shfunc->node.flags, ooflags;
+ int savnoerrexit;
char *fname = dupstring(name);
int obreaks, ocontflag, oloops, saveemulation, restore_sticky;
Eprog prog;
@@ -5472,6 +5491,11 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
trap_return--;
oldlastval = lastval;
oldnumpipestats = numpipestats;
+ savnoerrexit = noerrexit;
+ /*
+ * Suppression of ERR_RETURN is turned off in function scope.
+ */
+ noerrexit &= ~NOERREXIT_RETURN;
if (noreturnval) {
/*
* Easiest to use the heap here since we're bracketed
@@ -5690,6 +5714,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
if (trap_state == TRAP_STATE_PRIMED)
trap_return++;
ret = lastval;
+ noerrexit = savnoerrexit;
if (noreturnval) {
lastval = oldlastval;
numpipestats = oldnumpipestats;
diff --git a/Src/init.c b/Src/init.c
index d8c26aca2..87dd2e26d 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -1070,7 +1070,7 @@ setupvals(char *cmd, char *runscript, char *zsh_name)
sfcontext = SFC_NONE;
trap_return = 0;
trap_state = TRAP_STATE_INACTIVE;
- noerrexit = -1;
+ noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN | NOERREXIT_SIGNAL;
nohistsave = 1;
dirstack = znewlinklist();
bufstack = znewlinklist();
@@ -1199,7 +1199,7 @@ init_signals(void)
void
run_init_scripts(void)
{
- noerrexit = -1;
+ noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN | NOERREXIT_SIGNAL;
if (EMULATION(EMULATE_KSH|EMULATE_SH)) {
if (islogin)
diff --git a/Src/lex.c b/Src/lex.c
index b2d9b3f42..8493d4737 100644
--- a/Src/lex.c
+++ b/Src/lex.c
@@ -760,7 +760,7 @@ gettok(void)
return AMPER;
case LX1_BAR:
d = hgetc();
- if (d == '|')
+ if (d == '|' && !incasepat)
return DBAR;
else if (d == '&')
return BARAMP;
@@ -1058,7 +1058,7 @@ gettokstr(int c, int sub)
if (isset(SHGLOB)) {
if (sub || in_brace_param)
break;
- if (incasepat && !lexbuf.len)
+ if (incasepat > 0 && !lexbuf.len)
return INPAR;
if (!isset(KSHGLOB) && lexbuf.len)
goto brk;
@@ -1859,7 +1859,7 @@ exalias(void)
Reswd rw;
hwend();
- if (interact && isset(SHINSTDIN) && !strin && !incasepat &&
+ if (interact && isset(SHINSTDIN) && !strin && incasepat <= 0 &&
tok == STRING && !nocorrect && !(inbufflags & INP_ALIAS) &&
(isset(CORRECTALL) || (isset(CORRECT) && incmdpos)))
spckword(&tokstr, 1, incmdpos, 1);
diff --git a/Src/loop.c b/Src/loop.c
index f7eae307b..4859c976b 100644
--- a/Src/loop.c
+++ b/Src/loop.c
@@ -542,7 +542,7 @@ execif(Estate state, int do_exec)
end = state->pc + WC_IF_SKIP(code);
if (!noerrexit)
- noerrexit = 1;
+ noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN;
while (state->pc < end) {
code = *state->pc++;
if (wc_code(code) != WC_IF ||
@@ -567,7 +567,12 @@ execif(Estate state, int do_exec)
if (run) {
/* we need to ignore lastval until we reach execcmd() */
- noerrexit = olderrexit ? olderrexit : lastval ? 2 : 0;
+ if (olderrexit)
+ noerrexit = olderrexit;
+ else if (lastval)
+ noerrexit = NOERREXIT_EXIT | NOERREXIT_RETURN | NOERREXIT_UNTIL_EXEC;
+ else
+ noerrexit = 0;
cmdpush(run == 2 ? CS_ELSE : (s ? CS_ELIFTHEN : CS_IFTHEN));
execlist(state, 1, do_exec);
cmdpop();
diff --git a/Src/module.c b/Src/module.c
index 21d68b1ac..4ae78310f 100644
--- a/Src/module.c
+++ b/Src/module.c
@@ -649,11 +649,21 @@ getconddef(int inf, const char *name, int autol)
{
Conddef p;
int f = 1;
+ char *lookup, *s;
+
+ /* detokenize the Dash to the form encoded in lookup tables */
+ lookup = dupstring(name);
+ if (!lookup)
+ return NULL;
+ for (s = lookup; *s != '\0'; s++) {
+ if (*s == Dash)
+ *s = '-';
+ }
do {
for (p = condtab; p; p = p->next) {
if ((!!inf == !!(p->flags & CONDF_INFIX)) &&
- !strcmp(name, p->name))
+ !strcmp(lookup, p->name))
break;
}
if (autol && p && p->module) {
@@ -664,7 +674,7 @@ getconddef(int inf, const char *name, int autol)
if (f) {
(void)ensurefeature(p->module,
(p->flags & CONDF_INFIX) ? "C:" : "c:",
- (p->flags & CONDF_AUTOALL) ? NULL : name);
+ (p->flags & CONDF_AUTOALL) ? NULL : lookup);
f = 0;
p = NULL;
} else {
@@ -674,6 +684,7 @@ getconddef(int inf, const char *name, int autol)
} else
break;
} while (!p);
+
return p;
}
diff --git a/Src/parse.c b/Src/parse.c
index ba9cd61eb..27052527d 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -48,7 +48,11 @@ mod_export int incond;
/**/
mod_export int inredir;
-/* != 0 if we are about to read a case pattern */
+/*
+ * 1 if we are about to read a case pattern
+ * -1 if we are not quite sure
+ * 0 otherwise
+ */
/**/
int incasepat;
@@ -1194,6 +1198,7 @@ par_case(int *cmplx)
for (;;) {
char *str;
+ int skip_zshlex;
while (tok == SEPER)
zshlex();
@@ -1201,11 +1206,17 @@ par_case(int *cmplx)
break;
if (tok == INPAR)
zshlex();
- if (tok != STRING)
- YYERRORV(oecused);
- if (!strcmp(tokstr, "esac"))
- break;
- str = dupstring(tokstr);
+ if (tok == BAR) {
+ str = dupstring("");
+ skip_zshlex = 1;
+ } else {
+ if (tok != STRING)
+ YYERRORV(oecused);
+ if (!strcmp(tokstr, "esac"))
+ break;
+ str = dupstring(tokstr);
+ skip_zshlex = 0;
+ }
type = WC_CASE_OR;
pp = ecadd(0);
palts = ecadd(0);
@@ -1243,10 +1254,11 @@ par_case(int *cmplx)
* this doesn't affect our ability to match a | or ) as
* these are valid on command lines.
*/
- incasepat = 0;
+ incasepat = -1;
incmdpos = 1;
- for (;;) {
+ if (!skip_zshlex)
zshlex();
+ for (;;) {
if (tok == OUTPAR) {
ecstr(str);
ecadd(ecnpats++);
@@ -1302,10 +1314,26 @@ par_case(int *cmplx)
}
zshlex();
- if (tok != STRING)
+ switch (tok) {
+ case STRING:
+ /* Normal case */
+ str = dupstring(tokstr);
+ zshlex();
+ break;
+
+ case OUTPAR:
+ case BAR:
+ /* Empty string */
+ str = dupstring("");
+ break;
+
+ default:
+ /* Oops. */
YYERRORV(oecused);
- str = dupstring(tokstr);
+ break;
+ }
}
+ incasepat = 0;
par_save_list(cmplx);
if (tok == SEMIAMP)
type = WC_CASE_AND;
diff --git a/Src/signals.c b/Src/signals.c
index cad40f4eb..94f379e72 100644
--- a/Src/signals.c
+++ b/Src/signals.c
@@ -652,7 +652,7 @@ zhandler(int sig)
case SIGINT:
if (!handletrap(SIGINT)) {
if ((isset(PRIVILEGED) || isset(RESTRICTED)) &&
- isset(INTERACTIVE) && noerrexit < 0)
+ isset(INTERACTIVE) && (noerrexit & NOERREXIT_SIGNAL))
zexit(SIGINT, 1);
if (list_pipe || chline || simple_pline) {
breaks = loops;
diff --git a/Src/zsh.h b/Src/zsh.h
index ccd11db3d..abe9a9c82 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -456,6 +456,18 @@ enum {
#define FDT_PROC_SUBST 7
#endif
+/*
+ * Mask to get the basic FDT type.
+ */
+#define FDT_TYPE_MASK 15
+
+/*
+ * Bit flag that fd is saved for later restoration.
+ * Currently this is only use with FDT_INTERNAL. We use this fact so as
+ * not to have to mask checks against other types.
+ */
+#define FDT_SAVED_MASK 16
+
/* Flags for input stack */
#define INP_FREE (1<<0) /* current buffer can be free'd */
#define INP_ALIAS (1<<1) /* expanding alias or history */
@@ -2110,6 +2122,17 @@ enum source_return {
SOURCE_ERROR = 2
};
+enum noerrexit_bits {
+ /* Suppress ERR_EXIT and traps: global */
+ NOERREXIT_EXIT = 1,
+ /* Suppress ERR_RETURN: per function call */
+ NOERREXIT_RETURN = 2,
+ /* NOERREXIT only needed on way down */
+ NOERREXIT_UNTIL_EXEC = 4,
+ /* Force exit on SIGINT */
+ NOERREXIT_SIGNAL = 8
+};
+
/***********************************/
/* Definitions for history control */
/***********************************/