1ab2043b8SDevin Teskeif [ ! "$_STRINGS_SUBR" ]; then _STRINGS_SUBR=1 2ab2043b8SDevin Teske# 37323adacSDevin Teske# Copyright (c) 2006-2013 Devin Teske 4f8ea072aSDevin Teske# All rights reserved. 5ab2043b8SDevin Teske# 6ab2043b8SDevin Teske# Redistribution and use in source and binary forms, with or without 7ab2043b8SDevin Teske# modification, are permitted provided that the following conditions 8ab2043b8SDevin Teske# are met: 9ab2043b8SDevin Teske# 1. Redistributions of source code must retain the above copyright 10ab2043b8SDevin Teske# notice, this list of conditions and the following disclaimer. 11ab2043b8SDevin Teske# 2. Redistributions in binary form must reproduce the above copyright 12ab2043b8SDevin Teske# notice, this list of conditions and the following disclaimer in the 13ab2043b8SDevin Teske# documentation and/or other materials provided with the distribution. 14ab2043b8SDevin Teske# 15ab2043b8SDevin Teske# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 168e37a7c8SDevin Teske# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17ab2043b8SDevin Teske# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18ab2043b8SDevin Teske# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19ab2043b8SDevin Teske# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 208e37a7c8SDevin Teske# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21ab2043b8SDevin Teske# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22ab2043b8SDevin Teske# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23ab2043b8SDevin Teske# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24ab2043b8SDevin Teske# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25ab2043b8SDevin Teske# SUCH DAMAGE. 26ab2043b8SDevin Teske# 27ab2043b8SDevin Teske# $FreeBSD$ 28d3a0f918SDevin Teske# 29fcaed0c1SDevin Teske############################################################ INCLUDES 30fcaed0c1SDevin Teske 31fcaed0c1SDevin TeskeBSDCFG_SHARE="/usr/share/bsdconfig" 32fcaed0c1SDevin Teske. $BSDCFG_SHARE/common.subr || exit 1 33fcaed0c1SDevin Teske 34d3a0f918SDevin Teske############################################################ GLOBALS 35d3a0f918SDevin Teske 36d3a0f918SDevin Teske# 37d3a0f918SDevin Teske# Valid characters that can appear in an sh(1) variable name 38d3a0f918SDevin Teske# 39d3a0f918SDevin Teske# Please note that the character ranges A-Z and a-z should be avoided because 40d3a0f918SDevin Teske# these can include accent characters (which are not valid in a variable name). 41d3a0f918SDevin Teske# For example, A-Z matches any character that sorts after A but before Z, 42d3a0f918SDevin Teske# including A and Z. Although ASCII order would make more sense, that is not 43d3a0f918SDevin Teske# how it works. 44d3a0f918SDevin Teske# 45d3a0f918SDevin TeskeVALID_VARNAME_CHARS="0-9ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_" 46d3a0f918SDevin Teske 47d3a0f918SDevin Teske############################################################ FUNCTIONS 48ab2043b8SDevin Teske 49ab2043b8SDevin Teske# f_substr "$string" $start [ $length ] 50ab2043b8SDevin Teske# 51ab2043b8SDevin Teske# Simple wrapper to awk(1)'s `substr' function. 52ab2043b8SDevin Teske# 53ab2043b8SDevin Teskef_substr() 54ab2043b8SDevin Teske{ 55ab2043b8SDevin Teske local string="$1" start="${2:-0}" len="${3:-0}" 56ab2043b8SDevin Teske echo "$string" | awk "{ print substr(\$0, $start, $len) }" 57ab2043b8SDevin Teske} 58ab2043b8SDevin Teske 5960d8a2b5SDevin Teske# f_snprintf $var_to_set $size $format ... 6060d8a2b5SDevin Teske# 6160d8a2b5SDevin Teske# Similar to snprintf(3), write at most $size number of bytes into $var_to_set 6260d8a2b5SDevin Teske# using printf(1) syntax (`$format ...'). The value of $var_to_set is NULL 6360d8a2b5SDevin Teske# unless at-least one byte is stored from the output. 6460d8a2b5SDevin Teske# 6560d8a2b5SDevin Teskef_snprintf() 6660d8a2b5SDevin Teske{ 6760d8a2b5SDevin Teske local __var_to_set="$1" __size="$2" 6860d8a2b5SDevin Teske shift 2 # var_to_set/size 6960d8a2b5SDevin Teske eval "$__var_to_set"=\$\( printf \"\$@\" \| awk -v max=\"\$__size\" \'' 7060d8a2b5SDevin Teske { 7160d8a2b5SDevin Teske len = length($0) 7260d8a2b5SDevin Teske max -= len 7360d8a2b5SDevin Teske print substr($0,0,(max > 0 ? len : max + len)) 7460d8a2b5SDevin Teske if ( max < 0 ) exit 7560d8a2b5SDevin Teske max-- 7660d8a2b5SDevin Teske }'\' \) 7760d8a2b5SDevin Teske} 7860d8a2b5SDevin Teske 79dd5cc066SDevin Teske# f_vsnprintf $var_to_set $size $format $format_args 80dd5cc066SDevin Teske# 81dd5cc066SDevin Teske# Similar to vsnprintf(3), write at most $size number of bytes into $var_to_set 82dd5cc066SDevin Teske# using printf(1) syntax (`$format $format_args'). The value of $var_to_set is 83dd5cc066SDevin Teske# NULL unless at-least one byte is stored from the output. 84dd5cc066SDevin Teske# 85dd5cc066SDevin Teske# Example 1: 86dd5cc066SDevin Teske# 87dd5cc066SDevin Teske# limit=7 format="%s" 88dd5cc066SDevin Teske# format_args="'abc 123'" # 3-spaces between abc and 123 89dd5cc066SDevin Teske# f_vsnprintf foo $limit "$format" "$format_args" # foo=[abc 1] 90dd5cc066SDevin Teske# 91dd5cc066SDevin Teske# Example 2: 92dd5cc066SDevin Teske# 93dd5cc066SDevin Teske# limit=12 format="%s %s" 94dd5cc066SDevin Teske# format_args=" 'doghouse' 'foxhound' " 95dd5cc066SDevin Teske# # even more spaces added to illustrate escape-method 96dd5cc066SDevin Teske# f_vsnprintf foo $limit "$format" "$format_args" # foo=[doghouse fox] 97dd5cc066SDevin Teske# 98dd5cc066SDevin Teske# Example 3: 99dd5cc066SDevin Teske# 100dd5cc066SDevin Teske# limit=13 format="%s %s" 101dd5cc066SDevin Teske# f_shell_escape arg1 'aaa"aaa' # arg1=[aaa"aaa] (no change) 102dd5cc066SDevin Teske# f_shell_escape arg2 "aaa'aaa" # arg2=[aaa'\''aaa] (escaped s-quote) 103dd5cc066SDevin Teske# format_args="'$arg1' '$arg2'" # use single-quotes to surround args 104dd5cc066SDevin Teske# f_vsnprintf foo $limit "$format" "$format_args" # foo=[aaa"aaa aaa'a] 105dd5cc066SDevin Teske# 106dd5cc066SDevin Teske# In all of the above examples, the call to f_vsnprintf() does not change. Only 107dd5cc066SDevin Teske# the contents of $limit, $format, and $format_args changes in each example. 108dd5cc066SDevin Teske# 109dd5cc066SDevin Teskef_vsnprintf() 110dd5cc066SDevin Teske{ 111dd5cc066SDevin Teske eval f_snprintf \"\$1\" \"\$2\" \"\$3\" $4 112dd5cc066SDevin Teske} 113dd5cc066SDevin Teske 114ab2043b8SDevin Teske# f_longest_line_length 115ab2043b8SDevin Teske# 116ab2043b8SDevin Teske# Simple wrapper to an awk(1) script to print the length of the longest line of 117ab2043b8SDevin Teske# input (read from stdin). Supports the newline escape-sequence `\n' for 118ab2043b8SDevin Teske# splitting a single line into multiple lines. 119ab2043b8SDevin Teske# 120ab2043b8SDevin Teskef_longest_line_length_awk=' 121ab2043b8SDevin TeskeBEGIN { longest = 0 } 122ab2043b8SDevin Teske{ 123ab2043b8SDevin Teske if (split($0, lines, /\\n/) > 1) 124ab2043b8SDevin Teske { 125ab2043b8SDevin Teske for (n in lines) 126ab2043b8SDevin Teske { 127ab2043b8SDevin Teske len = length(lines[n]) 128ab2043b8SDevin Teske longest = ( len > longest ? len : longest ) 129ab2043b8SDevin Teske } 130ab2043b8SDevin Teske } 131ab2043b8SDevin Teske else 132ab2043b8SDevin Teske { 133ab2043b8SDevin Teske len = length($0) 134ab2043b8SDevin Teske longest = ( len > longest ? len : longest ) 135ab2043b8SDevin Teske } 136ab2043b8SDevin Teske} 137ab2043b8SDevin TeskeEND { print longest } 138ab2043b8SDevin Teske' 139ab2043b8SDevin Teskef_longest_line_length() 140ab2043b8SDevin Teske{ 141ab2043b8SDevin Teske awk "$f_longest_line_length_awk" 142ab2043b8SDevin Teske} 143ab2043b8SDevin Teske 144ab2043b8SDevin Teske# f_number_of_lines 145ab2043b8SDevin Teske# 146ab2043b8SDevin Teske# Simple wrapper to an awk(1) script to print the number of lines read from 147ab2043b8SDevin Teske# stdin. Supports newline escape-sequence `\n' for splitting a single line into 148ab2043b8SDevin Teske# multiple lines. 149ab2043b8SDevin Teske# 150ab2043b8SDevin Teskef_number_of_lines_awk=' 151ab2043b8SDevin TeskeBEGIN { num_lines = 0 } 152ab2043b8SDevin Teske{ 1537fba6f48SDevin Teske num_lines += split(" "$0, unused, /\\n/) 154ab2043b8SDevin Teske} 155ab2043b8SDevin TeskeEND { print num_lines } 156ab2043b8SDevin Teske' 157ab2043b8SDevin Teskef_number_of_lines() 158ab2043b8SDevin Teske{ 159ab2043b8SDevin Teske awk "$f_number_of_lines_awk" 160ab2043b8SDevin Teske} 161ab2043b8SDevin Teske 162ab2043b8SDevin Teske# f_isinteger $arg 163ab2043b8SDevin Teske# 164ab2043b8SDevin Teske# Returns true if argument is a positive/negative whole integer. 165ab2043b8SDevin Teske# 166ab2043b8SDevin Teskef_isinteger() 167ab2043b8SDevin Teske{ 168ab2043b8SDevin Teske local arg="$1" 169ab2043b8SDevin Teske 170ab2043b8SDevin Teske # Prevent division-by-zero 171ab2043b8SDevin Teske [ "$arg" = "0" ] && return $SUCCESS 172ab2043b8SDevin Teske 173ab2043b8SDevin Teske # Attempt to perform arithmetic divison (an operation which will exit 174ab2043b8SDevin Teske # with error unless arg is a valid positive/negative whole integer). 175ab2043b8SDevin Teske # 176fb7d723eSDevin Teske ( : $((0/$arg)) ) > /dev/null 2>&1 177ab2043b8SDevin Teske} 178ab2043b8SDevin Teske 1797323adacSDevin Teske# f_uriencode [$text] 1807323adacSDevin Teske# 1817323adacSDevin Teske# Encode $text for the purpose of embedding safely into a URL. Non-alphanumeric 1827323adacSDevin Teske# characters are converted to `%XX' sequence where XX represents the hexa- 1837323adacSDevin Teske# decimal ordinal of the non-alphanumeric character. If $text is missing, data 1847323adacSDevin Teske# is instead read from standard input. 1857323adacSDevin Teske# 1867323adacSDevin Teskef_uriencode_awk=' 1877323adacSDevin TeskeBEGIN { 1887323adacSDevin Teske output = "" 1897323adacSDevin Teske for (n = 0; n < 256; n++) pack[sprintf("%c", n)] = sprintf("%%%02x", n) 1907323adacSDevin Teske} 1917323adacSDevin Teske{ 1927323adacSDevin Teske sline = "" 1937323adacSDevin Teske slen = length($0) 1947323adacSDevin Teske for (n = 1; n <= slen; n++) { 1957323adacSDevin Teske char = substr($0, n, 1) 1967323adacSDevin Teske if ( char !~ /^[[:alnum:]_]$/ ) char = pack[char] 1977323adacSDevin Teske sline = sline char 1987323adacSDevin Teske } 1997323adacSDevin Teske output = output ( output ? "%0a" : "" ) sline 2007323adacSDevin Teske} 2017323adacSDevin TeskeEND { print output } 2027323adacSDevin Teske' 2037323adacSDevin Teskef_uriencode() 2047323adacSDevin Teske{ 2057323adacSDevin Teske if [ $# -gt 0 ]; then 2067323adacSDevin Teske echo "$1" | awk "$f_uriencode_awk" 2077323adacSDevin Teske else 2087323adacSDevin Teske awk "$f_uriencode_awk" 2097323adacSDevin Teske fi 2107323adacSDevin Teske} 2117323adacSDevin Teske 2127323adacSDevin Teske# f_uridecode [$text] 2137323adacSDevin Teske# 2147323adacSDevin Teske# Decode $text from a URI. Encoded characters are converted from their `%XX' 2157323adacSDevin Teske# sequence into original unencoded ASCII sequences. If $text is missing, data 2167323adacSDevin Teske# is instead read from standard input. 2177323adacSDevin Teske# 2187323adacSDevin Teskef_uridecode_awk=' 2197323adacSDevin TeskeBEGIN { for (n = 0; n < 256; n++) chr[n] = sprintf("%c", n) } 2207323adacSDevin Teske{ 2217323adacSDevin Teske sline = "" 2227323adacSDevin Teske slen = length($0) 2237323adacSDevin Teske for (n = 1; n <= slen; n++) 2247323adacSDevin Teske { 2257323adacSDevin Teske seq = substr($0, n, 3) 2267323adacSDevin Teske if ( seq ~ /^%[[:xdigit:]][[:xdigit:]]$/ ) { 2277323adacSDevin Teske hex = substr(seq, 2, 2) 2287323adacSDevin Teske sline = sline chr[sprintf("%u", "0x"hex)] 2297323adacSDevin Teske n += 2 2307323adacSDevin Teske } else 2317323adacSDevin Teske sline = sline substr(seq, 1, 1) 2327323adacSDevin Teske } 2337323adacSDevin Teske print sline 2347323adacSDevin Teske} 2357323adacSDevin Teske' 2367323adacSDevin Teskef_uridecode() 2377323adacSDevin Teske{ 2387323adacSDevin Teske if [ $# -gt 0 ]; then 2397323adacSDevin Teske echo "$1" | awk "$f_uridecode_awk" 2407323adacSDevin Teske else 2417323adacSDevin Teske awk "$f_uridecode_awk" 2427323adacSDevin Teske fi 2437323adacSDevin Teske} 2447323adacSDevin Teske 245d3a0f918SDevin Teske# f_replaceall $string $find $replace [$var_to_set] 246d3a0f918SDevin Teske# 247f82ca17bSDevin Teske# Replace all occurrences of $find in $string with $replace. If $var_to_set is 248d3a0f918SDevin Teske# either missing or NULL, the variable name is produced on standard out for 249d3a0f918SDevin Teske# capturing in a sub-shell (which is less recommended due to performance 250d3a0f918SDevin Teske# degradation). 251d3a0f918SDevin Teske# 252d3a0f918SDevin Teskef_replaceall() 253d3a0f918SDevin Teske{ 254d3a0f918SDevin Teske local __left="" __right="$1" 255d3a0f918SDevin Teske local __find="$2" __replace="$3" __var_to_set="$4" 256d3a0f918SDevin Teske while :; do 257d3a0f918SDevin Teske case "$__right" in *$__find*) 258d3a0f918SDevin Teske __left="$__left${__right%%$__find*}$__replace" 259d3a0f918SDevin Teske __right="${__right#*$__find}" 260d3a0f918SDevin Teske continue 261d3a0f918SDevin Teske esac 262d3a0f918SDevin Teske break 263d3a0f918SDevin Teske done 264d3a0f918SDevin Teske __left="$__left${__right#*$__find}" 265d3a0f918SDevin Teske if [ "$__var_to_set" ]; then 266d3a0f918SDevin Teske setvar "$__var_to_set" "$__left" 267d3a0f918SDevin Teske else 268d3a0f918SDevin Teske echo "$__left" 269d3a0f918SDevin Teske fi 270d3a0f918SDevin Teske} 271d3a0f918SDevin Teske 272d3a0f918SDevin Teske# f_str2varname $string [$var_to_set] 273d3a0f918SDevin Teske# 274d3a0f918SDevin Teske# Convert a string into a suitable value to be used as a variable name 275d3a0f918SDevin Teske# by converting unsuitable characters into the underscrore [_]. If $var_to_set 276d3a0f918SDevin Teske# is either missing or NULL, the variable name is produced on standard out for 277d3a0f918SDevin Teske# capturing in a sub-shell (which is less recommended due to performance 278d3a0f918SDevin Teske# degradation). 279d3a0f918SDevin Teske# 280d3a0f918SDevin Teskef_str2varname() 281d3a0f918SDevin Teske{ 282d3a0f918SDevin Teske local __string="$1" __var_to_set="$2" 283d3a0f918SDevin Teske f_replaceall "$__string" "[!$VALID_VARNAME_CHARS]" "_" "$__var_to_set" 284d3a0f918SDevin Teske} 285d3a0f918SDevin Teske 286d3a0f918SDevin Teske# f_shell_escape $string [$var_to_set] 287d3a0f918SDevin Teske# 288d3a0f918SDevin Teske# Escape $string for shell eval statement(s) by replacing all single-quotes 289d3a0f918SDevin Teske# with a special sequence that creates a compound string when interpolated 290d3a0f918SDevin Teske# by eval with surrounding single-quotes. 291d3a0f918SDevin Teske# 292d3a0f918SDevin Teske# For example: 293d3a0f918SDevin Teske# 294d3a0f918SDevin Teske# foo="abc'123" 295d3a0f918SDevin Teske# f_shell_escape "$foo" bar # bar=[abc'\''123] 29610908a6fSDevin Teske# eval echo \'$bar\' # produces abc'123 297d3a0f918SDevin Teske# 298d3a0f918SDevin Teske# This is helpful when processing an argument list that has to retain its 299d3a0f918SDevin Teske# escaped structure for later evaluations. 300d3a0f918SDevin Teske# 301d3a0f918SDevin Teske# WARNING: Surrounding single-quotes are not added; this is the responsibility 302d3a0f918SDevin Teske# of the code passing the escaped values to eval (which also aids readability). 303d3a0f918SDevin Teske# 304d3a0f918SDevin Teskef_shell_escape() 305d3a0f918SDevin Teske{ 306d3a0f918SDevin Teske local __string="$1" __var_to_set="$2" 307d3a0f918SDevin Teske f_replaceall "$__string" "'" "'\\''" "$__var_to_set" 308d3a0f918SDevin Teske} 309d3a0f918SDevin Teske 310d3a0f918SDevin Teske# f_shell_unescape $string [$var_to_set] 311d3a0f918SDevin Teske# 312d3a0f918SDevin Teske# The antithesis of f_shell_escape(), this function takes an escaped $string 313d3a0f918SDevin Teske# and expands it. 314d3a0f918SDevin Teske# 315d3a0f918SDevin Teske# For example: 316d3a0f918SDevin Teske# 317d3a0f918SDevin Teske# foo="abc'123" 318d3a0f918SDevin Teske# f_shell_escape "$foo" bar # bar=[abc'\''123] 319d3a0f918SDevin Teske# f_shell_unescape "$bar" # produces abc'123 320d3a0f918SDevin Teske# 321d3a0f918SDevin Teskef_shell_unescape() 322d3a0f918SDevin Teske{ 323d3a0f918SDevin Teske local __string="$1" __var_to_set="$2" 324d3a0f918SDevin Teske f_replaceall "$__string" "'\\''" "'" "$__var_to_set" 325d3a0f918SDevin Teske} 326d3a0f918SDevin Teske 327a96ea66fSDevin Teske# f_expand_number $string [$var_to_set] 328a96ea66fSDevin Teske# 329a96ea66fSDevin Teske# Unformat $string into a number, optionally to be stored in $var_to_set. This 330a96ea66fSDevin Teske# function follows the SI power of two convention. 331a96ea66fSDevin Teske# 332a96ea66fSDevin Teske# The prefixes are: 333a96ea66fSDevin Teske# 334a96ea66fSDevin Teske# Prefix Description Multiplier 335a96ea66fSDevin Teske# k kilo 1024 336a96ea66fSDevin Teske# M mega 1048576 337a96ea66fSDevin Teske# G giga 1073741824 338a96ea66fSDevin Teske# T tera 1099511627776 339a96ea66fSDevin Teske# P peta 1125899906842624 340a96ea66fSDevin Teske# E exa 1152921504606846976 341a96ea66fSDevin Teske# 342a96ea66fSDevin Teske# NOTE: Prefixes are case-insensitive. 343a96ea66fSDevin Teske# 344*9acbeddcSDevin Teske# Upon successful completion, success status is returned; otherwise the number 345*9acbeddcSDevin Teske# -1 is produced ($var_to_set set to -1 or if $var_to_set is NULL or missing) 346*9acbeddcSDevin Teske# on standard output. In the case of failure, the error status will be one of: 347a96ea66fSDevin Teske# 348*9acbeddcSDevin Teske# Status Reason 349*9acbeddcSDevin Teske# 1 Given $string contains no digits 350*9acbeddcSDevin Teske# 2 An unrecognized prefix was given 351*9acbeddcSDevin Teske# 3 Result too large to calculate 352a96ea66fSDevin Teske# 353a96ea66fSDevin Teskef_expand_number() 354a96ea66fSDevin Teske{ 355a96ea66fSDevin Teske local __string="$1" __var_to_set="$2" 356*9acbeddcSDevin Teske local __cp __num __bshift __maxinput 357a96ea66fSDevin Teske 358a96ea66fSDevin Teske # Remove any leading non-digits 359a96ea66fSDevin Teske while :; do 360a96ea66fSDevin Teske __cp="$__string" 361a96ea66fSDevin Teske __string="${__cp#[!0-9]}" 362a96ea66fSDevin Teske [ "$__string" = "$__cp" ] && break 363a96ea66fSDevin Teske done 364a96ea66fSDevin Teske 365*9acbeddcSDevin Teske # Produce `-1' if string didn't contain any digits 366a96ea66fSDevin Teske if [ ! "$__string" ]; then 367a96ea66fSDevin Teske if [ "$__var_to_set" ]; then 368a96ea66fSDevin Teske setvar "$__var_to_set" -1 369a96ea66fSDevin Teske else 370a96ea66fSDevin Teske echo -1 371a96ea66fSDevin Teske fi 372*9acbeddcSDevin Teske return 1 # 1 = "Given $string contains no digits" 373a96ea66fSDevin Teske fi 374a96ea66fSDevin Teske 375a96ea66fSDevin Teske # Store the numbers 376a96ea66fSDevin Teske __num="${__string%%[!0-9]*}" 377a96ea66fSDevin Teske 378a96ea66fSDevin Teske # Shortcut 379a96ea66fSDevin Teske if [ $__num -eq 0 ]; then 380a96ea66fSDevin Teske if [ "$__var_to_set" ]; then 381a96ea66fSDevin Teske setvar "$__var_to_set" 0 382a96ea66fSDevin Teske else 383a96ea66fSDevin Teske echo 0 384a96ea66fSDevin Teske fi 385a96ea66fSDevin Teske return $SUCCESS 386a96ea66fSDevin Teske fi 387a96ea66fSDevin Teske 388a96ea66fSDevin Teske # Remove all the leading numbers from the string to get at the prefix 389a96ea66fSDevin Teske while :; do 390a96ea66fSDevin Teske __cp="$__string" 391a96ea66fSDevin Teske __string="${__cp#[0-9]}" 392a96ea66fSDevin Teske [ "$__string" = "$__cp" ] && break 393a96ea66fSDevin Teske done 394a96ea66fSDevin Teske 395*9acbeddcSDevin Teske # 396*9acbeddcSDevin Teske # Test for invalid prefix (and determine bitshift length) 397*9acbeddcSDevin Teske # 398a96ea66fSDevin Teske case "$__string" in 399*9acbeddcSDevin Teske ""|[[:space:]]*) # Shortcut 400*9acbeddcSDevin Teske if [ "$__var_to_set" ]; then 401*9acbeddcSDevin Teske setvar "$__var_to_set" $__num 402*9acbeddcSDevin Teske else 403*9acbeddcSDevin Teske echo $__num 404*9acbeddcSDevin Teske fi 405*9acbeddcSDevin Teske return $SUCCESS ;; 406*9acbeddcSDevin Teske [Kk]*) __bshift=10 ;; 407*9acbeddcSDevin Teske [Mm]*) __bshift=20 ;; 408*9acbeddcSDevin Teske [Gg]*) __bshift=30 ;; 409*9acbeddcSDevin Teske [Tt]*) __bshift=40 ;; 410*9acbeddcSDevin Teske [Pp]*) __bshift=50 ;; 411*9acbeddcSDevin Teske [Ee]*) __bshift=60 ;; 412a96ea66fSDevin Teske *) 413a96ea66fSDevin Teske # Unknown prefix 414a96ea66fSDevin Teske if [ "$__var_to_set" ]; then 415a96ea66fSDevin Teske setvar "$__var_to_set" -1 416a96ea66fSDevin Teske else 417a96ea66fSDevin Teske echo -1 418a96ea66fSDevin Teske fi 419*9acbeddcSDevin Teske return 2 # 2 = "An unrecognized prefix was given" 420a96ea66fSDevin Teske esac 421a96ea66fSDevin Teske 422*9acbeddcSDevin Teske # Determine if the wheels fall off 423*9acbeddcSDevin Teske __maxinput=$(( 0x7fffffffffffffff >> $__bshift )) 424*9acbeddcSDevin Teske if [ $__num -gt $__maxinput ]; then 425*9acbeddcSDevin Teske # Input (before expanding) would exceed 64-bit signed int 426a96ea66fSDevin Teske if [ "$__var_to_set" ]; then 427a96ea66fSDevin Teske setvar "$__var_to_set" -1 428a96ea66fSDevin Teske else 429a96ea66fSDevin Teske echo -1 430a96ea66fSDevin Teske fi 431*9acbeddcSDevin Teske return 3 # 3 = "Result too large to calculate" 432a96ea66fSDevin Teske fi 433a96ea66fSDevin Teske 434*9acbeddcSDevin Teske # Shift the number out and produce it 435*9acbeddcSDevin Teske __num=$(( $__num << $__bshift )) 436a96ea66fSDevin Teske if [ "$__var_to_set" ]; then 437a96ea66fSDevin Teske setvar "$__var_to_set" $__num 438a96ea66fSDevin Teske else 439a96ea66fSDevin Teske echo $__num 440a96ea66fSDevin Teske fi 441a96ea66fSDevin Teske} 442a96ea66fSDevin Teske 443d3a0f918SDevin Teske############################################################ MAIN 444d3a0f918SDevin Teske 44556961fd7SDevin Teskef_dprintf "%s: Successfully loaded." strings.subr 44656961fd7SDevin Teske 447ab2043b8SDevin Teskefi # ! $_STRINGS_SUBR 448