Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/bin/sh Command line, and "set" command options processing cl...



details:   https://anonhg.NetBSD.org/src/rev/98870a4cc6cd
branches:  trunk
changeset: 824003:98870a4cc6cd
user:      kre <kre%NetBSD.org@localhost>
date:      Thu May 18 13:53:18 2017 +0000

description:
Command line, and "set" command options processing cleanup.

sh +c "command string"  no longer works (it must be -c)
sh +o   and   sh -o     no longer work (if you could call what they did
                        before working.)  nb: this is without an option name.
-ooo Opt1 Opt2 Opt3     no longer works (set & cmd line), this should be
                        -o Opt1 -o Opt2 -o Opt3   (same with +ooo of course).
-oOpt                   is now supported - option value (name of option in
                        this case) immediately following -o (or +o).
                        (as with other commands that use std opt parsing)
                        Both set comamnd and command line.

In addition, the output from "set +o" has shrunk dramatically, by borrowing
a trick from ksh93 (but implemented in a more traditional syntax).
"set +o" is required to produce a command (or commands) which when executed
later, will return all options to the state they were in when "set +o"
was done.  Previously that was done by generating a set command, with
every option listed (set -o opt +o other-opt ...) to set them all back
to their current setings.   Now we have a new "magic option" ("default")
which sets all options to their default values, so now set +o output
need only be "set -o default -o changed-opt ..." (only the options that
have been changed from their default values need be explicitly mentioned.)
The definition of "default value" for this is the value the shell set the
option to, after startup, after processing the command line (with any
flags, or -o option type settings), but before beginning processing any
user input (incuding startup files, like $ENV etc).

Anyone can execute "set -o default" of course, but only from a "set"
command (it makes no sense at all as a -o option to sh).   This also
causes "set +o" to be slightly more useful as a general command, as
ignoring the "set -o default" part of the result, it lists just those
options that have been altered after sh startup.  There is no +o default.
There isn't an option called "default" at all...

This causes some of the commented out text from sh.1 to become uncommented.

diffstat:

 bin/sh/options.c |  68 +++++++++++++++++++++++++++++++++++++++++++------------
 bin/sh/options.h |  18 +++++++++----
 bin/sh/sh.1      |  49 +++++++++++++++++++++++-----------------
 3 files changed, 93 insertions(+), 42 deletions(-)

diffs (275 lines):

diff -r 02071864d2bd -r 98870a4cc6cd bin/sh/options.c
--- a/bin/sh/options.c  Thu May 18 13:34:17 2017 +0000
+++ b/bin/sh/options.c  Thu May 18 13:53:18 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: options.c,v 1.47 2017/05/15 20:00:36 kre Exp $ */
+/*     $NetBSD: options.c,v 1.48 2017/05/18 13:53:18 kre Exp $ */
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)options.c  8.2 (Berkeley) 5/4/95";
 #else
-__RCSID("$NetBSD: options.c,v 1.47 2017/05/15 20:00:36 kre Exp $");
+__RCSID("$NetBSD: options.c,v 1.48 2017/05/18 13:53:18 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -88,13 +88,23 @@
 procargs(int argc, char **argv)
 {
        size_t i;
+       int psx;
 
        argptr = argv;
        if (argc > 0)
                argptr++;
+
+       psx = posix;            /* save what we set it to earlier */
+       /*
+        * option values are mostly boolean 0:off 1:on
+        * we use 2 (just in this routine) to mean "unknown yet"
+        */
        for (i = 0; i < NOPTS; i++)
                optlist[i].val = 2;
+       posix = psx;            /* restore before processing -o ... */
+
        options(1);
+
        if (*argptr == NULL && minusc == NULL)
                sflag = 1;
        if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
@@ -107,12 +117,24 @@
        if (usefork == 2)
                usefork = 1;
 #endif
-       for (i = 0; i < NOPTS; i++)
+#if DEBUG == 2
+       if (debug == 2)
+               debug = 1;
+#endif
+       /*
+        * Any options not dealt with as special cases just above,
+        * and which were not set on the command line, are set to
+        * their expected default values (mostly "off")
+        *
+        * then as each option is initialised, save its setting now
+        * as its "default" value for future use ("set -o default").
+        */
+       for (i = 0; i < NOPTS; i++) {
                if (optlist[i].val == 2)
-                       optlist[i].val = 0;
-#if DEBUG == 2
-       debug = 1;
-#endif
+                       optlist[i].val = optlist[i].dflt;
+               optlist[i].dflt = optlist[i].val;
+       }
+
        arg0 = argv[0];
        if (sflag == 0 && minusc == NULL) {
                commandname = argv[0];
@@ -187,13 +209,20 @@
                        break;
                }
                while ((c = *p++) != '\0') {
-                       if (c == 'c' && cmdline) {
+                       if (val == 1 && c == 'c' && cmdline) {
                                /* command is after shell args*/
                                minusc = empty;
                        } else if (c == 'o') {
-                               minus_o(*argptr, val);
-                               if (*argptr)
-                                       argptr++;
+                               if (*p != '\0')
+                                       minus_o(p, val + (cmdline ? val : 0));
+                               else if (*argptr)
+                                       minus_o(*argptr++,
+                                           val + (cmdline ? val : 0));
+                               else if (!cmdline)
+                                       minus_o(NULL, val);
+                               else
+                                       error("arg for %co missing", "+-"[val]);
+                               break;
 #ifdef DEBUG
                        } else if (c == 'D') {
                                if (*p) {
@@ -250,12 +279,14 @@
                        out1c('\n');
                        for (i = 0; i < NOPTS; i++) {
                                if (optlist[i].name)
-                                   out1fmt("%-16s%s\n", optlist[i].name,
+                                   out1fmt("%-19s %s\n", optlist[i].name,
                                        optlist[i].val ? "on" : "off");
                        }
                } else {
-                       out1str("set");
+                       out1str("set -o default");
                        for (i = 0; i < NOPTS; i++) {
+                               if (optlist[i].val == optlist[i].dflt)
+                                       continue;
                                if (optlist[i].name)
                                    out1fmt(" %co %s",
                                        "+-"[optlist[i].val], optlist[i].name);
@@ -266,12 +297,19 @@
                        out1c('\n');
                }
        } else {
+               if (val == 1 && equal(name, "default")) { /* special case */
+                       for (i = 0; i < NOPTS; i++)
+                               set_opt_val(i, optlist[i].dflt);
+                       return;
+               }
+               if (val)
+                       val = 1;
                for (i = 0; i < NOPTS; i++)
                        if (optlist[i].name && equal(name, optlist[i].name)) {
                                set_opt_val(i, val);
                                return;
                        }
-               error("Illegal option -o %s", name);
+               error("Illegal option %co %s", "+-"[val], name);
        }
 }
 
@@ -286,7 +324,7 @@
                        set_opt_val( i, val );
                        return;
                }
-       error("Illegal option -%c", flag);
+       error("Illegal option %c%c", "+-"[val], flag);
        /* NOTREACHED */
 }
 
diff -r 02071864d2bd -r 98870a4cc6cd bin/sh/options.h
--- a/bin/sh/options.h  Thu May 18 13:34:17 2017 +0000
+++ b/bin/sh/options.h  Thu May 18 13:53:18 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: options.h,v 1.25 2016/03/31 16:16:35 christos Exp $    */
+/*     $NetBSD: options.h,v 1.26 2017/05/18 13:53:18 kre Exp $ */
 
 /*-
  * Copyright (c) 1991, 1993
@@ -43,23 +43,29 @@
        char *optptr;           /* used by getopts */
 };
 
-
+/*
+ * Note that option default values can be changed at shell startup
+ * depending upon the environment in which the shell is running.
+ */
 struct optent {
        const char *name;               /* for set -o <name> */
        const char letter;              /* set [+/-]<letter> and $- */
        const char opt_set;             /* mutually exclusive option set */
        unsigned char val;              /* value of <letter>flag */
+       unsigned char dflt;             /* default value of flag */
 };
 
 /* Those marked [U] are required by posix, but have no effect! */
 
 #ifdef DEFINE_OPTIONS
-#define DEF_OPTS(name, letter, opt_set) {name, letter, opt_set, 0},
+#define DEF_OPTS_D(name,letter,opt_set,dflt) {name, letter, opt_set, 0, dflt },
 struct optent optlist[] = {
 #else
-#define DEF_OPTS(name, letter, opt_set)
+#define DEF_OPTS_D(name,letter,opt_set,dflt)
 #endif
-#define DEF_OPT(name,letter) DEF_OPTS(name, letter, 0)
+#define DEF_OPTS(name,letter,opt_set)  DEF_OPTS_D(name, letter, opt_set, 0)
+#define DEF_OPT(name,letter)           DEF_OPTS_D(name, letter, 0, 0)
+#define DEF_OPT_D(name,letter,dflt)    DEF_OPTS_D(name, letter, 0, dflt)
 
 DEF_OPT( "errexit",    'e' )   /* exit on error */
 #define eflag optlist[0].val
@@ -113,7 +119,7 @@
 #endif
 
 #ifdef DEFINE_OPTIONS
-       { 0, 0, 0, 0 },
+       { 0, 0, 0, 0, 0 },
 };
 #define NOPTS (sizeof optlist / sizeof optlist[0] - 1)
 int sizeof_optlist = sizeof optlist;
diff -r 02071864d2bd -r 98870a4cc6cd bin/sh/sh.1
--- a/bin/sh/sh.1       Thu May 18 13:34:17 2017 +0000
+++ b/bin/sh/sh.1       Thu May 18 13:53:18 2017 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: sh.1,v 1.141 2017/05/14 17:27:05 kre Exp $
+.\"    $NetBSD: sh.1,v 1.142 2017/05/18 13:53:18 kre Exp $
 .\" Copyright (c) 1991, 1993
 .\"    The Regents of the University of California.  All rights reserved.
 .\"
@@ -212,8 +212,8 @@
 turns the option on, while using a plus
 .Dq +
 disables the option.
-The following options can be set from the command line or
-with the
+The following options can be set from the command line and,
+unless otherwise stated, with the
 .Ic set
 built-in (described later).
 .Bl -tag -width \-WXXlineno_fn_relativeXX -offset indent
@@ -2231,33 +2231,40 @@
 flags, or clears them as described in the
 .Sx Argument List Processing
 section.
-.\" In addition to the options listed there,
-.\" when the
-.\" .Dq "option name"
-.\" given to
-.\" .Fl o
-.\" is
-.\" .Cm default
-.\" all of the options are reset to the values they had immediately
-.\" after
-.\" .Nm
-.\" initialization, before any startup scripts had been processed.
-.\" While this may be of use to users or scripts, its primary purpose
-.\" is for use in the output of
-.\" .Dq Ic set Cm +o ,
-.\" to avoid that command needing to list every available option.
-.\" There is no
-.\" .Cm +o default .
+In addition to the options listed there,
+when the
+.Dq "option name"
+given to
+.Ic set Fl o
+is
+.Cm default
+all of the options are reset to the values they had immediately
+after
+.Nm
+initialization, before any startup scripts, or other input, had been processed.
+While this may be of use to users or scripts, its primary purpose
+is for use in the output of
+.Dq Ic set Cm +o ,
+to avoid that command needing to list every available option.
+There is no
+.Cm +o default .
 .Pp
 The fourth use of the set command is to set the values of the shell's
 positional parameters to the specified arguments.
 To change the positional
 parameters without changing any options, use
-.Dq --
+.Dq -\|-
 as the first argument to set.
 If no following arguments are present, the set command
 will clear all the positional parameters (equivalent to executing
 .Dq shift $# . )
+Otherwise the following arguments become
+.Do \&$1 Dc Ns \&,
+.Do \&$2 Dc Ns \&,
+\&...,
+and
+.Dq \&$#
+is set to the number of arguments present.
 .It setvar Ar variable Ar value
 Assigns value to variable.
 (In general it is better to write



Home | Main Index | Thread Index | Old Index