xref: /onnv-gate/usr/src/lib/libshell/common/scripts/numtree1.sh (revision 12068:08a39a083754)
110898Sroland.mainz@nrubsig.org#!/usr/bin/ksh93
210898Sroland.mainz@nrubsig.org
310898Sroland.mainz@nrubsig.org#
410898Sroland.mainz@nrubsig.org# CDDL HEADER START
510898Sroland.mainz@nrubsig.org#
610898Sroland.mainz@nrubsig.org# The contents of this file are subject to the terms of the
710898Sroland.mainz@nrubsig.org# Common Development and Distribution License (the "License").
810898Sroland.mainz@nrubsig.org# You may not use this file except in compliance with the License.
910898Sroland.mainz@nrubsig.org#
1010898Sroland.mainz@nrubsig.org# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1110898Sroland.mainz@nrubsig.org# or http://www.opensolaris.org/os/licensing.
1210898Sroland.mainz@nrubsig.org# See the License for the specific language governing permissions
1310898Sroland.mainz@nrubsig.org# and limitations under the License.
1410898Sroland.mainz@nrubsig.org#
1510898Sroland.mainz@nrubsig.org# When distributing Covered Code, include this CDDL HEADER in each
1610898Sroland.mainz@nrubsig.org# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1710898Sroland.mainz@nrubsig.org# If applicable, add the following below this CDDL HEADER, with the
1810898Sroland.mainz@nrubsig.org# fields enclosed by brackets "[]" replaced with your own identifying
1910898Sroland.mainz@nrubsig.org# information: Portions Copyright [yyyy] [name of copyright owner]
2010898Sroland.mainz@nrubsig.org#
2110898Sroland.mainz@nrubsig.org# CDDL HEADER END
2210898Sroland.mainz@nrubsig.org#
2310898Sroland.mainz@nrubsig.org
2410898Sroland.mainz@nrubsig.org#
25*12068SRoger.Faulkner@Oracle.COM# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
2610898Sroland.mainz@nrubsig.org#
2710898Sroland.mainz@nrubsig.org
2810898Sroland.mainz@nrubsig.org#
2910898Sroland.mainz@nrubsig.org# numtree1 - basic compound variable tree demo+benchmark
3010898Sroland.mainz@nrubsig.org#
3110898Sroland.mainz@nrubsig.org
3210898Sroland.mainz@nrubsig.org# Solaris needs /usr/xpg6/bin:/usr/xpg4/bin because the tools in /usr/bin are not POSIX-conformant
3310898Sroland.mainz@nrubsig.orgexport PATH=/usr/xpg6/bin:/usr/xpg4/bin:/bin:/usr/bin
3410898Sroland.mainz@nrubsig.org
3510898Sroland.mainz@nrubsig.org# Make sure all math stuff runs in the "C" locale to avoid problems
3610898Sroland.mainz@nrubsig.org# with alternative # radix point representations (e.g. ',' instead of
3710898Sroland.mainz@nrubsig.org# '.' in de_DE.*-locales). This needs to be set _before_ any
3810898Sroland.mainz@nrubsig.org# floating-point constants are defined in this script).
3910898Sroland.mainz@nrubsig.orgif [[ "${LC_ALL}" != "" ]] ; then
4010898Sroland.mainz@nrubsig.org    export \
4110898Sroland.mainz@nrubsig.org        LC_MONETARY="${LC_ALL}" \
4210898Sroland.mainz@nrubsig.org        LC_MESSAGES="${LC_ALL}" \
4310898Sroland.mainz@nrubsig.org        LC_COLLATE="${LC_ALL}" \
4410898Sroland.mainz@nrubsig.org        LC_CTYPE="${LC_ALL}"
4510898Sroland.mainz@nrubsig.org        unset LC_ALL
4610898Sroland.mainz@nrubsig.orgfi
4710898Sroland.mainz@nrubsig.orgexport LC_NUMERIC=C
4810898Sroland.mainz@nrubsig.org
4910898Sroland.mainz@nrubsig.orgfunction fatal_error
5010898Sroland.mainz@nrubsig.org{
5110898Sroland.mainz@nrubsig.org	print -u2 "${progname}: $*"
5210898Sroland.mainz@nrubsig.org	exit 1
5310898Sroland.mainz@nrubsig.org}
5410898Sroland.mainz@nrubsig.org
5510898Sroland.mainz@nrubsig.orgfunction add_number_to_tree
5610898Sroland.mainz@nrubsig.org{
5710898Sroland.mainz@nrubsig.org	typeset treename=$1
5810898Sroland.mainz@nrubsig.org	integer num=$2
5910898Sroland.mainz@nrubsig.org	integer i
6010898Sroland.mainz@nrubsig.org	typeset nodepath # full name of compound variable
6110898Sroland.mainz@nrubsig.org	integer -a pe # path elements
62*12068SRoger.Faulkner@Oracle.COM	integer len
63*12068SRoger.Faulkner@Oracle.COM	typeset revnums="$(rev <<<"${num}")"
6410898Sroland.mainz@nrubsig.org
6510898Sroland.mainz@nrubsig.org	# first built an array containing the names of each path element
6610898Sroland.mainz@nrubsig.org	# (e.g. "135" results in an array containing "( 1 3 5 )")
67*12068SRoger.Faulkner@Oracle.COM	# 10#<number> is used to prevent leading zeros being interpreted
68*12068SRoger.Faulkner@Oracle.COM	# as octals
69*12068SRoger.Faulkner@Oracle.COM	for (( len=${#revnums} , i=$( printf "10#%s\n" "${revnums}" ) ; len > 0 ; len--, i=i/10 )) ; do
7010898Sroland.mainz@nrubsig.org		pe+=( $((i % 10)) )
7110898Sroland.mainz@nrubsig.org	done
7210898Sroland.mainz@nrubsig.org
7310898Sroland.mainz@nrubsig.org	# walk path described via the "pe" array and build nodes if
7410898Sroland.mainz@nrubsig.org	# there aren't any nodes yet
7510898Sroland.mainz@nrubsig.org	nodepath="${treename}"
7610898Sroland.mainz@nrubsig.org	for (( i=0 ; i < ${#pe[@]} ; i++ )) ; do
7710898Sroland.mainz@nrubsig.org		nameref x="${nodepath}"
78*12068SRoger.Faulkner@Oracle.COM
79*12068SRoger.Faulkner@Oracle.COM		# [[ -v ]] does not work for arrays because [[ -v ar ]]
80*12068SRoger.Faulkner@Oracle.COM		# is equal to [[ -v ar[0] ]]. In this case we can
81*12068SRoger.Faulkner@Oracle.COM		# use the output of typeset +p x.nodes
82*12068SRoger.Faulkner@Oracle.COM		[[ "${ typeset +p x.nodes ;}" == "" ]] && compound -a x.nodes
83*12068SRoger.Faulkner@Oracle.COM
8410898Sroland.mainz@nrubsig.org		nodepath+=".nodes[${pe[i]}]"
8510898Sroland.mainz@nrubsig.org	done
8610898Sroland.mainz@nrubsig.org
87*12068SRoger.Faulkner@Oracle.COM	# insert element (leaf)
8810898Sroland.mainz@nrubsig.org	nameref node="${nodepath}"
89*12068SRoger.Faulkner@Oracle.COM	[[ "${ typeset +p node.elements ;}" == "" ]] && integer -a node.elements
9010898Sroland.mainz@nrubsig.org	node.elements+=( ${num} )
91*12068SRoger.Faulkner@Oracle.COM
92*12068SRoger.Faulkner@Oracle.COM	# DEBUG only
93*12068SRoger.Faulkner@Oracle.COM	[[ "${!node.elements[*]}" != ""                ]] || fatal_error "assertion $LINENO FAILED"
94*12068SRoger.Faulkner@Oracle.COM	[[ "${ typeset +p node.elements ;}" == *-a*    ]] || fatal_error "assertion $LINENO FAILED"
95*12068SRoger.Faulkner@Oracle.COM	[[ "${ typeset +p node.elements ;}" == *-i*    ]] || fatal_error "assertion $LINENO FAILED"
96*12068SRoger.Faulkner@Oracle.COM	[[ -v node                                     ]] || fatal_error "assertion $LINENO FAILED"
97*12068SRoger.Faulkner@Oracle.COM	[[ -R node                                     ]] || fatal_error "assertion $LINENO FAILED"
98*12068SRoger.Faulkner@Oracle.COM	[[ "${ typeset +p ${!node} ;}" == *-C*         ]] || fatal_error "assertion $LINENO FAILED"
99*12068SRoger.Faulkner@Oracle.COM	[[ "${!x.nodes[*]}" != ""                      ]] || fatal_error "assertion $LINENO FAILED"
100*12068SRoger.Faulkner@Oracle.COM	[[ "${ typeset +p x.nodes ;}" == *-a*          ]] || fatal_error "assertion $LINENO FAILED"
101*12068SRoger.Faulkner@Oracle.COM	[[ "${ typeset +p x.nodes ;}" == *-C*          ]] || fatal_error "assertion $LINENO FAILED"
10210898Sroland.mainz@nrubsig.org
10310898Sroland.mainz@nrubsig.org	return 0
10410898Sroland.mainz@nrubsig.org}
10510898Sroland.mainz@nrubsig.org
10610898Sroland.mainz@nrubsig.org
10710898Sroland.mainz@nrubsig.org# floating-point version of "seq"
10810898Sroland.mainz@nrubsig.orgfunction floatseq
10910898Sroland.mainz@nrubsig.org{
11010898Sroland.mainz@nrubsig.org	float i
11110898Sroland.mainz@nrubsig.org	float arg1=$1
11210898Sroland.mainz@nrubsig.org	float arg2=$2
11310898Sroland.mainz@nrubsig.org	float arg3=$3
11410898Sroland.mainz@nrubsig.org
11510898Sroland.mainz@nrubsig.org	case $# in
11610898Sroland.mainz@nrubsig.org		1)
11710898Sroland.mainz@nrubsig.org			for (( i=1. ; i <= arg1 ; i=i+1. )) ; do
11810898Sroland.mainz@nrubsig.org				printf "%a\n" i
11910898Sroland.mainz@nrubsig.org			done
12010898Sroland.mainz@nrubsig.org			;;
12110898Sroland.mainz@nrubsig.org		2)
12210898Sroland.mainz@nrubsig.org			for (( i=arg1 ; i <= arg2 ; i=i+1. )) ; do
12310898Sroland.mainz@nrubsig.org				printf "%a\n" i
12410898Sroland.mainz@nrubsig.org			done
12510898Sroland.mainz@nrubsig.org			;;
12610898Sroland.mainz@nrubsig.org		3)
12710898Sroland.mainz@nrubsig.org			for (( i=arg1 ; i <= arg3 ; i+=arg2 )) ; do
12810898Sroland.mainz@nrubsig.org				printf "%a\n" i
12910898Sroland.mainz@nrubsig.org			done
13010898Sroland.mainz@nrubsig.org			;;
13110898Sroland.mainz@nrubsig.org		*)
13210898Sroland.mainz@nrubsig.org			print -u2 -f "%s: Illegal number of arguments %d\n" "$0" $#
13310898Sroland.mainz@nrubsig.org			return 1
13410898Sroland.mainz@nrubsig.org			;;
13510898Sroland.mainz@nrubsig.org	esac
13610898Sroland.mainz@nrubsig.org
13710898Sroland.mainz@nrubsig.org	return 0
13810898Sroland.mainz@nrubsig.org}
13910898Sroland.mainz@nrubsig.org
14010898Sroland.mainz@nrubsig.org
14110898Sroland.mainz@nrubsig.orgfunction usage
14210898Sroland.mainz@nrubsig.org{
14310898Sroland.mainz@nrubsig.org	OPTIND=0
14410898Sroland.mainz@nrubsig.org	getopts -a "${progname}" "${numtree1_usage}" OPT '-?'
14510898Sroland.mainz@nrubsig.org	exit 2
14610898Sroland.mainz@nrubsig.org}
14710898Sroland.mainz@nrubsig.org
14810898Sroland.mainz@nrubsig.org# main
14910898Sroland.mainz@nrubsig.orgbuiltin basename
15010898Sroland.mainz@nrubsig.orgbuiltin rev
15110898Sroland.mainz@nrubsig.org
15210898Sroland.mainz@nrubsig.orgset -o noglob
15310898Sroland.mainz@nrubsig.orgset -o errexit
15410898Sroland.mainz@nrubsig.orgset -o nounset
15510898Sroland.mainz@nrubsig.org
15610898Sroland.mainz@nrubsig.orgcompound base
15710898Sroland.mainz@nrubsig.org
15810898Sroland.mainz@nrubsig.orgcompound bench=(
15910898Sroland.mainz@nrubsig.org	float start
16010898Sroland.mainz@nrubsig.org	float stop
16110898Sroland.mainz@nrubsig.org)
16210898Sroland.mainz@nrubsig.org
16310898Sroland.mainz@nrubsig.orginteger i
16410898Sroland.mainz@nrubsig.org
16510898Sroland.mainz@nrubsig.orgtypeset progname="${ basename "${0}" ; }"
16610898Sroland.mainz@nrubsig.org
16710898Sroland.mainz@nrubsig.orgtypeset -r numtree1_usage=$'+
168*12068SRoger.Faulkner@Oracle.COM[-?\n@(#)\$Id: numtree1 (Roland Mainz) 2010-03-27 \$\n]
16910898Sroland.mainz@nrubsig.org[-author?Roland Mainz <roland.mainz@nrubsig.org>]
17010898Sroland.mainz@nrubsig.org[+NAME?numtree1 - generate sorted variable tree containing numbers]
17110898Sroland.mainz@nrubsig.org[+DESCRIPTION?\bnumtree1\b is a simple variable tree generator
17210898Sroland.mainz@nrubsig.org	sorts a given set of numbers into a ksh compound variable tree).
17310898Sroland.mainz@nrubsig.org	the application supports two different modes: \'seq\' takes
17410898Sroland.mainz@nrubsig.org	1-3 arguments to specify the set of numbers via seq(1) and
17510898Sroland.mainz@nrubsig.org	\'stdin\' reads the numbers from stdin (one per line)]
17610898Sroland.mainz@nrubsig.org
17710898Sroland.mainz@nrubsig.orgmethod [ arguments ]
17810898Sroland.mainz@nrubsig.org
17910898Sroland.mainz@nrubsig.org[+SEE ALSO?\bksh93\b(1), \bseq\b(1)]
18010898Sroland.mainz@nrubsig.org'
18110898Sroland.mainz@nrubsig.org
18210898Sroland.mainz@nrubsig.orgwhile getopts -a "${progname}" "${numtree1_usage}" OPT ; do
18310898Sroland.mainz@nrubsig.org#	printmsg "## OPT=|${OPT}|, OPTARG=|${OPTARG}|"
18410898Sroland.mainz@nrubsig.org	case ${OPT} in
18510898Sroland.mainz@nrubsig.org		*) usage ;;
18610898Sroland.mainz@nrubsig.org	esac
18710898Sroland.mainz@nrubsig.orgdone
18810898Sroland.mainz@nrubsig.orgshift $((OPTIND-1))
18910898Sroland.mainz@nrubsig.org
19010898Sroland.mainz@nrubsig.org# prechecks
19110898Sroland.mainz@nrubsig.org(( $# > 0 )) || usage
19210898Sroland.mainz@nrubsig.org
19310898Sroland.mainz@nrubsig.orgcmd=$1
19410898Sroland.mainz@nrubsig.orgshift
19510898Sroland.mainz@nrubsig.org
19610898Sroland.mainz@nrubsig.org# Read numbers from stdin outside benchmark loop
19710898Sroland.mainz@nrubsig.orgif [[ ${cmd} == 'stdin' ]] ; then
19810898Sroland.mainz@nrubsig.org	stdin_numbers="$( cat /dev/stdin )" || fatal_error "stdin read error"
19910898Sroland.mainz@nrubsig.orgfi
20010898Sroland.mainz@nrubsig.org
20110898Sroland.mainz@nrubsig.org(( bench.start=SECONDS ))
20210898Sroland.mainz@nrubsig.org
20310898Sroland.mainz@nrubsig.orgcase ${cmd} in
20410898Sroland.mainz@nrubsig.org	"seq")
20510898Sroland.mainz@nrubsig.org		for i in ${ floatseq "$@" ; } ; do
20610898Sroland.mainz@nrubsig.org			add_number_to_tree base "${i}"
20710898Sroland.mainz@nrubsig.org		done
20810898Sroland.mainz@nrubsig.org		;;
20910898Sroland.mainz@nrubsig.org	"stdin")
21010898Sroland.mainz@nrubsig.org		for i in ${stdin_numbers} ; do
21110898Sroland.mainz@nrubsig.org			add_number_to_tree base "${i}"
21210898Sroland.mainz@nrubsig.org		done
21310898Sroland.mainz@nrubsig.org		;;
21410898Sroland.mainz@nrubsig.org	"demo1")
21510898Sroland.mainz@nrubsig.org		for i in 1 32 33 34 34 38 90 ; do
21610898Sroland.mainz@nrubsig.org			add_number_to_tree base "${i}"
21710898Sroland.mainz@nrubsig.org		done
21810898Sroland.mainz@nrubsig.org		;;
21910898Sroland.mainz@nrubsig.org	"demo2")
22010898Sroland.mainz@nrubsig.org		for (( i=1000000000 ; i < 1000000000+10 ; i++ )) ; do
22110898Sroland.mainz@nrubsig.org			add_number_to_tree base "$i"
22210898Sroland.mainz@nrubsig.org		done
22310898Sroland.mainz@nrubsig.org		;;
22410898Sroland.mainz@nrubsig.org	*)
22510898Sroland.mainz@nrubsig.org		fatal_error "Invalid command ${cmd}."
22610898Sroland.mainz@nrubsig.org		;;
22710898Sroland.mainz@nrubsig.orgesac
22810898Sroland.mainz@nrubsig.org
22910898Sroland.mainz@nrubsig.org(( bench.stop=SECONDS ))
23010898Sroland.mainz@nrubsig.org
23110898Sroland.mainz@nrubsig.orgprint -u2 -f "# time used: %f\n" $((bench.stop - bench.start))
23210898Sroland.mainz@nrubsig.org
23310898Sroland.mainz@nrubsig.org# print tree
23410898Sroland.mainz@nrubsig.orgprint -v base
23510898Sroland.mainz@nrubsig.org
23610898Sroland.mainz@nrubsig.orgexit 0
23710898Sroland.mainz@nrubsig.org# EOF.
238