summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xship/build102
1 files changed, 56 insertions, 46 deletions
diff --git a/ship/build b/ship/build
index 486f4bed..10fc4345 100755
--- a/ship/build
+++ b/ship/build
@@ -5,6 +5,14 @@ set -euf
# [debug=true] build compile SRCFILE DSTFILE
# [debug=true] build deps SRCFILE...
build() {
+
+ # usage_pattern is used to extract build directive declarations.
+ usage_pattern='## usage: \(.*\) -> \([^ ]\+\) \(.*\)'
+
+ script='s/^'"$usage_pattern"'$/\2_directive='"'"'\1'"'"'/p' \
+ setf build_x_directive_loader '$(sed -n "$script" "$%s")' 0
+ eval "$build_x_directive_loader"
+
case "$1" in
compile) build_compile "$2" "$3";;
deps) shift; build_deps "$@";;
@@ -12,28 +20,7 @@ build() {
esac
}
-# usage: debug_script VARNAME [DESCRIPTION]
-debug_script() {
- if test "${debug-false}" = true; then
- printf '====== %s%s\n%s\n' \
- "$1" \
- "${2+" ($2)"}" \
- "$(eval echo \"\$$1\" | nl -b a)" >&2
- fi
-}
-
-## build directives
-build_info_directive='#@info'
-build_include_directive='#@include \([0-9A-Za-z]\+\)'
-
-input_parser="\
-s:^ *\([0-9]\+\) "$build_info_directive"$:build_info \1:
-s:^ *\([0-9]\+\) "$build_include_directive"$:build_include \1 \2:
-t
-s:^ *\([0-9]\+\) .*:echo \1p:"
-debug_script input_parser
-
-## usage: build_include LINENO LIBNAME
+## usage: #@include \([0-9A-Za-z]\+\) -> build_include \1 \2
build_include() { cat<<EOF
$1a\\
# begin $2
@@ -43,7 +30,7 @@ $1a\\
EOF
}
-## usage: build_info LINENO
+## usage: #@info -> build_info \1
build_info() { cat<<EOF
$1a\\
# this file was generated by //ship/build\\
@@ -54,37 +41,36 @@ EOF
## usage: build_compile SRCFILE DSTFILE
build_compile() {
- srcfile="$(cat "$1")"
- debug_script srcfile 'SRCFILE'
- while needs_compilation "$srcfile"; do
- script="$(make_sedscript_maker_shellscript "$srcfile")"
- srcfile="$(echo "$srcfile" | sed -n "$script")"
- debug_script srcfile 'sed sedscript srcfile'
+ script='s/^'"$usage_pattern"'$/\2_directive/p' \
+ setf build_directives '$(sed -n "$script" "$%s")' 0
+
+ script='
+ s/^'"$usage_pattern"'$/s:^ *\\([0-9]\\+\\) \1$:\2 \3:/p
+ $a\
+ t\
+ s:^ *\\([0-9]\\+\\) .*:echo \\1p:
+ ' \
+ setf input_parser '$(sed -n "$script" "$%s")' 0
+
+ setf incomplete_pattern '$(make_incomplete_pattern $%s)' build_directives
+
+ SRCFILE="$1" setf src '$(cat "$%s")' SRCFILE
+
+ while needs_compilation "$src" "$incomplete_pattern"; do
+ setf sedgen '$(echo "$%s" | nl -b a -s \ | sed "$%s")' src input_parser
+ setf sedscript '$(eval "$%s")' sedgen
+ setf src '$(echo "$%s" | sed -n "$%s")' src sedscript
done
- echo "$srcfile" > "$2"
+ echo "$src" > "$2"
chmod +x "$2"
}
-## usage: needs_compilation SHELLSCRIPT
+## usage: needs_compilation SHELLSCRIPT PATTERN
# Returns true if SRCFILE contains compilation directives.
needs_compilation() {
- echo "$1" |
- grep -q "^\\($build_include_directive\\|$build_info_directive\\)$"
-}
-
-## usage: make_sedscript_maker_shellscript SRCFILE
-# Print a shellscript that creates a sedscript that resolves all the build
-# directives in SRCFILE.
-make_sedscript_maker_shellscript() {
- sedscript_generator="$(echo "$1" | nl -b a -s ' ' | sed "$input_parser")"
- debug_script sedscript_generator 'sed input_parser srcfile'
-
- sedscript="$(eval "$sedscript_generator")"
- debug_script sedscript 'eval sedscript_generator'
-
- echo "$sedscript"
+ echo "$1" | grep -q "$2"
}
## usage: build_deps SRCFILE...
@@ -118,4 +104,28 @@ build_resolve() {
}
}
+## usage: make_incomplete_pattern BUILD_DIRECTIVES...
+make_incomplete_pattern() {
+ echo "^\\($(
+ for directive; do
+ eval echo \"\$$directive\"
+ done |
+ tr \\n \| |
+ sed 's/|/\\|/'
+ )\\)$"
+}
+
+## usage: setf NAME FMT [ARG...]
+setf() {
+ value_script="$(shift; printf "$@")"
+
+ eval "$1=$value_script"
+
+ if test "${debug-false}" = true; then
+ eval 'echo "$1=\"$value_script\""'
+ eval 'echo "'"\$$1"'"' | nl -b a
+ fi >&2
+}
+
+## main
build "$@"