17c2fbfb3SApril Chin######################################################################## 27c2fbfb3SApril Chin# # 37c2fbfb3SApril Chin# This software is part of the ast package # 4*3e14f97fSRoger A. Faulkner# Copyright (c) 1982-2010 AT&T Intellectual Property # 57c2fbfb3SApril Chin# and is licensed under the # 67c2fbfb3SApril Chin# Common Public License, Version 1.0 # 77c2fbfb3SApril Chin# by AT&T Intellectual Property # 87c2fbfb3SApril Chin# # 97c2fbfb3SApril Chin# A copy of the License is available at # 107c2fbfb3SApril Chin# http://www.opensource.org/licenses/cpl1.0.txt # 117c2fbfb3SApril Chin# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) # 127c2fbfb3SApril Chin# # 137c2fbfb3SApril Chin# Information and Software Systems Research # 147c2fbfb3SApril Chin# AT&T Research # 157c2fbfb3SApril Chin# Florham Park NJ # 167c2fbfb3SApril Chin# # 177c2fbfb3SApril Chin# David Korn <dgk@research.att.com> # 187c2fbfb3SApril Chin# # 197c2fbfb3SApril Chin######################################################################## 207c2fbfb3SApril Chin# 217c2fbfb3SApril Chin# variable tree test #002 227c2fbfb3SApril Chin# Propose of this test is whether ksh93 handles global variable trees 237c2fbfb3SApril Chin# and function-local variable trees the same way, including "nameref" 247c2fbfb3SApril Chin# and "unset" handling. 257c2fbfb3SApril Chin# 267c2fbfb3SApril Chin 277c2fbfb3SApril Chinfunction err_exit 287c2fbfb3SApril Chin{ 297c2fbfb3SApril Chin print -u2 -n "\t" 307c2fbfb3SApril Chin print -u2 -r ${Command}[$1]: "${@:2}" 317c2fbfb3SApril Chin (( Errors+=1 )) 327c2fbfb3SApril Chin} 337c2fbfb3SApril Chin 347c2fbfb3SApril Chinalias err_exit='err_exit $LINENO' 357c2fbfb3SApril Chin 367c2fbfb3SApril Chin# "built_tree1" and "built_tree2" are identical except the way how they test 377c2fbfb3SApril Chin# whether a variable exists: 387c2fbfb3SApril Chin# - "built_tree1" uses "${varname}" != "", e.g. looking whether the variable 397c2fbfb3SApril Chin# as non-zero length content 407c2fbfb3SApril Chin# - "built_tree2" uses "! (unset varname)", e.g. "unset" in a subshell 417c2fbfb3SApril Chinfunction build_tree1 427c2fbfb3SApril Chin{ 437c2fbfb3SApril Chin#set -o errexit -o xtrace 447c2fbfb3SApril Chin typeset index 457c2fbfb3SApril Chin typeset s 467c2fbfb3SApril Chin typeset i 477c2fbfb3SApril Chin typeset dummy 487c2fbfb3SApril Chin typeset a b c d e f 497c2fbfb3SApril Chin 507c2fbfb3SApril Chin nameref dest_tree="$1" # destination tree 517c2fbfb3SApril Chin nameref srcdata="$2" # source data 527c2fbfb3SApril Chin typeset tree_mode="$3" # mode to define the type of leads 537c2fbfb3SApril Chin 547c2fbfb3SApril Chin typeset -A dest_tree.l1 557c2fbfb3SApril Chin 567c2fbfb3SApril Chin for index in "${!srcdata.hashnodes[@]}" ; do 577c2fbfb3SApril Chin nameref node=srcdata.hashnodes["${index}"] 587c2fbfb3SApril Chin 597c2fbfb3SApril Chin for i in "${node.xlfd[@]}" ; do 607c2fbfb3SApril Chin IFS='-' read dummy a b c d e f <<<"$i" 617c2fbfb3SApril Chin 627c2fbfb3SApril Chin if [[ "$a" == "" ]] ; then 637c2fbfb3SApril Chin a="$dummy" 647c2fbfb3SApril Chin fi 657c2fbfb3SApril Chin 667c2fbfb3SApril Chin [[ "$a" == "" ]] && a='-' 677c2fbfb3SApril Chin [[ "$b" == "" ]] && b='-' 687c2fbfb3SApril Chin [[ "$c" == "" ]] && c='-' 697c2fbfb3SApril Chin 707c2fbfb3SApril Chin if [[ "${dest_tree.l1["$a"]}" == "" ]] ; then 717c2fbfb3SApril Chin #if ! (unset dest_tree.l1["$a"]) ; then 727c2fbfb3SApril Chin typeset -A dest_tree.l1["$a"].l2 737c2fbfb3SApril Chin fi 747c2fbfb3SApril Chin 757c2fbfb3SApril Chin if [[ "${dest_tree.l1["$a"].l2["$b"]}" == "" ]] ; then 767c2fbfb3SApril Chin #if ! (unset dest_tree.l1["$a"].l2["$b"]) ; then 777c2fbfb3SApril Chin typeset -A dest_tree.l1["$a"].l2["$b"].l3 787c2fbfb3SApril Chin fi 797c2fbfb3SApril Chin 807c2fbfb3SApril Chin if [[ "${!dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[*]}" == "" ]] ; then 817c2fbfb3SApril Chin typeset -A dest_tree.l1["$a"].l2["$b"].l3["$c"].entries 827c2fbfb3SApril Chin fi 837c2fbfb3SApril Chin 847c2fbfb3SApril Chin typeset new_index 857c2fbfb3SApril Chin if [[ "${tree_mode}" == "leaf_name" ]] ; then 867c2fbfb3SApril Chin new_index=$(( ${#dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[@]}+1 )) 877c2fbfb3SApril Chin else 887c2fbfb3SApril Chin new_index="${node.name}" 897c2fbfb3SApril Chin 907c2fbfb3SApril Chin # skip if the leaf node already exists 917c2fbfb3SApril Chin if [[ "${dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}]}" != "" ]] ; then 927c2fbfb3SApril Chin continue 937c2fbfb3SApril Chin fi 947c2fbfb3SApril Chin fi 957c2fbfb3SApril Chin 967c2fbfb3SApril Chin add_tree_leaf dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}] "${index}" "${tree_mode}" 977c2fbfb3SApril Chin done 987c2fbfb3SApril Chin done 997c2fbfb3SApril Chin 1007c2fbfb3SApril Chin return 0 1017c2fbfb3SApril Chin} 1027c2fbfb3SApril Chin 1037c2fbfb3SApril Chin# "built_tree1" and "built_tree2" are identical except the way how they test 1047c2fbfb3SApril Chin# whether a variable exists: 1057c2fbfb3SApril Chin# - "built_tree1" uses "${varname}" != "", e.g. looking whether the variable 1067c2fbfb3SApril Chin# as non-zero length content 1077c2fbfb3SApril Chin# - "built_tree2" uses "! (unset varname)", e.g. "unset" in a subshell 1087c2fbfb3SApril Chinfunction build_tree2 1097c2fbfb3SApril Chin{ 1107c2fbfb3SApril Chin#set -o errexit -o xtrace 1117c2fbfb3SApril Chin typeset index 1127c2fbfb3SApril Chin typeset s 1137c2fbfb3SApril Chin typeset i 1147c2fbfb3SApril Chin typeset dummy 1157c2fbfb3SApril Chin typeset a b c d e f 1167c2fbfb3SApril Chin 1177c2fbfb3SApril Chin nameref dest_tree="$1" # destination tree 1187c2fbfb3SApril Chin nameref srcdata="$2" # source data 1197c2fbfb3SApril Chin typeset tree_mode="$3" # mode to define the type of leads 1207c2fbfb3SApril Chin 1217c2fbfb3SApril Chin typeset -A dest_tree.l1 1227c2fbfb3SApril Chin 1237c2fbfb3SApril Chin for index in "${!srcdata.hashnodes[@]}" ; do 1247c2fbfb3SApril Chin nameref node=srcdata.hashnodes["${index}"] 1257c2fbfb3SApril Chin 1267c2fbfb3SApril Chin for i in "${node.xlfd[@]}" ; do 1277c2fbfb3SApril Chin IFS='-' read dummy a b c d e f <<<"$i" 1287c2fbfb3SApril Chin 1297c2fbfb3SApril Chin if [[ "$a" == "" ]] ; then 1307c2fbfb3SApril Chin a="$dummy" 1317c2fbfb3SApril Chin fi 1327c2fbfb3SApril Chin 1337c2fbfb3SApril Chin [[ "$a" == "" ]] && a='-' 1347c2fbfb3SApril Chin [[ "$b" == "" ]] && b='-' 1357c2fbfb3SApril Chin [[ "$c" == "" ]] && c='-' 1367c2fbfb3SApril Chin 1377c2fbfb3SApril Chin #if [[ "${dest_tree.l1["$a"]}" == "" ]] ; then 1387c2fbfb3SApril Chin if ! (unset dest_tree.l1["$a"]) ; then 1397c2fbfb3SApril Chin typeset -A dest_tree.l1["$a"].l2 1407c2fbfb3SApril Chin fi 1417c2fbfb3SApril Chin 1427c2fbfb3SApril Chin #if [[ "${dest_tree.l1["$a"].l2["$b"]}" == "" ]] ; then 1437c2fbfb3SApril Chin if ! (unset dest_tree.l1["$a"].l2["$b"]) ; then 1447c2fbfb3SApril Chin typeset -A dest_tree.l1["$a"].l2["$b"].l3 1457c2fbfb3SApril Chin fi 1467c2fbfb3SApril Chin 1477c2fbfb3SApril Chin if [[ "${!dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[*]}" == "" ]] ; then 1487c2fbfb3SApril Chin typeset -A dest_tree.l1["$a"].l2["$b"].l3["$c"].entries 1497c2fbfb3SApril Chin fi 1507c2fbfb3SApril Chin 1517c2fbfb3SApril Chin typeset new_index 1527c2fbfb3SApril Chin if [[ "${tree_mode}" == "leaf_name" ]] ; then 1537c2fbfb3SApril Chin new_index=$(( ${#dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[@]}+1 )) 1547c2fbfb3SApril Chin else 1557c2fbfb3SApril Chin new_index="${node.name}" 1567c2fbfb3SApril Chin 1577c2fbfb3SApril Chin # skip if the leaf node already exists 1587c2fbfb3SApril Chin if [[ "${dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}]}" != "" ]] ; then 1597c2fbfb3SApril Chin continue 1607c2fbfb3SApril Chin fi 1617c2fbfb3SApril Chin fi 1627c2fbfb3SApril Chin 1637c2fbfb3SApril Chin add_tree_leaf dest_tree.l1["$a"].l2["$b"].l3["$c"].entries[${new_index}] "${index}" "${tree_mode}" 1647c2fbfb3SApril Chin done 1657c2fbfb3SApril Chin done 1667c2fbfb3SApril Chin 1677c2fbfb3SApril Chin return 0 1687c2fbfb3SApril Chin} 1697c2fbfb3SApril Chin 1707c2fbfb3SApril Chin 1717c2fbfb3SApril Chinfunction add_tree_leaf 1727c2fbfb3SApril Chin{ 1737c2fbfb3SApril Chin nameref tree_leafnode="$1" 1747c2fbfb3SApril Chin nameref data_node=srcdata.hashnodes["$2"] 1757c2fbfb3SApril Chin typeset add_mode="$3" 1767c2fbfb3SApril Chin 1777c2fbfb3SApril Chin case "${add_mode}" in 1787c2fbfb3SApril Chin "leaf_name") 1797c2fbfb3SApril Chin tree_leafnode="${data_node.name}" 1807c2fbfb3SApril Chin return 0 1817c2fbfb3SApril Chin ;; 1827c2fbfb3SApril Chin "leaf_compound") 1837c2fbfb3SApril Chin tree_leafnode=( 1847c2fbfb3SApril Chin typeset name="${data_node.name}" 1857c2fbfb3SApril Chin typeset -a filenames=( "${data_node.filenames[@]}" ) 1867c2fbfb3SApril Chin typeset -a comments=( "${data_node.comments[@]}" ) 1877c2fbfb3SApril Chin typeset -a xlfd=( "${data_node.xlfd[@]}" ) 1887c2fbfb3SApril Chin ) 1897c2fbfb3SApril Chin return 0 1907c2fbfb3SApril Chin ;; 1917c2fbfb3SApril Chin *) 1927c2fbfb3SApril Chin print -u2 -f "ERROR: Unknown mode %s in add_tree_leaf\n" "${add_mode}" 1937c2fbfb3SApril Chin return 1 1947c2fbfb3SApril Chin ;; 1957c2fbfb3SApril Chin esac 1967c2fbfb3SApril Chin 1977c2fbfb3SApril Chin # not reached 1987c2fbfb3SApril Chin return 1 1997c2fbfb3SApril Chin} 2007c2fbfb3SApril Chin 2017c2fbfb3SApril Chin# "mysrcdata_local" and "mysrcdata_global" must be identical 2027c2fbfb3SApril Chintypeset mysrcdata_global=( 2037c2fbfb3SApril Chin typeset -A hashnodes=( 2047c2fbfb3SApril Chin [abcd]=( 2057c2fbfb3SApril Chin name='abcd' 2067c2fbfb3SApril Chin typeset -a xlfd=( 2077c2fbfb3SApril Chin '-urw-itc zapfchancery-medium-i-normal--0-0-0-0-p-0-iso8859-1' 2087c2fbfb3SApril Chin '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-adobe-fontspecific' 2097c2fbfb3SApril Chin '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-sun-fontspecific' 2107c2fbfb3SApril Chin ) 2117c2fbfb3SApril Chin typeset -a comments=( 2127c2fbfb3SApril Chin 'comment 1' 2137c2fbfb3SApril Chin 'comment 2' 2147c2fbfb3SApril Chin 'comment 3' 2157c2fbfb3SApril Chin ) 2167c2fbfb3SApril Chin typeset -a filenames=( 2177c2fbfb3SApril Chin '/home/foo/abcd_1' 2187c2fbfb3SApril Chin '/home/foo/abcd_2' 2197c2fbfb3SApril Chin '/home/foo/abcd_3' 2207c2fbfb3SApril Chin ) 2217c2fbfb3SApril Chin ) 2227c2fbfb3SApril Chin ) 2237c2fbfb3SApril Chin) 2247c2fbfb3SApril Chin 2257c2fbfb3SApril Chinmytree_global1=() 2267c2fbfb3SApril Chinmytree_global2=() 2277c2fbfb3SApril Chin 2287c2fbfb3SApril Chinfunction main 2297c2fbfb3SApril Chin{ 2307c2fbfb3SApril Chin # "mysrcdata_local" and "mysrcdata_global" must be identical 2317c2fbfb3SApril Chin typeset mysrcdata_local=( 2327c2fbfb3SApril Chin typeset -A hashnodes=( 2337c2fbfb3SApril Chin [abcd]=( 2347c2fbfb3SApril Chin name='abcd' 2357c2fbfb3SApril Chin typeset -a xlfd=( 2367c2fbfb3SApril Chin '-urw-itc zapfchancery-medium-i-normal--0-0-0-0-p-0-iso8859-1' 2377c2fbfb3SApril Chin '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-adobe-fontspecific' 2387c2fbfb3SApril Chin '-urw-itc zapfdingbats-medium-r-normal--0-0-0-0-p-0-sun-fontspecific' 2397c2fbfb3SApril Chin ) 2407c2fbfb3SApril Chin typeset -a comments=( 2417c2fbfb3SApril Chin 'comment 1' 2427c2fbfb3SApril Chin 'comment 2' 2437c2fbfb3SApril Chin 'comment 3' 2447c2fbfb3SApril Chin ) 2457c2fbfb3SApril Chin typeset -a filenames=( 2467c2fbfb3SApril Chin '/home/foo/abcd_1' 2477c2fbfb3SApril Chin '/home/foo/abcd_2' 2487c2fbfb3SApril Chin '/home/foo/abcd_3' 2497c2fbfb3SApril Chin ) 2507c2fbfb3SApril Chin ) 2517c2fbfb3SApril Chin ) 2527c2fbfb3SApril Chin ) 2537c2fbfb3SApril Chin 2547c2fbfb3SApril Chin #### Build tree using global tree variables 2557c2fbfb3SApril Chin build_tree1 mytree_global1 mysrcdata_global leaf_compound || \ 2567c2fbfb3SApril Chin err_exit 'build_tree1 mytree_global1 mysrcdata_global leaf_compound returned an error' 25734f9b3eeSRoland Mainz (( $(print -r -- "${mytree_global1}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_global1' too small" 2587c2fbfb3SApril Chin 2597c2fbfb3SApril Chin build_tree2 mytree_global2 mysrcdata_global leaf_compound || \ 2607c2fbfb3SApril Chin err_exit 'build_tree2 mytree_global2 mysrcdata_global leaf_compound returned an error' 26134f9b3eeSRoland Mainz (( $(print -r -- "${mytree_global2}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_global2' too small" 2627c2fbfb3SApril Chin 2637c2fbfb3SApril Chin 2647c2fbfb3SApril Chin #### build tree using local tree variables 2657c2fbfb3SApril Chin mytree_local1=() 2667c2fbfb3SApril Chin mytree_local2=() 2677c2fbfb3SApril Chin 2687c2fbfb3SApril Chin build_tree1 mytree_local1 mysrcdata_local leaf_compound || \ 2697c2fbfb3SApril Chin err_exit 'build_tree1 mytree_local1 mysrcdata_local leaf_compound returned an error' 27034f9b3eeSRoland Mainz (( $(print -r -- "${mytree_local1}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_local1' too small" 2717c2fbfb3SApril Chin 2727c2fbfb3SApril Chin build_tree2 mytree_local2 mysrcdata_local leaf_compound || \ 2737c2fbfb3SApril Chin err_exit 'build_tree2 mytree_local2 mysrcdata_local leaf_compound returned an error' 27434f9b3eeSRoland Mainz (( $(print -r -- "${mytree_local2}" | wc -l) > 10 )) || err_exit "compound tree 'mytree_local2' too small" 2757c2fbfb3SApril Chin 2767c2fbfb3SApril Chin 2777c2fbfb3SApril Chin #### Compare treess 2787c2fbfb3SApril Chin if [[ "${mytree_global1}" != "${mytree_local1}" ]] ; then 27934f9b3eeSRoland Mainz err_exit "compound trees 'mytree_global1' and 'mytree_local1' not identical" 2807c2fbfb3SApril Chin fi 2817c2fbfb3SApril Chin 2827c2fbfb3SApril Chin if [[ "${mytree_global1}" != "${mytree_global2}" ]] ; then 28334f9b3eeSRoland Mainz err_exit "compound trees 'mytree_global1' and 'mytree_global2' not identical" 2847c2fbfb3SApril Chin fi 2857c2fbfb3SApril Chin 2867c2fbfb3SApril Chin if [[ "${mytree_local1}" != "${mytree_local2}" ]] ; then 28734f9b3eeSRoland Mainz err_exit "compound trees 'mytree_local1' and 'mytree_local2' not identical" 2887c2fbfb3SApril Chin fi 2897c2fbfb3SApril Chin 2907c2fbfb3SApril Chin 2917c2fbfb3SApril Chin #### test "unset" in a subshell 2927c2fbfb3SApril Chin ( unset 'mytree_global1.l1[urw].l2[itc zapfdingbats]' ) || \ 29334f9b3eeSRoland Mainz err_exit "try 1: variable 'mytree_global1.l1[urw].l2[itc zapfdingbats]' not found" 2947c2fbfb3SApril Chin ( unset 'mytree_global1.l1[urw].l2[itc zapfdingbats]' ) || \ 29534f9b3eeSRoland Mainz err_exit "try 2: variable 'mytree_global1.l1[urw].l2[itc zapfdingbats]' not found" 2967c2fbfb3SApril Chin 2977c2fbfb3SApril Chin # remove parent node (array element) and then check whether the child is gone, too: 2987c2fbfb3SApril Chin ( 2997c2fbfb3SApril Chin unset 'mytree_global1.l1[urw].l2[itc zapfdingbats]' 30034f9b3eeSRoland Mainz [[ -v 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]'} ]] 30134f9b3eeSRoland Mainz ) && err_exit "global: parent node removed (array element), child still exists" 3027c2fbfb3SApril Chin ( 3037c2fbfb3SApril Chin unset 'mytree_local1.l1[urw].l2[itc zapfdingbats]' 30434f9b3eeSRoland Mainz [[ -v 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ]] 30534f9b3eeSRoland Mainz ) && err_exit "local: parent node removed (array element), child still exists" 3067c2fbfb3SApril Chin 3077c2fbfb3SApril Chin # remove parent node (array variable) and then check whether the child is gone, too: 3087c2fbfb3SApril Chin ( 3097c2fbfb3SApril Chin unset 'mytree_local1.l1[urw].l2' 31034f9b3eeSRoland Mainz [[ -v 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ]] 31134f9b3eeSRoland Mainz ) && err_exit "global: parent node removed (array variable), child still exists" 3127c2fbfb3SApril Chin ( 3137c2fbfb3SApril Chin unset 'mytree_local1.l1[urw].l2' 31434f9b3eeSRoland Mainz [[ -v 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' ]] 31534f9b3eeSRoland Mainz ) && err_exit "local: parent node removed (array variable), child still exists" 3167c2fbfb3SApril Chin 3177c2fbfb3SApril Chin 3187c2fbfb3SApril Chin #### test "unset" and compare trees 3197c2fbfb3SApril Chin unset 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' || 32034f9b3eeSRoland Mainz err_exit "variable 'mytree_global1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found" 3217c2fbfb3SApril Chin 3227c2fbfb3SApril Chin [[ "${mytree_global1}" != "${mytree_local1}" ]] || err_exit "mytree_global1 and mytree_local1 should differ" 3237c2fbfb3SApril Chin 3247c2fbfb3SApril Chin unset 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' || 32534f9b3eeSRoland Mainz err_exit "variable 'mytree_local1.l1[urw].l2[itc zapfdingbats].l3[medium].entries[abcd].filenames[0]' not found" 3267c2fbfb3SApril Chin 3277c2fbfb3SApril Chin # Compare trees (after "unset") 3287c2fbfb3SApril Chin if [[ "${mytree_global1}" != "${mytree_local1}" ]] ; then 32934f9b3eeSRoland Mainz err_exit "compound trees 'mytree_local1' and 'mytree_global1' not identical after unset" 3307c2fbfb3SApril Chin fi 3317c2fbfb3SApril Chin} 3327c2fbfb3SApril Chin 3337c2fbfb3SApril Chinmain 3347c2fbfb3SApril Chinexit $((Errors)) 335