summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--Doc/Zsh/invoke.yo60
-rw-r--r--Src/init.c56
-rw-r--r--Src/options.c45
-rw-r--r--Src/zsh.h2
-rw-r--r--Src/zsh.mdd51
6 files changed, 192 insertions, 31 deletions
diff --git a/ChangeLog b/ChangeLog
index 1a77d7843..7649ef8f8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2000-07-30  Andrew Main <zefram@zsh.org>
+
+	* 12434: Doc/Zsh/invoke.yo, Src/init.c, Src/options.c, Src/zsh.h,
+	Src/zsh.mdd: Allow options to be specified on the zsh command line
+	in the form of GNU-style long options.	Also handle --version
+	and --help.  Do not permit extra option letters to be stacked
+	after `-whatever-' (they used to be ignored).  Exit if the
+	command line specifies an option name that doesn't exist.
+
 2000-07-28  Bart Schaefer  <schaefer@zsh.org>
 
 	* 12393: Src/jobs.c: The `wait' builtin searches the job table for
diff --git a/Doc/Zsh/invoke.yo b/Doc/Zsh/invoke.yo
index 3a95bc81f..de0ed6b6b 100644
--- a/Doc/Zsh/invoke.yo
+++ b/Doc/Zsh/invoke.yo
@@ -4,34 +4,76 @@ cindex(invocation)
 sect(Invocation Options)
 cindex(flags, shell)
 cindex(shell flags)
-If the tt(-s) flag is not present and an argument is given,
-the first argument is taken to be the pathname of a script to
-execute.  The remaining arguments are assigned to the positional
-parameters.  The following flags are interpreted by the shell
-when invoked:
+The following flags are interpreted by the shell when invoked to determine
+where the shell will read commands from:
 
 startitem()
-item(tt(-c) var(string))(
-Read commands from var(string).
+item(tt(-c))(
+Take the first argument as a command to execute, rather than reading commands
+from a script or standard input.  If any further arguments are given, the
+first one is assigned to tt($0), rather than being used as a positional
+parameter.
 )
 item(tt(-i))(
 Force shell to be interactive.
 )
 item(tt(-s))(
-Read command from the standard input.
+Force shell to read commands from the standard input.
+If the tt(-s) flag is not present and an argument is given,
+the first argument is taken to be the pathname of a script to
+execute.
 )
 enditem()
 
+After the first one or two arguments have been appropriated as described above,
+the remaining arguments are assigned to the positional parameters.
+
 For further options, which are common to invocation and the tt(set)
 builtin, see
 ifzman(zmanref(zshoptions))\
 ifnzman(noderef(Options))\
-.  Flags may be specified by name using the tt(-o) option.  For example,
+.
+
+Options may be specified by name using the tt(-o) option.  tt(-o) acts like
+a single-letter option, but takes a following string as the option name.
+For example,
 
 example(zsh -x -o shwordsplit scr)
 
 runs the script tt(scr), setting the tt(XTRACE) option by the corresponding
 letter `tt(-x)' and the tt(SH_WORD_SPLIT) option by name.
+Options may be turned em(off) by name by using tt(PLUS()o) instead of tt(-o).
+tt(-o) can be stacked up with preceding single-letter options, so for example
+`tt(-xo shwordsplit)' or `tt(-xoshwordsplit)' is equivalent to
+`tt(-x -o shwordsplit)'.
+
+Options may also be specified by name in GNU long option style,
+`tt(--)var(option-name)'.  When this is done, `tt(-)' characters in the
+option name are permitted: they are translated into `tt(_)', and thus ignored.
+So, for example, `tt(zsh --sh-word-split)' invokes zsh with the
+tt(SH_WORD_SPLIT) option turned on.  Like other option syntaxes, options can
+be turned off by replacing the initial `tt(-)' with a `tt(PLUS())'; thus
+`tt(+-sh-word-split)' is equivalent to `tt(--no-sh-word-split)'.
+Unlike other option syntaxes, GNU-style long options cannot be stacked with
+any other options, so for example `tt(-x-shwordsplit)' is an error,
+rather than being treated like `tt(-x --shwordsplit)'.
+
+The special GNU-style option `tt(--version)' is handled; it sends to standard
+output the shell's version information, then exits successfully.
+`tt(--help)' is also handled; it sends to standard output a list of options
+that can be used when invoking the shell, then exits successfully.
+
+Option processing may be finished, allowing following arguments that start with
+`tt(-)' or `tt(PLUS())' to be treated as normal arguments, in two ways.
+Firstly, a lone `tt(-)' (or `tt(PLUS())') as an argument by itself ends option
+processing.  Secondly, a special option `tt(--)' (or `tt(PLUS()-)'), which may
+be specified on its own (which is the standard POSIX usage) or may be stacked
+with preceding options (so `tt(-x-)' is equivalent to `tt(-x --)').  Options
+are not permitted to be stacked after `tt(--)' (so `tt(-x-f)' is an error),
+but note the GNU-style option form discussed above, where `tt(--shwordsplit)'
+is permitted and does not end option processing.
+Except when emulating sh or ksh, the option `tt(-b)' is treated the same way
+as `tt(--)' for the purpose of ending option processing.
 
 startmenu()
 menu(Compatibility)
diff --git a/Src/init.c b/Src/init.c
index e190cee44..04ed141dd 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -34,6 +34,8 @@
 
 #include "init.pro"
 
+#include "version.h"
+
 /**/
 int noexitct = 0;
 
@@ -207,15 +209,35 @@ parseargs(char **argv)
     while (*argv && (**argv == '-' || **argv == '+')) {
 	char *args = *argv;
 	action = (**argv == '-');
-	if(!argv[0][1])
+	if (!argv[0][1])
 	    *argv = "--";
 	while (*++*argv) {
 	    /* The pseudo-option `--' signifies the end of options. *
 	     * `-b' does too, csh-style, unless we're emulating a   *
 	     * Bourne style shell.                                  */
 	    if (**argv == '-' || (!bourne && **argv == 'b')) {
-		argv++;
-		goto doneoptions;
+		if(!argv[0][1]) {
+		    argv++;
+		    goto doneoptions;
+		}
+		if(*argv != args+1 || **argv != '-')
+		    goto badoptionstring;
+		/* GNU-style long options */
+		++*argv;
+		if (!strcmp(*argv, "version")) {
+		    printf("zsh %s (%s-%s-%s)\n",
+			    ZSH_VERSION, MACHTYPE, VENDOR, OSTYPE);
+		    exit(0);
+		}
+		if (!strcmp(*argv, "help")) {
+		    printhelp();
+		    exit(0);
+		}
+		/* `-' characters are allowed in long options */
+		for(args = *argv; *args; args++)
+		    if(*args == '-')
+			*args = '_';
+		goto longoptions;
 	    }
 
 	    if (**argv == 'c') {         /* -c command */
@@ -230,9 +252,11 @@ parseargs(char **argv)
 		    zerr("string expected after -o", NULL, 0);
 		    exit(1);
 		}
-		if(!(optno = optlookup(*argv)))
+	    longoptions:
+		if (!(optno = optlookup(*argv))) {
 		    zerr("no such option: %s", *argv, 0);
-		else if (optno == RESTRICTED)
+		    exit(1);
+		} else if (optno == RESTRICTED)
 		    restricted = action;
 		else
 		    dosetopt(optno, action, 1);
@@ -241,6 +265,7 @@ parseargs(char **argv)
 		/* zsh's typtab not yet set, have to use ctype */
 		while (*++*argv)
 		    if (!isspace(STOUC(**argv))) {
+		    badoptionstring:
 			zerr("bad option string: `%s'", args, 0);
 			exit(1);
 		    }
@@ -292,6 +317,27 @@ parseargs(char **argv)
     argzero = ztrdup(argzero);
 }
 
+/**/
+static void
+printhelp(void)
+{
+    int bourne = (emulation == EMULATE_KSH || emulation == EMULATE_SH);
+
+    printf("Usage: %s [<options>] [<argument> ...]\n", argzero);
+    printf("\nSpecial options:\n");
+    printf("  --help     show this message, then exit\n");
+    printf("  --version  show zsh version number, then exit\n");
+    if(!bourne)
+	printf("  -b         end option processing, like --\n");
+    printf("  -c         take first argument as a command to execute\n");
+    printf("  -o OPTION  set an option by name (see below)\n");
+    printf("\nNormal options are named.  An option may be turned on by\n");
+    printf("`-o OPTION', `--OPTION', `+o no_OPTION' or `+-no-OPTION'.  An\n");
+    printf("option may be turned off by `-o no_OPTION', `--no-OPTION',\n");
+    printf("`+o OPTION' or `+-OPTION'.  Options are listed below only in\n");
+    printf("`--OPTION' or `--no-OPTION' form.\n");
+    printoptionlist();
+}
 
 /**/
 mod_export void
diff --git a/Src/options.c b/Src/options.c
index ea3bf13de..0bbe6b844 100644
--- a/Src/options.c
+++ b/Src/options.c
@@ -694,3 +694,48 @@ dashgetfn(Param pm)
     *val = '\0';
     return buf;
 }
+
+/* Print option list for --help */
+
+/**/
+void
+printoptionlist(void)
+{
+    short *lp;
+    char c;
+
+    printf("\nNamed options:\n");
+    scanhashtable(optiontab, 1, 0, OPT_ALIAS, printoptionlist_printoption, 0);
+    printf("\nOption aliases:\n");
+    scanhashtable(optiontab, 1, OPT_ALIAS, 0, printoptionlist_printoption, 0);
+    printf("\nOption letters:\n");
+    for(lp = optletters, c = FIRST_OPT; c <= LAST_OPT; lp++, c++) {
+	if(!*lp)
+	    continue;
+	printf("  -%c  ", c);
+	printoptionlist_printequiv(*lp);
+    }
+}
+
+/**/
+static void
+printoptionlist_printoption(HashNode hn, int ignored)
+{
+    Optname on = (Optname) hn;
+
+    if(on->flags & OPT_ALIAS) {
+	printf("  --%-19s  ", on->nam);
+	printoptionlist_printequiv(on->optno);
+    } else
+	printf("  --%s\n", on->nam);
+}
+
+/**/
+static void
+printoptionlist_printequiv(int optno)
+{
+    int isneg = optno < 0;
+
+    optno *= (isneg ? -1 : 1);
+    printf("  equivalent to --%s%s\n", isneg ? "no-" : "", optns[optno-1].nam);
+}
diff --git a/Src/zsh.h b/Src/zsh.h
index 49acf129c..a21fa16e6 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -1345,9 +1345,9 @@ enum {
     EXTENDEDHISTORY,
     FLOWCONTROL,
     FUNCTIONARGZERO,
+    GLOBOPT,
     GLOBALEXPORT,
     GLOBALRCS,
-    GLOBOPT,
     GLOBASSIGN,
     GLOBCOMPLETE,
     GLOBDOTS,
diff --git a/Src/zsh.mdd b/Src/zsh.mdd
index 244029d65..ad0d27bfe 100644
--- a/Src/zsh.mdd
+++ b/Src/zsh.mdd
@@ -1,3 +1,5 @@
+name=zsh/main
+
 nozshdep=1
 alwayslink=1
 
@@ -5,28 +7,48 @@ alwayslink=1
 
 objects="builtin.o compat.o cond.o exec.o glob.o hashtable.o \
 hist.o init.o input.o jobs.o lex.o linklist.o loop.o math.o \
-mem.o module.o options.o params.o parse.o prompt.o signals.o \
+mem.o module.o options.o params.o parse.o pattern.o prompt.o signals.o \
 signames.o subst.o text.o utils.o watch.o"
 
 headers="../config.h system.h zsh.h sigcount.h signals.h \
 prototypes.h hashtable.h ztype.h"
 
 :<<\Make
-signames.c: signames.awk @SIGNAL_H@
-	$(AWK) -f $(sdir)/signames.awk @SIGNAL_H@ > $@
+@CONFIG_MK@
+
+signames.c: signames1.awk signames2.awk ../config.h @SIGNAL_H@
+	$(AWK) -f $(sdir)/signames1.awk @SIGNAL_H@ >sigtmp.c
+	$(CPP) sigtmp.c >sigtmp.out
+	$(AWK) -f $(sdir)/signames2.awk sigtmp.out > $@
+	rm -f sigtmp.c sigtmp.out
 
 sigcount.h: signames.c
 	grep 'define.*SIGCOUNT' signames.c > $@
 
 init.o: bltinmods.list zshpaths.h zshxmods.h
 
-params.o: version.h
+init.o params.o: version.h
 
 version.h: $(sdir_top)/Config/version.mk
 	echo '#define ZSH_VERSION "'$(VERSION)'"' > $@
 
-zshpaths.h: FORCE
+zshpaths.h: Makemod $(CONFIG_INCS)
 	@echo '#define MODULE_DIR "'$(MODDIR)'"' > zshpaths.h.tmp
+	@if test x$(sitefndir) != xno; then \
+	  echo '#define SITEFPATH_DIR "'$(sitefndir)'"' >> zshpaths.h.tmp; \
+	fi
+	@if test x$(fndir) != xno; then \
+	  echo '#define FPATH_DIR "'$(fndir)'"' >> zshpaths.h.tmp; \
+	  if test x$(FUNCTIONS_SUBDIRS) != x -a \
+	  x$(FUNCTIONS_SUBDIRS) != xno; then \
+	    fpath_tmp="`for f in $$FUNCTIONS_INSTALL; do \
+	      echo $$f | sed s%/.*%%; \
+	    done | sort | uniq`"; \
+	    fpath_tmp="`echo $$fpath_tmp | sed 's/ /\", \"/g'`"; \
+	    echo "#define FPATH_SUBDIRS { \"$$fpath_tmp\" }" \
+	    >>zshpaths.h.tmp; \
+	  fi; \
+	fi
 	@if cmp -s zshpaths.h zshpaths.h.tmp; then \
 	    rm -f zshpaths.h.tmp; \
 	    echo "\`zshpaths.h' is up to date." ; \
@@ -43,19 +65,16 @@ zshxmods.h: modules-bltin xmods.conf
 	@echo "Creating \`$@'."
 	@( \
 	    binmods=`sed 's/^/ /;s/$$/ /' modules-bltin`; \
-	    for mod in `cat $(sdir_src)/xmods.conf`; do \
+	    for mod in `sed 's/^.* //' $(sdir_src)/xmods.conf`; do \
+		q_mod=`echo $$mod | sed 's,Q,Qq,g;s,_,Qu,g;s,/,Qs,g'`; \
 		case $$binmods in \
 		    *" $$mod "*) \
-			echo "#define    LINKED_XMOD_$$mod 1" ;; \
+			echo "#define    LINKED_XMOD_$$q_mod 1" ;; \
 		    *)  echo "#ifdef DYNAMIC"; \
-			echo "# define UNLINKED_XMOD_$$mod 1"; \
+			echo "# define UNLINKED_XMOD_$$q_mod 1"; \
 			echo "#endif" ;; \
 		esac; \
-	    done; \
-	    echo; \
-	    for mod in $$binmods; do \
-		echo "int boot_$$mod _((Module));"; \
-	    done; \
+	    done \
 	) > $@
 
 clean-here: clean.zsh
@@ -63,9 +82,9 @@ clean.zsh:
 	rm -f sigcount.h signames.c bltinmods.list version.h zshpaths.h zshxmods.h
 
 # This is not properly part of this module, but it is built as if it were.
-main.o: main.c zsh.mdh main.pro
+main.o: main.c zsh.mdh main.epro
 	$(CC) -c -I. $(CPPFLAGS) $(DEFS) $(CFLAGS) -o $@ $(sdir)/main.c
 
-main.pro: $(PROTODEPS)
-proto.zsh: main.pro
+main.syms: $(PROTODEPS)
+proto.zsh: main.epro
 Make