From fdf2867e5f08809ff3fccc78fb6df13a196e3efc Mon Sep 17 00:00:00 2001
From: Peter Stephenson
Date: Thu, 13 Jun 2013 18:38:33 +0100
Subject: 31444: Basic code for enable/disable -p
---
Src/builtin.c | 20 +++++--
Src/exec.c | 5 ++
Src/options.c | 1 +
Src/pattern.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Src/zsh.h | 16 ++++++
5 files changed, 205 insertions(+), 4 deletions(-)
(limited to 'Src')
diff --git a/Src/builtin.c b/Src/builtin.c
index bc91578b3..8516acd81 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -55,11 +55,11 @@ static struct builtin builtins[] =
BUILTIN("continue", BINF_PSPECIAL, bin_break, 0, 1, BIN_CONTINUE, NULL, NULL),
BUILTIN("declare", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%afghi:%klmprtuxz", NULL),
BUILTIN("dirs", 0, bin_dirs, 0, -1, 0, "clpv", NULL),
- BUILTIN("disable", 0, bin_enable, 0, -1, BIN_DISABLE, "afmrs", NULL),
+ BUILTIN("disable", 0, bin_enable, 0, -1, BIN_DISABLE, "afmprs", NULL),
BUILTIN("disown", 0, bin_fg, 0, -1, BIN_DISOWN, NULL, NULL),
BUILTIN("echo", BINF_SKIPINVALID, bin_print, 0, -1, BIN_ECHO, "neE", "-"),
BUILTIN("emulate", 0, bin_emulate, 0, -1, 0, "LR", NULL),
- BUILTIN("enable", 0, bin_enable, 0, -1, BIN_ENABLE, "afmrs", NULL),
+ BUILTIN("enable", 0, bin_enable, 0, -1, BIN_ENABLE, "afmprs", NULL),
BUILTIN("eval", BINF_PSPECIAL, bin_eval, 0, -1, BIN_EVAL, NULL, NULL),
BUILTIN("exit", BINF_PSPECIAL, bin_break, 0, 1, BIN_EXIT, NULL, NULL),
BUILTIN("export", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, BIN_EXPORT, "E:%F:%HL:%R:%TUZ:%afhi:%lprtu", "xg"),
@@ -467,7 +467,9 @@ bin_enable(char *name, char **argv, Options ops, int func)
int match = 0, returnval = 0;
/* Find out which hash table we are working with. */
- if (OPT_ISSET(ops,'f'))
+ if (OPT_ISSET(ops,'p')) {
+ return pat_enables(name, argv, func == BIN_ENABLE);
+ } else if (OPT_ISSET(ops,'f'))
ht = shfunctab;
else if (OPT_ISSET(ops,'r'))
ht = reswdtab;
@@ -5020,6 +5022,7 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func))
int opt_R = OPT_ISSET(ops, 'R');
int saveemulation, savehackchar;
int ret = 1, new_emulation;
+ unsigned int savepatterns;
char saveopts[OPT_SIZE], new_opts[OPT_SIZE];
char *cmd = 0;
const char *shname = *argv;
@@ -5061,7 +5064,8 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func))
if (!argv[1]) {
emulate(shname, OPT_ISSET(ops,'R'), &emulation, opts);
if (OPT_ISSET(ops,'L'))
- opts[LOCALOPTIONS] = opts[LOCALTRAPS] = 1;
+ opts[LOCALOPTIONS] = opts[LOCALTRAPS] = opts[LOCALPATTERNS] = 1;
+ clearpatterndisables();
return 0;
}
@@ -5082,6 +5086,13 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func))
goto restore;
}
+ savepatterns = savepatterndisables();
+ /*
+ * All emulations start with an empty set of pattern disables,
+ * hence no special "sticky" behaviour is required.
+ */
+ clearpatterndisables();
+
saveemulation = emulation;
emulation = new_emulation;
memcpy(opts, new_opts, sizeof(opts));
@@ -5131,6 +5142,7 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func))
sticky = save_sticky;
emulation = saveemulation;
memcpy(opts, saveopts, sizeof(opts));
+ restorepatterndisables(savepatterns);
restore:
keyboardhackchar = savehackchar;
inittyptab(); /* restore banghist */
diff --git a/Src/exec.c b/Src/exec.c
index 14c2ba003..75805d3f5 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -4627,6 +4627,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
}
starttrapscope();
+ startpatternscope();
pptab = pparams;
if (!(flags & PM_UNDEFINED))
@@ -4674,6 +4675,8 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
offptr++)
opts[*offptr] = 0;
}
+ /* All emulations start with pattern disables clear */
+ clearpatterndisables();
} else
restore_sticky = 0;
@@ -4774,6 +4777,8 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
scriptname = oldscriptname;
oflags = ooflags;
+ endpatternscope(); /* before restoring old LOCALPATTERNS */
+
if (restore_sticky) {
/*
* If we switched to an emulation environment just for
diff --git a/Src/options.c b/Src/options.c
index 480fccd57..ad869b253 100644
--- a/Src/options.c
+++ b/Src/options.c
@@ -179,6 +179,7 @@ static struct optname optns[] = {
{{NULL, "listrowsfirst", 0}, LISTROWSFIRST},
{{NULL, "listtypes", OPT_ALL}, LISTTYPES},
{{NULL, "localoptions", OPT_EMULATE|OPT_KSH}, LOCALOPTIONS},
+{{NULL, "localpatterns", OPT_EMULATE}, LOCALPATTERNS},
{{NULL, "localtraps", OPT_EMULATE|OPT_KSH}, LOCALTRAPS},
{{NULL, "login", OPT_SPECIAL}, LOGINSHELL},
{{NULL, "longlistjobs", 0}, LONGLISTJOBS},
diff --git a/Src/pattern.c b/Src/pattern.c
index 54d6e7cb3..a90d3cddc 100644
--- a/Src/pattern.c
+++ b/Src/pattern.c
@@ -232,6 +232,27 @@ static const char zpc_chars[ZPC_COUNT] = {
Hat, Pound, Bnullkeep, Quest, Star, '+', '!', '@'
};
+/*
+ * Corresponding strings used in enable/disable -p.
+ * NULL means no way of turning this on or off.
+ */
+static const char *zpc_strings[ZPC_COUNT] = {
+ NULL, NULL, "|", NULL, "~", "(", "?", "*", "[", "<",
+ "^", "#", NULL, "?(", "*(", "+(", "!(", "@("
+};
+
+/*
+ * Corresponding array of pattern disables as set by the user
+ * using "disable -p".
+ */
+static char zpc_disables[ZPC_COUNT];
+
+/*
+ * Stack of saved (compressed) zpc_disables for function scope.
+ */
+
+static struct zpc_disables_save *zpc_disables_stack;
+
/*
* Characters which terminate a simple string (ZPC_COUNT) or
* an entire pattern segment (the first ZPC_SEG_COUNT).
@@ -414,7 +435,19 @@ static long rn_offs;
static void
patcompcharsset(void)
{
+ char *spp, *disp;
+ int i;
+
+ /* Initialise enabled special characters */
memcpy(zpc_special, zpc_chars, ZPC_COUNT);
+ /* Apply user disables from disable -p */
+ for (i = 0, spp = zpc_special, disp = zpc_disables;
+ i < ZPC_COUNT;
+ i++, spp++, disp++) {
+ if (*disp)
+ *spp = Marker;
+ }
+
if (!isset(EXTENDEDGLOB)) {
/* Extended glob characters are not active */
zpc_special[ZPC_TILDE] = zpc_special[ZPC_HAT] =
@@ -3799,3 +3832,137 @@ freepatprog(Patprog prog)
if (prog && prog != dummy_patprog1 && prog != dummy_patprog2)
zfree(prog, prog->size);
}
+
+/* Disable or reenable a pattern character */
+
+/**/
+int
+pat_enables(const char *cmd, char **patp, int enable)
+{
+ int ret = 0;
+ const char **stringp;
+ char *disp;
+
+ if (!*patp) {
+ int done = 0;
+ for (stringp = zpc_strings, disp = zpc_disables;
+ stringp < zpc_strings + ZPC_COUNT;
+ stringp++, disp++) {
+ if (!*stringp)
+ continue;
+ if (enable ? *disp : !*disp)
+ continue;
+ if (done)
+ putc(' ', stdout);
+ printf("'%s'", *stringp);
+ done = 1;
+ }
+ if (done)
+ putc('\n', stdout);
+ return 0;
+ }
+
+ for (; *patp; patp++) {
+ for (stringp = zpc_strings, disp = zpc_disables;
+ stringp < zpc_strings + ZPC_COUNT;
+ stringp++, disp++) {
+ if (*stringp && !strcmp(*stringp, *patp)) {
+ *disp = (char)!enable;
+ break;
+ }
+ }
+ if (stringp == zpc_strings + ZPC_COUNT) {
+ zerrnam(cmd, "invalid pattern: %s", *patp);
+ ret = 1;
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * Save the current state of pattern disables, returning the saved value.
+ */
+
+/**/
+unsigned int
+savepatterndisables(void)
+{
+ unsigned int disables, bit;
+ char *disp;
+
+ disables = 0;
+ for (bit = 1, disp = zpc_disables;
+ disp < zpc_disables + ZPC_COUNT;
+ bit <<= 1, disp++) {
+ if (*disp)
+ disables |= bit;
+ }
+ return disables;
+}
+
+/*
+ * Function scope saving pattern enables.
+ */
+
+/**/
+void
+startpatternscope(void)
+{
+ Zpc_disables_save newdis;
+
+ newdis = (Zpc_disables_save)zalloc(sizeof(*newdis));
+ newdis->next = zpc_disables_stack;
+ newdis->disables = savepatterndisables();
+
+ zpc_disables_stack = newdis;
+}
+
+/*
+ * Restore completely the state of pattern disables.
+ */
+
+/**/
+void
+restorepatterndisables(unsigned int disables)
+{
+ char *disp;
+ unsigned int bit;
+
+ for (bit = 1, disp = zpc_disables;
+ disp < zpc_disables + ZPC_COUNT;
+ bit <<= 1, disp++) {
+ if (disables & bit)
+ *disp = 1;
+ else
+ *disp = 0;
+ }
+}
+
+/*
+ * Function scope to restore pattern enables if localpatterns is turned on.
+ */
+
+/**/
+void
+endpatternscope(void)
+{
+ Zpc_disables_save olddis;
+
+ olddis = zpc_disables_stack;
+ zpc_disables_stack = olddis->next;
+
+ if (isset(LOCALPATTERNS))
+ restorepatterndisables(olddis->disables);
+
+ zfree(olddis, sizeof(*olddis));
+}
+
+/* Reinitialise pattern disables */
+
+/**/
+void
+clearpatterndisables(void)
+{
+ memset(zpc_disables, 0, ZPC_COUNT);
+}
diff --git a/Src/zsh.h b/Src/zsh.h
index 639c2b746..299357de8 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -1413,6 +1413,21 @@ enum zpc_chars {
ZPC_COUNT /* Number of special chararacters */
};
+/*
+ * Structure to save disables special characters for function scope.
+ */
+struct zpc_disables_save {
+ struct zpc_disables_save *next;
+ /*
+ * Bit vector of ZPC_COUNT disabled characters.
+ * We'll live dangerously and assumed ZPC_COUNT is no greater
+ * than the number of bits an an unsigned int.
+ */
+ unsigned int disables;
+};
+
+typedef struct zpc_disables_save *Zpc_disables_save;
+
/*
* Special match types used in character classes. These
* are represented as tokens, with Meta added. The character
@@ -2074,6 +2089,7 @@ enum {
LISTROWSFIRST,
LISTTYPES,
LOCALOPTIONS,
+ LOCALPATTERNS,
LOCALTRAPS,
LOGINSHELL,
LONGLISTJOBS,
--
cgit 1.4.1