diff options
Diffstat (limited to 'tools')
-rwxr-xr-x | tools/shpp.sh | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/tools/shpp.sh b/tools/shpp.sh new file mode 100755 index 0000000..c54c7b7 --- /dev/null +++ b/tools/shpp.sh @@ -0,0 +1,165 @@ +#!/bin/sh +# +# Shell command language preprocessor +# +# Copyright (C) 2015 Patrick "P. J." McDermott +# +# This program 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. +# +# This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + +set -u + +VERSION='0.1.0' +FS="$(printf '\034')" + +die() +{ + local fmt="${1}" + shift 1 + + printf "shpp: ${fmt}\n" "${@}" + exit 2 +} + +preprocess() +{ + local vars="${1}" + local input="${2}" + local output="${3}" + local def= + local var= + local val= + + # Open output file. + if [ "x${output}" = 'x-' ]; then + if ! exec 3>&1; then + die 'Cannot duplicate output file descriptor' + fi + else + if ! exec 3>"${outfile}~"; then + die 'Cannot open file "%s"' "${output}~" + fi + fi + + IFS="${FS}" + for def in ${vars}; do + case "${def}" in + *=*) + var="${def%%=*}" + val="${def#*=}" + ;; + *) + var="${def%%=*}" + val='true' + ;; + esac + case "${var}" in + *[!A-Za-z0-9_]*) + error 'Invalid variable name "%s"' "${var}" + continue + ;; + [0-9]*) + error 'Invalid variable name "%s"' "${var}" + continue + ;; + esac + printf "%s='" "${var}" >&3 + printf '%s' "${val}" | sed "s/'/'\\\\''/g" >&3 + printf "'\n" >&3 + done + unset IFS + + # Read input file. + if ! cat "${input}" >&3; then + die 'Cannot read file "%s"' "${input}" + fi + + # Close output file, make it executable, and set its name. + if ! [ "x${output}" = 'x-' ]; then + exec 3>&- + if ! mv "${output}~" "${output}"; then + die 'Cannot rename file to "%s"' "${output}" + fi + fi +} + +usage() +{ + printf 'Usage: %s [option ...] <infile> [<outfile>]\n' "${0}" +} + +help() +{ + usage + cat <<EOF +Options: + -h Display this information + -V Display preprocessor version information + -D <var>[=<val>] Predefine <var> as a variable with value <val> (default + "true") +EOF +} + +version() +{ + cat <<EOF +shpp ${VERSION} +Copyright (C) 2015 Patrick "P. J." McDermott +License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>. +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law. +EOF +} + +main() +{ + local opt= + local vars= + local infile= + local outfile= + + while getopts 'hVD:' opt; do + case "${opt}" in + 'h') + help + exit + ;; + 'V') + version + exit + ;; + 'D') + vars="${vars}${OPTARG}${FS}" + ;; + esac + done + shift $(($OPTIND - 1)) + + case ${#} in + 1) + infile="${1}" + outfile='-' + ;; + 2) + infile="${1}" + outfile="${2}" + ;; + *) + usage >&2 + exit 1 + esac + + preprocess "${vars}" "${infile}" "${outfile}" +} + +main "${@}" |