# Functions for setting and substituting variables # # Copyright (C) 2012, 2014, 2019 Patrick 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 # . _SUBSTVARS_MAX_DEPTH=50 _SUBSTVAR_TRIM_SED=' 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, and p; # print the results. }; ' set_substvar() { local name="${1}" local value="${2}" shift 2 # Validate variable name and convert to lower case. case "${name}" in *[!A-Za-z0-9-]* | '') warn "$(get_msg 'substvar_invalid')" "${name}" return 1 ;; esac name="$(printf '%s' "${name}" | tr 'A-Z-' 'a-z_')" # Trim leading and trailing whitespace from value. value="$(printf '%s' "${value}" | sed -n "${_SUBSTVAR_TRIM_SED}")" eval "substvar_${name}=\"\${value}\"" return 0 } substvars() { local string="${1}" shift 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}" # Validate the variable name. case "${name}" in *[!A-Za-z0-9-]* | '') warn "$(get_msg 'substvar_invalid')" "${name}" # Remove the variable expansion altogether. We can't # just leave the variable unexpanded, because the # presence of the "${" characters would cause this # parser to loop infinitely. string="${lhs}${rhs}" continue esac # Perform the substitution. name_tr="$(printf '%s' "${name}" | tr 'A-Z-' 'a-z_')" if eval "[ x\"\${substvar_${name_tr}:+set}\" = x'set' ]" then name_tr="substvar_${name_tr}" else warn "$(get_msg 'substvar_unknown')" "${name}" string="${lhs}${rhs}" continue fi value="$(eval "printf '%s' \"\${${name_tr}}\"")" string="${lhs}${value}${rhs}" depth=$((${depth} + 1)) done printf '%s\n' "${string}" return 0 }