diff --git a/inc/md2html.cfg b/inc/md2html.cfg index 5866aca21..215628be0 100644 --- a/inc/md2html.cfg +++ b/inc/md2html.cfg @@ -52,13 +52,10 @@ # # -d topdir set topdir (def: if 'git rev-parse --is-inside-work-tree' is true, then # topdir is output of 'git rev-parse --show-toplevel') -# -D def 'def' is default HTML phase name (def: 'default' is default phase name) +# NOTE: -d may only be used in command_options (getopt phase 0) # -# -i inc inc files are located under topdir/inc (def: inc files are under topdir/inc) -# -# -c md2html.cfg Use md2html.cfg as the configuration file (def: use inc/md2html.cfg) -# -C dir cd dir (def: if 'git rev-parse --is-inside-work-tree' is true, then -# cd to the output of 'git rev-parse --show-cdup') +# -c md2html.cfg Use md2html.cfg as the configuration file (def: use topdir/inc/md2html.cfg) +# NOTE: -c may only be used in command_options (getopt phase 0) # # -H phase=name use 'phase.name.html' file for HTML phase named 'phase' (def: use 'phase.default.html') # -H phase=. ignore processing for HTML phase 'phase' (def: process HTML phase) @@ -69,9 +66,8 @@ # -b . skip HTML phase number 20 (def: do nothing during HTML phase number 20) # -B optstr run 'before tool' with options found in 'optstr' (def: do not add any options to 'before tool') # -# -p tool path to 'pandoc tool' wrapper used in HTML phase number 21 is 'tool' (def: use inc/pandoc.sh) +# -p tool run 'pandoc tool' wrapper (not path to pandoc) during HTML phase number 21 (def: use inc/pandoc.sh) # -p . skip HTML phase number 21 (def: do nothing during HTML phase number 21) -# NOTE: The 'tool' is a 'pandoc tool' wrapper tool, NOT the path to the actual pandoc application. # -P optstr run 'pandoc tool' with options found in 'optstr' (def: use only the 'pandoc tool' default options) # # -a tool run 'after tool' during HTML phase number 20 (def: do not output after pandoc tool) @@ -85,11 +81,13 @@ # # -o tool Use output tool, 'tool', to generate option lines (def: do not) # -o . disable use of 'output tool' (def: do not use an 'output tool') +# NOTE: -o may only be used in command_options and cfg_options (getopt phases 0 and 1) # -O tool=optstr run the 'token replace' named 'tool' with options found in 'optstr' (def: do not add any options) # NOTE: The 'tool' string may not contain = (equal), nor double-quote, nor single-quote. +# NOTE: -O may only be used in command_options and cfg_options (getopt phases 0 and 1) # -# -e exitcode force exit with exitcode (def: exit based on success or failure of the action) -# -E string output string, followed by newline, to stderr (def: do not) +# -e string output string, followed by newline, to stderr (def: do not) +# -E exitcode force exit with exitcode (def: exit based on success or failure of the action) # # The output from 'before tool' (unless -b .) will be used in HTML phase number 20 (before pandoc processing). # The output from 'pandoc tool' (unless -p .) will be used HTML phase number 21 (pandoc processing). @@ -120,14 +118,14 @@ # # The command options are evaluated in the following getopt phases: # -# 0. collect command line options, up to but not including any '--' or up to the command line filename argument(s) -# 0a. ((evaluate all getopt phase 0 options)) +# getopt phase 0. collect command line options, up to but not including any '--' or up to the command line filename argument(s) +# getopt phase 0a. ((evaluate all getopt phase 0 options)) # -# 1. collect 'cfg_options' from the first md2html.cfg line where 'file_glob' matched the filename argument -# 1a. ((evaluate all getopt phase 1 options)) +# getopt phase 1. collect 'cfg_options' from the first md2html.cfg line where 'file_glob' matched the filename argument +# getopt phase 1a. ((evaluate all getopt phase 1 options, except '-d topdir', '-c md2html.cfg' are ignored)) # -# 2. collect output of '-o tool' from getopt phase 0a and then from getopt phase 1a, in the order collected -# 2a. ((evaluate all getopt phase 2 options, except that any new '-o tool' are ignored)) +# getopt phase 2. collect output of '-o tool' from getopt phase 0a and then from getopt phase 1a, in the order collected +# getopt phase 2a. ((evaluate all getopt phase 2 options, except '-d topdir', '-c md2html.cfg', '-o tool' are ignored)) # # Command line options are evaluated in order, during each getopt phase (i.e., getopt phase 0a, then 1a, phase 2a). # @@ -140,8 +138,8 @@ # Also in the case of '-s token=value', later '-s token=value' only overrides an earlier use of '-s' # for the same 'token' only. # -# When '-e exitcode' is evaluated, the application will exit with the 'exitcode' value. If one wishes to also -# output a message to stderr, the '-E string' must come BEFORE any '-e exitcode' in the command line. +# When '-E exitcode' is evaluated, the application will exit with the 'exitcode' value. If one wishes to also +# output a message to stderr, the '-e string' must come BEFORE any '-E exitcode' in the command line. # # All tokens (i.e., strings of the form '%%token%%') MUST be substituted (by some -s token=value) # in all HTML output, except during phase numbers 20-29 (i.e., except 'before tool' output, pandoc output, @@ -262,7 +260,7 @@ # Exit 9 for any markdown file that we have not previously configured -*.md -E "markdown file does not match any md2html.cfg line" -e 200 +*.md -e "markdown file does not match any md2html.cfg line" -E 200 # Last, everything else is silently ignored diff --git a/tmp/README.md b/tmp/README.md index 1a6036861..043223f12 100644 --- a/tmp/README.md +++ b/tmp/README.md @@ -580,6 +580,25 @@ entries where the "created_by" (5th) field is non-null. See This file is formed by the [fix_csv.sh](fix_csv.sh) tool. +### [sample_getopt.sh](sample_getopt.sh) + +This is a demo of the 3 phase parse of command line options and +arguments for that a markdown to HTML tool that uses the `inc/md2html.cfg` +configuration file. + +Try: + +```sh +./sample_getopt.sh -v 3 foo +``` + +This tool performs a somewhat complicated 3 phase getopt parse of +simulated command line options and arguments that a tool converting +markdown to HTML and using the `inc/md2html.cfg` configuration file +would perform. The tool does not actually use the `inc/md2html.cfg`, +it just simulates the complex 3 phase getopt parsing procedure. + + ### [sql/winners.sql](sql/winners.sql) This is a SQL file, extracted from another SQL file that was used in the past @@ -613,6 +632,7 @@ Examples: An HTML template for what goes into the top of constructed HTML pages. + Constructed HTML pages will be as follows: 0. [template-top.html](template-top.html) diff --git a/tmp/sample_getopt.sh b/tmp/sample_getopt.sh new file mode 100755 index 000000000..bc94d782d --- /dev/null +++ b/tmp/sample_getopt.sh @@ -0,0 +1,647 @@ +#!/usr/bin/env bash +# +# sample_getopt.sh - sample command line option parsing +# +# Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved. +# +# Permission to use, copy, modify, and distribute this software and +# its documentation for any purpose and without fee is hereby granted, +# provided that the above copyright, this permission notice and text +# this comment, and the disclaimer below appear in all of the following: +# +# supporting documentation +# source copies +# source works derived from this source +# binaries derived from this source or from derived source +# +# LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO +# EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. +# +# chongo (Landon Curt Noll, http://www.isthe.com/chongo/index.html) /\oo/\ +# +# Share and enjoy! :-) + +# firewall - bash must be version 4,2 or later +# +# We must declare arrays with -ag or -Ag +# +if [[ ${BASH_VERSINFO[0]} -lt 4 || ${BASH_VERSINFO[0]} -eq 4 && ${BASH_VERSINFO[1]} -lt 2 ]]; then + echo "$0: ERROR: bash version must be >= 4.2: $BASH_VERSION" 1>&2 + exit 4 +fi + +# set usage message +# +export USAGE="usage: $0 [-h] [-v level] [-V] [-n] [-N] + [-d topdir] [-c md2html.cfg] [-H phase=name ..] + [-b tool] [-B optstr] [-p tool] [-P optstr] [-a tool] [-A optstr] + [-s token=value ..] [-S] [-o tool ..] [-O tool=optstr ..] + [-e string ..] [-E exitcode] filename_arg + + -h print help message and exit + -v level set verbosity level (def level: 0) + -V print version string and exit + + -n go thru the actions, but do not update any files (def: do the action) + -N do not process file, just ignore the file (def: process the file) + + -d topdir set topdir (def: if 'git rev-parse --is-inside-work-tree' is true, then + topdir is output of 'git rev-parse --show-toplevel') + NOTE: -d may only be used in command_options (getopt phase 0) + + -c md2html.cfg Use md2html.cfg as the configuration file (def: use topdir/inc/md2html.cfg) + NOTE: -c may only be used in command_options (getopt phase 0) + + -H phase=name use 'phase.name.html' file for HTML phase named 'phase' (def: use 'phase.default.html') + -H phase=. ignore processing for HTML phase 'phase' (def: process HTML phase) + NOTE: The 'phase' string may not contain = (equal), nor / (slash). + NOTE: The 'phase.name.html' file is assumed under the 'topdir/inc' directory. + + -b tool run 'before tool' during HTML phase number 20 (def: do not output before pandoc tool) + -b . skip HTML phase number 20 (def: do nothing during HTML phase number 20) + -B optstr run 'before tool' with options found in 'optstr' (def: do not add any options to 'before tool') + + -p tool run 'pandoc tool' wrapper (not path to pandoc) during HTML phase number 21 (def: use inc/pandoc.sh) + -p . skip HTML phase number 21 (def: do nothing during HTML phase number 21) + -P optstr run 'pandoc tool' with options found in 'optstr' (def: use only the 'pandoc tool' default options) + + -a tool run 'after tool' during HTML phase number 20 (def: do not output after pandoc tool) + -a . skip HTML phase number 22 (def: do nothing during HTML phase number 22) + -A optstr run 'after tool' with options found in 'optstr' (def: do not add any options to 'after tool') + + -s token=value substitute %%token%% with value except in HTML phase numbers 20-29 (def: do not substitute) + NOTE: The 'token' string may not contain ; (semicolon), nor = (equal), nor % (percent). + NOTE: The 'value' string may not contain ; (semicolon). + -S failure to replace a %%token%% is not an error (def: exit non-zero for non-substituted tokens) + + -o tool Use output tool, 'tool', to generate option lines (def: do not) + -o . disable use of 'output tool' (def: do not use an 'output tool') + NOTE: -o may only be used in command_options and cfg_options (getopt phases 0 and 1) + -O tool=optstr run the 'token replace' named 'tool' with options found in 'optstr' (def: do not add any options) + NOTE: The 'tool' string may not contain = (equal), nor double-quote, nor single-quote. + NOTE: -O may only be used in command_options and cfg_options (getopt phases 0 and 1) + + -e string output string, followed by newline, to stderr (def: do not) + -E exitcode force exit with exitcode (def: exit based on success or failure of the action) + + filename_arg + +Exit codes: + 0 all OK + 2 -h and help string printed or -V and version string printed + 3 command line error + 4 bash version is < 4.2 + >= 10 < 200 internal error + >= 200 tool error + +$NAME version: $VERSION" + +################################## +# command line parsing functions # +################################## + +# setup global variables +# +# Call this once at the start of the shell script. +# +function global_variable_setup +{ + local n # loop index + + # setup + # + export VERSION="0.1 2023-12-10" + NAME=$(basename "$0") + export NAME + # + export V_FLAG=0 + export NOOP=0 + export DO_NOT_PROCESS=0 + export TOPDIR + export REPO_URL="https://github.com/ioccc-src/temp-test-ioccc" + export REPO_NAME="temp-test-ioccc" + export MD2HTML_CFG + export BEFORE_TOOL + export BEFORE_TOOL_OPTSTR + export PANDOC_WRAPPER + export PANDOC_WRAPPER_OPTSTR + export AFTER_TOOL + export AFTER_TOOL_OPTSTR + unset TOKEN + declare -Ag TOKEN + export CAP_S_FLAG + unset OUTPUT_TOOL + declare -ag OUTPUT_TOOL + unset OUTPUT_TOOL_OPTSTR + declare -Ag OUTPUT_TOOL_OPTSTR + + # determine path to topdir if we are in a git repo + # + GIT_TOOL=$(type -P git) + export GIT_TOOL + if [[ -z "$GIT_TOOL" ]]; then + echo "$0: FATAL: git tool is not installed or not in PATH" 1>&2 + exit 11 + fi + "$GIT_TOOL" rev-parse --is-inside-work-tree >/dev/null 2>&1 + status="$?" + if [[ $status -eq 0 ]]; then + TOPDIR=$("$GIT_TOOL" rev-parse --show-toplevel) + fi + + # setup phase names in phase array + # + unset PHASE_NAME + declare -ag PHASE_NAME + PHASE_NAME=(top head body header topnav begin-row begin-leftcolumn sidenav end-leftcolumn + end-leftcolumn begin-rightcolumn before-content before-content after-content + end-row footer bottom) + unset HTML_PHASE_NAME + declare -Ag HTML_PHASE_NAME + for n in "${PHASE_NAME[@]}"; do + HTML_PHASE_NAME[$n]="default" + done + + # initialize command line parse pass number + # + export GETOPT_PHASE=0 +} + +# print the usage message, exit code and version information +# +# Call this to print the usage message, by default to stdout. +# However one might usually want to do: +# +# print_usage 1>&2 +# +function print_usage +{ + # print usage message + # + echo "$USAGE" +} + +# parse command line arguments +# +# You MUST call this function at least once AND after calling global_variable_setup. +# You may call this function again, after setting a new command line args. For example: +# +# global_variable_setup # must be first +# parse_command_line # parse the command line given to the shell script +# +# # collect and parse command line arguments +# ARG="$1" # for example, grab only the first command line argument +# +# # do whatever you need to do in terms of validating the resulting effect on +# # global variables and validating command like options +# +# # perform the actions as needed +# +# # set new command like options and parse them +# set -- -s token0=value0 -o inc/foo.sh -O inc/foo.sh="-v 3" -s token1=vaulue1 +# parse_command_line +# +# # do whatever you need to do in terms of validating the resulting effect on +# # global variables and validating command like options +# +# # perform the actions as needed +# +# # set new command like options and parse them +# set -- -s token2=value2 -o inc/bar.sh -O inc/bar.sh="-v 1" -s token4=vaulue4 +# parse_command_line +# +# # do whatever you need to do in terms of validating the resulting effect on +# # global variables and validating command like options +# +# # perform the actions as needed +# +function parse_command_line +{ + local flag # getopts found flag + local NAME_VALUE # name=value string + local NAME # name from name=value + local VALUE # value from name=value + + # setup that will effectively clear any previous getopts state + # + unset OPTIND + + # parse command line + # + while getopts :hv:VnNd:c:H:b:B:p:P:a:A:s:So:O:e:E: flag; do + case "$flag" in + h) print_usage 1>&2 + exit 2 + ;; + v) V_FLAG="$OPTARG" + ;; + V) echo "$VERSION" + exit 2 + ;; + n) NOOP="true" + ;; + N) DO_NOT_PROCESS="true" + ;; + d) # -d only in getopt phase 0 + if [[ $GETOPT_PHASE -gt 0 ]]; then + echo "$0: ERROR: -d may only be used during getopt phase 0, current getopt phase: $GETOPT_PHASE" 1>&2 + echo 1>&2 + print_usage 1>&2 + exit 3 + fi + # + TOPDIR="$OPTARG" + ;; + c) # -c only in getopt phase 0 + if [[ $GETOPT_PHASE -gt 0 ]]; then + echo "$0: ERROR: -c may only be used during getopt phase 0, current getopt phase: $GETOPT_PHASE" 1>&2 + echo 1>&2 + print_usage 1>&2 + exit 3 + fi + # + MD2HTML_CFG="$OPTARG" + ;; + H) # parse: -H phase=name + NAME_VALUE="$OPTARG" + case "$NAME_VALUE" in + *=*) # parse name=value + NAME=${NAME_VALUE%%=*} + VALUE=${NAME_VALUE#*=} + ;; + *) echo "$0: ERROR: -H option not in phase=name form" 1>&2 + echo 1>&2 + print_usage 1>&2 + exit 3 + ;; + esac + # name cannot contain a = + if [[ $NAME == *'='* ]]; then + echo "$0: ERROR: -H name=value, name cannot contain a = character: $NAME_VALUE" 1>&2 + echo 1>&2 + print_usage 1>&2 + exit 3 + fi + # name cannot contain a / + if [[ $NAME == *'/'* ]]; then + echo "$0: ERROR: -H name=value, name cannot contain a / character: $NAME_VALUE" 1>&2 + echo 1>&2 + print_usage 1>&2 + exit 3 + fi + # name must be a known phase name + if [[ -z ${HTML_PHASE_NAME[$NAME]} ]]; then + echo "$0: ERROR: -H name=value, name is unknown" 1>&2 + for n in "${PHASE_NAME[@]}"; do + echo "$0: notice: valid name: $n" + done 1>&2 + echo 1>&2 + print_usage 1>&2 + exit 3 + fi + # treat VALUE of . as an HTML PHASE name unset + # + if [[ $VALUE == . ]]; then + # unset phase name + HTML_PHASE_NAME[$NAME]= + else + # change phase name + HTML_PHASE_NAME[$NAME]="$VALUE" + fi + ;; + b) # parse: -p tool + if [[ $OPTARG == . ]]; then + # unset before tool + BEFORE_TOOL= + else + # change before tool + BEFORE_TOOL="$OPTARG" + fi + ;; + B) BEFORE_TOOL_OPTSTR="$OPTARG" + ;; + p) # parse -p tool + if [[ $OPTARG == . ]]; then + # unset pandoc wrapper tool + PANDOC_WRAPPER= + else + # change pandoc wrapper tool + PANDOC_WRAPPER="$OPTARG" + fi + ;; + P) BEFORE_TOOL_OPTSTR="$OPTARG" + ;; + a) # parse: -a tool + if [[ $OPTARG == . ]]; then + # unset after tool + AFTER_TOOL= + else + # change after tool + AFTER_TOOL="$OPTARG" + fi + ;; + A) AFTER_TOOL_OPTSTR="$OPTARG" + ;; + s) # parse: -s token=value + NAME_VALUE="$OPTARG" + case "$NAME_VALUE" in + *=*) # parse name=value + NAME=${NAME_VALUE%%=*} + VALUE=${NAME_VALUE#*=} + ;; + *) echo "$0: ERROR: -H option not in phase=name form" 1>&2 + echo 1>&2 + print_usage 1>&2 + exit 3 + ;; + esac + # token cannot contain a ; + if [[ $NAME == *';'* ]]; then + echo "$0: ERROR: -H name=value, token cannot contain a ; character: $NAME_VALUE" 1>&2 + echo 1>&2 + print_usage 1>&2 + exit 3 + fi + # token cannot contain a = + if [[ $NAME == *'='* ]]; then + echo "$0: ERROR: -H name=value, token cannot contain a = character: $NAME_VALUE" 1>&2 + echo 1>&2 + print_usage 1>&2 + exit 3 + fi + # token cannot contain a % + if [[ $NAME == *'%'* ]]; then + echo "$0: ERROR: -H name=value, token cannot contain a % character: $NAME_VALUE" 1>&2 + echo 1>&2 + print_usage 1>&2 + exit 3 + fi + # value cannot contain a ; + if [[ $VALUE == *';'* ]]; then + echo "$0: ERROR: -H name=value, value cannot contain a ; character: $NAME_VALUE" 1>&2 + echo 1>&2 + print_usage 1>&2 + exit 3 + fi + # set %%token%% value + TOKEN[$NAME]="$VALUE" + ;; + S) CAP_S_FLAG="true" + ;; + o) # -o only in getopt phase 0 and 1 + if [[ $GETOPT_PHASE -gt 1 ]]; then + echo "$0: ERROR: -o may only be used during getopt phase 0 and 1, current getopt phase: $GETOPT_PHASE" 1>&2 + echo 1>&2 + print_usage 1>&2 + exit 3 + fi + # + OUTPUT_TOOL+=("$OPTARG") + ;; + O) # -O only in getopt phase 0 and 1 + if [[ $GETOPT_PHASE -gt 1 ]]; then + echo "$0: ERROR: -o may only be used during getopt phase 0 and 1, current getopt phase: $GETOPT_PHASE" 1>&2 + echo 1>&2 + print_usage 1>&2 + exit 3 + fi + # + # parse: -O tool=optstr + NAME_VALUE="$OPTARG" + case "$NAME_VALUE" in + *=*) # parse name=value + NAME=${NAME_VALUE%%=*} + VALUE=${NAME_VALUE#*=} + ;; + *) echo "$0: ERROR: -H option not in phase=name form" 1>&2 + echo 1>&2 + print_usage 1>&2 + exit 3 + ;; + esac + # token cannot contain a = + if [[ $NAME == *'='* ]]; then + echo "$0: ERROR: -H name=value, token cannot contain a = character: $NAME_VALUE" 1>&2 + echo 1>&2 + print_usage 1>&2 + exit 3 + fi + # token cannot contain a double-quote + if [[ $NAME == *'"'* ]]; then + echo "$0: ERROR: -H name=value, token cannot contain a double-quote character: $NAME_VALUE" 1>&2 + echo 1>&2 + print_usage 1>&2 + exit 3 + fi + # token cannot contain a single-quote + if [[ $NAME == *'"'* ]]; then + echo "$0: ERROR: -H name=value, token cannot contain a single-quote character: $NAME_VALUE" 1>&2 + echo 1>&2 + print_usage 1>&2 + exit 3 + fi + # set tool optstr value + OUTPUT_TOOL_OPTSTR[$NAME]="$VALUE" + ;; + e) echo "$OPTARG" 1>&2 + ;; + E) exit "$OPTARG" + ;; + \?) echo "$0: ERROR: invalid option: -$OPTARG" 1>&2 + echo 1>&2 + print_usage 1>&2 + exit 3 + ;; + :) echo "$0: ERROR: option -$OPTARG requires an argument" 1>&2 + echo 1>&2 + print_usage 1>&2 + exit 3 + ;; + *) echo "$0: ERROR: unexpected value from getopts: $flag" 1>&2 + echo 1>&2 + print_usage 1>&2 + exit 3 + ;; + esac + done + + # increment command line parse pass number + # + ((++GETOPT_PHASE)) +} + +# required initial variable setup +# +global_variable_setup + +################## +# getopt phase 0 # +################## + +# process command line arguments +# +parse_command_line "$@" + +# parse the command line arguments +# +if [[ $V_FLAG -ge 1 ]]; then + echo "$0: debug[1]: debug level: $V_FLAG" 1>&2 + echo "$0: debug[1]: after 1st call to parse_command_line, OPTIND: $OPTIND" 1>&2 +fi +# +shift $(( OPTIND - 1 )); +# +if [[ $V_FLAG -ge 1 ]]; then + echo "$0: debug[1]: 1st parse_command_line call file argument count: $#" 1>&2 +fi +if [[ $# -ne 1 ]]; then + echo "$0: ERROR: 1st parse_command_line call expected 1 arg, found: $#" 1>&2 + print_usage 1>&2 + exit 3 +fi +# +export FILE="$1" +if [[ $V_FLAG -ge 1 ]]; then + echo "$0: debug[1]: FILE=$FILE" 1>&2 +fi + +# verify that we have a topdir directory +# +if [[ -z $TOPDIR ]]; then + echo "$0: ERROR: cannot find top of git repo directory" 1>&2 + echo "$0: Notice: if needed: $GIT_TOOL clone $REPO_URL; cd $REPO_NAME" 1>&2 + exit 12 +fi +if [[ ! -d $TOPDIR ]]; then + echo "$0: ERROR: TOPDIR is not a directory: $TOPDIR" 1>&2 + echo "$0: Notice: if needed: $GIT_TOOL clone $REPO_URL; cd $REPO_NAME" 1>&2 + exit 13 +fi + +# verify that we have in inc directory +# +export INC="$TOPDIR/inc" +if [[ ! -d $TOPDIR/inc ]]; then + echo "$0: ERROR: inc is not a directory under TOPDIR/inc: $TOPDIR/inc" 1>&2 + exit 14 +fi + +# verify we have a readable md2html.cfg file +# +if [[ -z $MD2HTML_CFG ]]; then + MD2HTML_CFG="$INC/md2html.cfg" +fi +if [[ ! -e $MD2HTML_CFG ]]; then + echo "$0: ERROR: md2html.cfg does not exist: $MD2HTML_CFG" 1>&2 + exit 15 +fi +if [[ ! -f $MD2HTML_CFG ]]; then + echo "$0: ERROR: md2html.cfg is not a file: $MD2HTML_CFG" 1>&2 + exit 16 +fi +if [[ ! -r $MD2HTML_CFG ]]; then + echo "$0: ERROR: md2html.cfg is not a readable file: $MD2HTML_CFG" 1>&2 + exit 17 +fi + +# cd to topdir +# +if [[ ! -e $TOPDIR ]]; then + echo "$0: ERROR: cannot cd to non-existent path: $TOPDIR" 1>&2 + exit 18 +fi +if [[ ! -d $TOPDIR ]]; then + echo "$0: ERROR: cannot cd to a non-directory: $TOPDIR" 1>&2 + exit 19 +fi +export CD_FAILED +cd "$TOPDIR" || CD_FAILED="true" +if [[ -n $CD_FAILED ]]; then + echo "$0: ERROR: cd $TOPDIR failed" 1>&2 + exit 20 +fi + +################## +# getopt phase 1 # +################## + +# pretend that $FILE matches a line in md2html.cfg and that this is was the rest of the configuration line +# +set -- -s token0=value0 -o inc/foo.sh -O inc/foo.sh="-v 3" -s token1=vaulue1 + +# parse the command line arguments +# +parse_command_line "$@" + +# parse the command line arguments +# +if [[ $V_FLAG -ge 1 ]]; then + echo "$0: debug[1]: after 2nd call to parse_command_line, OPTIND: $OPTIND" 1>&2 +fi +# +shift $(( OPTIND - 1 )); +# +if [[ $V_FLAG -ge 1 ]]; then + echo "$0: debug[1]: 2nd parse_command_line call file argument count: $#" 1>&2 +fi +if [[ $# -ne 0 ]]; then + echo "$0: ERROR: 2nd parse_command_line call expected 0 arg, found: $#" 1>&2 + print_usage 1>&2 + exit 3 +fi + +################## +# getopt phase 2 # +################## + +# pretend that the tool: +# +# inc/foo.sh -v 3 +# +# has produced these additional command line options +# +set -- -s token2=value2 -s token3=value3 + +# parse the new options on the command line +# +parse_command_line "$@" + +# parse the command line arguments +# +if [[ $V_FLAG -ge 1 ]]; then + echo "$0: debug[1]: after 3rd call to parse_command_line, OPTIND: $OPTIND" 1>&2 +fi +# +shift $(( OPTIND - 1 )); +# +if [[ $V_FLAG -ge 1 ]]; then + echo "$0: debug[1]: 3rd parse_command_line call file argument count: $#" 1>&2 +fi +if [[ $# -ne 0 ]]; then + echo "$0: ERROR: 3rd parse_command_line call expected 0 arg, found: $#" 1>&2 + print_usage 1>&2 + exit 3 +fi + +# report TOKEN sed patterns +# +if [[ $V_FLAG -ge 3 ]]; then + for n in "${!TOKEN[@]}"; do + VALUE="${TOKEN[$n]}" + echo "$0: debug[3]: token replacement: sed -e s;%%$n%%;$VALUE;g" 1>&2 + done +fi + +# report output tool and output tool arguments +# +if [[ $V_FLAG -ge 3 ]]; then + for n in "${!OUTPUT_TOOL[@]}"; do + VALUE="${OUTPUT_TOOL[$n]}" + echo "$0: debug[3]: output tool: $VALUE args: ${OUTPUT_TOOL_OPTSTR[$VALUE]}" 1>&2 + done +fi