xref: /titanic_51/usr/src/lib/libshell/common/scripts/numtree1.sh (revision 34de876298c5177ddeb98f3af7e4e3012f16e2a7)
1#!/usr/bin/ksh93
2
3#
4# CDDL HEADER START
5#
6# The contents of this file are subject to the terms of the
7# Common Development and Distribution License (the "License").
8# You may not use this file except in compliance with the License.
9#
10# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11# or http://www.opensolaris.org/os/licensing.
12# See the License for the specific language governing permissions
13# and limitations under the License.
14#
15# When distributing Covered Code, include this CDDL HEADER in each
16# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17# If applicable, add the following below this CDDL HEADER, with the
18# fields enclosed by brackets "[]" replaced with your own identifying
19# information: Portions Copyright [yyyy] [name of copyright owner]
20#
21# CDDL HEADER END
22#
23
24#
25# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
26# Use is subject to license terms.
27#
28
29#
30# numtree1 - basic compound variable tree demo+benchmark
31#
32
33# Solaris needs /usr/xpg6/bin:/usr/xpg4/bin because the tools in /usr/bin are not POSIX-conformant
34export PATH=/usr/xpg6/bin:/usr/xpg4/bin:/bin:/usr/bin
35
36# Make sure all math stuff runs in the "C" locale to avoid problems
37# with alternative # radix point representations (e.g. ',' instead of
38# '.' in de_DE.*-locales). This needs to be set _before_ any
39# floating-point constants are defined in this script).
40if [[ "${LC_ALL}" != "" ]] ; then
41    export \
42        LC_MONETARY="${LC_ALL}" \
43        LC_MESSAGES="${LC_ALL}" \
44        LC_COLLATE="${LC_ALL}" \
45        LC_CTYPE="${LC_ALL}"
46        unset LC_ALL
47fi
48export LC_NUMERIC=C
49
50function fatal_error
51{
52	print -u2 "${progname}: $*"
53	exit 1
54}
55
56function add_number_to_tree
57{
58	typeset treename=$1
59	integer num=$2
60	integer i
61	typeset nodepath # full name of compound variable
62	integer -a pe # path elements
63
64	# first built an array containing the names of each path element
65	# (e.g. "135" results in an array containing "( 1 3 5 )")
66	for (( i=$(rev <<<$num) ; i > 0 ; i=i/10 )) ; do
67		pe+=( $((i % 10)) )
68	done
69
70	# walk path described via the "pe" array and build nodes if
71	# there aren't any nodes yet
72	nodepath="${treename}"
73	for (( i=0 ; i < ${#pe[@]} ; i++ )) ; do
74		nameref x="${nodepath}"
75		[[ ! -v x.node ]] && compound -C -a x.nodes
76
77		nodepath+=".nodes[${pe[i]}]"
78	done
79
80	# insert element
81	nameref node="${nodepath}"
82	[[ ! -v node.elements ]] && integer -a node.elements
83	node.elements+=( ${num} )
84
85	return 0
86}
87
88
89# floating-point version of "seq"
90function floatseq
91{
92	float i
93	float arg1=$1
94	float arg2=$2
95	float arg3=$3
96
97	case $# in
98		1)
99			for (( i=1. ; i <= arg1 ; i=i+1. )) ; do
100				printf "%a\n" i
101			done
102			;;
103		2)
104			for (( i=arg1 ; i <= arg2 ; i=i+1. )) ; do
105				printf "%a\n" i
106			done
107			;;
108		3)
109			for (( i=arg1 ; i <= arg3 ; i+=arg2 )) ; do
110				printf "%a\n" i
111			done
112			;;
113		*)
114			print -u2 -f "%s: Illegal number of arguments %d\n" "$0" $#
115			return 1
116			;;
117	esac
118
119	return 0
120}
121
122
123function usage
124{
125	OPTIND=0
126	getopts -a "${progname}" "${numtree1_usage}" OPT '-?'
127	exit 2
128}
129
130# main
131builtin basename
132builtin rev
133
134set -o noglob
135set -o errexit
136set -o nounset
137
138compound base
139
140compound bench=(
141	float start
142	float stop
143)
144
145integer i
146
147typeset progname="${ basename "${0}" ; }"
148
149typeset -r numtree1_usage=$'+
150[-?\n@(#)\$Id: numtree1 (Roland Mainz) 2009-08-17 \$\n]
151[-author?Roland Mainz <roland.mainz@nrubsig.org>]
152[+NAME?numtree1 - generate sorted variable tree containing numbers]
153[+DESCRIPTION?\bnumtree1\b is a simple variable tree generator
154	sorts a given set of numbers into a ksh compound variable tree).
155	the application supports two different modes: \'seq\' takes
156	1-3 arguments to specify the set of numbers via seq(1) and
157	\'stdin\' reads the numbers from stdin (one per line)]
158
159method [ arguments ]
160
161[+SEE ALSO?\bksh93\b(1), \bseq\b(1)]
162'
163
164while getopts -a "${progname}" "${numtree1_usage}" OPT ; do
165#	printmsg "## OPT=|${OPT}|, OPTARG=|${OPTARG}|"
166	case ${OPT} in
167		*) usage ;;
168	esac
169done
170shift $((OPTIND-1))
171
172# prechecks
173(( $# > 0 )) || usage
174
175cmd=$1
176shift
177
178# Read numbers from stdin outside benchmark loop
179if [[ ${cmd} == 'stdin' ]] ; then
180	stdin_numbers="$( cat /dev/stdin )" || fatal_error "stdin read error"
181fi
182
183(( bench.start=SECONDS ))
184
185case ${cmd} in
186	"seq")
187		for i in ${ floatseq "$@" ; } ; do
188			add_number_to_tree base "${i}"
189		done
190		;;
191	"stdin")
192		for i in ${stdin_numbers} ; do
193			add_number_to_tree base "${i}"
194		done
195		;;
196	"demo1")
197		for i in 1 32 33 34 34 38 90 ; do
198			add_number_to_tree base "${i}"
199		done
200		;;
201	"demo2")
202		for (( i=1000000000 ; i < 1000000000+10 ; i++ )) ; do
203			add_number_to_tree base "$i"
204		done
205		;;
206	*)
207		fatal_error "Invalid command ${cmd}."
208		;;
209esac
210
211(( bench.stop=SECONDS ))
212
213print -u2 -f "# time used: %f\n" $((bench.stop - bench.start))
214
215# print tree
216print -v base
217
218exit 0
219# EOF.
220