diff --git a/NEWS b/NEWS index 6bafbaf61..23b339fbf 100644 --- a/NEWS +++ b/NEWS @@ -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 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: - Fixed a crash when using 'cd' in a virtual/non-forking subshell in a diff --git a/src/cmd/ksh93/COMPATIBILITY b/src/cmd/ksh93/COMPATIBILITY index b5520f409..ed43495a0 100644 --- a/src/cmd/ksh93/COMPATIBILITY +++ b/src/cmd/ksh93/COMPATIBILITY @@ -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 exit status if an input/output error occurs. -10. The 'unalias' builtin will now return a non-zero status if it tries to - remove a previously set alias that is not currently set. +10. The 'typeset' builtin now properly detects and reports options that + cannot be used together if they are given as part of the same command. ____________________________________________________________________________ diff --git a/src/cmd/ksh93/bltins/typeset.c b/src/cmd/ksh93/bltins/typeset.c index e7772caf9..71de5466a 100644 --- a/src/cmd/ksh93/bltins/typeset.c +++ b/src/cmd/ksh93/bltins/typeset.c @@ -195,7 +195,7 @@ int b_typeset(int argc,register char *argv[],Shbltin_t *context) const char *optstring = sh_opttypeset; Namdecl_t *ntp = (Namdecl_t*)context->ptr; 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)); 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; if(tdata.argnum < 0) errormsg(SH_DICT,ERROR_exit(1), e_badfield, tdata.argnum); + isadjust = 1; if(n=='Z') flag |= NV_ZFILL; else @@ -377,18 +378,36 @@ endargs: argv--; if((flag&NV_ZFILL) && !(flag&NV_LJUST)) 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++; + } if((flag&NV_BINARY) && (flag&(NV_LJUST|NV_UTOL|NV_LTOU))) + { + errormsg(SH_DICT,2,e_optincompat2,"-b","-L/-u/-l"); error_info.errors++; + } if((flag&NV_MOVE) && (flag&~(NV_MOVE|NV_VARNAME|NV_ASSIGN))) + { + errormsg(SH_DICT,2,e_optincompat1,"-m"); error_info.errors++; + } if((flag&NV_REF) && (flag&~(NV_REF|NV_IDENT|NV_ASSIGN))) + { + errormsg(SH_DICT,2,e_optincompat1,"-n"); error_info.errors++; + } if((flag&NV_TYPE) && (flag&~(NV_TYPE|NV_VARNAME|NV_ASSIGN))) + { + errormsg(SH_DICT,2,e_optincompat1,"-T"); error_info.errors++; + } 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++; + } if(sflag && troot==tdata.sh->fun_tree) { /* static function */ diff --git a/src/cmd/ksh93/data/builtins.c b/src/cmd/ksh93/data/builtins.c index f43f506d0..5ad14dff4 100644 --- a/src/cmd/ksh93/data/builtins.c +++ b/src/cmd/ksh93/data/builtins.c @@ -1718,7 +1718,7 @@ USAGE_LICENSE ; 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 "[+NAME?typeset - declare or display variables with attributes]" "[+DESCRIPTION?Without the \b-f\b option, \btypeset\b sets, unsets, " @@ -1738,7 +1738,7 @@ USAGE_LICENSE "[+?Note also the following builtin command equivalents:]{" "[+autoload?\btypeset -fu\b]" "[+compound?\btypeset -C\b]" - "[+float?\btypeset -lE\b]" + "[+float ?\btypeset -lE\b]" "[+functions?\btypeset -f\b]" "[+integer?\btypeset -li\b]" "[+nameref?\btypeset -n\b]" @@ -1768,11 +1768,9 @@ USAGE_LICENSE "[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.]" "[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 " - "used with any other options.]" + "moved to \aname\a. The original variable will be unset.]" "[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 " - "any other options.]" + "references. \aname\a cannot contain a \b.\b.]" "[p?Causes the output to be in a format that can be used as input to the " "shell to recreate the attributes for variables.]" "[r?Enables readonly. Once enabled it cannot be disabled. See " @@ -1830,6 +1828,9 @@ USAGE_LICENSE "\n" "\n[name[=value]...]\n" " -f [name...]\n" +" -m [name=name...]\n" +" -n [name=name...]\n" +" -T [tname[=(type definition)]...]\n" "\n" "[+EXIT STATUS?]{" "[+0?No errors occurred.]" diff --git a/src/cmd/ksh93/data/msg.c b/src/cmd/ksh93/data/msg.c index 0d0e9c5ea..f810421fb 100644 --- a/src/cmd/ksh93/data/msg.c +++ b/src/cmd/ksh93/data/msg.c @@ -50,6 +50,8 @@ const char e_query[] = "no query process"; const char e_history[] = "no history file"; const char e_histopen[] = "cannot open history file"; 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_argtype[] = "invalid argument of type %c"; const char e_oneoperand[] = "one operand expected"; diff --git a/src/cmd/ksh93/include/name.h b/src/cmd/ksh93/include/name.h index 5f75c717a..f2fef4121 100644 --- a/src/cmd/ksh93/include/name.h +++ b/src/cmd/ksh93/include/name.h @@ -230,6 +230,8 @@ extern const Namdisc_t ENUM_disc; extern char nv_local; extern Dtdisc_t _Nvdisc; extern const char *nv_discnames[]; +extern const char e_optincompat1[]; +extern const char e_optincompat2[]; extern const char e_subscript[]; extern const char e_nullset[]; extern const char e_notset[]; diff --git a/src/cmd/ksh93/sh.1 b/src/cmd/ksh93/sh.1 index b8cc46d8f..7a4a5f0f8 100644 --- a/src/cmd/ksh93/sh.1 +++ b/src/cmd/ksh93/sh.1 @@ -7799,13 +7799,30 @@ cannot be exported. .PD .PP The -.B \-i -attribute cannot be specified along with +.BR \-i , +.BR \-F , +.BR \-E , +and +.B \-X +options cannot be specified along with .BR \-R , .BR \-L , -.BR \-Z , 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 Using .B \+ diff --git a/src/cmd/ksh93/tests/types.sh b/src/cmd/ksh93/tests/types.sh index 1a7fa16ff..91585325f 100755 --- a/src/cmd/ksh93/tests/types.sh +++ b/src/cmd/ksh93/tests/types.sh @@ -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' # ====== -# '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 "$SHELL" -c 'typeset -T al=(typeset bar); al foo=(bar=testset)' || err_exit "type names that start with 'a' don't work"