summaryrefslogtreecommitdiffstats
path: root/src/substvars.sh
diff options
context:
space:
mode:
Diffstat (limited to 'src/substvars.sh')
-rw-r--r--src/substvars.sh103
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
+}