svn commit: r295197 - head/usr.sbin/bsdconfig/share

Devin Teske dteske at FreeBSD.org
Wed Feb 3 04:02:52 UTC 2016


Author: dteske
Date: Wed Feb  3 04:02:50 2016
New Revision: 295197
URL: https://svnweb.freebsd.org/changeset/base/295197

Log:
  f_substr(): Optimized recipe if running under bash
  
  This makes runnig f_substr() faster than it was when running under bash,
  but both sh and dash are still faster when using the non-bash recipe which
  features dynamically unrolled loops.

Modified:
  head/usr.sbin/bsdconfig/share/strings.subr

Modified: head/usr.sbin/bsdconfig/share/strings.subr
==============================================================================
--- head/usr.sbin/bsdconfig/share/strings.subr	Wed Feb  3 03:55:08 2016	(r295196)
+++ head/usr.sbin/bsdconfig/share/strings.subr	Wed Feb  3 04:02:50 2016	(r295197)
@@ -67,52 +67,58 @@ f_isinteger()
 # Similar to awk(1)'s substr(), return length substring of string that begins
 # at start position counted from 1.
 #
-f_substr()
-{
-	local OPTIND=1 OPTARG __flag __var_to_set=
-	while getopts v: __flag; do
-		case "$__flag" in
-		v) __var_to_set="$OPTARG" ;;
+case "$BASH_VERSION" in
+*?*)
+	f_substr()
+	{
+		local __var_to_set=
+		case "$1" in
+		-v) __var_to_set="$2"; shift 2 ;;
+		-v?*) __var_to_set="${2#-v}"; shift 1 ;;
 		esac
-	done
-	shift $(( $OPTIND - 1 ))
-
-	local __tmp="$1" __start="${2:-1}" __size="$3"
-	local __tbuf __tbuf_len __trim __trimq
+		local __tmp="$1" __start="${2:-1}"  __len="$3"
+		[ "$__start" -gt 0 ] 2> /dev/null &&
+			__start=$(( $__start - 1 ))
+		if [ ! "$__var_to_set" ]; then
+			eval echo \"\${__tmp:\$__start${__len:+:\$__len}}\"
+			return $?
+		fi
+		if [ "$__len" ]; then
+			eval $__var_to_set=\"\${__tmp:\$__start:\$__len}\"
+		else
+			eval $__var_to_set=\"\${__tmp:\$__start}\"
+		fi
+	}
+	;;
+*)
+	# NB: On FreeBSD, sh(1) runs this faster than bash(1) runs the above
+	f_substr()
+	{
+		local OPTIND=1 OPTARG __flag __var_to_set=
+		while getopts v: __flag; do
+			case "$__flag" in
+			v) __var_to_set="$OPTARG" ;;
+			esac
+		done
+		shift $(( $OPTIND - 1 ))
 
-	if [ ! "$__tmp" ]; then
-		[ "$__var_to_set" ] && setvar "$__var_to_set" ""
-		return ${SUCCESS:-0}
-	fi
-	[ "$__start" -ge 1 ] 2> /dev/null || __start=1
-	if ! [ "${__size:-1}" -ge 1 ] 2> /dev/null; then
-		[ "$__var_to_set" ] && setvar "$__var_to_set" ""
-		return ${FAILURE:-1}
-	fi
+		local __tmp="$1" __start="${2:-1}" __size="$3"
+		local __tbuf __tbuf_len __trim __trimq
 
-	__trim=$(( $__start - 1 ))
-	while [ $__trim -gt 0 ]; do
-		__tbuf="?"
-		__tbuf_len=1
-		while [ $__tbuf_len -lt $(( $__trim / $__tbuf_len )) ]; do
-			__tbuf="$__tbuf?"
-			__tbuf_len=$(( $__tbuf_len + 1 ))
-		done
-		__trimq=$(( $__trim / $__tbuf_len ))
-		__trim=$(( $__trim - $__tbuf_len * $__trimq ))
-		while [ $__trimq -gt 0 ]; do
-			__tmp="${__tmp#$__tbuf}"
-			__trimq=$(( $__trimq - 1 ))
-		done
-	done
+		if [ ! "$__tmp" ]; then
+			[ "$__var_to_set" ] && setvar "$__var_to_set" ""
+			return ${SUCCESS:-0}
+		fi
+		[ "$__start" -ge 1 ] 2> /dev/null || __start=1
+		if ! [ "${__size:-1}" -ge 1 ] 2> /dev/null; then
+			[ "$__var_to_set" ] && setvar "$__var_to_set" ""
+			return ${FAILURE:-1}
+		fi
 
-	local __tmp_size=${#__tmp}
-	local __mask __mask_len
-	__trim=$(( $__tmp_size - ${__size:-$__tmp_size} ))
-	while [ $__trim -gt 0 ]; do
-		__tbuf="?"
-		__tbuf_len=1
-		if [ $__trim -le $__size ]; then
+		__trim=$(( $__start - 1 ))
+		while [ $__trim -gt 0 ]; do
+			__tbuf="?"
+			__tbuf_len=1
 			while [ $__tbuf_len -lt $(( $__trim / $__tbuf_len )) ]
 			do
 				__tbuf="$__tbuf?"
@@ -121,37 +127,66 @@ f_substr()
 			__trimq=$(( $__trim / $__tbuf_len ))
 			__trim=$(( $__trim - $__tbuf_len * $__trimq ))
 			while [ $__trimq -gt 0 ]; do
-				__tmp="${__tmp%$__tbuf}"
+				__tmp="${__tmp#$__tbuf}"
 				__trimq=$(( $__trimq - 1 ))
 			done
-		else
-			__mask="$__tmp"
-			while [ $__tbuf_len -lt $(( $__size / $__tbuf_len )) ]
-			do
-				__tbuf="$__tbuf?"
-				__tbuf_len=$(( $__tbuf_len + 1 ))
-			done
-			__trimq=$(( $__size / $__tbuf_len ))
-			if [ $(( $__trimq * $__tbuf_len )) -ne $__size ]; then
-				__tbuf="$__tbuf?"
-				__tbuf_len=$(( $__tbuf_len + 1 ))
+		done
+
+		local __tmp_size=${#__tmp}
+		local __mask __mask_len
+		__trim=$(( $__tmp_size - ${__size:-$__tmp_size} ))
+		while [ $__trim -gt 0 ]; do
+			__tbuf="?"
+			__tbuf_len=1
+			if [ $__trim -le $__size ]; then
+				while [ $__tbuf_len -lt $((
+					$__trim / $__tbuf_len
+				)) ]; do
+					__tbuf="$__tbuf?"
+					__tbuf_len=$(( $__tbuf_len + 1 ))
+				done
+				__trimq=$(( $__trim / $__tbuf_len ))
+				__trim=$(( $__trim - $__tbuf_len * $__trimq ))
+				while [ $__trimq -gt 0 ]; do
+					__tmp="${__tmp%$__tbuf}"
+					__trimq=$(( $__trimq - 1 ))
+				done
+			else
+				__mask="$__tmp"
+				while [ $__tbuf_len -lt $((
+					$__size / $__tbuf_len
+				)) ]; do
+					__tbuf="$__tbuf?"
+					__tbuf_len=$(( $__tbuf_len + 1 ))
+				done
+				__trimq=$(( $__size / $__tbuf_len ))
+				if [ $__size -ne $((
+					$__trimq * $__tbuf_len
+				)) ]; then
+					__tbuf="$__tbuf?"
+					__tbuf_len=$(( $__tbuf_len + 1 ))
+				fi
+				__mask_len=$((
+					$__tmp_size - $__tbuf_len * $__trimq
+				))
+				__trim=$((
+					$__tmp_size - $__mask_len - $__size
+				))
+				while [ $__trimq -gt 0 ]; do
+					__mask="${__mask#$__tbuf}"
+					__trimq=$(( $__trimq - 1 ))
+				done
+				__tmp="${__tmp%"$__mask"}"
 			fi
-			__mask_len=$(( $__tmp_size - $__tbuf_len * $__trimq ))
-			__trim=$(( $__tmp_size - $__mask_len - $__size ))
-			while [ $__trimq -gt 0 ]; do
-				__mask="${__mask#$__tbuf}"
-				__trimq=$(( $__trimq - 1 ))
-			done
-			__tmp="${__tmp%"$__mask"}"
-		fi
-	done
+		done
 
-	if [ "$__var_to_set" ]; then
-		setvar "$__var_to_set" "$__tmp"
-	else
-		echo "$__tmp"
-	fi
-}
+		if [ "$__var_to_set" ]; then
+			setvar "$__var_to_set" "$__tmp"
+		else
+			echo "$__tmp"
+		fi
+	}
+esac
 
 # f_sprintf $var_to_set $format [$arguments ...]
 #


More information about the svn-src-all mailing list