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