Arrange for set -o and $- output to be sorted, rather than more

or less random (and becoming worse as more options are added.)
Since the data is known at compile time, sort at compile time,
rather than at run time.
This commit is contained in:
kre 2017-05-28 00:38:01 +00:00
parent 46a6e1093a
commit f359a311bc
5 changed files with 217 additions and 81 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.107 2017/05/15 18:34:56 kre Exp $
# $NetBSD: Makefile,v 1.108 2017/05/28 00:38:01 kre Exp $
# @(#)Makefile 8.4 (Berkeley) 5/5/95
.include <bsd.own.mk>
@ -9,7 +9,7 @@ SHSRCS= alias.c arith_token.c arithmetic.c cd.c echo.c error.c eval.c exec.c \
miscbltin.c mystring.c options.c parser.c redir.c show.c trap.c \
output.c var.c test.c kill.c syntax.c
GENSRCS=builtins.c init.c nodes.c
GENHDRS=builtins.h nodes.h token.h nodenames.h
GENHDRS=builtins.h nodes.h token.h nodenames.h optinit.h
SRCS= ${SHSRCS} ${GENSRCS}
DPSRCS+=${GENHDRS}
@ -77,6 +77,10 @@ nodenames.h: mknodenames.sh nodes.h
${_MKTARGET_CREATE}
${SCRIPT_ENV} ${HOST_SH} ${.ALLSRC} > ${.TARGET}
optinit.h: mkoptions.sh option.list
${_MKTARGET_CREATE}
${SCRIPT_ENV} ${HOST_SH} ${.ALLSRC} ${.TARGET} ${.OBJDIR}
.if ${USETOOLS} == "yes"
NBCOMPATLIB= -L${TOOLDIR}/lib -lnbcompat
.endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: expand.c,v 1.105 2017/04/26 17:43:33 christos Exp $ */
/* $NetBSD: expand.c,v 1.106 2017/05/28 00:38:01 kre Exp $ */
/*-
* Copyright (c) 1991, 1993
@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)expand.c 8.5 (Berkeley) 5/15/95";
#else
__RCSID("$NetBSD: expand.c,v 1.105 2017/04/26 17:43:33 christos Exp $");
__RCSID("$NetBSD: expand.c,v 1.106 2017/05/28 00:38:01 kre Exp $");
#endif
#endif /* not lint */
@ -941,9 +941,9 @@ numvar:
expdest = cvtnum(num, expdest);
break;
case '-':
for (i = 0; optlist[i].name || optlist[i].letter; i++) {
if (optlist[i].val && optlist[i].letter)
STPUTC(optlist[i].letter, expdest);
for (i = 0; i < option_flags; i++) {
if (optlist[optorder[i]].val)
STPUTC(optlist[optorder[i]].letter, expdest);
}
break;
case '@':

147
bin/sh/mkoptions.sh Normal file
View File

@ -0,0 +1,147 @@
#! /bin/sh
# $NetBSD: mkoptions.sh,v 1.1 2017/05/28 00:38:01 kre Exp $
#
# It would be more sensible to generate 2 .h files, one which
# is for everyone to use, defines the "variables" and (perhaps) generates
# the externs (though they could just be explicit in options.h)
# and one just for options.c which generates the initialisation.
#
# But then I'd have to deal with making the Makefile handle that properly...
# (this is simpler there, and it just means a bit more sh compile time.)
set -f
IFS=' ' # blank, tab (no newline)
IF="$1"
OF="${3+$3/}$2"
{
printf '/*\n * File automatically generated by %s.\n' "$0"
printf ' * Do not edit, do not add to cvs.\n'
printf ' */\n\n'
printf '#ifdef DEFINE_OPTIONS\n'
printf '#define DEF_OPT(a,b,c,d,e) { a, b, c, d, e },\n'
printf 'struct optent optlist[] = {\n'
printf '#else\n'
printf '#define DEF_OPT(a,b,c,d,e)\n'
printf '#endif\n\n'
} >"${OF}"
FIRST=true
I=0
while read line
do
# Look for comments in various styles, and ignore them
# preprocessor statements are simply output verbatim
# but use them only first or last. one #ifdef/#endif at end is OK
case "${line}" in
'') continue;;
/*) continue;;
\**) continue;;
\;*) continue;;
\#*) printf '%s\n\n' "${line}" >&4; continue;;
esac
set -- ${line%%[ ]#*}
var="$1" name="$2"
case "${var}" in
('' | [!A-Za-z_]* | *[!A-Za-z0-9_]*)
printf >&2 "Bad var name: '%s'\\n" "${var}"
# exit 1
continue # just ignore it for now
esac
case "${name}" in
# =) name=${var};; # probably not a good idea
?) set -- ${var} '' $name $3 $4; name= ;;
esac
chr="$3" set="$4" dflt="$5"
case "${chr}" in
-) chr= set= dflt="$4";;
''|?) ;;
*) printf >&2 'flag "%s": Not a character\n' "${chr}"; continue;;
esac
# options must have some kind of name, or they are useless...
test -z "${name}${chr}" && continue
case "${set}" in
-) set= ;;
[01]) dflt="${set}"; set= ;;
''|?) ;;
*) printf >&2 'set "%s": Not a character\n' "${set}"; continue;;
esac
if [ -n "${name}" ]
then
printf ' DEF_OPT("%s", ' "${name}" >&4
else
printf ' DEF_OPT(0, ' >&4
fi
if [ -n "${chr}" ]
then
printf "'%s', " "${chr}" >&4
else
printf '0, ' >&4
fi
if [ -n "${set}" ]
then
printf "'%s', 0, " "${set}" >&4
else
printf '0, 0, ' >&4
fi
if [ -n "${dflt}" ]
then
printf '%s )\n' "${dflt}" >&4
else
printf '0 )\n' >&4
fi
printf '#define %s optlist[%d].val\n\n' "${var}" "${I}" >&4
I=$((I + 1))
test -z "${chr}" && continue
printf '%s %d\n' "${chr}" $((I - 1))
done < "$IF" 4>>"${OF}" | sort -t' ' -k1,1f -k1,1r | while read chr index
do
if $FIRST
then
printf '#ifdef DEFINE_OPTIONS\n'
printf ' { 0, 0, 0, 0, 0 }\n};\n\n'
printf 'const unsigned char optorder[] = {\n'
FIRST=false
fi
printf '\t%s,\n' "${index}"
done >>"${OF}"
{
printf '};\n\n'
printf '#define NOPTS (sizeof optlist / sizeof optlist[0] - 1)\n'
printf 'int sizeof_optlist = sizeof optlist;\n\n'
printf \
'const int option_flags = (sizeof optorder / sizeof optorder[0]);\n'
printf '\n#else\n\n'
printf 'extern struct optent optlist[];\n'
printf 'extern int sizeof_optlist;\n'
printf 'extern const unsigned char optorder[];\n'
printf 'extern const int option_flags;\n'
printf '\n#endif\n'
} >> "${OF}"
exit 0

57
bin/sh/option.list Normal file
View File

@ -0,0 +1,57 @@
/* $NetBSD: option.list,v 1.1 2017/05/28 00:38:01 kre Exp $ */
/*
* define the shell's settable options
*/
/*
* format is up to 5 columns... (followed by anything)
* end of line comments can be introduced by ' #' (space/tab hash) to eol.
* proprocessor directoves can be (kind of) interspersed as required
*
* The columns are:
* 1. internal shell "var name" (required)
* 2. option long name
* if a single char, then no long name, and remaining
* columns shift left (this becomes the short name)
* 3. option short name (single character name)
* if '-' or absent then no short name
* if neither long nor short name, line is ignored
* 4. option set short name (name of option equiv class)
* if '-' or absent then no class
* 5. efault value of option
* if absent, default is 0
* only 0 or 1 possible (0==off 1==on)
*/
/*
* The order of the lines below gives the order they are listed by set -o
* Options labelled '[U]' are not (yet, maybe ever) implemented.
*/
aflag allexport a # export all variables
cdprint cdprint # always print result of a cd
Eflag emacs E V # enable emacs style editing
eflag errexit e # exit on command error ($? != 0)
usefork fork F # use fork(2) instead of vfork(2)
Iflag ignoreeof I # do not exit interactive shell on EOF
iflag interactive i # interactive shell
mflag monitor m # enable job control
Cflag noclobber C # do not overwrite files when using >
nflag noexec n # do not execue commands
fflag noglob f # no pathname expansion
nolog nolog # [U] no func definitions in history
pflag nopriv p # preserve privs if set[ug]id
bflag notify b # [U] report bg job completion
uflag nounset u # expanding unset var is an error
posix posix # be closer to POSIX compat
qflag quietprofile q # disable -v/-x in startup files
sflag stdin s # read from standard input
tabcomplete tabcomplete # make <tab> cause filename expansion
hflag trackall h # [U] locate cmds in funcs during defn
vflag verbose v # echo commands as read
Vflag vi V V # enable vi style editing
xflag xtrace x # trace command execution
#ifdef DEBUG
debug debug # enable internal shell debugging
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: options.h,v 1.26 2017/05/18 13:53:18 kre Exp $ */
/* $NetBSD: options.h,v 1.27 2017/05/28 00:38:01 kre Exp $ */
/*-
* Copyright (c) 1991, 1993
@ -55,79 +55,7 @@ struct optent {
unsigned char dflt; /* default value of flag */
};
/* Those marked [U] are required by posix, but have no effect! */
#ifdef DEFINE_OPTIONS
#define DEF_OPTS_D(name,letter,opt_set,dflt) {name, letter, opt_set, 0, dflt },
struct optent optlist[] = {
#else
#define DEF_OPTS_D(name,letter,opt_set,dflt)
#endif
#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
DEF_OPT( "noglob", 'f' ) /* no pathname expansion */
#define fflag optlist[1].val
DEF_OPT( "ignoreeof", 'I' ) /* do not exit on EOF */
#define Iflag optlist[2].val
DEF_OPT( "interactive",'i' ) /* interactive shell */
#define iflag optlist[3].val
DEF_OPT( "monitor", 'm' ) /* job control */
#define mflag optlist[4].val
DEF_OPT( "noexec", 'n' ) /* do not exec commands */
#define nflag optlist[5].val
DEF_OPT( "stdin", 's' ) /* read from stdin */
#define sflag optlist[6].val
DEF_OPT( "xtrace", 'x' ) /* trace after expansion */
#define xflag optlist[7].val
DEF_OPT( "verbose", 'v' ) /* trace read input */
#define vflag optlist[8].val
DEF_OPTS( "vi", 'V', 'V' ) /* vi style editing */
#define Vflag optlist[9].val
DEF_OPTS( "emacs", 'E', 'V' ) /* emacs style editing */
#define Eflag optlist[10].val
DEF_OPT( "noclobber", 'C' ) /* do not overwrite files with > */
#define Cflag optlist[11].val
DEF_OPT( "allexport", 'a' ) /* export all variables */
#define aflag optlist[12].val
DEF_OPT( "notify", 'b' ) /* [U] report completion of background jobs */
#define bflag optlist[13].val
DEF_OPT( "nounset", 'u' ) /* error expansion of unset variables */
#define uflag optlist[14].val
DEF_OPT( "quietprofile", 'q' )
#define qflag optlist[15].val
DEF_OPT( "nolog", 0 ) /* [U] no functon defs in command history */
#define nolog optlist[16].val
DEF_OPT( "cdprint", 0 ) /* always print result of cd */
#define cdprint optlist[17].val
DEF_OPT( "tabcomplete", 0 ) /* <tab> causes filename expansion */
#define tabcomplete optlist[18].val
DEF_OPT( "fork", 'F' ) /* use fork(2) instead of vfork(2) */
#define usefork optlist[19].val
DEF_OPT( "nopriv", 'p' ) /* preserve privs even if set{u,g}id */
#define pflag optlist[20].val
DEF_OPT( "trackall", 'h' ) /* [U] locate cmds in funcs when defined */
#define hflag optlist[21].val
DEF_OPT( "posix", 0 ) /* operate in posix mode */
#define posix optlist[22].val
#ifdef DEBUG
DEF_OPT( "debug", 0 ) /* enable debug prints */
#define debug optlist[23].val
#endif
#ifdef DEFINE_OPTIONS
{ 0, 0, 0, 0, 0 },
};
#define NOPTS (sizeof optlist / sizeof optlist[0] - 1)
int sizeof_optlist = sizeof optlist;
#else
extern struct optent optlist[];
extern int sizeof_optlist;
#endif
#include "optinit.h"
extern char *minusc; /* argument to -c option */
extern char *arg0; /* $0 */