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