about summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
authorBart Schaefer <barts@users.sourceforge.net>2012-03-07 06:10:42 +0000
committerBart Schaefer <barts@users.sourceforge.net>2012-03-07 06:10:42 +0000
commitfa8a0e241c8ac9eb48ab9fc2d8bb3105088e0db9 (patch)
treee0369814c4201b9dfe4ca087620b574f4fb35059 /Src
parenta0d24f0bf3bfc7509557089bd6e0336f8da0494f (diff)
downloadzsh-fa8a0e241c8ac9eb48ab9fc2d8bb3105088e0db9.tar.gz
zsh-fa8a0e241c8ac9eb48ab9fc2d8bb3105088e0db9.tar.xz
zsh-fa8a0e241c8ac9eb48ab9fc2d8bb3105088e0db9.zip
30320: "emulate" accepts invocation-time flags; other small doc tweaks.
Diffstat (limited to 'Src')
-rw-r--r--Src/builtin.c57
-rw-r--r--Src/init.c119
-rw-r--r--Src/options.c2
3 files changed, 105 insertions, 73 deletions
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) {