diff options
Diffstat (limited to 'src/substvars.sh')
-rw-r--r-- | src/substvars.sh | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/src/substvars.sh b/src/substvars.sh new file mode 100644 index 0000000..c2bc3f8 --- /dev/null +++ b/src/substvars.sh @@ -0,0 +1,103 @@ +# Functions for setting and substituting variables +# +# Copyright (C) 2012, 2014 Patrick "P. J." McDermott +# +# This file is part of the ProteanOS Development Kit. +# +# The ProteanOS Development Kit is free software: you can redistribute +# it and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# The ProteanOS Development Kit is distributed in the hope that it +# will be useful, but WITHOUT ANY WARRANTY; without even the implied +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with the ProteanOS Development Kit. If not, see +# <http://www.gnu.org/licenses/>. + +substvars_max_depth=50 + +set_substvar() +{ + local name="${1}" + local value="${2}" + + # Convert variable name to lower case and validate. + name="$(printf '%s\n' "${name}" | tr 'A-Z-' 'a-z_')" + case "${name:- }" in + *[!a-z0-9_]*) + warn "$(get_msg 'substvar_invalid')" "${name}" + return 1 + ;; + esac + + # Trim leading and trailing newline characters from value. + value="$(printf '%s\n' "${value}" | sed -n ' + H; # Store each input line in the hold space. + ${ # At the last line of input: + g; # Restore the hold space into the pattern space. + s/^[\n]*//; # Remove leading newline characters. + s/[\n]*$//; # Remove trailing newline characters. + p; # Print the results. + }; + ')" + + # Escape single quotes in value. + value="$(printf '%s\n' "${value}" | sed "s/'/'\\\\''/g")" + + eval "substvar_${name}='${value}'" + + return 0 +} + +substvars() +{ + local string="${1}" + local depth= + local lhs= + local name= + local rhs= + local old_rhs= + local value= + + # Logic inspired by that of dpkg's Dpkg::Substvars::substvars() + # subroutine. + + depth=0 + + while :; do + lhs="${string%%\$\{*}" + if [ ${#lhs} -eq ${#string} ]; then + # No "${" was found. + break + fi + string="${string#*\$\{}" + name="${string%%\}*}" + rhs="${string#*\}}" + + if [ ${#rhs} -lt ${#old_rhs} ]; then + # Reset the nesting counter if we've advanced the right + # side of the matched space. + depth=0 + fi + if [ ${depth} -ge ${substvars_max_depth} ]; then + # Warn of possible recursion. + warn "$(get_msg 'substvar_deep_nesting')" + return 1 + fi + old_rhs="${rhs}" + + # Perform the substitution. + name="$(printf '%s\n' "${name}" | tr 'A-Z-' 'a-z_')" + value="$(eval "printf '%s\n' \"\${substvar_${name}}\"")" + string="${lhs}${value}${rhs}" + depth=$(($depth + 1)) + done + + printf '%s\n' "${string}" + + return 0 +} |