1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2024-12-29 16:25:35 +01:00

31444: Basic code for enable/disable -p

This commit is contained in:
Peter Stephenson 2013-06-13 18:38:33 +01:00
parent e36e7d9ade
commit fdf2867e5f
8 changed files with 313 additions and 12 deletions

View file

@ -291,8 +291,8 @@ enditem()
findex(disable)
cindex(disabling commands)
cindex(commands, disabling)
item(tt(disable) [ tt(-afmrs) ] var(name) ...)(
Temporarily disable the var(name)d hash table elements. The default
item(tt(disable) [ tt(-afmprs) ] var(name) ...)(
Temporarily disable the var(name)d hash table elements or patterns. The default
is to disable builtin commands. This allows you to use an external
command with the same name as a builtin command. The tt(-a) option
causes tt(disable) to act on regular or global aliases. The tt(-s)
@ -305,6 +305,80 @@ quoted to prevent them from undergoing filename expansion), and all hash
table elements from the corresponding hash table matching these patterns
are disabled. Disabled objects can be enabled with the tt(enable)
command.
With the option tt(-p), var(name) ... refer to elements of the
shell's pattern syntax as described in noderef(Filename Generation).
Certain elements can be disabled separately, as given below.
Note that patterns
not allowed by the current settings for the options tt(EXTENDED_GLOB),
tt(KSH_GLOB) and tt(SH_GLOB) are never enabled, regardless of the
setting here. For example, if tt(EXTENDED_GLOB) is not active,
the pattern tt(^) is ineffective even if `tt(disable -p "^")' has
not been issued. The list below indicates any option settings
that restrict the use of the pattern. It should be noted that
setting tt(SH_GLOB) has a wider effect then merely disabling patterns
as certain expressions, in particular those involving parentheses,
are parsed differently.
The following patterns may be disabled; all
the strings need quoting on the command line to prevent them from
being interpreted immediately as patterns and the patterns are
shown below in single quotes as a reminder.
startitem()
item(tt('?'))(
The pattern character tt(?) wherever it occurs, including when preceding
a parenthesis with tt(KSH_GLOB).
)
item(tt('*'))(
The pattern character tt(*) wherever it occurs, including recursive
globbing and when preceding a parenthesis with tt(KSH_GLOB).
)
item('LSQUARE()')(
Character classes.
)
item(tt('<') (tt(NO_SH_GLOB)))(
Numeric ranges.
)
item(tt('|') (tt(NO_SH_GLOB)))(
Alternation in grouped patterns, case statements, or KSH_GLOB
parenthesised expressions.
)
item(tt('LPAR()') (tt(NO_SH_GLOB)))(
Grouping using single parentheses. Disabling this does not disable the
use of parentheses for tt(KSH_GLOB) where they are introduced by a
special character, nor for glob qualifiers (use `tt(setopt
NO_BARE_GLOB_QUAL)' to disable glob qualifiers that use parentheses
only).
)
item(tt('~') (tt(EXTENDED_GLOB)))(
Exclusion in the form var(A)tt(~)var(B).
)
item(tt('^') (tt(EXTENDED_GLOB)))(
Exclusion in the form var(A)tt(^)var(B).
)
item(tt('#') (tt(EXTENDED_GLOB)))(
The pattern character tt(#) wherever it occurs, both for
repetition of a previous pattern and for indicating globbing flags.
)
item(tt('?LPAR()') (tt(KSH_GLOB)))(
The grouping form tt(?LPAR())var(...)tt(RPAR()). Note this is also
disabled if tt('?') is disabled.
)
item(tt('*LPAR()') (tt(KSH_GLOB)))(
The grouping form tt(*LPAR())var(...)tt(RPAR()). Note this is also
disabled if tt('*') is disabled.
)
item(tt('PLUS()LPAR()') (tt(KSH_GLOB)))(
The grouping form tt(PLUS()LPAR())var(...)tt(RPAR()).
)
item(tt('!LPAR()') (tt(KSH_GLOB)))(
The grouping form tt(!LPAR())var(...)tt(RPAR()).
)
item(tt('@LPAR()') (tt(KSH_GLOB)))(
The grouping form tt(@LPAR())var(...)tt(RPAR()).
)
enditem()
)
findex(disown)
cindex(jobs, disowning)
@ -376,7 +450,9 @@ the section COMPATIBILITY in zmanref(zsh)
ifnzman(\
noderef(Compatibility)
)\
.
. In addition to setting shell options, the command also restores
the pristine state of pattern enables, as if all patterns had been
enabled using tt(enable -p).
If the tt(emulate) command occurs inside a function that has been
marked for execution tracing with tt(functions -t) then the tt(xtrace)
@ -390,9 +466,11 @@ are reset to their default value corresponding to the specified emulation
mode, except for certain options describing the interactive
environment; otherwise, only those options likely to cause portability
problems in scripts and functions are altered. If the tt(-L) switch is given,
the options tt(LOCAL_OPTIONS) and tt(LOCAL_TRAPS) will be set as
well, causing the effects of the tt(emulate) command and any tt(setopt) and
tt(trap) commands to be local to the immediately surrounding shell
the options tt(LOCAL_OPTIONS), tt(LOCAL_PATTERNS) and tt(LOCAL_TRAPS)
will be set as
well, causing the effects of the tt(emulate) command and any tt(setopt),
tt(disable -p) or tt(enable -b), and tt(trap) commands to be local to
the immediately surrounding shell
function, if any; normally these options are turned off in all emulation
modes except tt(ksh). The tt(-L) switch is mutually exclusive with the
use of tt(-c) in var(flags).
@ -414,7 +492,8 @@ Use of tt(-c) enables `sticky' emulation mode for functions defined
within the evaluated expression: the emulation mode is associated
thereafter with the function so that whenever the function is executed
the emulation (respecting the tt(-R) switch, if present) and all
options are set before entry to the function, and restored after exit.
options are set (and pattern disables cleared)
before entry to the function, and the state is restored after exit.
If the function is called when the sticky emulation is already in
effect, either within an `tt(emulate) var(shell) tt(-c)' expression or
within another function with the same sticky emulation, entry and exit
@ -471,7 +550,7 @@ endsitem()
findex(enable)
cindex(enabling commands)
cindex(commands, enabling)
item(tt(enable) [ tt(-afmrs) ] var(name) ...)(
item(tt(enable) [ tt(-afmprs) ] var(name) ...)(
Enable the var(name)d hash table elements, presumably disabled
earlier with tt(disable). The default is to enable builtin commands.
The tt(-a) option causes tt(enable) to act on regular or global aliases.
@ -483,6 +562,13 @@ printed. With the tt(-m) flag the arguments are taken as patterns
(should be quoted) and all hash table elements from the corresponding
hash table matching these patterns are enabled. Enabled objects can be
disabled with the tt(disable) builtin command.
tt(enable -p) reenables patterns disabled with tt(disable -p). Note
that it does not override globbing options; for example, `tt(enable -p
"~")' does not cause the pattern character tt(~) to be active unless
the tt(EXTENDED_GLOB) option is also set. To enable all possible
patterns (so that they may be invidually disabled with tt(disable -p)),
use `tt(setopt EXTENDED_GLOB KSH_GLOB NO_SH_GLOB)'.
)
findex(eval)
cindex(evaluating arguments as commands)

View file

@ -1618,6 +1618,19 @@ A shell function can also guarantee itself a known shell configuration
with a formulation like `tt(emulate -L zsh)'; the tt(-L) activates
tt(LOCAL_OPTIONS).
)
pindex(LOCAL_PATTERNS)
pindex(NO_LOCAL_PATTERNS)
pindex(LOCALPATTERNS)
pindex(NOLOCALPATTERNS)
item(tt(LOCAL_PATTERNS))(
If this option is set at the point of return from a shell function,
the state of pattern disables, as set with the builtin command
`tt(disable -p)', is restored to what it was when the function was
entered. The behaviour of this option is similar to the effect
of tt(LOCAL_OPTIONS) on options; hence `tt(emulate -L sh)' (or
indeed any other emulation with the tt(-L) option) activates
tt(LOCAL_PATTERNS).
)
pindex(LOCAL_TRAPS)
pindex(NO_LOCAL_TRAPS)
pindex(LOCALTRAPS)

View file

@ -33,6 +33,7 @@ DEFINEMACRO(RQUOTE)(0)(CHAR(39))
DEFINEMACRO(LPAR)(0)(CHAR(40))
DEFINEMACRO(RPAR)(0)(CHAR(41))
DEFINEMACRO(PLUS)(0)(CHAR(43))
DEFINEMACRO(LSQUARE)(0)(CHAR(91))
DEFINEMACRO(DASH)(0)(ifztexi(--)ifnztexi(-))

View file

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

View file

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

View file

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

View file

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

View file

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