diff options
-rwxr-xr-x | tools/shmin.sh | 292 |
1 files changed, 0 insertions, 292 deletions
diff --git a/tools/shmin.sh b/tools/shmin.sh deleted file mode 100755 index d4386c6..0000000 --- a/tools/shmin.sh +++ /dev/null @@ -1,292 +0,0 @@ -#!/bin/sh -# -# Shell command language minifier -# -# 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' -HT=' ' -LF=' -' - -c= -output='' - -die() -{ - local fmt="${1}" - shift 1 - - printf "shmin: ${fmt}\n" "${@}" >&2 - exit 2 -} - -fgetc() -{ - # Damn command substitutions eat trailing whitespace. Even if - # whitespace is the /only/ thing printed and exactly what we want from - # the command. - c="$(dd bs=1 count=1 <&3 2>/dev/null; printf '.')" - c="${c%.}" -} - -parse() -{ - local buffer='' - local escaped=false - - # Check for magic number or other first-line comment. - fgetc - if [ "x${c}" = 'x#' ]; then - # Comment - fgetc - if [ "x${c}" = 'x!' ]; then - # Magic number - buffer="${buffer}#!" - while :; do - fgetc - buffer="${buffer}${c}" - if [ "x${c}" = "x${LF}" ]; then - break - fi - done - else - while :; do - if [ "x${c}" = "x${LF}" ]; then - break - fi - fgetc - done - fi - fi - - # Strip leading whitespace on the first line. - while :; do - case "${c}" in - ' ' | "${HT}" | "${LF}") - ;; - *) - break - ;; - esac - fgetc - done - - # Parse the rest of the file. - # Like any good parser, this is some very ugly and fragile code. - # Whitespace code must come before comment code must come before newline - # code must come before everything else. - while :; do - if [ "x${c}" = 'x' ]; then - break - fi - if [ "x${c}" = 'x ' ] || [ "x${c}" = "x${HT}" ]; then - # Whitespace - while :; do - fgetc - case "${c}" in - ' ' | "${HT}") - ;; - "${LF}" | '#') - # Eat trailing whitespace. - break - ;; - '') return 1;; - *) - # Condense whitespace. - buffer="${buffer} " - break - ;; - esac - done - fi - if [ "x${c}" = 'x#' ]; then - # Comment - while :; do - fgetc - if [ "x${c}" = "x${LF}" ]; then - break - fi - [ "x${c}" = 'x' ] && return 1 - done - fi - if [ "x${c}" = "x${LF}" ]; then - # Strip empty lines and leading whitespace. - while :; do - fgetc - case "${c}" in - ' ' | "${HT}" | "${LF}") - ;; - *) - buffer="${buffer}${LF}" - break - ;; - esac - done - fi - if [ "x${c}" = 'x\' ]; then - # Backslash - buffer="${buffer}${c}" - fgetc - buffer="${buffer}${c}" - [ "x${c}" = 'x' ] && return 1 - continue - fi - if [ "x${c}" = "x'" ]; then - # Single quotes - buffer="${buffer}${c}" - while :; do - fgetc - buffer="${buffer}${c}" - if [ "x${c}" = "x'" ]; then - break - fi - [ "x${c}" = 'x' ] && return 1 - done - fgetc - continue - fi - if [ "x${c}" = 'x"' ]; then - # Double quotes - buffer="${buffer}${c}" - while :; do - fgetc - buffer="${buffer}${c}" - if ${escaped}; then - escaped=false - continue - fi - if [ "x${c}" = 'x\' ]; then - escaped=true - continue - fi - if [ "x${c}" = 'x"' ]; then - break - fi - [ "x${c}" = 'x' ] && return 1 - done - fgetc - continue - fi - buffer="${buffer}${c}" - fgetc - done - - printf '%s' "${buffer}" -} - -minify() -{ - local input="${1}" - local buffer='' - - # Open input file. - if ! exec 3<"${input}"; then - die 'Cannot open file "%s"' "${input}" - fi - - # Parse input. - if ! buffer="$(parse)"; then - die 'Syntax error in input' - exec 3<&- - fi - - # We made it. Now close input file. - if ! exec 3<&-; then - die 'Cannot close file "%s"' "${input}" - fi - - # Write the output. - if [ "x${output}" = 'x-' ]; then - printf '%s\n' "${buffer}" - else - if ! printf '%s\n' "${buffer}" >"${output}~"; then - die 'Cannot write file "%s"' "${output}~" - fi - if ! cat "${output}~" >"${output}"; then - die 'Cannot rename file to "%s"' "${output}" - fi - if ! rm "${output}~"; then - die 'Cannot remove file "%s"' "${output}~" - fi - fi -} - -usage() -{ - printf 'Usage: %s [option ...] <file>\n' "${0}" -} - -help() -{ - usage - cat <<EOF -Options: - -h Display this information - -V Display minifier version information - -o <output> Write the minified output to <output>, instead of replacing the - existing file -EOF -} - -version() -{ - cat <<EOF -shmin ${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 input= - - while getopts 'hVo:' opt; do - case "${opt}" in - 'h') - help - exit - ;; - 'V') - version - exit - ;; - 'o') - output="${OPTARG}" - ;; - esac - done - shift $(($OPTIND - 1)) - - if [ ${#} -ne 1 ]; then - usage >&2 - exit 1 - fi - input="${1}" - - if [ "x${output}" = 'x' ]; then - output="${input}" - fi - - minify "${input}" -} - -main "${@}" |