diff --git a/usr.sbin/bsdconfig/share/strings.subr b/usr.sbin/bsdconfig/share/strings.subr index 4621fdae659c..f78948b42f6b 100644 --- a/usr.sbin/bsdconfig/share/strings.subr +++ b/usr.sbin/bsdconfig/share/strings.subr @@ -341,17 +341,19 @@ f_shell_unescape() # # NOTE: Prefixes are case-insensitive. # -# Upon successful completion, the value 0 is returned (or stored to -# $var_to_set); otherwise -1. Reasons for a -1 return include: +# Upon successful completion, success status is returned; otherwise the number +# -1 is produced ($var_to_set set to -1 or if $var_to_set is NULL or missing) +# on standard output. In the case of failure, the error status will be one of: # -# Given $string contains no digits. -# An unrecognized prefix was given. -# Result too large to calculate. +# Status Reason +# 1 Given $string contains no digits +# 2 An unrecognized prefix was given +# 3 Result too large to calculate # f_expand_number() { local __string="$1" __var_to_set="$2" - local __cp __num + local __cp __num __bshift __maxinput # Remove any leading non-digits while :; do @@ -360,14 +362,14 @@ f_expand_number() [ "$__string" = "$__cp" ] && break done - # Return `-1' if string didn't contain any digits + # Produce `-1' if string didn't contain any digits if [ ! "$__string" ]; then if [ "$__var_to_set" ]; then setvar "$__var_to_set" -1 else echo -1 fi - return $FAILURE + return 1 # 1 = "Given $string contains no digits" fi # Store the numbers @@ -390,9 +392,23 @@ f_expand_number() [ "$__string" = "$__cp" ] && break done - # Test for invalid prefix + # + # Test for invalid prefix (and determine bitshift length) + # case "$__string" in - ""|[KkMmGgTtPpEe]*) : known prefix ;; + ""|[[:space:]]*) # Shortcut + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" $__num + else + echo $__num + fi + return $SUCCESS ;; + [Kk]*) __bshift=10 ;; + [Mm]*) __bshift=20 ;; + [Gg]*) __bshift=30 ;; + [Tt]*) __bshift=40 ;; + [Pp]*) __bshift=50 ;; + [Ee]*) __bshift=60 ;; *) # Unknown prefix if [ "$__var_to_set" ]; then @@ -400,29 +416,23 @@ f_expand_number() else echo -1 fi - return $FAILURE + return 2 # 2 = "An unrecognized prefix was given" esac - # Multiply the number out - case "$__string" in - [Kk]) __num=$(( $__num * 1024 )) ;; - [Mm]) __num=$(( $__num * 1048576 )) ;; - [Gg]) __num=$(( $__num * 1073741824 )) ;; - [Tt]) __num=$(( $__num * 1099511627776 )) ;; - [Pp]) __num=$(( $__num * 1125899906842624 )) ;; - [Ee]) __num=$(( $__num * 1152921504606846976 )) ;; - esac - if [ $__num -le 0 ]; then - # Arithmetic overflow + # Determine if the wheels fall off + __maxinput=$(( 0x7fffffffffffffff >> $__bshift )) + if [ $__num -gt $__maxinput ]; then + # Input (before expanding) would exceed 64-bit signed int if [ "$__var_to_set" ]; then setvar "$__var_to_set" -1 else echo -1 fi - return $FAILURE + return 3 # 3 = "Result too large to calculate" fi - # Return the number + # Shift the number out and produce it + __num=$(( $__num << $__bshift )) if [ "$__var_to_set" ]; then setvar "$__var_to_set" $__num else