diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | Doc/Zsh/invoke.yo | 60 | ||||
-rw-r--r-- | Src/init.c | 56 | ||||
-rw-r--r-- | Src/options.c | 45 | ||||
-rw-r--r-- | Src/zsh.h | 2 | ||||
-rw-r--r-- | Src/zsh.mdd | 51 |
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 |