From fa8a0e241c8ac9eb48ab9fc2d8bb3105088e0db9 Mon Sep 17 00:00:00 2001 From: Bart Schaefer Date: Wed, 7 Mar 2012 06:10:42 +0000 Subject: 30320: "emulate" accepts invocation-time flags; other small doc tweaks. --- Src/builtin.c | 57 ++++++++++++++++------------ Src/init.c | 119 +++++++++++++++++++++++++++++++++++----------------------- Src/options.c | 2 + 3 files changed, 105 insertions(+), 73 deletions(-) (limited to 'Src') diff --git a/Src/builtin.c b/Src/builtin.c index b43c08235..c32b1c023 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -58,7 +58,7 @@ static struct builtin builtins[] = BUILTIN("disable", 0, bin_enable, 0, -1, BIN_DISABLE, "afmrs", 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, 3, 0, "LR", NULL), + BUILTIN("emulate", 0, bin_emulate, 0, -1, 0, "LR", NULL), BUILTIN("enable", 0, bin_enable, 0, -1, BIN_ENABLE, "afmrs", 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), @@ -4958,14 +4958,14 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func)) { int opt_L = OPT_ISSET(ops, 'L'); int opt_R = OPT_ISSET(ops, 'R'); - int saveemulation, savesticky_emulation; - int ret; + int saveemulation, savesticky_emulation, savehackchar; + int ret = 1; char saveopts[OPT_SIZE]; + char *cmd = 0; + const char *shname = *argv; /* without arguments just print current emulation */ - if (!*argv) { - const char *shname; - + if (!shname) { if (opt_L || opt_R) { zwarnnam("emulate", "not enough arguments"); return 1; @@ -4995,39 +4995,46 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func)) /* with single argument set current emulation */ if (!argv[1]) { - emulate(*argv, OPT_ISSET(ops,'R')); + emulate(shname, OPT_ISSET(ops,'R')); if (OPT_ISSET(ops,'L')) opts[LOCALOPTIONS] = opts[LOCALTRAPS] = 1; return 0; } - /* If "-c command" is given, evaluate command using specified - * emulation mode. - */ - if (strcmp(argv[1], "-c")) { - zwarnnam("emulate", "unknown argument %s", argv[1]); - return 1; - } + argv++; + memcpy(saveopts, opts, sizeof(opts)); + savehackchar = keyboardhackchar; + cmd = parseopts("emulate", &argv); - if (!argv[2]) { - zwarnnam("emulate", "not enough arguments"); - return 1; + /* parseopts() has consumed anything that looks like an option */ + if (*argv) { + zwarnnam("emulate", "unknown argument %s", *argv); + goto restore; } - if (opt_L) { - zwarnnam("emulate", "option -L incompatible with -c"); - return 1; - } + /* If "-c command" is given, evaluate command using specified + * emulation mode. + */ + if (cmd) { + if (opt_L) { + zwarnnam("emulate", "option -L incompatible with -c"); + goto restore; + } + *--argv = cmd; /* on stack, never free()d, see execbuiltin() */ + } else + return 0; - memcpy(saveopts, opts, sizeof(opts)); saveemulation = emulation; savesticky_emulation = sticky_emulation; - emulate(*argv, OPT_ISSET(ops,'R')); + emulate(shname, OPT_ISSET(ops,'R')); sticky_emulation = emulation; - ret = eval(argv+2); - memcpy(opts, saveopts, sizeof(opts)); + ret = eval(argv); sticky_emulation = savesticky_emulation; emulation = saveemulation; + restore: + memcpy(opts, saveopts, sizeof(opts)); + keyboardhackchar = savehackchar; + inittyptab(); /* restore banghist */ return ret; } diff --git a/Src/init.c b/Src/init.c index 9820070fb..1212a48d9 100644 --- a/Src/init.c +++ b/Src/init.c @@ -215,6 +215,7 @@ loop(int toplevel, int justonce) return LOOP_OK; } +/* Shared among parseargs(), parseopts(), init_io(), and init_misc() */ static char *cmd; static int restricted; @@ -222,9 +223,7 @@ static int restricted; static void parseargs(char **argv, char **runscript) { - int optionbreak = 0; char **x; - int action, optno; LinkList paramlist; argzero = *argv++; @@ -247,6 +246,49 @@ parseargs(char **argv, char **runscript) opts[SHINSTDIN] = 0; opts[SINGLECOMMAND] = 0; + cmd = parseopts(NULL, &argv); + + paramlist = znewlinklist(); + if (*argv) { + if (unset(SHINSTDIN)) { + if (cmd) + argzero = *argv; + else + *runscript = *argv; + opts[INTERACTIVE] &= 1; + argv++; + } + while (*argv) + zaddlinknode(paramlist, ztrdup(*argv++)); + } else if (!cmd) + opts[SHINSTDIN] = 1; + if(isset(SINGLECOMMAND)) + opts[INTERACTIVE] &= 1; + opts[INTERACTIVE] = !!opts[INTERACTIVE]; + if (opts[MONITOR] == 2) + opts[MONITOR] = opts[INTERACTIVE]; + if (opts[HASHDIRS] == 2) + opts[HASHDIRS] = opts[INTERACTIVE]; + pparams = x = (char **) zshcalloc((countlinknodes(paramlist) + 1) * sizeof(char *)); + + while ((*x++ = (char *)getlinknode(paramlist))); + free(paramlist); + argzero = ztrdup(argzero); +} + +/**/ +mod_export char * +parseopts(char *nam, char ***argvp) +{ + int optionbreak = 0; + int action, optno; + char *cmd = 0; /* deliberately hides static */ + char **argv = *argvp; + +#define WARN_OPTION(F, S) if (nam) zwarnnam(nam, F, S); else zerr(F, S) +#define LAST_OPTION(N) \ + if (nam) { if (*argv) argv++; goto doneargv; } else exit(N) + /* loop through command line options (begins with "-" or "+") */ while (!optionbreak && *argv && (**argv == '-' || **argv == '+')) { char *args = *argv; @@ -267,11 +309,11 @@ parseargs(char **argv, char **runscript) if (!strcmp(*argv, "version")) { printf("zsh %s (%s-%s-%s)\n", ZSH_VERSION, MACHTYPE, VENDOR, OSTYPE); - exit(0); + LAST_OPTION(0); } if (!strcmp(*argv, "help")) { printhelp(); - exit(0); + LAST_OPTION(0); } /* `-' characters are allowed in long options */ for(args = *argv; *args; args++) @@ -292,73 +334,54 @@ parseargs(char **argv, char **runscript) if (!*++*argv) argv++; if (!*argv) { - zerr("string expected after -o"); - exit(1); + WARN_OPTION("string expected after -o", NULL); + LAST_OPTION(1); } longoptions: if (!(optno = optlookup(*argv))) { - zerr("no such option: %s", *argv); - exit(1); - } else if (optno == RESTRICTED) + WARN_OPTION("no such option: %s", *argv); + LAST_OPTION(1); + } else if (optno == RESTRICTED && !nam) restricted = action; - else - dosetopt(optno, action, 1); + else if ((optno == EMACSMODE || optno == VIMODE) && nam) + WARN_OPTION("can't change option: %s", *argv); + else if (dosetopt(optno, action, !nam) && nam) + WARN_OPTION("can't change option: %s", *argv); break; } else if (isspace(STOUC(**argv))) { /* zsh's typtab not yet set, have to use ctype */ while (*++*argv) if (!isspace(STOUC(**argv))) { - badoptionstring: - zerr("bad option string: `%s'", args); - exit(1); + badoptionstring: + WARN_OPTION("bad option string: '%s'", args); + LAST_OPTION(1); } break; } else { if (!(optno = optlookupc(**argv))) { - zerr("bad option: -%c", **argv); - exit(1); - } else if (optno == RESTRICTED) + WARN_OPTION("bad option: -%c", **argv); + LAST_OPTION(1); + } else if (optno == RESTRICTED && !nam) restricted = action; - else - dosetopt(optno, action, 1); + else if ((optno == EMACSMODE || optno == VIMODE) && nam) + WARN_OPTION("can't change option: %s", *argv); + else if (dosetopt(optno, action, !nam) && nam) + WARN_OPTION("can't change option: -%c", **argv); } } argv++; } - doneoptions: - paramlist = znewlinklist(); + doneoptions: if (cmd) { if (!*argv) { - zerr("string expected after -%s", cmd); - exit(1); + WARN_OPTION("string expected after -%s", cmd); + LAST_OPTION(1); } cmd = *argv++; } - if (*argv) { - if (unset(SHINSTDIN)) { - if (cmd) - argzero = *argv; - else - *runscript = *argv; - opts[INTERACTIVE] &= 1; - argv++; - } - while (*argv) - zaddlinknode(paramlist, ztrdup(*argv++)); - } else if (!cmd) - opts[SHINSTDIN] = 1; - if(isset(SINGLECOMMAND)) - opts[INTERACTIVE] &= 1; - opts[INTERACTIVE] = !!opts[INTERACTIVE]; - if (opts[MONITOR] == 2) - opts[MONITOR] = opts[INTERACTIVE]; - if (opts[HASHDIRS] == 2) - opts[HASHDIRS] = opts[INTERACTIVE]; - pparams = x = (char **) zshcalloc((countlinknodes(paramlist) + 1) * sizeof(char *)); - - while ((*x++ = (char *)getlinknode(paramlist))); - free(paramlist); - argzero = ztrdup(argzero); + doneargv: + *argvp = argv; + return cmd; } /**/ diff --git a/Src/options.c b/Src/options.c index 48df16045..c6db75372 100644 --- a/Src/options.c +++ b/Src/options.c @@ -767,6 +767,8 @@ dosetopt(int optno, int value, int force) return -1; #endif /* GETPWNAM_FAKED */ } else if ((optno == EMACSMODE || optno == VIMODE) && value) { + if (sticky_emulation) + return -1; zleentry(ZLE_CMD_SET_KEYMAP, optno); opts[(optno == EMACSMODE) ? VIMODE : EMACSMODE] = 0; } else if (optno == SUNKEYBOARDHACK) { -- cgit 1.4.1