1######################################################################## 2# # 3# This software is part of the ast package # 4# Copyright (c) 1982-2008 AT&T Intellectual Property # 5# and is licensed under the # 6# Common Public License, Version 1.0 # 7# by AT&T Intellectual Property # 8# # 9# A copy of the License is available at # 10# http://www.opensource.org/licenses/cpl1.0.txt # 11# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # 12# # 13# Information and Software Systems Research # 14# AT&T Research # 15# Florham Park NJ # 16# # 17# David Korn <dgk@research.att.com> # 18# # 19######################################################################## 20# 21# variable tree test #002 22# Propose of this test is whether ksh93 handles global variable trees 23# and function-local variable trees the same way, including "nameref" 24# and "unset" handling. 25# 26 27function err_exit 28{ 29 print -u2 -n "\t" 30 print -u2 -r ${Command}[$1]: "${@:2}" 31 (( Errors+=1 )) 32} 33 34alias err_exit='err_exit $LINENO' 35 36# "built_tree1" and "built_tree2" are identical except the way how they test 37# whether a variable exists: 38# - "built_tree1" uses "${varname}" != "", e.g. looking whether the variable 39# as non-zero length content 40# - "built_tree2" uses "! (unset varname)", e.g. "unset" in a subshell 41function build_tree1 42{ 43#set -o errexit -o xtrace 44 typeset index 45 typeset s 46 typeset i 47 typeset dummy 48 typeset a b c d e f 49 50 nameref dest_tree="$1" # destination tree 51 nameref srcdata="$2" # source data 52 typeset tree_mode="$3" # mode to define the type of leads 53 54 typeset -A dest_tree.l1 55 56 for index in "${!srcdata.hashnodes[@]}" ; do 57 nameref node=srcdata.hashnodes["${index}"] 58 59 for i in "${node.xlfd[@]}" ; do 60 IFS='-' read dummy a b c d e f <<<"$i" 61 62 if [[ "$a" == "" ]] ; then 63 a="$dummy" 64 fi 65 66 [[ "$a" == "" ]] && a='-' 67 [[ "$b" == "" ]] && b='-' 68 [[ "$c" == "" ]] && c='-' 69 70 if [[ "${dest_tree.l1["$a"]}" == "" ]] ; then 71 #if ! (unset dest_tree.l1["$a"]) ; then 72 typeset -A dest_tree.l1["$a"].l2 73 fi 74 75 if [[ "${dest_tree.l1["$a"].l2["$b"]}" == "" ]] ; then 76 #if ! (unset dest_tree.l1["$a"].l2["$b"]) ; then 77 typeset -A dest_tree.l1["$a"].l2["$b"].l3 78 fi 79 80 if [[ "${!dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[*]}" == "" ]] ; then 81 typeset -A dest_tree.l1["$a"].l2["$b"].l3["$c"].entries 82 fi 83 84 typeset new_index 85 if [[ "${tree_mode}" == "leaf_name" ]] ; then 86 new_index=$(( ${#dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[@]}+1 )) 87 else 88 new_index="${node.name}" 89 90 # skip if the leaf node already exists 91 if [[ "${dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}]}" != "" ]] ; then 92 continue 93 fi 94 fi 95 96 add_tree_leaf dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}] "${index}" "${tree_mode}" 97 done 98 done 99 100 return 0 101} 102 103# "built_tree1" and "built_tree2" are identical except the way how they test 104# whether a variable exists: 105# - "built_tree1" uses "${varname}" != "", e.g. looking whether the variable 106# as non-zero length content 107# - "built_tree2" uses "! (unset varname)", e.g. "unset" in a subshell 108function build_tree2 109{ 110#set -o errexit -o xtrace 111 typeset index 112 typeset s 113 typeset i 114 typeset dummy 115 typeset a b c d e f 116 117 nameref dest_tree="$1" # destination tree 118 nameref srcdata="$2" # source data 119 typeset tree_mode="$3" # mode to define the type of leads 120 121 typeset -A dest_tree.l1 122 123 for index in "${!srcdata.hashnodes[@]}" ; do 124 nameref node=srcdata.hashnodes["${index}"] 125 126 for i in "${node.xlfd[@]}" ; do 127 IFS='-' read dummy a b c d e f <<<"$i" 128 129 if [[ "$a" == "" ]] ; then 130 a="$dummy" 131 fi 132 133 [[ "$a" == "" ]] && a='-' 134 [[ "$b" == "" ]] && b='-' 135 [[ "$c" == "" ]] && c='-' 136 137 #if [[ "${dest_tree.l1["$a"]}" == "" ]] ; then 138 if ! (unset dest_tree.l1["$a"]) ; then 139 typeset -A dest_tree.l1["$a"].l2 140 fi 141 142 #if [[ "${dest_tree.l1["$a"].l2["$b"]}" == "" ]] ; then 143 if ! (unset dest_tree.l1["$a"].l2["$b"]) ; then 144 typeset -A dest_tree.l1["$a"].l2["$b"].l3 145 fi 146 147 if [[ "${!dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[*]}" == "" ]] ; then 148 typeset -A dest_tree.l1["$a"].l2["$b"].l3["$c"].entries 149 fi 150 151 typeset new_index 152 if [[ "${tree_mode}" == "leaf_name" ]] ; then 153 new_index=$(( ${#dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[@]}+1 )) 154 else 155 new_index="${node.name}" 156 157 # skip if the leaf node already exists 158 if [[ "${dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}]}" != "" ]] ; then 159 continue 160 fi 161 fi 162 163 add_tree_leaf dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}] "${index}" "${tree_mode}" 164 done 165 done 166 167 return 0 168} 169 170 171function add_tree_leaf 172{ 173 nameref tree_leafnode="$1" 174 nameref data_node=srcdata.hashnodes["$2"] 175 typeset add_mode="$3" 176 177 case "${add_mode}" in 178 "leaf_name") 179 tree_leafnode="${data_node.name}" 180 return 0 181 ;; 182 "leaf_compound") 183 tree_leafnode=( 184 typeset name="${data_node.name}" 185 typeset -a filenames=( "${data_node.filenames[@]}" ) 186 typeset -a comments=( "${data_node.comments[@]}" ) 187 typeset -a xlfd=( "${data_node.xlfd[@]}" ) 188 ) 189 return 0 190 ;; 191 *) 192 print -u2 -f "ERROR: Unknown mode %s in add_tree_leaf\n" "${add_mode}" 193 return 1 194 ;; 195 esac 196 197 # not reached 198 return 1 199} 200 201# "mysrcdata_local" and "mysrcdata_global" must be identical 202typeset mysrcdata_global=( 203 typeset -A hashnodes=( 204 [abcd]=( 205 name='abcd' 206 typeset -a xlfd=( 207 '-urw-itc zapfchancery-medium-i-normal--0-0-0-0-p-0-iso8859-1' 208 '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-adobe-fontspecific' 209 '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-sun-fontspecific' 210 ) 211 typeset -a comments=( 212 'comment 1' 213 'comment 2' 214 'comment 3' 215 ) 216 typeset -a filenames=( 217 '/home/foo/abcd_1' 218 '/home/foo/abcd_2' 219 '/home/foo/abcd_3' 220 ) 221 ) 222 ) 223) 224 225mytree_global1=() 226mytree_global2=() 227 228function main 229{ 230 # "mysrcdata_local" and "mysrcdata_global" must be identical 231 typeset mysrcdata_local=( 232 typeset -A hashnodes=( 233 [abcd]=( 234 name='abcd' 235 typeset -a xlfd=( 236 '-urw-itc zapfchancery-medium-i-normal--0-0-0-0-p-0-iso8859-1' 237 '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-adobe-fontspecific' 238 '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-sun-fontspecific' 239 ) 240 typeset -a comments=( 241 'comment 1' 242 'comment 2' 243 'comment 3' 244 ) 245 typeset -a filenames=( 246 '/home/foo/abcd_1' 247 '/home/foo/abcd_2' 248 '/home/foo/abcd_3' 249 ) 250 ) 251 ) 252 ) 253 254 #### Build tree using global tree variables 255 build_tree1 mytree_global1 mysrcdata_global leaf_compound || \ 256 err_exit 'build_tree1 mytree_global1 mysrcdata_global leaf_compound returned an error' 257 (( $(print -r -- "${mytree_global1}" | wc -l) > 10 )) || err_exit "Compound tree 'mytree_global1' too small." 258 259 build_tree2 mytree_global2 mysrcdata_global leaf_compound || \ 260 err_exit 'build_tree2 mytree_global2 mysrcdata_global leaf_compound returned an error' 261 (( $(print -r -- "${mytree_global2}" | wc -l) > 10 )) || err_exit "Compound tree 'mytree_global2' too small." 262 263 264 #### build tree using local tree variables 265 mytree_local1=() 266 mytree_local2=() 267 268 build_tree1 mytree_local1 mysrcdata_local leaf_compound || \ 269 err_exit 'build_tree1 mytree_local1 mysrcdata_local leaf_compound returned an error' 270 (( $(print -r -- "${mytree_local1}" | wc -l) > 10 )) || err_exit "Compound tree 'mytree_local1' too small." 271 272 build_tree2 mytree_local2 mysrcdata_local leaf_compound || \ 273 err_exit 'build_tree2 mytree_local2 mysrcdata_local leaf_compound returned an error' 274 (( $(print -r -- "${mytree_local2}" | wc -l) > 10 )) || err_exit "Compound tree 'mytree_local2' too small." 275 276 277 #### Compare treess 278 if [[ "${mytree_global1}" != "${mytree_local1}" ]] ; then 279 err_exit "Compound trees 'mytree_global1' and 'mytree_local1' not identical" 280 fi 281 282 if [[ "${mytree_global1}" != "${mytree_global2}" ]] ; then 283 err_exit "Compound trees 'mytree_global1' and 'mytree_global2' not identical" 284 fi 285 286 if [[ "${mytree_local1}" != "${mytree_local2}" ]] ; then 287 err_exit "Compound trees 'mytree_local1' and 'mytree_local2' not identical" 288 fi 289 290 291 #### test "unset" in a subshell 292 ( unset 'mytree_global1.l1[urw].l2[itc zapfdingbats]' ) || \ 293 err_exit "Try 1: Variable 'mytree_global1.l1[urw].l2[itc zapfdingbats]' not found." 294 ( unset 'mytree_global1.l1[urw].l2[itc zapfdingbats]' ) || \ 295 err_exit "Try 2: Variable 'mytree_global1.l1[urw].l2[itc zapfdingbats]' not found." 296 297 # remove parent node (array element) and then check whether the child is gone, too: 298 ( 299 unset 'mytree_global1.l1[urw].l2[itc zapfdingbats]' 300 unset 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' 301 ) && err_exit "Global: Parent node removed (array element), child still exists" 302 ( 303 unset 'mytree_local1.l1[urw].l2[itc zapfdingbats]' 304 unset 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' 305 ) && err_exit "Local: Parent node removed (array element), child still exists" 306 307 # remove parent node (array variable) and then check whether the child is gone, too: 308 ( 309 unset 'mytree_local1.l1[urw].l2' 310 unset 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' 311 ) && err_exit "Global: Parent node removed (array variable), child still exists" 312 ( 313 unset 'mytree_local1.l1[urw].l2' 314 unset 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' 315 ) && err_exit "Local: Parent node removed (array variable), child still exists" 316 317 318 #### test "unset" and compare trees 319 unset 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' || 320 err_exit "Variable 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found." 321 322 [[ "${mytree_global1}" != "${mytree_local1}" ]] || err_exit "mytree_global1 and mytree_local1 should differ" 323 324 unset 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' || 325 err_exit "Variable 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found." 326 327 # Compare trees (after "unset") 328 if [[ "${mytree_global1}" != "${mytree_local1}" ]] ; then 329 err_exit "Compound trees 'mytree_local1' and 'mytree_global1' not identical after unset" 330 fi 331} 332 333main 334exit $((Errors)) 335