summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/scripts/checklistings
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2015-09-05 22:16:03 +0000
committerKarl Berry <karl@freefriends.org>2015-09-05 22:16:03 +0000
commit458ae81ef20dbea77877876c44a0de359afd55de (patch)
tree9a307a71a169b831bd2dff1f1408638a86218e8a /Master/texmf-dist/scripts/checklistings
parent412a3bd77bd76014472d93aa65ce8d7b75809ebb (diff)
checklistings (3sep15)
git-svn-id: svn://tug.org/texlive/trunk@38300 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/scripts/checklistings')
-rwxr-xr-xMaster/texmf-dist/scripts/checklistings/checklistings.sh446
1 files changed, 446 insertions, 0 deletions
diff --git a/Master/texmf-dist/scripts/checklistings/checklistings.sh b/Master/texmf-dist/scripts/checklistings/checklistings.sh
new file mode 100755
index 00000000000..4131d9acbc4
--- /dev/null
+++ b/Master/texmf-dist/scripts/checklistings/checklistings.sh
@@ -0,0 +1,446 @@
+#!/bin/sh
+#
+# checklistings #
+# version 1.0 #
+# #
+# Timothy Bourke <tim@tbrk.org> #
+# Inria #
+# École normale supérieure #
+# #
+# Marc Pouzet <pouzet@ens.fr> #
+# Université Pierre et Marie Curie #
+# École normale supérieure #
+# Inria #
+#
+
+##
+# Configuration
+SCRIPT=$(basename "$0")
+SUFFIX=.chkl
+
+RED=""
+BLUE=""
+BLACK=""
+
+ADJUSTLINETEXT=line
+
+##
+# Command-line
+
+usage () {
+ printf '%s: check source code exported from LaTeX documents.\n' "$SCRIPT"
+ printf 'usage: %s [options] [file ...]\n' "$SCRIPT"
+ printf '\n'
+ printf ' options:\n'
+ printf ' --no-colors log to terminal without control codes\n'
+ printf ' --no-line-adjust do not try to adjust error line numbers\n'
+ printf '\n'
+}
+
+unset INFILES
+while [ -n "$1" ]; do
+ case "$1" in
+ --no-colors)
+ unset RED BLUE BLACK
+ ;;
+ --no-line-adjust)
+ unset ADJUSTLINETEXT
+ ;;
+ --h)
+ usage
+ exit 0
+ ;;
+ --help)
+ usage
+ exit 0
+ ;;
+ -*)
+ printf "%s: unrecognized option '%s'\n" "$SCRIPT" "$1"
+ usage
+ exit 1
+ ;;
+ *${SUFFIX})
+ INFILES="$INFILES $1"
+ ;;
+ *)
+ INFILES="$INFILES $1${SUFFIX}"
+ ;;
+ esac
+ shift
+done
+
+if [ -z "$INFILES" ]; then
+ INFILES=$(ls ./*${SUFFIX})
+fi
+
+##
+# Allocate temporary files
+
+cleanup() {
+ rm -f "${OUTFILE}" "${ERRFILE}"
+}
+OUTFILE=$(mktemp -t "${SCRIPT}.out.XXXXXX") || exit 1
+ERRFILE=$(mktemp -t "${SCRIPT}.err.XXXXXX") || (cleanup; exit 1)
+trap cleanup 1 2 15
+
+##
+# Code
+
+#
+# Given
+# var a variable to store the result
+# name the filename prefix
+# num an id number
+# generate a filename from name and num and store it in var.
+#
+setfilename() {
+ var="$1"
+ name="$2"
+ num="$3"
+ if [ "$num" -lt 10 ]; then
+ eval "$var='${name}000${num}'"
+ elif [ "$num" -lt 100 ]; then
+ eval "$var='${name}00${num}'"
+ elif [ "$num" -lt 1000 ]; then
+ eval "$var='${name}0${num}'"
+ else
+ eval "$var='${name}${num}'"
+ fi
+}
+
+#
+# If the WITHOPEN option is set, create a modified program text (with a
+# different name) whose first lines import dependencies.
+# Args:
+# filename the id of the program text
+# openfilenums its dependencies (id list)
+#
+addopen() {
+ filename="$1"
+ openfilenums="$2"
+ unset of f
+
+ if [ -n "$WITHOPEN" ]; then
+ setfilename f "$PREFIX" "$filename"
+ if [ -f "$SUBDIR$f$EXT" ]; then
+
+ openfiles=""
+ for n in $openfilenums; do
+ setfilename of "$WITHOPEN" "$n"
+ # shellcheck disable=SC2154
+ openfiles="$openfiles ${INCLUDECMD} $of"
+ done
+
+ setfilename of "$WITHOPEN" "$filename"
+ if [ -n "$openfiles" ]; then
+ addedlines=$((addedlines + 1))
+ printf '%s \n' "$openfiles" > "$SUBDIR$of$EXT"
+ cat "$SUBDIR$f$EXT" >> "$SUBDIR$of$EXT"
+ else
+ cat "$SUBDIR$f$EXT" > "$SUBDIR$of$EXT"
+ fi
+ fi
+ fi
+}
+
+# A filename string for sed that ignores the case (BSD sed has no i flag)
+makeicfilename() {
+ IFILENAME=""
+ for l in $(printf "%s" "$FILENAME" | sed -e 's/\(.\)/\1 /g'); do
+ L="$(printf "%s" "$l" | tr "[:lower:]" "[:upper:]")"
+ IFILENAME="${IFILENAME}[$L$l]"
+ done
+}
+
+#
+# Given
+# $ERRFILE path to the file containing error messages
+# $ADJUSTLINETEXT the text preceding the line number (default: "line")
+# if empty or unset, no adjustments are made.
+# $addedlines the amount by which to decrement line numbers
+#
+adjustlinenumbers() {
+ if [ -n "$ADJUSTLINETEXT" ]; then
+ printf '' > "$ERRFILE-adjusted"
+ while read line
+ do
+ linen=$(expr "$line" : ".*$ADJUSTLINETEXT *\([0-9][0-9]*\).*")
+ if [ -n "$linen" ]; then
+ before=$(expr "$line" : "^\(.*$ADJUSTLINETEXT *\)$linen.*$")
+ after=$(expr "$line" : "^.*$ADJUSTLINETEXT *$linen\(.*\)$")
+ newlinen=$((linen - addedlines))
+ printf "%s%s%s\n" "$before" "$newlinen" "$after" \
+ >> "$ERRFILE-adjusted"
+ else
+ printf "%s\n" "$line" >> "$ERRFILE-adjusted"
+ fi
+ done < "$ERRFILE"
+ mv "$ERRFILE-adjusted" "$ERRFILE"
+ fi
+}
+
+#
+# Given
+# num a program (id)
+# openfilenums its dependencies (id list)
+# (Try to) Compile the program and create a corresponding .tex file that
+# summarizes the results for reading back into the source document.
+#
+compile() {
+ num="$1"
+ openfilenums="$2"
+ unset ifile ofile outf of FILENAME
+
+ # Decide whether to use the original program source or the version
+ # augmented to import dependencies.
+ if [ -n "$WITHOPEN" ]; then
+ FILENAME=${WITHOPEN}
+ else
+ FILENAME=${PREFIX}
+ fi
+ makeicfilename
+
+ # Generate the program (ifile) and output (ofile) filenames
+ setfilename ifile "$FILENAME" "$num"
+ # shellcheck disable=SC2154
+ ipath="$SUBDIR$ifile$EXT"
+ setfilename ofile "$PREFIX" "$num"
+ # shellcheck disable=SC2154
+ opath="$SUBDIR$ofile.tex"
+ opath_msg="$SUBDIR$ofile.msg"
+ opath_err="$SUBDIR$ofile.err"
+ opath_html="$SUBDIR$ofile.html"
+
+ # Check that the input file exists
+ if [ -f "$ipath" ]; then
+ printf '> %s%s...%s\n' "$BLUE" "$ofile$EXT" "$BLACK"
+ else
+ printf '%s> %s%s: program source not found.%s\n' \
+ "$RED" "$ofile" "$EXT" "$BLACK"
+ return 1
+ fi
+
+ # Generate a list of dependency filenames to pass to the compiler
+ openfiles=""
+ for n in $openfilenums; do
+ setfilename of "$FILENAME" "$n"
+ openfiles="$openfiles $SUBDIR$of$EXT"
+ done
+
+ # Invoke the compiler
+ # shellcheck disable=SC2086
+ $COMPILER $COMPILERFLAGS $openfiles $LASTFLAGS "$ipath" \
+ >"$OUTFILE" 2>"$ERRFILE"
+ COMPILERSTATUS=$?
+ adjustlinenumbers
+
+ # Start the output tex file with the compilation command as a comment
+ printf '%% %s\n' "$COMPILER $COMPILERFLAGS $openfiles \
+ $LASTFLAGS $ipath ($COMPILERSTATUS)" > "$opath"
+
+ # Signal compilation success (\chklistingtrue) or not (\chklistingfalse)
+ if [ "$COMPILERSTATUS" -eq 0 ]; then
+ printf '\\chklistingtrue\n' >> "$opath"
+ if [ "$SHOULDFAIL" -eq 1 ]; then
+ printf '%s unexpected success (line %s/ page %s)!%s\n' \
+ "$RED" "$LINENUM" "$PAGENUM" "$BLACK" >&2
+ fi
+ else
+ printf '\\chklistingfalse\n' >> "$opath"
+ if [ "$SHOULDFAIL" -eq 0 ]; then
+ printf "%s unexpected failure (line %s / page %s)!%s\n" \
+ "$RED" "$LINENUM" "$PAGENUM" "$BLACK" >&2
+ while read line
+ do
+ printf " | %s\n" "$line"
+ done < "$ERRFILE" >&2
+ fi
+ fi
+
+ # Include a sanitized compilation command (\setchklistingcmd)
+ printf '\setchklistingcmd{%s %s \\chklistingfile}\n' \
+ "${COMPILERNAME}" "${LASTFLAGS}" >> "$opath"
+
+ # Include the compiler's stdout
+ printf "%s\n" '\begin{ChkListingMsg}' >> "$opath"
+ if [ "$(wc -l < "$OUTFILE")" -eq 0 ]; then
+ printf "Failed.\n" >> "$opath"
+ else
+ sed -e "s#$SUBDIR$ifile#$PREFIX#g" \
+ -e "s#$IFILENAME[0-9][0-9][0-9][0-9]\.##g" \
+ "$OUTFILE" > "$opath_msg"
+ cat "$opath_msg" >> "$opath"
+ fi
+ printf "%s\n" '\end{ChkListingMsg}' >> "$opath"
+
+ # Include the compiler's stderr
+ printf "%s\n" '\begin{ChkListingErr}' >> "$opath"
+ if [ "$(wc -l < "$ERRFILE")" -eq 0 ]; then
+ printf "%s\n" "Success." >> "$opath"
+ else
+ sed -e "s#$SUBDIR$ifile#$PREFIX#g" \
+ -e "s#$IFILENAME[0-9][0-9][0-9][0-9]\.##g" \
+ "$ERRFILE" > "$opath_err"
+ cat "$opath_err" >> "$opath"
+ fi
+ printf "%s\n" '\end{ChkListingErr}' >> "$opath"
+
+ # Filter to html if necessary
+ if [ -n "$HTMLFILTER" ]; then
+ # shellcheck disable=SC2086
+ if [ "$HTMLFILTER" = "cat" ]; then
+ printf '<pre>\n' > "$opath_html"
+ $HTMLFILTER "$ipath" >> "$opath_html"
+ printf '</pre>\n' >> "$opath_html"
+ else
+ $HTMLFILTER "$ipath" > "$opath_html"
+ fi
+ fi
+
+ return 0
+}
+
+locked=
+dooption() {
+ opt_name="$1"
+ opt_value="$2"
+
+ case "$opt_name" in
+ lock\ *)
+ opt_name=${opt_name#lock }
+ locked="$locked $opt_name "
+ ;;
+ *)
+ if [ "$(expr "$locked" : ".* $opt_name .*")" -ne 0 ]; then
+ printf \
+ 'info: %s: ignoring locked option ''%s''\n' \
+ "$infile" "$opt_name" >&2
+ return
+ fi
+ ;;
+ esac
+
+ case "$opt_name" in
+ subdir)
+ SUBDIR="$opt_value" ;;
+ prefix)
+ PREFIX="$opt_value" ;;
+ ext)
+ EXT="$opt_value" ;;
+ compiler)
+ COMPILER="${opt_value}"
+ COMPILERNAME="$(basename "${COMPILER}")"
+ ;;
+ compilerflags)
+ COMPILERFLAGS="${opt_value}" ;;
+ lastflags)
+ LASTFLAGS="${opt_value}" ;;
+ includecmd)
+ INCLUDECMD="${opt_value}"
+ if [ -z "$INCLUDECMD" ]; then
+ WITHOPEN=
+ else
+ WITHOPEN=Withopen
+ fi
+ ;;
+ htmlfilter)
+ HTMLFILTER="${opt_value}" ;;
+ esac
+}
+
+subdirs=
+readchkl() {
+ infile=$1
+ unset l existing openfilenums filenum opennums
+
+ # Process each line of the command file
+ while read l; do
+ addedlines=0
+ case $l in
+ [[:digit:]]*:*)
+ # a snippet to be compiled
+ filenum=$(expr "$l" : '\(.*\):.*')
+ openfilenums=$(expr "$l" : '.*:\(.*\)')
+
+ # build up a list of dependencies in opennums
+ opennums=""
+ for n in $openfilenums; do
+ case $n in
+ \[page=*)
+ PAGENUM=$(expr "$n" : '\[page=\(.*\)\]')
+ if [ "$PAGENUM" = "" ]; then
+ PAGENUM="unknown"
+ fi
+ ;;
+ \])
+ # ignore invalid patterns when checklistings.sty
+ # cannot expand \thepage properly (due to a
+ # conflicting package setting) and instead produces
+ # '[page=\thepage ]' which is read as two tokens:
+ # '[page=\thepage' and ']'.
+ ;;
+ \[line=*\])
+ LINENUM=$(expr "$n" : '\[line=\(.*\)\]')
+ ;;
+ \[fail\])
+ SHOULDFAIL=1
+ ;;
+ \[skip=*\])
+ addedlines=$(expr "$n" : '\[skip=\([0-9][0-9]*\)\]')
+ ;;
+ *)
+ if [ "$n" -eq "$n" ] 2>/dev/null; then
+ opennums="$opennums $n"
+ else
+ printf \
+ "%swarning: %s: ignoring unresolved include '%s'%s\n" \
+ "$RED" "$filenum" "$n" "$BLACK" >&2
+ fi
+ ;;
+ esac
+ done
+
+ addopen "$filenum" "$opennums"
+ compile "$filenum" "$opennums"
+ ;;
+
+ *=*)
+ n="$(expr "$l" : '\([^=]*\)=.*')"
+ v="$(expr "$l" : '.*=\(.*\)')"
+ dooption "$n" "$v"
+ if [ "$n" = "subdir" ]; then
+ existing=$(expr "$subdirs" : ".*::${SUBDIR}:\\([^:]*\\):.*")
+ if [ -n "$existing" ]; then
+ printf "%swarning: %s: subdir=%s already used by %s!%s\n" \
+ "$RED" "$infile" "$SUBDIR" "$existing" "$BLACK" >&2
+ fi
+ fi
+ ;;
+
+ *)
+ if [ -n "$l" ]; then
+ printf "%sbad %s: %s%s\n" "$RED" "$infile" "$l" "$BLACK" >&2
+ fi
+ ;;
+ esac
+ unset PAGENUM
+ unset LINENUM
+ SHOULDFAIL=0
+ done < "$1"
+ subdirs="$subdirs::$SUBDIR:$infile:"
+}
+
+# Loop through each checklistings command file
+for f in ${INFILES}; do
+
+ # Add the suffix if necessary (as latex does)
+ case $f in
+ *${SUFFIX}) ;;
+ *) infile="$f$SUFFIX" ;;
+ esac
+
+ readchkl "$f"
+done
+
+cleanup
+