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