1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-02-15 04:32:24 +00:00

typeset: add error msgs for incompatible options; improve usage msg

This adds informative error messages if incompatible options are
given. It also documents the exclusive -m, -n and -T options on
separate usage lines, as was already done with -f. The usage
message for incompatible options now looks something like this:

| $ ksh -c 'typeset -L10 -F -f -i foo'
| ksh: typeset: -i/-F/-E/-X cannot be used with -L/-R/-Z
| ksh: typeset: -f cannot be used with other options
| Usage: typeset [-bflmnprstuxACHS] [-a[type]] [-i[base]] [-E[n]]
|                [-F[n]] [-L[n]] [-M[mapping]] [-R[n]] [-X[n]]
|                [-h string] [-T[tname]] [-Z[n]] [name[=value]...]
|    Or: typeset -f [name...]
|    Or: typeset -m [name=name...]
|    Or: typeset -n [name=name...]
|    Or: typeset -T [tname[=(type definition)]...]
|  Help: typeset [ --help | --man ] 2>&1

(see also the previous commit, e21a053e)

Unfortunately the first "Usage" line has some redundancies with the
"Or:" lines showing separate usages. It doesn't seem to be possible
to avoid this; it's a flaw in how libast generates everything
(usage, help, manual) from one huge getopt(3) string. I still think
the three added "Or:" lines are an improvement as it wasn't
previously shown that these options need to be used on their own.

src/cmd/ksh93/bltins/typeset.c: b_typeset():
- Instead of only showing a generic usage message, add an
  informative error message if incompatible options were given.
- Conflicting options detection was failing because NV_LJUST and
  NV_EXPNOTE have the same bitmask value. Use a new 'isadjust'
  flag for -L/-R/-Z to remember if one of these was set.
- Detect conflict between -L/-R/-Z and a float option, not just -i.

src/cmd/ksh93/include/name.h, src/cmd/ksh93/data/msg.c:
- Add the two new error messages for incompatible options.

src/cmd/ksh93/data/builtins.c: sh_opttypeset[]:
- Add a space after 'float' in in "[+float?\btypeset -lE\b]" as
  this makes 'float' appear on its own line, improving formatting.
- Show -m, -n, -T on separate usage lines like -f, as none of these
  can be combined with other options.
- Remove "cannot be combined with other options" from -m and -n
  descriptions, as that should now be clear from the separate usage
  lines -- and even if not, the error message is now informative.

src/cmd/ksh93/sh.1, src/cmd/ksh93/COMPATIBILITY:
- Update.

src/cmd/ksh93/tests/types.sh:
- Remove obsolete test: 'typeset -RF' is no longer accepted.
  (It crashed in 93u+, so this is not an incompatibility...)

Resolves: https://github.com/ksh93/ksh/issues/48
This commit is contained in:
Martijn Dekker 2021-01-21 00:24:13 +00:00
parent e21a053e19
commit 0a10e76ccc
8 changed files with 58 additions and 17 deletions

3
NEWS
View file

@ -8,6 +8,9 @@ Any uppercase BUG_* names are modernish shell bug IDs.
- Fixed: executing a DEBUG trap in a command substitution had side effects - Fixed: executing a DEBUG trap in a command substitution had side effects
on the exit status ($?) of non-trap commands. on the exit status ($?) of non-trap commands.
- The typeset builtin command now gives an informative error message if an
incompatible combination of options is given.
2021-01-19: 2021-01-19:
- Fixed a crash when using 'cd' in a virtual/non-forking subshell in a - Fixed a crash when using 'cd' in a virtual/non-forking subshell in a

View file

@ -68,8 +68,8 @@ For more details, see the NEWS file and for complete details, see the git log.
9. The 'print', 'printf' and 'echo' builtin commands now return a nonzero 9. The 'print', 'printf' and 'echo' builtin commands now return a nonzero
exit status if an input/output error occurs. exit status if an input/output error occurs.
10. The 'unalias' builtin will now return a non-zero status if it tries to 10. The 'typeset' builtin now properly detects and reports options that
remove a previously set alias that is not currently set. cannot be used together if they are given as part of the same command.
____________________________________________________________________________ ____________________________________________________________________________

View file

@ -195,7 +195,7 @@ int b_typeset(int argc,register char *argv[],Shbltin_t *context)
const char *optstring = sh_opttypeset; const char *optstring = sh_opttypeset;
Namdecl_t *ntp = (Namdecl_t*)context->ptr; Namdecl_t *ntp = (Namdecl_t*)context->ptr;
Dt_t *troot; Dt_t *troot;
int isfloat=0, shortint=0, sflag=0; int isfloat=0, isadjust=0, shortint=0, sflag=0;
memset((void*)&tdata,0,sizeof(tdata)); memset((void*)&tdata,0,sizeof(tdata));
tdata.sh = context->shp; tdata.sh = context->shp;
@ -297,6 +297,7 @@ int b_typeset(int argc,register char *argv[],Shbltin_t *context)
tdata.argnum = (int)opt_info.num; tdata.argnum = (int)opt_info.num;
if(tdata.argnum < 0) if(tdata.argnum < 0)
errormsg(SH_DICT,ERROR_exit(1), e_badfield, tdata.argnum); errormsg(SH_DICT,ERROR_exit(1), e_badfield, tdata.argnum);
isadjust = 1;
if(n=='Z') if(n=='Z')
flag |= NV_ZFILL; flag |= NV_ZFILL;
else else
@ -377,18 +378,36 @@ endargs:
argv--; argv--;
if((flag&NV_ZFILL) && !(flag&NV_LJUST)) if((flag&NV_ZFILL) && !(flag&NV_LJUST))
flag |= NV_RJUST; flag |= NV_RJUST;
if((flag&NV_INTEGER) && (flag&(NV_LJUST|NV_RJUST|NV_ZFILL))) if((isfloat || flag&NV_INTEGER) && isadjust)
{
errormsg(SH_DICT,2,e_optincompat2,"-i/-F/-E/-X","-L/-R/-Z");
error_info.errors++; error_info.errors++;
}
if((flag&NV_BINARY) && (flag&(NV_LJUST|NV_UTOL|NV_LTOU))) if((flag&NV_BINARY) && (flag&(NV_LJUST|NV_UTOL|NV_LTOU)))
{
errormsg(SH_DICT,2,e_optincompat2,"-b","-L/-u/-l");
error_info.errors++; error_info.errors++;
}
if((flag&NV_MOVE) && (flag&~(NV_MOVE|NV_VARNAME|NV_ASSIGN))) if((flag&NV_MOVE) && (flag&~(NV_MOVE|NV_VARNAME|NV_ASSIGN)))
{
errormsg(SH_DICT,2,e_optincompat1,"-m");
error_info.errors++; error_info.errors++;
}
if((flag&NV_REF) && (flag&~(NV_REF|NV_IDENT|NV_ASSIGN))) if((flag&NV_REF) && (flag&~(NV_REF|NV_IDENT|NV_ASSIGN)))
{
errormsg(SH_DICT,2,e_optincompat1,"-n");
error_info.errors++; error_info.errors++;
}
if((flag&NV_TYPE) && (flag&~(NV_TYPE|NV_VARNAME|NV_ASSIGN))) if((flag&NV_TYPE) && (flag&~(NV_TYPE|NV_VARNAME|NV_ASSIGN)))
{
errormsg(SH_DICT,2,e_optincompat1,"-T");
error_info.errors++; error_info.errors++;
}
if(troot==tdata.sh->fun_tree && ((isfloat || flag&~(NV_FUNCT|NV_TAGGED|NV_EXPORT|NV_LTOU)))) if(troot==tdata.sh->fun_tree && ((isfloat || flag&~(NV_FUNCT|NV_TAGGED|NV_EXPORT|NV_LTOU))))
{
errormsg(SH_DICT,2,e_optincompat1,"-f");
error_info.errors++; error_info.errors++;
}
if(sflag && troot==tdata.sh->fun_tree) if(sflag && troot==tdata.sh->fun_tree)
{ {
/* static function */ /* static function */

View file

@ -1718,7 +1718,7 @@ USAGE_LICENSE
; ;
const char sh_opttypeset[] = const char sh_opttypeset[] =
"+[-1c?\n@(#)$Id: typeset (AT&T Research/ksh93) 2020-07-15 $\n]" "+[-1c?\n@(#)$Id: typeset (AT&T Research/ksh93) 2021-01-20 $\n]"
USAGE_LICENSE USAGE_LICENSE
"[+NAME?typeset - declare or display variables with attributes]" "[+NAME?typeset - declare or display variables with attributes]"
"[+DESCRIPTION?Without the \b-f\b option, \btypeset\b sets, unsets, " "[+DESCRIPTION?Without the \b-f\b option, \btypeset\b sets, unsets, "
@ -1738,7 +1738,7 @@ USAGE_LICENSE
"[+?Note also the following builtin command equivalents:]{" "[+?Note also the following builtin command equivalents:]{"
"[+autoload?\btypeset -fu\b]" "[+autoload?\btypeset -fu\b]"
"[+compound?\btypeset -C\b]" "[+compound?\btypeset -C\b]"
"[+float?\btypeset -lE\b]" "[+float ?\btypeset -lE\b]"
"[+functions?\btypeset -f\b]" "[+functions?\btypeset -f\b]"
"[+integer?\btypeset -li\b]" "[+integer?\btypeset -li\b]"
"[+nameref?\btypeset -n\b]" "[+nameref?\btypeset -n\b]"
@ -1768,11 +1768,9 @@ USAGE_LICENSE
"[l?Without \b-i\b, sets character mapping to \btolower\b. When used " "[l?Without \b-i\b, sets character mapping to \btolower\b. When used "
"with \b-i\b, \b-E\b, or \b-F\b indicates long variant.]" "with \b-i\b, \b-E\b, or \b-F\b indicates long variant.]"
"[m?Move. The value is the name of a variable whose value will be " "[m?Move. The value is the name of a variable whose value will be "
"moved to \aname\a. The original variable will be unset. Cannot be " "moved to \aname\a. The original variable will be unset.]"
"used with any other options.]"
"[n?Name reference. The value is the name of a variable that \aname\a " "[n?Name reference. The value is the name of a variable that \aname\a "
"references. \aname\a cannot contain a \b.\b. Cannot be used with " "references. \aname\a cannot contain a \b.\b.]"
"any other options.]"
"[p?Causes the output to be in a format that can be used as input to the " "[p?Causes the output to be in a format that can be used as input to the "
"shell to recreate the attributes for variables.]" "shell to recreate the attributes for variables.]"
"[r?Enables readonly. Once enabled it cannot be disabled. See " "[r?Enables readonly. Once enabled it cannot be disabled. See "
@ -1830,6 +1828,9 @@ USAGE_LICENSE
"\n" "\n"
"\n[name[=value]...]\n" "\n[name[=value]...]\n"
" -f [name...]\n" " -f [name...]\n"
" -m [name=name...]\n"
" -n [name=name...]\n"
" -T [tname[=(type definition)]...]\n"
"\n" "\n"
"[+EXIT STATUS?]{" "[+EXIT STATUS?]{"
"[+0?No errors occurred.]" "[+0?No errors occurred.]"

View file

@ -50,6 +50,8 @@ const char e_query[] = "no query process";
const char e_history[] = "no history file"; const char e_history[] = "no history file";
const char e_histopen[] = "cannot open history file"; const char e_histopen[] = "cannot open history file";
const char e_option[] = "%s: bad option(s)"; const char e_option[] = "%s: bad option(s)";
const char e_optincompat1[] = "%s cannot be used with other options";
const char e_optincompat2[] = "%s cannot be used with %s";
const char e_toomany[] = "open file limit exceeded"; const char e_toomany[] = "open file limit exceeded";
const char e_argtype[] = "invalid argument of type %c"; const char e_argtype[] = "invalid argument of type %c";
const char e_oneoperand[] = "one operand expected"; const char e_oneoperand[] = "one operand expected";

View file

@ -230,6 +230,8 @@ extern const Namdisc_t ENUM_disc;
extern char nv_local; extern char nv_local;
extern Dtdisc_t _Nvdisc; extern Dtdisc_t _Nvdisc;
extern const char *nv_discnames[]; extern const char *nv_discnames[];
extern const char e_optincompat1[];
extern const char e_optincompat2[];
extern const char e_subscript[]; extern const char e_subscript[];
extern const char e_nullset[]; extern const char e_nullset[];
extern const char e_notset[]; extern const char e_notset[];

View file

@ -7799,13 +7799,30 @@ cannot be exported.
.PD .PD
.PP .PP
The The
.B \-i .BR \-i ,
attribute cannot be specified along with .BR \-F ,
.BR \-E ,
and
.B \-X
options cannot be specified along with
.BR \-R , .BR \-R ,
.BR \-L , .BR \-L ,
.BR \-Z ,
or or
.BR \-f . .BR \-Z .
The
.B \-b
option cannot be specified along with
.BR \-L ,
.BR \-u ,
or
.BR \-l .
The
.BR \-f ,
.BR \-m ,
.BR \-n ,
and
.B \-T
options cannot be used together with any other option.
.PP .PP
Using Using
.B \+ .B \+

View file

@ -639,9 +639,6 @@ bar.foo+=(bam)
[[ ${bar.foo[0]} == bam ]] || err_exit 'appending to empty array variable in type does not create element 0' [[ ${bar.foo[0]} == bam ]] || err_exit 'appending to empty array variable in type does not create element 0'
# ====== # ======
# 'typeset -RF' should not create variables that cause crashes
"$SHELL" -c 'typeset -RF foo=1; test $foo' || err_exit 'typeset -RF does not work'
# Type names that have 'a' as the first letter should be functional # Type names that have 'a' as the first letter should be functional
"$SHELL" -c 'typeset -T al=(typeset bar); al foo=(bar=testset)' || err_exit "type names that start with 'a' don't work" "$SHELL" -c 'typeset -T al=(typeset bar); al foo=(bar=testset)' || err_exit "type names that start with 'a' don't work"