1247280Sdteskeif [ ! "$_STRUCT_SUBR" ]; then _STRUCT_SUBR=1 2247280Sdteske# 3247280Sdteske# Copyright (c) 2012-2013 Devin Teske 4252980Sdteske# All rights reserved. 5247280Sdteske# 6247280Sdteske# Redistribution and use in source and binary forms, with or without 7247280Sdteske# modification, are permitted provided that the following conditions 8247280Sdteske# are met: 9247280Sdteske# 1. Redistributions of source code must retain the above copyright 10247280Sdteske# notice, this list of conditions and the following disclaimer. 11247280Sdteske# 2. Redistributions in binary form must reproduce the above copyright 12247280Sdteske# notice, this list of conditions and the following disclaimer in the 13247280Sdteske# documentation and/or other materials provided with the distribution. 14247280Sdteske# 15247280Sdteske# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16252987Sdteske# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17247280Sdteske# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18247280Sdteske# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19247280Sdteske# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20252987Sdteske# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21247280Sdteske# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22247280Sdteske# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23247280Sdteske# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24247280Sdteske# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25247280Sdteske# SUCH DAMAGE. 26247280Sdteske# 27247280Sdteske# $FreeBSD$ 28247280Sdteske# 29247280Sdteske############################################################ INCLUDES 30247280Sdteske 31247280SdteskeBSDCFG_SHARE="/usr/share/bsdconfig" 32247280Sdteske. $BSDCFG_SHARE/common.subr || exit 1 33247280Sdteske 34247280Sdteske############################################################ FUNCTIONS 35247280Sdteske 36247280Sdteske# f_struct_define $type $member_name1 ... 37247280Sdteske# 38247280Sdteske# Define a new `structure' type $type made up of the properties $member_name1 39247280Sdteske# $member_name2 and so-on. Properties are not typed and can hold any type of 40247280Sdteske# data (including names of other structs). 41247280Sdteske# 42247280Sdteske# Before creating instances of a struct (using f_struct_new $type $name) you 43247280Sdteske# should use this function to define $type. 44247280Sdteske# 45247280Sdteske# Both $type and member names should consist only of alpha-numeric letters or 46247280Sdteske# the underscore. 47247280Sdteske# 48247280Sdteskef_struct_define() 49247280Sdteske{ 50247280Sdteske local type="$1" 51247280Sdteske [ "$type" ] || return $FAILURE 52247280Sdteske shift 53247280Sdteske setvar "_struct_typedef_$type" "$*" 54247280Sdteske} 55247280Sdteske 56247280Sdteske# f_struct_new $type $name 57247280Sdteske# 58247280Sdteske# Create a new `structure' named $name of type $type. There are two ways to 59247280Sdteske# access properties of a struct, but they are not equal (each method has its 60247280Sdteske# own unique benefits, discussed below). 61247280Sdteske# 62247280Sdteske# The primary method of accessing (both setting and getting) properties of any 63247280Sdteske# struct is through the f_struct() function below. 64247280Sdteske# 65247280Sdteske# The secondary method of accessing data is by using $name as a function. 66247280Sdteske# 67247280Sdteske# Both access methods are cross-platform compatible with any version of sh(1). 68247280Sdteske# Below is an example of the primary access method: 69247280Sdteske# 70247280Sdteske# f_struct_new MY_STRUCT_TYPE my_struct 71247280Sdteske# f_struct my_struct set abc 123 72247280Sdteske# f_struct my_struct get abc # prints 123 to stdout 73247280Sdteske# f_struct my_struct get abc abc # sets local variable $abc to 123 74247280Sdteske# 75247280Sdteske# Alternatively, the secondary access method (details below): 76247280Sdteske# 77247280Sdteske# f_struct_new MY_STRUCT_TYPE my_struct 78247280Sdteske# my_struct set abc 123 79247280Sdteske# my_struct get abc # prints 123 to stdout 80247280Sdteske# my_struct get abc abc # sets local variable $abc to 123 81247280Sdteske# 82247280Sdteske# The secondary form should only be used if/when: 83247280Sdteske# + You are certain that the structure already exists 84247280Sdteske# + You want a syntax error if/when the struct does not exist 85247280Sdteske# 86247280Sdteske# The primary benefit to the secondary form is syntax cleanliness and read- 87247280Sdteske# ability. If you are unsure if a given struct exists (which would cause a 88247280Sdteske# syntax error when using this form), you can use the primary access method to 89247280Sdteske# first test for the existence of the struct. For example: 90247280Sdteske# 91247280Sdteske# if f_struct my_struct; then 92247280Sdteske# my_struct get abc # only executed if my_struct exists 93247280Sdteske# fi 94247280Sdteske# 95247280Sdteske# For more information, see the f_struct() function. 96247280Sdteske# 97247280Sdteskef_struct_new() 98247280Sdteske{ 99247280Sdteske local type="$1" name="$2" 100247280Sdteske f_dprintf "f_struct_new: type=[%s] name=[%s]" "$type" "$name" 101247280Sdteske [ "$name" ] || return $FAILURE 102247280Sdteske setvar "_struct_type_$name" "$type" || return $FAILURE 103247280Sdteske # OK to use bare $name at this point 104247280Sdteske eval $name\(\){ f_struct $name \"\$@\"\; } 105247280Sdteske} 106247280Sdteske 107247280Sdteske# f_struct $name 108247280Sdteske# f_struct $name get $property [$var_to_set] 109247280Sdteske# f_struct $name set $property $new_value 110247280Sdteske# f_struct $name unset $property 111247280Sdteske# 112247280Sdteske# Access routine for getting, setting, unsetting, and testing properties of 113247280Sdteske# `structures'. 114247280Sdteske# 115247280Sdteske# If only given $name, returns success if struct $name has been created (using 116247280Sdteske# the f_struct_new() function above). 117247280Sdteske# 118247280Sdteske# For getting properties of a struct (versus setting) there are two methods of 119247280Sdteske# access. If $var_to_set is missing or NULL, the value of the property is 120247280Sdteske# printed to standard output for capturing in a sub-shell (which is less- 121247280Sdteske# recommended because of performance degredation; for example, when called in a 122247280Sdteske# loop). Returns success unless the property is unset. 123247280Sdteske# 124247280Sdteske# For setting properties of a struct, sets the value of $property to $new_value 125247280Sdteske# and returns success. 126247280Sdteske# 127247280Sdteske# For unsetting, the underlying environment variable associated with the given 128247280Sdteske# $property is unset. 129247280Sdteske# 130247280Sdteskef_struct() 131247280Sdteske{ 132247280Sdteske local __name="$1" __action="$2" __property="$3" 133247280Sdteske case $# in 134247280Sdteske 0) return $FAILURE ;; 135264840Sdteske 1) f_have "$__name" ;; 136247280Sdteske *) case "$__action" in 137247280Sdteske get) local __var_to_set="$4" 138247280Sdteske f_getvar "_struct_value_${__name}_$__property" "$__var_to_set" 139247280Sdteske ;; 140247280Sdteske set) local new_value="$4" 141247280Sdteske setvar "_struct_value_${__name}_$__property" "$new_value" ;; 142247280Sdteske unset) unset "_struct_value_${__name}_$__property" ;; 143247280Sdteske esac 144247280Sdteske esac 145247280Sdteske # Return the status of the last command above 146247280Sdteske} 147247280Sdteske 148247280Sdteske# f_struct_free $name 149247280Sdteske# 150247280Sdteske# Unset the collection of environment variables and accessor-function 151247280Sdteske# associated with struct $name. 152247280Sdteske# 153247280Sdteskef_struct_free() 154247280Sdteske{ 155247280Sdteske local name="$1" type member members 156247280Sdteske f_getvar "_struct_type_$name" type 157247280Sdteske f_dprintf "f_struct_free: name=[%s] type=[%s]" "$name" "$type" 158247280Sdteske [ "$name" ] || return $FAILURE 159247280Sdteske f_getvar "_struct_typedef_$type" members 160247280Sdteske for member in $members; do 161247280Sdteske f_struct "$name" unset $member 162247280Sdteske done 163247280Sdteske unset -f "$name" 164247280Sdteske unset "_struct_type_$name" 165247280Sdteske} 166247280Sdteske 167247280Sdteske# f_struct_copy $from_name $to_name 168247280Sdteske# 169247280Sdteske# Copy the properties of one struct to another. If struct $to_name does not 170247280Sdteske# exist, it is created. If struct $from_name does not exist, nothing is done 171247280Sdteske# and struct $to_name remains unmodified. 172247280Sdteske# 173247280Sdteske# Returns success unless struct $to_name did not exist and f_struct_new() was 174247280Sdteske# unable to create it. 175247280Sdteske# 176247280Sdteskef_struct_copy() 177247280Sdteske{ 178247280Sdteske local from_name="$1" to_name="$2" type 179247280Sdteske f_dprintf "f_struct_copy: from_name=[%s] to_name=[%s]" \ 180247280Sdteske "$from_name" "$to_name" 181247280Sdteske f_getvar "_struct_type_$from_name" type 182247280Sdteske f_struct "$to_name" || 183247280Sdteske f_struct_new "$type" "$to_name" || return $FAILURE 184247280Sdteske f_struct "$from_name" || return $SUCCESS 185247280Sdteske f_dprintf "f_struct_copy: copying properties from %s to %s" \ 186247280Sdteske "$from_name" "$to_name" 187247280Sdteske local property properties from_value n=0 k=0 188247280Sdteske f_getvar "_struct_typedef_$type" properties 189247280Sdteske for property in $properties; do 190247280Sdteske k=$(( $k + 1 )) 191247280Sdteske if f_struct "$from_name" get $property from_value; then 192247280Sdteske f_struct "$to_name" set $property "$from_value" 193247280Sdteske n=$(( $n + 1 )) 194247280Sdteske else 195247280Sdteske f_struct "$to_name" unset $property 196247280Sdteske fi 197247280Sdteske done 198247280Sdteske f_dprintf "f_struct_copy: copied %u of %u properties from %s to %s" \ 199247280Sdteske "$n" "$k" "$from_name" "$to_name" 200247280Sdteske} 201247280Sdteske 202247280Sdteske############################################################ MAIN 203247280Sdteske 204247280Sdteskef_dprintf "%s: Successfully loaded." struct.subr 205247280Sdteske 206247280Sdteskefi # ! $_STRUCT_SUBR 207