diff --git a/Makefile b/Makefile
index 8941094c1..129a1738e 100644
--- a/Makefile
+++ b/Makefile
@@ -99,7 +99,7 @@ all:
.PHONY: all alt data everything diff_orig_prog diff_prog_orig \
diff_alt_prog diff_prog_alt diff_orig_alt diff_alt_orig \
- clean clobber install genpath new_year love haste waste maker \
+ clean clobber install genpath new_year genpath_top love haste waste maker \
easter_egg sandwich supernova deep_magic magic charon pluto
# alternative executable
@@ -409,9 +409,8 @@ tab_check:
#
genpath:
@echo '=-=-=-=-= IOCCC begin make $@ =-=-=-=-='
- @${RM} -f .tmp.genpath
+ @${MAKE} genpath_top
@-for i in ${YEARS}; do \
- echo "$$i" >> .tmp.genpath; \
if [[ -f $$i/Makefile ]]; then \
echo "cd $$i; make $@"; \
(cd $$i; make $@); \
@@ -419,14 +418,6 @@ genpath:
echo "Warning: $$i/Makefile not found, skipping $$i for $@ processing" 1>&2 ; \
fi; \
done
- ${SORT} -n -u .tmp.genpath -o .tmp.genpath;
- @-if ${CMP} -s .tmp.genpath .top; then \
- ${RM} -f .tmp.genpath; \
- else \
- ${MV} -f .tmp.genpath .top; \
- ${CHMOD} 0444 .top; \
- echo "updated .top"; \
- fi
@echo '=-=-=-=-= IOCCC complete make $@ =-=-=-=-='
# generate YYYY level .filelist
@@ -783,6 +774,24 @@ new_year:
(echo ${YEARS} ${NEW_YEAR}) | ${TR} ' ' '\012' | ${SORT} -n) | \
${FMT} -p | ${SED} -e '2,$$s/^/\t/' -e 's/$$/ \\/' -e '$$s/ \\//'
+# form the top level .top only
+#
+genpath_top:
+ @echo '=-=-=-=-= IOCCC begin make $@ =-=-=-=-='
+ @${RM} -f .tmp.genpath
+ @-for i in ${YEARS}; do \
+ echo "$$i" >> .tmp.genpath; \
+ done
+ ${SORT} -n -u .tmp.genpath -o .tmp.genpath;
+ @-if ${CMP} -s .tmp.genpath .top; then \
+ ${RM} -f .tmp.genpath; \
+ else \
+ ${MV} -f .tmp.genpath .top; \
+ ${CHMOD} 0444 .top; \
+ echo "updated .top"; \
+ fi
+ @echo '=-=-=-=-= IOCCC complete make $@ =-=-=-=-='
+
##################
# 133t hacker rulz
diff --git a/bin/README.md b/bin/README.md
index 4b7223d9c..76afe9b71 100644
--- a/bin/README.md
+++ b/bin/README.md
@@ -82,7 +82,7 @@ need to do so.
This tool is used my the [Judges](../judges.html) as part of the final
steps to announce a new winning IOCCC entry.
-For example:
+Usage:
```
mkdir -p YYYY/dir
@@ -98,13 +98,13 @@ Here, `YYYY/dir` must the path to the winning IOCCC entry.
Run a command on all winning entries.
-For example:
+Usage:
```
bin/all-run.sh -v 3 bin/quick-readme2index.sh -v 1
```
-Or for example:
+Alternate usage:
```
bin/all-run.sh -v 3 bin/readme2index.sh -v 1
@@ -117,13 +117,13 @@ Or for example:
Run a command on all IOCCC years.
-For example:
+Usage:
```
bin/all-years.sh -v 1 bin/gen-year-index.sh -v 1
```
-Or for example:
+Alternate usage:
```
bin/all-years.sh -v 1 bin/chk-entry.sh
@@ -137,7 +137,7 @@ Or for example:
Check an entry directory to verify that both the files in its manifest
(`.entry.json`) exist and that no other files exist.
-For example:
+Usage:
```
bin/chk-entry.sh 2020/ferguson1
@@ -167,7 +167,7 @@ title
This tool updates `.entry.json` files entries whose content is modified.
-For example:
+Usage:
```
bin/csv2entry.sh -v 1
@@ -218,6 +218,28 @@ that the `.entry.json` contains a manifest (or any of the other required JSON
content).
+
+### [cvt-submission.sh](%%REPO_URL%%/bin/cvt-submission.sh)
+
+
+Given a submission (that has won the IOCCC), with a `.auth.json`
+and `.info.json` and NO `.entry.json` file, we convert the
+`.auth.json` and `.info.json` into a new `.entry.json` file.
+
+We will also form, as needed, new `author/author_handle.json`
+files for new authors, and update `author/author_handle.json`
+for authors who won previously.
+
+Usage:
+
+```
+ bin/cvt-submission.sh -v 1 YYYY/dir
+```
+
+Here, `YYYY/dir` is the path of the submission under the `YYYY`
+year directory.
+
+
### [entry2csv.sh](%%REPO_URL%%/bin/entry2csv.sh)
@@ -257,7 +279,7 @@ from the `TOPDIR`.
Generate a list of files in an entry's manifest (the `.entry.json` file).
-For example:
+Usage:
```
awk -f bin/filelist.entry.json.awk 2020/ferguson1/.entry.json
@@ -579,10 +601,9 @@ the [md2html tool](index.html#md2html).
This tool is used my the [Judges](../judges.html) as part of the final
steps to announce a new set of winning IOCCC entries.
-For example:
+Usage:
```
- mkdir -p YYYY
bin/new-year.sh -v 1 YYYY
```
diff --git a/bin/add-dir.sh b/bin/add-dir.sh
index 39ac34f51..999e621fa 100755
--- a/bin/add-dir.sh
+++ b/bin/add-dir.sh
@@ -357,7 +357,7 @@ fi
#
if [[ -z $NOOP ]]; then
- # append entry directory path to .top
+ # append entry directory path to .year
#
if [[ $V_FLAG -ge 3 ]]; then
echo "$0: debug[3]: appending YYYY_DIR: $YYYY_DIR to: $DOT_YEAR" 1>&2
@@ -377,7 +377,7 @@ if [[ -z $NOOP ]]; then
exit 11
fi
- # firewall
+ # firewall - verify YYYY_DIR in .year
#
if grep -E -q "^$YYYY_DIR$" "$DOT_YEAR"; then
if [[ $V_FLAG -ge 1 ]]; then
diff --git a/bin/cvt-submission.sh b/bin/cvt-submission.sh
new file mode 100755
index 000000000..9494d7474
--- /dev/null
+++ b/bin/cvt-submission.sh
@@ -0,0 +1,390 @@
+#!/usr/bin/env bash
+#
+# cvt-submission.sh - convert a submission into an entry
+#
+# Given a submission (that has won the IOCCC), with a `.auth.json`
+# and `.info.json` and NO `.entry.json` file, we convert the
+# `.auth.json` and `.info.json` into a new `.entry.json` file.
+#
+# We will form, as needed, new `author/author_handle.json`
+# files for new authors, and update `author/author_handle.json`
+# for authors who won previously.
+#
+# There are functions that this tool will NOT do:
+#
+# * This tool will not remove `.auth.json`
+# * This tool will not remove `.info.json`
+# * This tool will not remove `remarks.md`
+# * This tool will not verify that Makefile has the required rules
+# * This will will not form `README.md` author notes from `remarks.md`
+# * This will will not add this entry to the year level Makefile
+#
+# Copyright (c) 2024 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 - run only with a bash that is version 5.1.8 or later
+#
+# The "/usr/bin/env bash" command must result in using a bash that
+# is version 5.1.8 or later.
+#
+# We could relax this version and insist on version 4.2 or later. Versions
+# of bash between 4.2 and 5.1.7 might work. However, to be safe, we will require
+# bash version 5.1.8 or later.
+#
+# WHY 5.1.8 and not 4.2? This safely is done because macOS Homebrew bash we
+# often use is "version 5.2.26(1)-release" or later, and the RHEL Linux bash we
+# use often use is "version 5.1.8(1)-release" or later. These versions are what
+# we initially tested. We recommend you either upgrade bash or install a newer
+# version of bash and adjust your $PATH so that "/usr/bin/env bash" finds a bash
+# that is version 5.1.8 or later.
+#
+# NOTE: The macOS shipped, as of 2024 March 15, a version of bash is something like
+# bash "version 3.2.57(1)-release". That macOS shipped version of bash
+# will NOT work. For users of macOS we recommend you install Homebrew,
+# (see https://brew.sh), and then run "brew install bash" which will
+# typically install it into /opt/homebrew/bin/bash, and then arrange your $PATH
+# so that "/usr/bin/env bash" finds "/opt/homebrew/bin" (or whatever the
+# Homebrew bash is).
+#
+# NOTE: And while MacPorts might work, we noticed a number of subtle differences
+# with some of their ported tools to suggest you might be better off
+# with installing Homebrew (see https://brew.sh). No disrespect is intended
+# to the MacPorts team as they do a commendable job. Nevertheless we ran
+# into enough differences with MacPorts environments to suggest you
+# might find a better experience with this tool under Homebrew instead.
+#
+if [[ -z ${BASH_VERSINFO[0]} ||
+ ${BASH_VERSINFO[0]} -lt 5 ||
+ ${BASH_VERSINFO[0]} -eq 5 && ${BASH_VERSINFO[1]} -lt 1 ||
+ ${BASH_VERSINFO[0]} -eq 5 && ${BASH_VERSINFO[1]} -eq 1 && ${BASH_VERSINFO[2]} -lt 8 ]]; then
+ echo "$0: ERROR: bash version needs to be >= 5.1.8: $BASH_VERSION" 1>&2
+ echo "$0: Warning: bash version >= 4.2 might work but 5.1.8 was the minimum we tested" 1>&2
+ echo "$0: Notice: For macOS users: install Homebrew (see https://brew.sh), then run" \
+ ""brew install bash" and then modify your \$PATH so that \"#!/usr/bin/env bash\"" \
+ "finds the Homebrew installed (usually /opt/homebrew/bin/bash) version of bash" 1>&2
+ exit 4
+fi
+
+
+# setup bash file matching
+#
+# We must declare arrays with -ag or -Ag, and we need loops to "export" modified variables.
+# This requires a bash with a version 4.2 or later. See the larger comment above about bash versions.
+#
+shopt -s nullglob # enable expanded to nothing rather than remaining unexpanded
+shopt -u failglob # disable error message if no matches are found
+shopt -u dotglob # disable matching files starting with .
+shopt -u nocaseglob # disable strict case matching
+shopt -u extglob # enable extended globbing patterns
+shopt -s globstar # enable ** to match all files and zero or more directories and subdirectories
+
+
+# set variables referenced in the usage message
+#
+export VERSION="1.0 2024-07-22"
+NAME=$(basename "$0")
+export NAME
+export V_FLAG=0
+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 5
+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
+export TOPDIR
+export REPO_URL="https://github.com/ioccc-src/temp-test-ioccc/blob/master"
+#
+export NOOP=
+export DO_NOT_PROCESS=
+
+
+# usage
+#
+export USAGE="usage: $0 [-h] [-v level] [-V] [-d topdir] [-n] [-N] YYYY/dir
+
+ -h print help message and exit
+ -v level set verbosity level (def level: 0)
+ -V print version string and exit
+
+ -d topdir set topdir (def: $TOPDIR)
+
+ -n go thru the actions, but do not update any files (def: do the action)
+ -N do not process anything, just parse arguments (def: process something)
+
+ YYYY/dir path from topdir to entry directory
+
+Exit codes:
+ 0 all OK
+ 1 invalid year
+ 2 -h and help string printed or -V and version string printed
+ 3 command line error
+ 4 bash version is too old
+ 5 some internal tool is not found or not an executable file
+ 6 problems found with or in the topdir or topdir/YYYY directory
+ >= 10 internal error
+
+$NAME version: $VERSION"
+
+# parse command line
+#
+while getopts :hv:Vd:nN flag; do
+ case "$flag" in
+ h) echo "$USAGE" 1>&2
+ exit 2
+ ;;
+ v) V_FLAG="$OPTARG"
+ ;;
+ V) echo "$VERSION"
+ exit 2
+ ;;
+ d) TOPDIR="$OPTARG"
+ ;;
+ n) NOOP="-n"
+ ;;
+ N) DO_NOT_PROCESS="-N"
+ ;;
+ \?) 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
+ echo "$USAGE" 1>&2
+ exit 3
+ ;;
+ *) echo "$0: ERROR: unexpected value from getopts: $flag" 1>&2
+ echo 1>&2
+ echo "$USAGE" 1>&2
+ exit 3
+ ;;
+ esac
+done
+
+# remove the options
+#
+shift $(( OPTIND - 1 ));
+#
+if [[ $V_FLAG -ge 5 ]]; then
+ echo "$0: debug[5]: file argument count: $#" 1>&2
+fi
+#
+# verify arg count and parse args
+#
+if [[ $# -ne 1 ]]; then
+ echo "$0: ERROR: expected 1 arg, found: $#" 1>&2
+ echo 1>&2
+ echo "$USAGE" 1>&2
+ exit 3
+fi
+export ENTRY_PATH="$1"
+
+
+# verify that we have a topdir directory
+#
+REPO_NAME=$(basename "$REPO_URL")
+export REPO_NAME
+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 6
+fi
+if [[ ! -e $TOPDIR ]]; then
+ echo "$0: ERROR: TOPDIR does not exist: $TOPDIR" 1>&2
+ echo "$0: Notice: if needed: $GIT_TOOL clone $REPO_URL; cd $REPO_NAME" 1>&2
+ exit 6
+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 6
+fi
+
+# cd to topdir
+#
+if [[ ! -e $TOPDIR ]]; then
+ echo "$0: ERROR: cannot cd to non-existent path: $TOPDIR" 1>&2
+ exit 6
+fi
+if [[ ! -d $TOPDIR ]]; then
+ echo "$0: ERROR: cannot cd to a non-directory: $TOPDIR" 1>&2
+ exit 6
+fi
+export CD_FAILED
+if [[ $V_FLAG -ge 5 ]]; then
+ echo "$0: debug[5]: about to: cd $TOPDIR" 1>&2
+fi
+cd "$TOPDIR" || CD_FAILED="true"
+if [[ -n $CD_FAILED ]]; then
+ echo "$0: ERROR: cd $TOPDIR failed" 1>&2
+ exit 6
+fi
+if [[ $V_FLAG -ge 3 ]]; then
+ echo "$0: debug[3]: now in directory: $(/bin/pwd)" 1>&2
+fi
+
+
+# verify we have a non-empty readable .top file
+#
+export TOP_FILE=".top"
+if [[ ! -e $TOP_FILE ]]; then
+ echo "$0: ERROR: .top does not exist: $TOP_FILE" 1>&2
+ exit 6
+fi
+if [[ ! -f $TOP_FILE ]]; then
+ echo "$0: ERROR: .top is not a regular file: $TOP_FILE" 1>&2
+ exit 6
+fi
+if [[ ! -r $TOP_FILE ]]; then
+ echo "$0: ERROR: .top is not an readable file: $TOP_FILE" 1>&2
+ exit 6
+fi
+if [[ ! -s $TOP_FILE ]]; then
+ echo "$0: ERROR: .top is not a non-empty readable file: $TOP_FILE" 1>&2
+ exit 6
+fi
+
+
+# verify that we have an bin subdirectory
+#
+export BIN_PATH="$TOPDIR/bin"
+if [[ ! -d $BIN_PATH ]]; then
+ echo "$0: ERROR: bin is not a directory under topdir: $BIN_PATH" 1>&2
+ exit 6
+fi
+export BIN_DIR="bin"
+
+
+# verify that ENTRY_PATH is a entry directory
+#
+if [[ ! -d $ENTRY_PATH ]]; then
+ echo "$0: ERROR: arg is not a directory: $ENTRY_PATH" 1>&2
+ exit 3
+fi
+if [[ ! -w $ENTRY_PATH ]]; then
+ echo "$0: ERROR: arg is not a writable directory: $ENTRY_PATH" 1>&2
+ exit 3
+fi
+export YEAR_DIR=${ENTRY_PATH%%/*}
+if [[ -z $YEAR_DIR ]]; then
+ echo "$0: ERROR: arg not in YYYY/dir form: $ENTRY_PATH" 1>&2
+ exit 3
+fi
+export ENTRY_DIR=${ENTRY_PATH#*/}
+if [[ -z $ENTRY_DIR ]]; then
+ echo "$0: ERROR: arg: $ENTRY_PATH not in $YEAR_DIR/dir form: $ENTRY_PATH" 1>&2
+ exit 3
+fi
+if [[ $ENTRY_DIR = */* ]]; then
+ echo "$0: ERROR: dir from arg: $ENTRY_PATH contains a /: $ENTRY_DIR" 1>&2
+ exit 3
+fi
+if [[ ! -d $YEAR_DIR ]]; then
+ echo "$0: ERROR: YYYY from arg: $ENTRY_PATH is not a directory: $YEAR_DIR" 1>&2
+ exit 3
+fi
+export ENTRY_ID="${YEAR_DIR}_${ENTRY_DIR}"
+export DOT_YEAR="$YEAR_DIR/.year"
+# Now that we have moved to topdir, form and verify YYYY_DIR is a writable directory
+export YYYY_DIR="$YEAR_DIR/$ENTRY_DIR"
+if [[ ! -e $YYYY_DIR ]]; then
+ echo "$0: ERROR: YYYY/dir from arg: $ENTRY_PATH does not exist: $YYYY_DIR" 1>&2
+ exit 7
+fi
+if [[ ! -d $YYYY_DIR ]]; then
+ echo "$0: ERROR: YYYY/dir from arg: $ENTRY_PATH is not a directory: $YYYY_DIR" 1>&2
+ exit 7
+fi
+if [[ ! -w $YYYY_DIR ]]; then
+ echo "$0: ERROR: YYYY/dir from arg: $ENTRY_PATH is not a writable directory: $YYYY_DIR" 1>&2
+ exit 7
+fi
+
+
+# print running info if verbose
+#
+# If -v 3 or higher, print exported variables in order that they were exported.
+#
+if [[ $V_FLAG -ge 3 ]]; then
+ echo "$0: debug[3]: VERSION=$VERSION" 1>&2
+ echo "$0: debug[3]: NAME=$NAME" 1>&2
+ echo "$0: debug[3]: V_FLAG=$V_FLAG" 1>&2
+ echo "$0: debug[3]: GIT_TOOL=$GIT_TOOL" 1>&2
+ echo "$0: debug[3]: TOPDIR=$TOPDIR" 1>&2
+ echo "$0: debug[3]: REPO_URL=$REPO_URL" 1>&2
+ echo "$0: debug[3]: NOOP=$NOOP" 1>&2
+ echo "$0: debug[3]: DO_NOT_PROCESS=$DO_NOT_PROCESS" 1>&2
+ echo "$0: debug[3]: ENTRY_PATH=$ENTRY_PATH" 1>&2
+ echo "$0: debug[3]: REPO_NAME=$REPO_NAME" 1>&2
+ echo "$0: debug[3]: CD_FAILED=$CD_FAILED" 1>&2
+ echo "$0: debug[3]: TOP_FILE=$TOP_FILE" 1>&2
+ echo "$0: debug[3]: BIN_PATH=$BIN_PATH" 1>&2
+ echo "$0: debug[3]: BIN_DIR=$BIN_DIR" 1>&2
+ echo "$0: debug[3]: YEAR_DIR=$YEAR_DIR" 1>&2
+ echo "$0: debug[3]: ENTRY_DIR=$ENTRY_DIR" 1>&2
+ echo "$0: debug[3]: ENTRY_ID=$ENTRY_ID" 1>&2
+ echo "$0: debug[3]: DOT_YEAR=$DOT_YEAR" 1>&2
+ echo "$0: debug[3]: YYYY_DIR=$YYYY_DIR" 1>&2
+fi
+
+# -N stops early before any processing is performed
+#
+if [[ -n $DO_NOT_PROCESS ]]; then
+ if [[ $V_FLAG -ge 3 ]]; then
+ echo "$0: debug[3]: arguments parsed, -N given, exiting 0" 1>&2
+ fi
+ exit 0
+fi
+
+
+# verify that YEAR is already in .top
+#
+if ! grep -E -q "^$YEAR_DIR$" "$TOP_FILE"; then
+ echo "$0: ERROR: YEAR_DIR: $YEAR_DIR not found in: $TOP_FILE" 1>&2
+ echo "$0: notice: consider running: bin/new-year.sh $YEAR_DIR -v 1" 1>&2
+ exit 10
+fi
+
+
+# case: without -n
+#
+if [[ -z $NOOP ]]; then
+
+ : # XXX - add code here - XXX #
+
+# case: with -n
+#
+elif [[ $V_FLAG -ge 3 ]]; then
+ echo "$0: debug[3]: -n disabled adding YYYY_DIR: $YYYY_DIR to $DOT_YEAR" 1>&2
+fi
+
+
+# All Done!!! All Done!!! -- Jessica Noll, Age 2
+#
+exit 0
diff --git a/bin/gen-years.sh b/bin/gen-years.sh
index 0b07fb58c..86b1e49d3 100755
--- a/bin/gen-years.sh
+++ b/bin/gen-years.sh
@@ -85,7 +85,7 @@ shopt -s globstar # enable ** to match all files and zero or more directories an
# set variables referenced in the usage message
#
-export VERSION="1.3.4 2024-07-13"
+export VERSION="1.3.5 2024-07-22"
NAME=$(basename "$0")
export NAME
export V_FLAG=0
@@ -663,6 +663,19 @@ for YYYY in $("$TAC_TOOL" "$TOP_FILE"); do
continue
fi
+ # Verify $YYYY/$YYYY.tar.bz2
+ #
+ if [[ ! -e $YYYY/$YYYY.tar.bz2 ]]; then
+ echo "$0: ERROR: compressed tarball for YYYY: $YYYY is missing: $YYYY/$YYYY.tar.bz2" 1>&2
+ EXIT_CODE="6" # exit 6
+ echo "$0: Warning: EXIT_CODE set to: $EXIT_CODE" 1>&2
+ continue
+ fi
+ if [[ ! -s $YYYY/$YYYY.tar.bz2 ]]; then
+ echo "$0: Warning: compressed tarball for YYYY: $YYYY is empty: $YYYY/$YYYY.tar.bz2" 1>&2
+ echo "$0: notice: continuing the processing of YYYY: $YYYY" 1>&2
+ fi
+
# write leading markdown for this IOCCC year
#
{
@@ -795,6 +808,19 @@ for YYYY in $("$TAC_TOOL" "$TOP_FILE"); do
continue
fi
+ # Verify $YYYY_DIR/README.md
+ #
+ if [[ ! -e $YYYY_DIR/README.md ]]; then
+ echo "$0: ERROR: README.md for YYYY: $YYYY is missing: $YYYY_DIR/README.md" 1>&2
+ EXIT_CODE="7" # exit 7
+ echo "$0: Warning: EXIT_CODE set to: $EXIT_CODE" 1>&2
+ continue
+ fi
+ if [[ ! -s $YYYY_DIR/README.md ]]; then
+ echo "$0: Warning: README.md for YYYY/dir: $YYYY_DIR/README.md is empty: $YYYY_DIR/README.md" 1>&2
+ echo "$0: notice: continuing the processing of YYYY: $YYYY" 1>&2
+ fi
+
# output markdown for this entry
#
echo "* "
diff --git a/bin/index.html b/bin/index.html
index 1f25a5926..f8e9b1c1e 100644
--- a/bin/index.html
+++ b/bin/index.html
@@ -438,7 +438,7 @@ need to do so.
This tool is used my the Judges as part of the final
steps to announce a new winning IOCCC entry.
-For example:
+Usage:
mkdir -p YYYY/dir
bin/add-dir.sh YYYY/dir
Here, YYYY/dir must the path to the winning IOCCC entry.
@@ -446,24 +446,24 @@ steps to announce a new winning IOCCC entry.
Run a command on all winning entries.
-For example:
+Usage:
bin/all-run.sh -v 3 bin/quick-readme2index.sh -v 1
-Or for example:
+Alternate usage:
bin/all-run.sh -v 3 bin/readme2index.sh -v 1
Run a command on all IOCCC years.
-For example:
+Usage:
bin/all-years.sh -v 1 bin/gen-year-index.sh -v 1
-Or for example:
+Alternate usage:
bin/all-years.sh -v 1 bin/chk-entry.sh
Check an entry directory to verify that both the files in its manifest
(.entry.json) exist and that no other files exist.
-For example:
+Usage:
bin/chk-entry.sh 2020/ferguson1
If you wish to run it on all entries, we recommend that this tool be invoked via
the top level Makefile:
@@ -481,7 +481,7 @@ the top level Makefile:
title
This tool updates .entry.json files entries whose content is modified.
-For example:
+Usage:
bin/csv2entry.sh -v 1
There is no requirement to sort the CSV files, nor convert
them to UNIX format, nor append a final newline to the file.
@@ -518,6 +518,19 @@ semantic checks. For example, this tool does NOT verif
the .entry.json file matches the files in the YYYY/dir directory, or even
that the .entry.json contains a manifest (or any of the other required JSON
content).
+
+Given a submission (that has won the IOCCC), with a .auth.json
+and .info.json and NO .entry.json file, we convert the
+.auth.json and .info.json into a new .entry.json file.
+We will also form, as needed, new author/author_handle.json
+files for new authors, and update author/author_handle.json
+for authors who won previously.
+Usage:
+ bin/cvt-submission.sh -v 1 YYYY/dir
+Here, YYYY/dir is the path of the submission under the YYYY
+year directory.
@@ -546,7 +559,7 @@ from the TOPDIR.
Generate a list of files in an entry’s manifest (the .entry.json file).
-For example:
+Usage:
awk -f bin/filelist.entry.json.awk 2020/ferguson1/.entry.json
In this case the command will list all the files of the
2020/ferguson1 winning entry.
@@ -718,9 +731,8 @@ the md2html tool.
This tool is used my the Judges as part of the final
steps to announce a new set of winning IOCCC entries.
-For example:
- mkdir -p YYYY
- bin/new-year.sh -v 1 YYYY
+Usage:
+ bin/new-year.sh -v 1 YYYY
Here, YYYY must be a new 4-digit IOCCC year.
diff --git a/bin/new-year.sh b/bin/new-year.sh
index fcc4e8117..eb262654f 100755
--- a/bin/new-year.sh
+++ b/bin/new-year.sh
@@ -2,8 +2,7 @@
#
# new-year.sh - add a new IOCCC year
#
-# We update .top with a new 4-digit IOCCC year if such a sub-directory exists
-# and the IOCCC year is not already in the .top file.
+# We update the ${YEAR} make variable in the top level `Makefile`.
#
# Copyright (c) 2024 by Landon Curt Noll. All Rights Reserved.
#
@@ -88,7 +87,7 @@ shopt -s globstar # enable ** to match all files and zero or more directories an
# set variables referenced in the usage message
#
-export VERSION="1.1 2024-07-21"
+export VERSION="1.2 2024-07-21"
NAME=$(basename "$0")
export NAME
export V_FLAG=0
@@ -105,6 +104,7 @@ if [[ $status -eq 0 ]]; then
fi
export TOPDIR
export REPO_URL="https://github.com/ioccc-src/temp-test-ioccc/blob/master"
+export TEMPLATE="template"
#
export NOOP=
export DO_NOT_PROCESS=
@@ -225,14 +225,6 @@ fi
# cd to topdir
#
-if [[ ! -e $TOPDIR ]]; then
- echo "$0: ERROR: cannot cd to non-existent path: $TOPDIR" 1>&2
- exit 6
-fi
-if [[ ! -d $TOPDIR ]]; then
- echo "$0: ERROR: cannot cd to a non-directory: $TOPDIR" 1>&2
- exit 6
-fi
export CD_FAILED
if [[ $V_FLAG -ge 5 ]]; then
echo "$0: debug[5]: about to: cd $TOPDIR" 1>&2
@@ -269,7 +261,7 @@ fi
# verify we have a non-empty readable Makefile
-
+#
export MAKE_FILE="Makefile"
if [[ ! -e $MAKE_FILE ]]; then
echo "$0: ERROR: .top does not exist: $MAKE_FILE" 1>&2
@@ -300,6 +292,7 @@ if [[ $V_FLAG -ge 3 ]]; then
echo "$0: debug[3]: GIT_TOOL=$GIT_TOOL" 1>&2
echo "$0: debug[3]: TOPDIR=$TOPDIR" 1>&2
echo "$0: debug[3]: REPO_URL=$REPO_URL" 1>&2
+ echo "$0: debug[3]: TEMPLATE=$TEMPLATE" 1>&2
echo "$0: debug[3]: NOOP=$NOOP" 1>&2
echo "$0: debug[3]: DO_NOT_PROCESS=$DO_NOT_PROCESS" 1>&2
echo "$0: debug[3]: YEAR=$YEAR" 1>&2
@@ -319,6 +312,168 @@ if [[ -n $DO_NOT_PROCESS ]]; then
fi
+# Create YYYY directory if needed
+#
+if [[ -z $NOOP ]]; then
+
+ # case: YYYY does not exist
+ #
+ if [[ ! -e $YEAR ]]; then
+ if [[ $V_FLAG -ge 3 ]]; then
+ echo "$0: debug[3]: about to: mkdir -p $YEAR" 1>&2
+ fi
+ mkdir -p "$YEAR"
+ status="$?"
+ if [[ $status -ne 0 ]]; then
+ echo "$0: ERROR: mkdir -p $YEAR failed," \
+ "error code: $status" 1>&2
+ exit 10
+ elif [[ $V_FLAG -ge 1 ]]; then
+ echo "$0: debug[1]: created directory: $YEAR" 1>&2
+ fi
+
+ # case: YYYY exists but is not a directory
+ #
+ elif [[ ! -d $YEAR ]]; then
+ echo "$0: ERROR: exists but is not a directory: $YEAR" 1>&2
+ exit 11
+ fi
+
+elif [[ $V_FLAG -ge 3 && ! -d $YEAR ]]; then
+ echo "$0: debug[3]: -n disabled creating missing directory: $YEAR" 1>&2
+fi
+
+
+# Add the template Makefile if there is no YYYY/Makefile file
+#
+export YEAR_MAKEFILE="$YEAR/Makefile"
+if [[ -z $NOOP ]]; then
+
+ # case: YYYY/Makefile does not exist
+ #
+ if [[ ! -e $YEAR_MAKEFILE ]]; then
+
+ # verify that the template directory exists
+ #
+ if [[ ! -d $TEMPLATE ]]; then
+ echo "$0: ERROR: YYYY/Makefile: $YEAR_MAKEFILE does not exist and" \
+ "template is missing: $TEMPLATE" 1>&2
+ exit 12
+ fi
+
+ # verify that the YYYY/Makefile template is a file
+ #
+ export YEAR_MAKEFILE_TEMPLATE="$TEMPLATE/Makefile.year"
+ if [[ ! -f $YEAR_MAKEFILE_TEMPLATE ]]; then
+ echo "$0: ERROR: YYYY/Makefile: $YEAR_MAKEFILE does not exist and" \
+ "template Makefile is missing: $YEAR_MAKEFILE_TEMPLATE" 1>&2
+ exit 13
+ fi
+
+ # form year Makefile
+ #
+ if [[ $V_FLAG -ge 3 ]]; then
+ echo "$0: debug[3]: about to: sed -e ... $YEAR_MAKEFILE_TEMPLATE > $YEAR_MAKEFILE" 0>&2
+ fi
+ sed -e "s/%%YEAR%%/$YEAR/g" "$YEAR_MAKEFILE_TEMPLATE" > "$YEAR_MAKEFILE"
+ status="$?"
+ if [[ $status -ne 0 ]]; then
+ echo "$0: ERROR: sed -e .. $YEAR_MAKEFILE_TEMPLATE > $YEAR_MAKEFILE filed," \
+ "error code: $status" 1>&2
+ exit 14
+ elif [[ $V_FLAG -ge 1 ]]; then
+ echo "$0: debug[1]: updated Makefile: $MAKE_FILE" 1>&2
+ fi
+
+ # case: YYYY exists but is not a file
+ #
+ elif [[ ! -d $YEAR ]]; then
+ echo "$0: ERROR: YYYY/Makefile exists but is not a file: $YEAR_MAKEFILE" 1>&2
+ exit 15
+ fi
+
+elif [[ $V_FLAG -ge 3 && ! -f $YEAR_MAKEFILE ]]; then
+ echo "$0: debug[3]: -n disabled creating Makefile: $YEAR_MAKEFILE" 1>&2
+fi
+
+
+# form an empty YYYY/.year file if needed
+#
+export YEAR_FILE="$YEAR/.year"
+if [[ -z $NOOP ]]; then
+
+ # case: .year file does not exist
+ #
+ if [[ ! -e $YEAR_FILE ]]; then
+
+ if [[ $V_FLAG -ge 3 ]]; then
+ echo "$0: debug[3]: about to: touch $YEAR_FILE" 1>&2
+ fi
+ touch "$YEAR_FILE"
+ status="$?"
+ if [[ $status -ne 0 ]]; then
+ echo "$0: ERROR: touch $YEAR_FILE filed," \
+ "error code: $status" 1>&2
+ exit 16
+ elif [[ $V_FLAG -ge 1 ]]; then
+ echo "$0: debug[1]: created: $YEAR_FILE" 1>&2
+ fi
+
+ elif [[ ! -f $YEAR_FILE ]]; then
+ echo "$0: ERROR: .year exists but is not a file: $YEAR_FILE" 1>&2
+ exit 17
+ fi
+
+elif [[ $V_FLAG -ge 3 && ! -e $YEAR_FILE ]]; then
+ echo "$0: debug[3]: -n disabled creating .year: $YEAR_FILE" 1>&2
+fi
+
+
+# form an empty YYYY/.filelist file if needed
+#
+export YEAR_FILELIST="$YEAR/.filelist"
+if [[ -z $NOOP ]]; then
+
+ # case: .filelist does not exist
+ #
+ if [[ ! -e $YEAR_FILELIST ]]; then
+
+ if [[ $V_FLAG -ge 3 ]]; then
+ echo "$0: debug[3]: about to: touch $YEAR_FILELIST" 1>&2
+ fi
+ touch "$YEAR_FILELIST"
+ status="$?"
+ if [[ $status -ne 0 ]]; then
+ echo "$0: ERROR: touch $YEAR_FILELIST filed," \
+ "error code: $status" 1>&2
+ exit 18
+ elif [[ $V_FLAG -ge 1 ]]; then
+ echo "$0: debug[1]: created: $YEAR_FILELIST" 1>&2
+ fi
+
+ if [[ $V_FLAG -ge 3 ]]; then
+ echo "$0: debug[3]: about to: make genfilelist YEARS=$YEAR" 1>&2
+ fi
+ make genfilelist YEARS="$YEAR"
+ status="$?"
+ if [[ $status -ne 0 ]]; then
+ echo "$0: ERROR: make genfilelist YEARS=$YEAR filed," \
+ "error code: $status" 1>&2
+ exit 19
+ elif [[ $V_FLAG -ge 1 ]]; then
+ echo "$0: debug[1]: updated: $YEAR_FILELIST" 1>&2
+ fi
+
+ elif [[ ! -f $YEAR_FILE ]]; then
+ echo "$0: ERROR: .filelist exists but is not a file: $YEAR_FILELIST" 1>&2
+ exit 20
+ fi
+
+elif [[ $V_FLAG -ge 3 && ! -e $YEAR_FILELIST ]]; then
+ echo "$0: debug[3]: -n disabled creating .filelist: $YEAR_FILELIST" 1>&2
+fi
+
+
# create a temporary Makefile
#
export TMP_MAKEFILE=".tmp.$NAME.MAKEFILE.$$.tmp"
@@ -329,13 +484,13 @@ trap 'rm -f $TMP_MAKEFILE; exit' 0 1 2 3 15
rm -f "$TMP_MAKEFILE"
if [[ -e $TMP_MAKEFILE ]]; then
echo "$0: ERROR: cannot remove temporary Makefile: $TMP_MAKEFILE" 1>&2
- exit 10
+ exit 21
fi
echo '# author_handle,entry_id,entry_id,entry_id,…,,,,,,,,,,,,,,,' > \
"$TMP_MAKEFILE"
if [[ ! -e $TMP_MAKEFILE ]]; then
echo "$0: ERROR: cannot create temporary Makefile: $TMP_MAKEFILE" 1>&2
- exit 11
+ exit 22
fi
@@ -350,18 +505,18 @@ status="$?"
if [[ $status -ne 0 ]]; then
echo "$0: ERROR: make new_year NEW_YEAR=\"$YEAR\" >> \"$TMP_MAKEFILE\" failed," \
"error code: $status" 1>&2
- exit 12
+ exit 23
fi
sed -n -e '/^# END - DO NOT REMOVE THIS LINE - make new_year also uses this #/,$p' "$MAKE_FILE" >> "$TMP_MAKEFILE"
-# Update Makefile if different and not -n
+# Update Makefile if is changes and not -n
#
if [[ -z $NOOP ]]; then
if cmp -s "$TMP_MAKEFILE" "$MAKE_FILE"; then
- # case: author_wins.csv did not change
+ # case: Makefile did not change
#
if [[ $V_FLAG -ge 5 ]]; then
echo "$0: debug[5]: Makefile file did not change: $MAKE_FILE" 1>&2
@@ -384,28 +539,28 @@ if [[ -z $NOOP ]]; then
if [[ $status -ne 0 ]]; then
echo "$0: ERROR: mv -f -- $TMP_MAKEFILE $MAKE_FILE filed," \
"error code: $status" 1>&2
- exit 13
+ exit 24
elif [[ $V_FLAG -ge 1 ]]; then
echo "$0: debug[1]: updated Makefile: $MAKE_FILE" 1>&2
fi
if [[ ! -s $MAKE_FILE ]]; then
echo "$0: ERROR: not a non-empty Makefile: $MAKE_FILE" 1>&2
- exit 14
+ exit 25
fi
- # update .top and friends
+ # update .top
#
if [[ $V_FLAG -ge 3 ]]; then
- echo "$0: debug[3]: about to run: make genpath >/dev/null" 1>&2
+ echo "$0: debug[3]: about to: make genpath_top >/dev/null" 1>&2
fi
- make genpath >/dev/null
+ make genpath_top >/dev/null
status="$?"
if [[ $status -ne 0 ]]; then
- echo "$0: ERROR: make genpath >/dev/null failed," \
+ echo "$0: ERROR: make -fC$YEAR genpath_top >/dev/null failed," \
"error code: $status" 1>&2
- exit 15
+ exit 26
elif [[ $V_FLAG -ge 1 ]]; then
- echo "$0: debug[1]: updated .top and friends" 1>&2
+ echo "$0: debug[1]: updated .top" 1>&2
fi
fi
diff --git a/template/Makefile.entry b/template/Makefile.entry
new file mode 100644
index 000000000..1f197232d
--- /dev/null
+++ b/template/Makefile.entry
@@ -0,0 +1,287 @@
+#!/usr/bin/env make
+#
+# prog - an example Makefile <<=== change "an example Makefile" to a suitable title for entry
+#
+# Please copy this file into your entry directory under the name: Makefile
+# Modify the resulting Makefile as needed.
+
+
+#############################
+# shell used by this Makefile
+#############################
+#
+SHELL= bash
+
+#######################
+# common tool locations
+#######################
+#
+CC= cc
+GINDENT= gindent
+MV= mv
+RM= rm
+TRUE= true
+
+# Common C compiler warnings to silence
+#
+# Example: CSILENCE= -Wno-some-thing -Wno-another-thing
+#
+# NOTE: If you add -Wno-stuff to CSILENCE, please update
+# CUNKNOWN in the next comment block.
+#
+# NOTE: Please don't add -Wno-unknown-warning-option to CSILENCE.
+#
+#
+CSILENCE=
+
+# Attempt to silence unknown warnings
+#
+# If you add -Wno-stuff to CSILENCE, then please change CUNKNOWN to read:
+#
+# CUNKNOWN= -Wno-unknown-warning-option
+#
+CUNKNOWN=
+
+# Common C compiler warning flags
+#
+CWARN= -Wall -Wextra -pedantic ${CSILENCE} ${CUNKNOWN}
+
+# The standard to compile against
+#
+# Your IOCCC submission is free to require older C standards, or
+# even not specify a C standard at all. We suggest trying
+# for -std=gnu17, but that is not a requirement and you won't
+# be penalized if you name CSTD empty or use another
+# well known and reasonably widely implemented C standard.
+#
+CSTD= -std=gnu17
+
+# Compiler bit architecture
+#
+# Example for 32-bitness: ARCH= -m32
+# Example for 64-bitness: ARCH= -m64
+#
+# NOTE: Normally one should not specify a specific architecture.
+#
+ARCH=
+
+# Defines that are needed to compile
+#
+# Example: -Dfoo -Dbar=baz
+#
+CDEFINE=
+
+# Include files that are needed to compile
+#
+# Example: CINCLUDE= -include stdio.h
+#
+CINCLUDE=
+
+# Other flags to pass to the C compiler
+#
+# Example: COTHER= -fno-math-errno
+#
+COTHER=
+
+# Optimization
+#
+OPT= -O3 -g3
+
+# Default flags for ANSI C compilation
+#
+CFLAGS= ${CSTD} ${CWARN} ${ARCH} ${CDEFINE} ${CINCLUDE} ${COTHER} ${OPT}
+
+# Libraries needed to build
+#
+LDFLAGS=
+
+# C compiler to use
+#
+CC= cc
+
+# Compiler add-ons or replacements for clang only
+#
+ifeq "$(findstring $(CLANG),${CC})" "$(CLANG)"
+#
+CSILENCE+=
+#
+CWARN+= -Weverything
+#
+endif
+
+# Specific add-ons or replacements for gcc only
+#
+ifeq "$(findstring $(GCC),${CC})" "$(GCC)"
+#
+CSILENCE+=
+#
+CWARN+=
+#
+endif
+
+
+###########################################
+# Special Makefile variables for this entry
+###########################################
+
+# what to build
+#
+PROG= prog
+OBJ= ${PROG}.o
+TARGET= ${PROG}
+
+# list any data files supplied with the submission
+#
+DATA=
+
+
+#################
+# build the entry
+#################
+#
+all: data ${TARGET}
+ @${TRUE}
+
+.PHONY: all data clean clobber
+
+# how to compile
+#
+${PROG}: ${PROG}.c
+ ${CC} ${CFLAGS} $< -o $@ ${LDFLAGS}
+
+# data files
+#
+data: ${DATA}
+ @${TRUE}
+
+# one suggested way to run the program
+#
+try: ${PROG} ${DATA}
+ @# remove these comments
+ @# notice how we do not assume . is in the path
+ @# change this next line as needed
+ echo ./${PROG} some arguments
+
+
+###############
+# utility rules
+###############
+#
+clean:
+ ${RM} -f ${OBJ}
+ @-if [ -f indent.c ]; then \
+ echo ${RM} -f indent.c; \
+ ${RM} -f indent.c; \
+ fi
+
+clobber: clean
+ ${RM} -f ${TARGET}
+ @-if [ -e sandwich ]; then \
+ ${RM} -f sandwich; \
+ echo 'ate sandwich'; \
+ fi
+
+# Do not install prog, please!
+#
+install:
+ @echo "Dr. Spock says that is not logical!"
+ @${TRUE}
+
+# you may be able to misunderstand the source by reading indent.c
+#
+indent.c: ${PROG}.c
+ @if which "${GINDENT}" >/dev/null 2>&1; then \
+ echo ${RM} -f $@; \
+ ${RM} -f $@; \
+ echo "${GINDENT} < $< > $@"; \
+ ${GINDENT} < $< > $@; \
+ elif which "${INDENT}" >/dev/null 2>&1; then \
+ echo ${RM} -f $@; \
+ ${RM} -f $@; \
+ echo "${INDENT} < $< > $@"; \
+ ${INDENT} < $< > $@; \
+ else \
+ echo "no indent tool found, ident $< yourself, sorry"; \
+ echo "exit 17"; \
+ exit 17; \
+ fi
+
+
+# NOTE: Don't worry if you don't understand stuff below
+#
+##################
+# 133t hacker rulz
+##################
+#
+love:
+ @echo 'not war?'
+
+waste:
+ @echo $@
+
+haste:
+ ${MAKE} waste
+
+maker: haste
+ @echo 'Participate in a maker faire'
+ ${MAKE} love
+
+easter_egg: maker
+ @echo "You are expected to often misunderstand this $${RANDOM} magic, Eggy!"
+ @echo "chongo '
' /\\oo/\\"
+ @echo "p.s.: Careful with That Axe, Eugene!"
+
+sandwich: easter_egg
+ @if [ `id -u` -eq 0 ]; then \
+ echo 'Okay.'; \
+ echo "$${RANDOM}`date +%s`$${RANDOM}" > $@; \
+ else \
+ echo 'What? Make it yourself.'; \
+ echo "Did you forget the magic word?"; \
+ fi
+
+# Understand the history of the Homebrew Computer Club
+# as well as the West Coast Computer Faire and
+# you might be confused different. :-)
+#
+supernova: sandwich
+ @-if [ -r .code_anal ]; then \
+ ${RM} -f .code_anal_v6; \
+ else \
+ echo "Planet deniers, like some members of the IAU, are so cute when they try to defend their logic"; \
+ fi
+ @echo "A $@ helps ${MAKE} the elements that help form planets"
+
+deep_magic: supernova
+ @-if [ -r .code_anal ]; then \
+ ccode_analysis --deep_magic 7889066cdbdf09b0408021754586e895be641cc9be29e7eafd3ca65359541f17 \
+ --FNV1a_hash_512_bit -v2 "${PROG}" "${PROG}.c"; \
+ else \
+ echo "Wrong! Do it again!"; \
+ sleep 1; \
+ echo "Wrong! Do it again!"; \
+ sleep 1; \
+ echo "Wrong! Do it again!"; \
+ fi
+
+magic: deep_magic
+ @-if [ -r .code_anal ]; then \
+ ccode_analysis --level 20003 --mode 5717175 --FNV1a_hash_512_bit -v2 "${PROG}" "${PROG}.c"; \
+ else \
+ echo "If you don't eat yer meat, you can't have any pudding!"; \
+ echo "How can you have any pudding if you don't eat yer meat?!"; \
+ fi
+
+# The IOCCC resident astronomer states
+#
+charon: magic
+ @echo "$@ is a dwarf planet"
+ @echo "Dwarf planets are a type of planet"
+ @echo "Therefore IAU, $@ is a planet"
+
+pluto: charon
+ @echo "See https://www.hou.usra.edu/meetings/lpsc2017/pdf/1448.pdf for a good definition of a planet"
+ @echo "$@ is a dwarf planet"
+ @echo "Dwarf planets are a type of planet"
+ @echo "Therefore, $@ is a planet"
+ @echo "The geophysical definition of planet gives us ~110 planets in our solar system"
diff --git a/template/Makefile.year b/template/Makefile.year
new file mode 100644
index 000000000..2fafde2b5
--- /dev/null
+++ b/template/Makefile.year
@@ -0,0 +1,418 @@
+#!/usr/bin/env make
+#
+# %%YEAR%% Makefile
+
+################################################################################
+#
+# IOCCC winning entry code may not work on your system. What was liked/allowed
+# and worked in the past may no longer be liked/allowed or compile/run today.
+#
+# Bug fixes, corrections and typo fixes are VERY WELCOME. If you see a problem,
+# first check this URL for a list of known bugs and (mis)features of IOCCC entries:
+#
+# https://www.ioccc.org/bugs.html
+#
+# GitHub pull requests are welcome! Please see the above URL for details.
+#
+################################################################################
+#
+# This file is Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved.
+# You are free to share and adapt this file under the terms of this license:
+#
+# Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
+#
+# For more information, see: https://creativecommons.org/licenses/by-sa/4.0/
+
+
+#############################
+# shell used by this Makefile
+#############################
+#
+SHELL= bash
+
+#######################
+# common tool locations
+#######################
+#
+include ../var.mk
+
+
+###############
+# IOCCC entries
+###############
+#
+ENTRIES=
+
+YEAR= %%YEAR%%
+
+
+###################
+# build all entries
+###################
+#
+all:
+ @echo '=-=-= ${YEAR} begin make $@ =-=-='
+ @echo
+ @for i in ${ENTRIES}; do \
+ echo "=-= start ${YEAR}/$$i =-="; \
+ echo "(cd $$i && ${MAKE} $@)"; \
+ (cd $$i && ${MAKE} $@); \
+ echo "=-= end ${YEAR}/$$i =-="; \
+ echo; \
+ done
+ @echo '=-=-= ${YEAR} complete make $@ =-=-='
+
+.PHONY: all alt data everything diff_orig_prog diff_prog_orig \
+ diff_alt_prog diff_prog_alt diff_orig_alt diff_alt_orig \
+ clean clobber install genpath love haste waste maker \
+ easter_egg sandwich supernova deep_magic magic charon pluto
+
+# alternative executable
+#
+alt:
+ @echo '=-=-= ${YEAR} begin make $@ =-=-='
+ @echo
+ @for i in ${ENTRIES}; do \
+ echo "=-= start ${YEAR}/$$i =-="; \
+ echo "(cd $$i && ${MAKE} $@)"; \
+ (cd $$i && ${MAKE} $@); \
+ echo "=-= end ${YEAR}/$$i =-="; \
+ echo; \
+ done
+ @echo '=-=-= ${YEAR} complete make $@ =-=-='
+
+# data files
+#
+data:
+ @echo '=-=-= ${YEAR} begin make $@ =-=-='
+ @echo
+ @for i in ${ENTRIES}; do \
+ echo "=-= start ${YEAR}/$$i =-="; \
+ echo "(cd $$i && ${MAKE} $@)"; \
+ (cd $$i && ${MAKE} $@); \
+ echo "=-= end ${YEAR}/$$i =-="; \
+ echo; \
+ done
+ @echo '=-=-= ${YEAR} complete make $@ =-=-='
+
+# both all and alt
+#
+everything:
+ @echo '=-=-= ${YEAR} begin make $@ =-=-='
+ @echo
+ @for i in ${ENTRIES}; do \
+ echo "=-= start ${YEAR}/$$i =-="; \
+ echo "(cd $$i && ${MAKE} $@)"; \
+ (cd $$i && ${MAKE} $@); \
+ echo "=-= end ${YEAR}/$$i =-="; \
+ echo; \
+ done
+ @echo '=-=-= ${YEAR} complete make $@ =-=-='
+
+
+#####################
+# make a difference #
+#####################
+#
+# diff orig source and source
+#
+diff_orig_prog:
+ @echo '=-=-= ${YEAR} begin make $@ =-=-='
+ @echo
+ @for i in ${ENTRIES}; do \
+ echo "=-= start ${YEAR}/$$i =-="; \
+ echo "(cd $$i && ${MAKE} $@)"; \
+ (cd $$i && ${MAKE} $@); \
+ echo "=-= end ${YEAR}/$$i =-="; \
+ echo; \
+ done
+ @echo '=-=-= ${YEAR} complete make $@ =-=-='
+
+# diff source and orig source
+#
+diff_prog_orig:
+ @echo '=-=-= ${YEAR} begin make $@ =-=-='
+ @echo
+ @for i in ${ENTRIES}; do \
+ echo "=-= start ${YEAR}/$$i =-="; \
+ echo "(cd $$i && ${MAKE} $@)"; \
+ (cd $$i && ${MAKE} $@); \
+ echo "=-= end ${YEAR}/$$i =-="; \
+ echo; \
+ done
+ @echo '=-=-= ${YEAR} complete make $@ =-=-='
+
+# diff alt source and source
+#
+diff_alt_prog:
+ @echo '=-=-= ${YEAR} begin make $@ =-=-='
+ @echo
+ @for i in ${ENTRIES}; do \
+ echo "=-= start ${YEAR}/$$i =-="; \
+ echo "(cd $$i && ${MAKE} $@)"; \
+ (cd $$i && ${MAKE} $@); \
+ echo "=-= end ${YEAR}/$$i =-="; \
+ echo; \
+ done
+ @echo '=-=-= ${YEAR} complete make $@ =-=-='
+
+# diff source and alt source
+#
+diff_prog_alt:
+ @echo '=-=-= ${YEAR} begin make $@ =-=-='
+ @echo
+ @for i in ${ENTRIES}; do \
+ echo "=-= start ${YEAR}/$$i =-="; \
+ echo "(cd $$i && ${MAKE} $@)"; \
+ (cd $$i && ${MAKE} $@); \
+ echo "=-= end ${YEAR}/$$i =-="; \
+ echo; \
+ done
+ @echo '=-=-= ${YEAR} complete make $@ =-=-='
+
+# diff orig and alt
+#
+diff_orig_alt:
+ @echo '=-=-= ${YEAR} begin make $@ =-=-='
+ @echo
+ @for i in ${ENTRIES}; do \
+ echo "=-= start ${YEAR}/$$i =-="; \
+ echo "(cd $$i && ${MAKE} $@)"; \
+ (cd $$i && ${MAKE} $@); \
+ echo "=-= end ${YEAR}/$$i =-="; \
+ echo; \
+ done
+ @echo '=-=-= ${YEAR} complete make $@ =-=-='
+
+# diff alt and orig
+diff_alt_orig:
+ @echo '=-=-= ${YEAR} begin make $@ =-=-='
+ @echo
+ @for i in ${ENTRIES}; do \
+ echo "=-= start ${YEAR}/$$i =-="; \
+ echo "(cd $$i && ${MAKE} $@)"; \
+ (cd $$i && ${MAKE} $@); \
+ echo "=-= end ${YEAR}/$$i =-="; \
+ echo; \
+ done
+ @echo '=-=-= ${YEAR} complete make $@ =-=-='
+
+
+###############
+# utility rules
+###############
+#
+clean:
+ @echo '=-=-= ${YEAR} begin make $@ =-=-='
+ @echo
+ @for i in ${ENTRIES}; do \
+ echo "=-= start ${YEAR}/$$i =-="; \
+ echo "(cd $$i && ${MAKE} $@)"; \
+ (cd $$i && ${MAKE} $@); \
+ echo "=-= end ${YEAR}/$$i =-="; \
+ echo; \
+ done
+ @echo '=-=-= ${YEAR} complete make $@ =-=-='
+
+clobber:
+ @echo '=-=-= ${YEAR} begin make $@ =-=-='
+ @echo
+ @for i in ${ENTRIES}; do \
+ echo "=-= start ${YEAR}/$$i =-="; \
+ echo "(cd $$i && ${MAKE} $@)"; \
+ (cd $$i && ${MAKE} $@); \
+ echo "=-= end ${YEAR}/$$i =-="; \
+ echo; \
+ done
+ @echo '=-=-= ${YEAR} complete make $@ =-=-='
+
+install:
+ @echo '=-=-= ${YEAR} begin make $@ =-=-='
+ @echo
+ @for i in ${ENTRIES}; do \
+ echo "=-= start ${YEAR}/$$i =-="; \
+ echo "(cd $$i && ${MAKE} $@)"; \
+ (cd $$i && ${MAKE} $@); \
+ echo "=-= end ${YEAR}/$$i =-="; \
+ echo; \
+ done
+ @echo '=-=-= ${YEAR} complete make $@ =-=-='
+
+indent.c:
+ @echo '=-=-= ${YEAR} begin make $@ =-=-='
+ @echo
+ @for i in ${ENTRIES}; do \
+ echo "=-= start ${YEAR}/$$i =-="; \
+ echo "(cd $$i && ${MAKE} $@)"; \
+ (cd $$i && ${MAKE} $@); \
+ echo "=-= end ${YEAR}/$$i =-="; \
+ echo; \
+ done
+ @echo '=-=-= ${YEAR} complete make $@ =-=-='
+
+genpath:
+ @echo '=-=-= IOCCC begin make $@ =-=-='
+ @${RM} -f .tmp.genpath
+ @${TOUCH} .tmp.genpath
+ @-for i in ${ENTRIES}; do \
+ echo "${YEAR}/$$i" >> .tmp.genpath; \
+ rm -f "$$i/.tmp.genpath"; \
+ echo "${YEAR}/$$i" >> "$$i/.tmp.genpath"; \
+ if ${CMP} -s "$$i/.tmp.genpath" "$$i/.path"; then \
+ rm -f "$$i/.tmp.genpath"; \
+ echo "$$i/.path already up to date"; \
+ else \
+ ${MV} -f "$$i/.tmp.genpath" "$$i/.path"; \
+ ${CHMOD} 0444 "$$i/.path"; \
+ echo "updated $$i/.path"; \
+ fi; \
+ done
+ @-if ${CMP} -s .tmp.genpath .year; then \
+ ${RM} -f .tmp.genpath; \
+ echo ".year already up to date"; \
+ else \
+ ${MV} -f .tmp.genpath .year; \
+ ${CHMOD} 0444 .year; \
+ echo "updated .year"; \
+ fi
+ @echo '=-=-= IOCCC complete make $@ =-=-='
+
+
+##################
+# 133t hacker rulz
+##################
+#
+love:
+ @echo '=-=-= ${YEAR} begin make $@ =-=-='
+ @echo
+ @for i in ${ENTRIES}; do \
+ echo "=-= start ${YEAR}/$$i =-="; \
+ echo "(cd $$i && ${MAKE} $@)"; \
+ (cd $$i && ${MAKE} $@); \
+ echo "=-= end ${YEAR}/$$i =-="; \
+ echo; \
+ done
+ @echo '=-=-= ${YEAR} complete make $@ =-=-='
+
+haste:
+ @echo '=-=-= ${YEAR} begin make $@ =-=-='
+ @echo
+ @for i in ${ENTRIES}; do \
+ echo "=-= start ${YEAR}/$$i =-="; \
+ echo "(cd $$i && ${MAKE} $@)"; \
+ (cd $$i && ${MAKE} $@); \
+ echo "=-= end ${YEAR}/$$i =-="; \
+ echo; \
+ done
+ @echo '=-=-= ${YEAR} complete make $@ =-=-='
+
+waste:
+ @echo '=-=-= ${YEAR} begin make $@ =-=-='
+ @echo
+ @for i in ${ENTRIES}; do \
+ echo "=-= start ${YEAR}/$$i =-="; \
+ echo "(cd $$i && ${MAKE} $@)"; \
+ (cd $$i && ${MAKE} $@); \
+ echo "=-= end ${YEAR}/$$i =-="; \
+ echo; \
+ done
+ @echo '=-=-= ${YEAR} complete make $@ =-=-='
+
+maker:
+ @echo '=-=-= ${YEAR} begin make $@ =-=-='
+ @echo
+ @for i in ${ENTRIES}; do \
+ echo "=-= start ${YEAR}/$$i =-="; \
+ echo "(cd $$i && ${MAKE} $@)"; \
+ (cd $$i && ${MAKE} $@); \
+ echo "=-= end ${YEAR}/$$i =-="; \
+ echo; \
+ done
+ @echo '=-=-= ${YEAR} complete make $@ =-=-='
+
+easter_egg:
+ @echo '=-=-= ${YEAR} begin make $@ =-=-='
+ @echo
+ @for i in ${ENTRIES}; do \
+ echo "=-= start ${YEAR}/$$i =-="; \
+ echo "(cd $$i && ${MAKE} $@)"; \
+ (cd $$i && ${MAKE} $@); \
+ echo "=-= end ${YEAR}/$$i =-="; \
+ echo; \
+ done
+ @echo '=-=-= ${YEAR} complete make $@ =-=-='
+
+sandwich:
+ @echo '=-=-= ${YEAR} begin make $@ =-=-='
+ @echo
+ @for i in ${ENTRIES}; do \
+ echo "=-= start ${YEAR}/$$i =-="; \
+ echo "(cd $$i && ${MAKE} $@)"; \
+ (cd $$i && ${MAKE} $@); \
+ echo "=-= end ${YEAR}/$$i =-="; \
+ echo; \
+ done
+ @echo '=-=-= ${YEAR} complete make $@ =-=-='
+
+
+# The IOCCC resident astronomer states
+#
+supernova:
+ @echo '=-=-= ${YEAR} begin make $@ =-=-='
+ @echo
+ @for i in ${ENTRIES}; do \
+ echo "=-= start ${YEAR}/$$i =-="; \
+ echo "(cd $$i && ${MAKE} $@)"; \
+ (cd $$i && ${MAKE} $@); \
+ echo "=-= end ${YEAR}/$$i =-="; \
+ echo; \
+ done
+ @echo '=-=-= ${YEAR} complete make $@ =-=-='
+
+deep_magic:
+ @echo '=-=-= ${YEAR} begin make $@ =-=-='
+ @echo
+ @for i in ${ENTRIES}; do \
+ echo "=-= start ${YEAR}/$$i =-="; \
+ echo "(cd $$i && ${MAKE} $@)"; \
+ (cd $$i && ${MAKE} $@); \
+ echo "=-= end ${YEAR}/$$i =-="; \
+ echo; \
+ done
+ @echo '=-=-= ${YEAR} complete make $@ =-=-='
+
+magic:
+ @echo '=-=-= ${YEAR} begin make $@ =-=-='
+ @echo
+ @for i in ${ENTRIES}; do \
+ echo "=-= start ${YEAR}/$$i =-="; \
+ echo "(cd $$i && ${MAKE} $@)"; \
+ (cd $$i && ${MAKE} $@); \
+ echo "=-= end ${YEAR}/$$i =-="; \
+ echo; \
+ done
+ @echo '=-=-= ${YEAR} complete make $@ =-=-='
+
+charon:
+ @echo '=-=-= ${YEAR} begin make $@ =-=-='
+ @echo
+ @for i in ${ENTRIES}; do \
+ echo "=-= start ${YEAR}/$$i =-="; \
+ echo "(cd $$i && ${MAKE} $@)"; \
+ (cd $$i && ${MAKE} $@); \
+ echo "=-= end ${YEAR}/$$i =-="; \
+ echo; \
+ done
+ @echo '=-=-= ${YEAR} complete make $@ =-=-='
+
+pluto:
+ @echo '=-=-= ${YEAR} begin make $@ =-=-='
+ @echo
+ @for i in ${ENTRIES}; do \
+ echo "=-= start ${YEAR}/$$i =-="; \
+ echo "(cd $$i && ${MAKE} $@)"; \
+ (cd $$i && ${MAKE} $@); \
+ echo "=-= end ${YEAR}/$$i =-="; \
+ echo; \
+ done
+ @echo '=-=-= ${YEAR} complete make $@ =-=-='