xref: /titanic_50/usr/src/lib/libshell/common/scripts/numtree1.sh (revision 3e14f97f673e8a630f076077de35afdd43dc1587)
134f9b3eeSRoland Mainz#!/usr/bin/ksh93
234f9b3eeSRoland Mainz
334f9b3eeSRoland Mainz#
434f9b3eeSRoland Mainz# CDDL HEADER START
534f9b3eeSRoland Mainz#
634f9b3eeSRoland Mainz# The contents of this file are subject to the terms of the
734f9b3eeSRoland Mainz# Common Development and Distribution License (the "License").
834f9b3eeSRoland Mainz# You may not use this file except in compliance with the License.
934f9b3eeSRoland Mainz#
1034f9b3eeSRoland Mainz# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1134f9b3eeSRoland Mainz# or http://www.opensolaris.org/os/licensing.
1234f9b3eeSRoland Mainz# See the License for the specific language governing permissions
1334f9b3eeSRoland Mainz# and limitations under the License.
1434f9b3eeSRoland Mainz#
1534f9b3eeSRoland Mainz# When distributing Covered Code, include this CDDL HEADER in each
1634f9b3eeSRoland Mainz# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1734f9b3eeSRoland Mainz# If applicable, add the following below this CDDL HEADER, with the
1834f9b3eeSRoland Mainz# fields enclosed by brackets "[]" replaced with your own identifying
1934f9b3eeSRoland Mainz# information: Portions Copyright [yyyy] [name of copyright owner]
2034f9b3eeSRoland Mainz#
2134f9b3eeSRoland Mainz# CDDL HEADER END
2234f9b3eeSRoland Mainz#
2334f9b3eeSRoland Mainz
2434f9b3eeSRoland Mainz#
25*3e14f97fSRoger A. Faulkner# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
2634f9b3eeSRoland Mainz#
2734f9b3eeSRoland Mainz
2834f9b3eeSRoland Mainz#
2934f9b3eeSRoland Mainz# numtree1 - basic compound variable tree demo+benchmark
3034f9b3eeSRoland Mainz#
3134f9b3eeSRoland Mainz
3234f9b3eeSRoland Mainz# Solaris needs /usr/xpg6/bin:/usr/xpg4/bin because the tools in /usr/bin are not POSIX-conformant
3334f9b3eeSRoland Mainzexport PATH=/usr/xpg6/bin:/usr/xpg4/bin:/bin:/usr/bin
3434f9b3eeSRoland Mainz
3534f9b3eeSRoland Mainz# Make sure all math stuff runs in the "C" locale to avoid problems
3634f9b3eeSRoland Mainz# with alternative # radix point representations (e.g. ',' instead of
3734f9b3eeSRoland Mainz# '.' in de_DE.*-locales). This needs to be set _before_ any
3834f9b3eeSRoland Mainz# floating-point constants are defined in this script).
3934f9b3eeSRoland Mainzif [[ "${LC_ALL}" != "" ]] ; then
4034f9b3eeSRoland Mainz    export \
4134f9b3eeSRoland Mainz        LC_MONETARY="${LC_ALL}" \
4234f9b3eeSRoland Mainz        LC_MESSAGES="${LC_ALL}" \
4334f9b3eeSRoland Mainz        LC_COLLATE="${LC_ALL}" \
4434f9b3eeSRoland Mainz        LC_CTYPE="${LC_ALL}"
4534f9b3eeSRoland Mainz        unset LC_ALL
4634f9b3eeSRoland Mainzfi
4734f9b3eeSRoland Mainzexport LC_NUMERIC=C
4834f9b3eeSRoland Mainz
4934f9b3eeSRoland Mainzfunction fatal_error
5034f9b3eeSRoland Mainz{
5134f9b3eeSRoland Mainz	print -u2 "${progname}: $*"
5234f9b3eeSRoland Mainz	exit 1
5334f9b3eeSRoland Mainz}
5434f9b3eeSRoland Mainz
5534f9b3eeSRoland Mainzfunction add_number_to_tree
5634f9b3eeSRoland Mainz{
5734f9b3eeSRoland Mainz	typeset treename=$1
5834f9b3eeSRoland Mainz	integer num=$2
5934f9b3eeSRoland Mainz	integer i
6034f9b3eeSRoland Mainz	typeset nodepath # full name of compound variable
6134f9b3eeSRoland Mainz	integer -a pe # path elements
62*3e14f97fSRoger A. Faulkner	integer len
63*3e14f97fSRoger A. Faulkner	typeset revnums="$(rev <<<"${num}")"
6434f9b3eeSRoland Mainz
6534f9b3eeSRoland Mainz	# first built an array containing the names of each path element
6634f9b3eeSRoland Mainz	# (e.g. "135" results in an array containing "( 1 3 5 )")
67*3e14f97fSRoger A. Faulkner	# 10#<number> is used to prevent leading zeros being interpreted
68*3e14f97fSRoger A. Faulkner	# as octals
69*3e14f97fSRoger A. Faulkner	for (( len=${#revnums} , i=$( printf "10#%s\n" "${revnums}" ) ; len > 0 ; len--, i=i/10 )) ; do
7034f9b3eeSRoland Mainz		pe+=( $((i % 10)) )
7134f9b3eeSRoland Mainz	done
7234f9b3eeSRoland Mainz
7334f9b3eeSRoland Mainz	# walk path described via the "pe" array and build nodes if
7434f9b3eeSRoland Mainz	# there aren't any nodes yet
7534f9b3eeSRoland Mainz	nodepath="${treename}"
7634f9b3eeSRoland Mainz	for (( i=0 ; i < ${#pe[@]} ; i++ )) ; do
7734f9b3eeSRoland Mainz		nameref x="${nodepath}"
78*3e14f97fSRoger A. Faulkner
79*3e14f97fSRoger A. Faulkner		# [[ -v ]] does not work for arrays because [[ -v ar ]]
80*3e14f97fSRoger A. Faulkner		# is equal to [[ -v ar[0] ]]. In this case we can
81*3e14f97fSRoger A. Faulkner		# use the output of typeset +p x.nodes
82*3e14f97fSRoger A. Faulkner		[[ "${ typeset +p x.nodes ;}" == "" ]] && compound -a x.nodes
8334f9b3eeSRoland Mainz
8434f9b3eeSRoland Mainz		nodepath+=".nodes[${pe[i]}]"
8534f9b3eeSRoland Mainz	done
8634f9b3eeSRoland Mainz
87*3e14f97fSRoger A. Faulkner	# insert element (leaf)
8834f9b3eeSRoland Mainz	nameref node="${nodepath}"
89*3e14f97fSRoger A. Faulkner	[[ "${ typeset +p node.elements ;}" == "" ]] && integer -a node.elements
9034f9b3eeSRoland Mainz	node.elements+=( ${num} )
9134f9b3eeSRoland Mainz
92*3e14f97fSRoger A. Faulkner	# DEBUG only
93*3e14f97fSRoger A. Faulkner	[[ "${!node.elements[*]}" != ""                ]] || fatal_error "assertion $LINENO FAILED"
94*3e14f97fSRoger A. Faulkner	[[ "${ typeset +p node.elements ;}" == *-a*    ]] || fatal_error "assertion $LINENO FAILED"
95*3e14f97fSRoger A. Faulkner	[[ "${ typeset +p node.elements ;}" == *-i*    ]] || fatal_error "assertion $LINENO FAILED"
96*3e14f97fSRoger A. Faulkner	[[ -v node                                     ]] || fatal_error "assertion $LINENO FAILED"
97*3e14f97fSRoger A. Faulkner	[[ -R node                                     ]] || fatal_error "assertion $LINENO FAILED"
98*3e14f97fSRoger A. Faulkner	[[ "${ typeset +p ${!node} ;}" == *-C*         ]] || fatal_error "assertion $LINENO FAILED"
99*3e14f97fSRoger A. Faulkner	[[ "${!x.nodes[*]}" != ""                      ]] || fatal_error "assertion $LINENO FAILED"
100*3e14f97fSRoger A. Faulkner	[[ "${ typeset +p x.nodes ;}" == *-a*          ]] || fatal_error "assertion $LINENO FAILED"
101*3e14f97fSRoger A. Faulkner	[[ "${ typeset +p x.nodes ;}" == *-C*          ]] || fatal_error "assertion $LINENO FAILED"
102*3e14f97fSRoger A. Faulkner
10334f9b3eeSRoland Mainz	return 0
10434f9b3eeSRoland Mainz}
10534f9b3eeSRoland Mainz
10634f9b3eeSRoland Mainz
10734f9b3eeSRoland Mainz# floating-point version of "seq"
10834f9b3eeSRoland Mainzfunction floatseq
10934f9b3eeSRoland Mainz{
11034f9b3eeSRoland Mainz	float i
11134f9b3eeSRoland Mainz	float arg1=$1
11234f9b3eeSRoland Mainz	float arg2=$2
11334f9b3eeSRoland Mainz	float arg3=$3
11434f9b3eeSRoland Mainz
11534f9b3eeSRoland Mainz	case $# in
11634f9b3eeSRoland Mainz		1)
11734f9b3eeSRoland Mainz			for (( i=1. ; i <= arg1 ; i=i+1. )) ; do
11834f9b3eeSRoland Mainz				printf "%a\n" i
11934f9b3eeSRoland Mainz			done
12034f9b3eeSRoland Mainz			;;
12134f9b3eeSRoland Mainz		2)
12234f9b3eeSRoland Mainz			for (( i=arg1 ; i <= arg2 ; i=i+1. )) ; do
12334f9b3eeSRoland Mainz				printf "%a\n" i
12434f9b3eeSRoland Mainz			done
12534f9b3eeSRoland Mainz			;;
12634f9b3eeSRoland Mainz		3)
12734f9b3eeSRoland Mainz			for (( i=arg1 ; i <= arg3 ; i+=arg2 )) ; do
12834f9b3eeSRoland Mainz				printf "%a\n" i
12934f9b3eeSRoland Mainz			done
13034f9b3eeSRoland Mainz			;;
13134f9b3eeSRoland Mainz		*)
13234f9b3eeSRoland Mainz			print -u2 -f "%s: Illegal number of arguments %d\n" "$0" $#
13334f9b3eeSRoland Mainz			return 1
13434f9b3eeSRoland Mainz			;;
13534f9b3eeSRoland Mainz	esac
13634f9b3eeSRoland Mainz
13734f9b3eeSRoland Mainz	return 0
13834f9b3eeSRoland Mainz}
13934f9b3eeSRoland Mainz
14034f9b3eeSRoland Mainz
14134f9b3eeSRoland Mainzfunction usage
14234f9b3eeSRoland Mainz{
14334f9b3eeSRoland Mainz	OPTIND=0
14434f9b3eeSRoland Mainz	getopts -a "${progname}" "${numtree1_usage}" OPT '-?'
14534f9b3eeSRoland Mainz	exit 2
14634f9b3eeSRoland Mainz}
14734f9b3eeSRoland Mainz
14834f9b3eeSRoland Mainz# main
14934f9b3eeSRoland Mainzbuiltin basename
15034f9b3eeSRoland Mainzbuiltin rev
15134f9b3eeSRoland Mainz
15234f9b3eeSRoland Mainzset -o noglob
15334f9b3eeSRoland Mainzset -o errexit
15434f9b3eeSRoland Mainzset -o nounset
15534f9b3eeSRoland Mainz
15634f9b3eeSRoland Mainzcompound base
15734f9b3eeSRoland Mainz
15834f9b3eeSRoland Mainzcompound bench=(
15934f9b3eeSRoland Mainz	float start
16034f9b3eeSRoland Mainz	float stop
16134f9b3eeSRoland Mainz)
16234f9b3eeSRoland Mainz
16334f9b3eeSRoland Mainzinteger i
16434f9b3eeSRoland Mainz
16534f9b3eeSRoland Mainztypeset progname="${ basename "${0}" ; }"
16634f9b3eeSRoland Mainz
16734f9b3eeSRoland Mainztypeset -r numtree1_usage=$'+
168*3e14f97fSRoger A. Faulkner[-?\n@(#)\$Id: numtree1 (Roland Mainz) 2010-03-27 \$\n]
16934f9b3eeSRoland Mainz[-author?Roland Mainz <roland.mainz@nrubsig.org>]
17034f9b3eeSRoland Mainz[+NAME?numtree1 - generate sorted variable tree containing numbers]
17134f9b3eeSRoland Mainz[+DESCRIPTION?\bnumtree1\b is a simple variable tree generator
17234f9b3eeSRoland Mainz	sorts a given set of numbers into a ksh compound variable tree).
17334f9b3eeSRoland Mainz	the application supports two different modes: \'seq\' takes
17434f9b3eeSRoland Mainz	1-3 arguments to specify the set of numbers via seq(1) and
17534f9b3eeSRoland Mainz	\'stdin\' reads the numbers from stdin (one per line)]
17634f9b3eeSRoland Mainz
17734f9b3eeSRoland Mainzmethod [ arguments ]
17834f9b3eeSRoland Mainz
17934f9b3eeSRoland Mainz[+SEE ALSO?\bksh93\b(1), \bseq\b(1)]
18034f9b3eeSRoland Mainz'
18134f9b3eeSRoland Mainz
18234f9b3eeSRoland Mainzwhile getopts -a "${progname}" "${numtree1_usage}" OPT ; do
18334f9b3eeSRoland Mainz#	printmsg "## OPT=|${OPT}|, OPTARG=|${OPTARG}|"
18434f9b3eeSRoland Mainz	case ${OPT} in
18534f9b3eeSRoland Mainz		*) usage ;;
18634f9b3eeSRoland Mainz	esac
18734f9b3eeSRoland Mainzdone
18834f9b3eeSRoland Mainzshift $((OPTIND-1))
18934f9b3eeSRoland Mainz
19034f9b3eeSRoland Mainz# prechecks
19134f9b3eeSRoland Mainz(( $# > 0 )) || usage
19234f9b3eeSRoland Mainz
19334f9b3eeSRoland Mainzcmd=$1
19434f9b3eeSRoland Mainzshift
19534f9b3eeSRoland Mainz
19634f9b3eeSRoland Mainz# Read numbers from stdin outside benchmark loop
19734f9b3eeSRoland Mainzif [[ ${cmd} == 'stdin' ]] ; then
19834f9b3eeSRoland Mainz	stdin_numbers="$( cat /dev/stdin )" || fatal_error "stdin read error"
19934f9b3eeSRoland Mainzfi
20034f9b3eeSRoland Mainz
20134f9b3eeSRoland Mainz(( bench.start=SECONDS ))
20234f9b3eeSRoland Mainz
20334f9b3eeSRoland Mainzcase ${cmd} in
20434f9b3eeSRoland Mainz	"seq")
20534f9b3eeSRoland Mainz		for i in ${ floatseq "$@" ; } ; do
20634f9b3eeSRoland Mainz			add_number_to_tree base "${i}"
20734f9b3eeSRoland Mainz		done
20834f9b3eeSRoland Mainz		;;
20934f9b3eeSRoland Mainz	"stdin")
21034f9b3eeSRoland Mainz		for i in ${stdin_numbers} ; do
21134f9b3eeSRoland Mainz			add_number_to_tree base "${i}"
21234f9b3eeSRoland Mainz		done
21334f9b3eeSRoland Mainz		;;
21434f9b3eeSRoland Mainz	"demo1")
21534f9b3eeSRoland Mainz		for i in 1 32 33 34 34 38 90 ; do
21634f9b3eeSRoland Mainz			add_number_to_tree base "${i}"
21734f9b3eeSRoland Mainz		done
21834f9b3eeSRoland Mainz		;;
21934f9b3eeSRoland Mainz	"demo2")
22034f9b3eeSRoland Mainz		for (( i=1000000000 ; i < 1000000000+10 ; i++ )) ; do
22134f9b3eeSRoland Mainz			add_number_to_tree base "$i"
22234f9b3eeSRoland Mainz		done
22334f9b3eeSRoland Mainz		;;
22434f9b3eeSRoland Mainz	*)
22534f9b3eeSRoland Mainz		fatal_error "Invalid command ${cmd}."
22634f9b3eeSRoland Mainz		;;
22734f9b3eeSRoland Mainzesac
22834f9b3eeSRoland Mainz
22934f9b3eeSRoland Mainz(( bench.stop=SECONDS ))
23034f9b3eeSRoland Mainz
23134f9b3eeSRoland Mainzprint -u2 -f "# time used: %f\n" $((bench.stop - bench.start))
23234f9b3eeSRoland Mainz
23334f9b3eeSRoland Mainz# print tree
23434f9b3eeSRoland Mainzprint -v base
23534f9b3eeSRoland Mainz
23634f9b3eeSRoland Mainzexit 0
23734f9b3eeSRoland Mainz# EOF.
238