Improved build system

This fixes a lot of the problems with the build by using a normal Makefile
as it is intended to be used.  To do this, tamed was created.  See the
manual and commit messages for more information.  bin/tame{,d} also have
more information.  More information will follow in the manual in the future.

There is also more cleanup to follow; I just want to get this committed so
that people can take advantage of it and stop some of the suffering.
master v3.3.0
Mike Gerwitz 2018-10-11 22:26:58 -04:00
commit 01671f8345
32 changed files with 2954 additions and 356 deletions

1
.gitignore vendored
View File

@ -7,6 +7,7 @@
*.info
# autotools- and configure-generated
/bin/dslc
/Makefile.in
/Makefile
/aclocal.m4

View File

@ -16,7 +16,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
##
SUBDIRS = doc progtest
SUBDIRS = src/current/src doc progtest
path_src = src
path_test = test

View File

@ -14,12 +14,13 @@ designed to aid in the development, understanding, and maintenance of systems
performing numerous calculations on a complex graph of dependencies,
conditions, and a large number of inputs.
This system was developed at LoVullo Associates to handle the complexity of
comparative insurance rating systems. It is a domain-specific language (DSL)
that itself encourages, through the use of templates, the creation of sub-DSLs.
TAME itself is at heart a calculator—processing only numerical input and
output—driven by quantifiers as predicates. Calculations and quantifiers are
written declaratively without concern for order of execution.
This system was developed at R-T Specialty (formerly LoVullo Associates) to
handle the complexity of comparative insurance rating systems. It is a
domain-specific language (DSL) that itself encourages, through the use of
templates, the creation of sub-DSLs. TAME itself is at heart a
calculator—processing only numerical input and output—driven by quantifiers
as predicates. Calculations and quantifiers are written declaratively
without concern for order of execution.
The system has powerful dependency resolution and data flow capabilities.
@ -27,15 +28,10 @@ TAME consists of a macro processor (implementing a metalanguage), numerous
compilers for various targets (JavaScript, HTML documentation and debugging
environment, LaTeX, and others), linkers, and supporting tools. The input
grammar is XML, and the majority of the project (including the macro processor,
compilers, and linkers) are written in XSLT. There is a reason for that odd
compilers, and linkers) is written in XSLT. There is a reason for that odd
choice; until an explanation is provided, know that someone is perverted enough
to implement a full compiler in XSLT.
More information will become available as various portions are liberated
during refactoring. [tame-core](https://github.com/lovullo/tame-core) is
TAME's core library, and [hoxsl](https://savannah.nongnu.org/projects/hoxsl)
was developed as a supporting library.
## "Current"
The current state of the project as used in production is found in
@ -54,6 +50,19 @@ instance. Available formats are:
- [Info][doc-info]
## Getting Started
To get started, make sure Saxon version 9 or later is available and its path
set as `SAXON_CP`; that the path to hoxsl is set via `HOXSL`; and then run
the `bootstrap` script:
```bash
$ export SAXON_CP=/path/to/saxon9he.jar
$ export HOXSL=/path/to/hoxsl/root
$ ./boostrap
```
## Hacking
Information for TAME developers can be found in the file `HACKING`.

28
bin/dslc.in 100644
View File

@ -0,0 +1,28 @@
#!/bin/bash
# Listen for TAME commands (compilers, linker, etc)
#
# Copyright (C) 2018 R-T Specialty, LLC.
#
# 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/>.
#
# @AUTOGENERATED@
##
declare -r mypath=$( dirname "$( readlink -f "$0" )" )
declare -r dslc_jar="$mypath/../src/current/src/dslc.jar"
CLASSPATH="$CLASSPATH:@DSLC_CLASSPATH@:$dslc_jar" \
"@JAVA@" @JAVA_OPTS@ \
com.lovullo.dslc.DslCompiler

240
bin/tame 100755
View File

@ -0,0 +1,240 @@
#!/bin/bash
# Client for TAME daemon (tamed)
#
# Copyright (C) 2018 R-T Specialty, LLC.
#
# 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 -euo pipefail
declare -r mypath=$( dirname "$( readlink -f "$0" )" )
declare -ri EX_NOTAMED=1 # tried to start tamed but failed
declare -ri EX_USAGE=64 # incorrect usage; sysexits.h
# Send a single command to a runner and observe the result
#
# stdin will be directed to the runner. stdout of the runner will be
# echoed until a line beginning with "DONE" is found, after which this
# procedure will return with the exit code indicated by the runner.
command-runner()
{
local -ri id="${1?Missing id}"
local -r root="${2?Missing root run path}"
shift 2
local -r base="$root/$id"
local -ri pid=$( cat "$base/pid" )
# TODO flock
verify-runner "$base" "$pid"
# forward signals to runner so that build is actually halted
# (rather than continuing in background after we die)
trap 'kill -TERM $pid &>/dev/null' INT TERM
# all remaining arguments are passed to the runner
echo "$@" > "$base/0"
# output lines from runner until we reach a line stating "DONE"
while read line; do
# don't parse words in the initial read because we may be
# dealing with a lot of lines
if [ "${line:0:5}" == "DONE " ]; then
read _ code _ <<< "$line"
return "$code"
fi
echo "$line"
done < "$base/1"
}
# Verify that a runner is available
#
# If the runner is offline or not owned by $UID, then exit with
# a non-zero status.
verify-runner()
{
local -r base="${1?Missing base}"
local -ri pid="${2?Missing pid}"
ps "$pid" &>/dev/null || {
echo "error: runner $id ($pid) is offline!" >&2
exit "$EX_NOTAMED"
}
test -O "$base/0" || {
echo "error: runner $id ($pid) is not owned by $USER!" >&2
exit "$EX_NOTAMED"
}
}
# Wait somewhat impatiently for tamed
#
# Assumes that tamed's runner 0 is running once the pidfile becomes
# available. Polls for a maximum of six seconds before giving up
# and exiting with a non-zero status.
wait-for-tamed()
{
local -r base="${1?Missing base}"
# we could use inotify, but that is not installed by default
# on Debian systems, so let's just poll rather than introduce
# another dependency (give up after 6 seconds)
local -i i=12
while test $((i--)); do
test ! -f "$base/0/pid" || return 0
sleep 0.5
done
# still not available
echo 'error: tamed still unavailable; giving up' >&2
exit "$EX_NOTAMED"
}
# Start tamed if it is not already running
#
# If tamed is already running, nothing will happen; otherwise, start
# tamed and wait impatiently for the runner to become available.
#
# Even if tamed is started, wait for runner 0 to become available;
# this ensures that tamed is initialized even if this script is run
# after tamed is started but before it has fully come online (e.g
# parallel make).
start-tamed()
{
local -r root="${1?Missing root}"
local -ri pid=$( cat "$root/pid" 2>/dev/null )
ps "$pid" &>/dev/null || {
echo "starting tamed at $root..."
# tell tamed to clean up so that we eliminate race conditions
# with wait-for-tamed (this will also kill any stray processes
# that a previous tamed may have spawned but didn't get the
# chance to clean up)
kill-tamed "$root" || true
# start tamed and allow it to persist for future commands
"$mypath/tamed" "$root" & disown
}
# wait for tamed even if it was already started (just in
# case this script was executed right after tamed started
# but before it is done initializing)
wait-for-tamed "$root"
}
# Kill tamed
#
# Ask tamed to kill itself.
kill-tamed()
{
local -r root="${1?Missing root}"
"$mypath/tamed" --kill "$root"
}
# Filter dslc output to essential information
#
# The original output of dslc is quite noisy; this filters it down
# to only errors and warnings.
#
# Eventually, dslc out to be modified to handle filtering its own
# output rather than wasting cycles doing this filtering.
saneout()
{
awk ' \
/^~~~~\[begin /,/^~~~~\[end / { next } \
/^rm / { next } \
/^COMMAND / { next } \
/^Exception|^\t+at / { \
if ( /^E/ ) { \
print; \
print "Stack trace written to run-*.log"; \
} \
next; \
} \
/([Ww]arning|[Nn]otice)[: ]/ { printf "\033[0;33m"; w++; out=1; } \
/[Ff]atal:/ { printf "\033[0;31m"; out=1; } \
/!|[Ee]rror:/ { printf "\033[0;31m"; e++; out=1; } \
/internal:/ { printf "\033[0;35m"; out=1; } \
/internal error:/ { printf "\033[1m"; out=1; } \
/^[^[]/ || out { print; printf "\033[0;0m"; out=0; } \
'
}
# Output usage information and exit
usage()
{
cat <<EOF
Usage: $0 [-v|--verbose] cmdline
Or: $0 --kill
Send command line CMDLINE to a tamed runner. Start tamed if
not already running.
Options:
--help show this message
--kill kill tamed
-v, --verbose show runner logs
Environment Variables:
TAME_VERBOSE when greater than zero, show runner logs
(see also --verbose)
EOF
exit $EX_USAGE
}
# Run tame
main()
{
local -r root=/run/user/$UID/tamed
local outcmd=saneout
test $# -gt 0 || usage
case "${1:-}" in
--kill) kill-tamed "$root"; exit;;
-v|--verbose) outcmd=cat;;
--help) usage;;
esac
# alternative to --verbose
if [ "${TAME_VERBOSE:-0}" -ge 1 ]; then
outcmd=cat
fi
start-tamed "$root"
# for now we only support a single runner
command-runner 0 "$root" "$@" \
| tee -a "run-0.log" \
| "$outcmd"
}
main "$@"

245
bin/tamed 100755
View File

@ -0,0 +1,245 @@
#!/bin/bash
# Daemon for accepting TAME commands (compilers, linker, etc)
#
# Copyright (C) 2018 R-T Specialty, LLC.
#
# 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 -euo pipefail
declare -r mypath=$( dirname "$( readlink -f "$0" )" )
declare -ri EX_RUNNING=1
declare -ri EX_USAGE=64 # incorrect usage; sysexits.h
declare -ri EX_CANTCREAT=73 # cannot create file; sysexits.h
# number of seconds before runners are considered unused and terminate
declare -ri TAMED_STALL_SECONDS="${TAMED_STALL_SECONDS:-30}"
# set by `main', global for `cleanup'
declare root=
# Create FIFOs for runner
#
# The FIFOs are intended to be attached to stderr and stdout
# of the runner and will be created relative to the given
# root path ROOT.
#
# If a FIFO cannot be created, exit with EX_CANTCREAT.
mkfifos()
{
local -r root="${1?Missing root path}"
mkdir -p "$root"
# note that there's no stderr; see `add-runner'
for n in 0 1; do
rm -f "$root-$n"
mkfifo -m 0600 "$root/$n" || {
echo "fatal: failed to create FIFO at $in"
exit $EX_CANTCREAT
}
# keep FIFOs open so we don't get EOF from writers
tail -f >"$root/$n" &
done
}
# Spawn a runner
#
# A new runner is created by spawning dslc and attaching
# new FIFOs under the given id ID relative to the given
# run path ROOT. The PID of the runner will be stored
# alongside the FIFOs in a pidfile `pid'.
spawn-runner()
{
local -ri id="${1?Missing id}"
local -r root="${2?Missing root run path}"
local -r base="$root/$id"
mkfifos "$base"
# monitor runner usage and kill when inactive
stall-monitor "$base" &
# loop to restart runner in case of crash
while true; do
"$mypath/dslc" < "$base/0" &> "$base/1"
echo "warning: runner $id exited with code ${PIPESTATUS[0]}; restarting" >&2
done &
echo "$!" > "$base/pid"
echo "runner $id ($!): $base"
}
# Kill runner at BASE when it becomes inactive for TAMED_STALL_SECONDS
# seconds
#
# This monitors the modification time on the stdout FIFO. stdin does not
# need to be monitored since dslc immediately echoes back commands it
# receives.
#
# dslc is pretty chatty at the time of writing this, so TAMED_STALL_SECONDS
# can easily be <=30s even for large packages. This may need to change in
# the future if it becomes too much less chatty. Increase that environment
# variable if runners stall unexpectedly in the middle of builds.
stall-monitor()
{
local -r base="${1?Missing base}"
# monitor output FIFO modification time
while true; do
local -i since=$( date +%s )
sleep "$TAMED_STALL_SECONDS"
local -i last=$( stat -c%Y "$base/1" )
# keep waiting if there has been activity since $since
test "$last" -le "$since" || continue
# no activity; kill
local -r pid=$( cat "$base/pid" )
kill "$pid"
wait "$pid" 2>/dev/null
# this stall subprocess is no longer needed
break
done
}
# Exit if tamed is already running at path ROOT
#
# If tamed is already running at ROOT, exit with status
# EX_RUNNING; otherwise, do nothing except output a warning
# if a stale pid file exists.
abort-if-running()
{
local -r root="${1?Missing root rundir}"
local -ri pid=$( cat "$root/pid" 2>/dev/null )
test "$pid" -gt 0 || return 0
! ps "$pid" &>/dev/null || {
echo "fatal: tamed is already running at $root (pid $pid)!"
exit $EX_RUNNING
}
test -z "$pid" || {
echo "warning: clearing stale tamed (pid $pid)"
}
}
# Kill running tamed at path ROOT
#
# If no pidfile is found at ROOT, do nothing. This sends a
# signal only to the parent tamed process, _not_ individual
# runners; the target tamed is expected to clean up itself.
# Consequently, if a tamed terminated abnormally without
# cleaning up, this will not solve that problem.
kill-running()
{
local -r root="${1?Missing root}"
local -r pid=$( cat "$root"/pid 2>/dev/null )
test -n "$pid" || return 0
echo "killing tamed at $root ($pid)..."
kill "$pid"
}
# Clean up child processes before exit
#
# This should be called before exit (perhaps by a trap). Kills
# the entire process group.
#
# Do not attach this to a SIGTERM trap or it will infinitely
# recurse.
cleanup()
{
rm -rf "$root"
kill 0
}
# Output usage information and exit
usage()
{
cat <<EOF
Usage: $0 [--kill] [runpath]
Start tamed and runners. Do not fork into background process.
The default value of RUNPATH is \`/run/user/$UID/tamed'.
Only one runner is currently supported. tamed exits once all
runners have terminated. Runners will be killed once they are
inactive for at least TAMED_STALL_SECONDS (default 30).
Options:
--help show this message
--kill kill a runing tamed at path RUNPATH
Environment Variables:
TAMED_STALL_SECONDS number of seconds of runner inactivity before
runner is automatically killed (default 30)
EOF
exit $EX_USAGE
}
# Run tamed
main()
{
local kill=
case "${1:-}" in
--kill) kill=1; shift;;
--help) usage;;
esac
root="${1:-/run/user/$UID/tamed}"
# kill if requested
test -z "$kill" || {
kill-running "$root"
exit
}
abort-if-running "$root"
# clean up background processes before we exit
trap exit TERM
trap cleanup EXIT
# start fresh
rm -rf "$root"; mkdir -p "$root"
echo $$ > "$root/pid"
# only a single runner for now
spawn-runner 0 "$root"
wait -n
}
main "$@"

36
bootstrap 100755
View File

@ -0,0 +1,36 @@
#!/bin/bash
# Bootstrap from source repository
#
# Copyright (C) 2018 R-T Specialty, LLC.
#
# 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 -euo pipefail
export SAXON_CP="${SAXON_CP?Missing path to saxon9he.jar}"
export RATER_CLASSPATH="${RATER_CLASSPATH:-$SAXON_CP}"
export HOXSL="${HOXSL?Missing path to hoxsl}"
test "${1:-}" = -n || git submodule update --init --recursive
cd progtest \
&& { which npm && npm install || true; } \
&& ./autogen.sh && ./configure \
&& cd - \
&& { test -e hoxsl || ln -s ../hoxsl; } \
&& autoreconf -fvi \
&& ./configure \
&& make all

View File

@ -1,215 +0,0 @@
# @configure_input@
#
# Compiles packages written in the Calc DSL.
#
# Copyright (C) 2018 R-T Specialty, LLC.
#
# 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/>.
#
# Note that this build process is unconventional in order to avoid the startup
# costs that would be associated with executing dslc with each and every package
# (see the other Makefile for more information). Therefore, everything is
# written to .cqueue for later processing by dslc.
#
# The issue of re-building based on timestamps---which Make would normally take
# care of exclusively---must also be given special care now that we are handling
# the building separately from Make. Each enqueued request also touches the
# destination file to update its timestamp, ensuring that it is seen by Make as
# modified (as if it were compiled) and therefore will trigger the building of
# the targets that depend upon it. In the case of the object files (xmlo), a
# temporary file is created when it is enqueued. As part of the queued request
# for compilation is a request to delete this temporary file. In the event that
# the build fails, this temporary file will be seen and will force a rebuild of
# the file, despite its timestamp.
#
# The same issue does not exist for xmle, js, and html files, since they have
# linear dependency trees and dslc will rm the file on failure, which
# obliterates the timestamp.
# #
path_rates := $(path_suppliers)/rates
path_map := map
path_c1map := $(path_map)/c1
path_dsl := rater
path_ui := ui
path_suppliers := suppliers
path_lv := lovullo
path_srv := srv
src_suppliers := $(wildcard $(path_suppliers)/*.xml)
src_map := $(wildcard $(path_map)/*.xml)
src_c1map := $(wildcard $(path_c1map)/*.xml)
dest_summary_html := $(patsubst \
$(path_suppliers)/%.xml, \
$(path_suppliers)/%.html, \
$(src_suppliers))
dest_standalone := $(patsubst \
$(path_suppliers)/%.xml, \
$(path_suppliers)/%.js, \
$(src_suppliers))
dest_map := $(patsubst \
$(path_map)/%.xml, \
$(path_map)/%.xmle, \
$(src_map))
dest_c1map := $(patsubst \
$(path_c1map)/%.xml, \
$(path_c1map)/%.php, \
$(src_c1map))
compiled_suppliers := $(src_suppliers:.xml=.xmlo)
linked_suppliers := $(src_suppliers:.xml=.xmle)
comma := ,
extless_supp_delim := $(subst .xml,,$(subst .xml ,$(comma),$(src_suppliers)))
cqueue=.cqueue
ant = @ANT@ -e
.DELETE_ON_ERROR:
.PHONY: default clean \
interp-rate-tables summary-html c1map \
standalones program-ui program-ui-immediate program-data-copy \
do-build version FORCE
# these files will never be deleted when Make considers them to be intermediate
# (e.g. when building summary pages), since they are still needed or take a
# while to build
.PRECIOUS: %.js %.xml %.xmle %.xmlo
SHELL = /bin/bash -O extglob
default: program-ui c1map FORCE
program-ui: standalones ui/package.js ui/Program.js program-ui-immediate
program-ui-immediate: ui/html/index.phtml
include suppliers.mk
# starts with a fresh cqueue
prexmlo:
@>$(cqueue)
summary-html: $(dest_summary_html) ;
%.html: %.js
@echo "summary $*.xmle $@" >>.cqueue
@touch $@
standalones: $(dest_standalone)
%.xmle: %.xmlo
@echo "link $< $@" >>.cqueue
@touch $@
%.js: %.xmle
@echo "standalone $< $@" >>.cqueue
@touch $@
# C1 XML (specific recipes are in suppliers.mk)
c1map: $(dest_c1map)
%.dot: %.xmlo
@echo "dot $< $@" >> .cqueue
%.dote: %.xmle
@echo "dot $< $@" >> .cqueue
%.svg: %.dote
dot -Tsvg "$<" > "$@"
%.svg: %.dot
dot -Tsvg "$<" > "$@"
%.xml: %.dat
rater/tools/tdat2xml $< > $@
%.xml: %.typelist
rater/tame/build-aux/list2typedef $(*F) < $< > $@
%.csvo: %.csvm
rater/tools/csvm2csv $< > $@
%.csvo: %.csvi
rater/tools/csvi $< > $@
%.csvo: %.csv
cp $< $@
%.xml: %.csvo
rater/tools/csv2xml $< > $@
version: .version.xml
.version.xml: FORCE
git log HEAD^.. -1 --pretty=format:'<version>%h</version>' > .version.xml
ui/program.expanded.xml: ui/program.xml | .version.xml
@echo "progui-expand $< $@" >> .cqueue
ui/Program.js: ui/program.expanded.xml ui/package.js
@echo "progui-class $< $@ include-path=../../../ui/" >> .cqueue
ui/html/index.phtml: ui/program.expanded.xml
@echo "progui-html $< $@ out-path=./" >> .cqueue
ui/package-dfns.xmlo: ui/package-dfns.xml
ui/package-dfns.xml: ui/program.expanded.xml
@echo "progui-pkg $< $@" >> .cqueue
ui/package-map.xmlo: ui/package-map.xml
ui/package-map.xml: ui/program.expanded.xml ui/package-dfns.xml
@echo "progui-pkg-map $< $@" >> .cqueue
# for the time being, this does not depend on clean-rate-tables because $(ant) will
specs:
$(MAKE) -C doc/specs
#
# this will eventually go away once we don't have X-repo klugery
# for the time being, this does not depend on clean-rate-tables because ant will
# run it
clean:
find $(path_suppliers) $(path_map) $(path_c1map) common/ rater/core rater/lv \( \
-name '*.xmlo' \
-o -name '*.xmle' \
-o -name '*.js' \
-o -name '*.html' \
-o -name '*.dep' \
-o -name '*.tmp' \
\) -exec rm -v {} \;
rm -rf $(path_ui)/package-dfns.* \
$(path_ui)/package-map.* \
$(path_ui)/program.expanded.xml \
$(path_ui)/include.js \
$(path_ui)/Program.js \
$(path_ui)/html
find . -path '*/tables/*.csvm' -o -path '*/territories/*.dat' \
| sed 's/\.csvm$$/\.xml/; s/\.dat$$/\.xml/' \
| xargs rm -fv
# generates a Makefile that will properly build all package dependencies; note
# that territory and rate packages also have includes; see top of this file for
# an explanation
suppliers.mk:
$(ant) pkg-dep \
&& mv $(path_ui)/program.dep $(path_ui)/package-dfns.dep
xmlo_cmd='@echo "validate $$(patsubst %.tmp,%.xml,$$<) $$@" >> .cqueue \
&& echo "compile $$(patsubst %.tmp,%.xml,$$<) $$@" >> .cqueue \
&& echo "rm $$(patsubst %.xmlo,%.tmp,$$@)" >> .cqueue \
&& touch $$@ \
&& touch -d +1sec $$(patsubst %.xmlo,%.tmp,$$@) >> .cqueue' \
./rater/tame/build-aux/gen-make common/ $(path_suppliers)/ $(path_dsl)/ $(path_map)/ $(path_ui)/ >$@ \
&& ./rater/tame/build-aux/gen-c1make $(path_c1map)/*.xml >>$@
me-a-sandwich:
@test $$EUID -eq 0 \
&& echo 'You actually ran me as root? Are you insane!?' \
|| echo 'Make it yourself.'
# simply forces a job to run, thereby forcing the invocation of the secondary
# Makefile (this is not explicitly required, because of prepare, but signifies
# intent and is self-documenting)
FORCE: ;

View File

@ -16,15 +16,7 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# This fragment exists as a kluge to provide support for running a command
# after all targets have been run (in this case, dslc).
#
# A list of everything to be compiled is output into .cqueue, which is then
# picked up by dslc; this avoids the overhead of starting the JVM,
# recompiling XSL stylesheets, etc, which is quite substantial.
#
# !!! Unfortunately, this does not yet support parallel job execution.
##
path_rates := $(path_suppliers)/rates
path_map := map
@ -38,63 +30,153 @@ path_srv := srv
path_lvroot := lvroot
path_intralov_root := "intralov-root/@program@"
.PHONY: FORCE prepare program-data-copy lvroot program-ui-immediate test
src_suppliers := $(wildcard $(path_suppliers)/*.xml)
src_map := $(wildcard $(path_map)/*.xml)
src_c1map := $(wildcard $(path_c1map)/*.xml)
JAVA_HEAP_SIZE ?= 5120M
JAVA_STACK_SIZE ?= 5M
dest_summary_html := $(patsubst \
$(path_suppliers)/%.xml, \
$(path_suppliers)/%.html, \
$(src_suppliers))
dest_standalone := $(patsubst \
$(path_suppliers)/%.xml, \
$(path_suppliers)/%.js, \
$(src_suppliers))
dest_map := $(patsubst \
$(path_map)/%.xml, \
$(path_map)/%.xmle, \
$(src_map))
dest_c1map := $(patsubst \
$(path_c1map)/%.xml, \
$(path_c1map)/%.php, \
$(src_c1map))
compiled_suppliers := $(src_suppliers:.xml=.xmlo)
linked_suppliers := $(src_suppliers:.xml=.xmle)
comma := ,
extless_supp_delim := $(subst .xml,,$(subst .xml ,$(comma),$(src_suppliers)))
ant = @ANT@ -e
.PHONY: FORCE default program-data-copy lvroot program-ui-immediate test \
default clean interp-rate-tables summary-html c1map standalones \
program-ui version FORCE
default: program-ui c1map FORCE
.DELETE_ON_ERROR:
# less verbose output; all to runlog
define saneout
time -f 'total time: %E' awk ' \
BEGIN { e=0; w=0; } \
{ printf "[%d] ", systime() >> ".runlog"; print >> ".runlog"; } \
/^~~~~\[begin /,/^~~~~\[end / { next } \
/^rm / { next } \
/^Exception|^\t+at / { \
if ( /^E/ ) { \
print; \
print "Stack trace written to .runlog"; \
} \
next; \
} \
/[Ww]arning:|[Nn]otice:/ { printf "\033[0;33m"; w++; out=1; } \
/[Ff]atal:/ { printf "\033[0;31m"; out=1; } \
/!|[Ee]rror:/ { printf "\033[0;31m"; e++; out=1; } \
/internal:/ { printf "\033[0;35m"; out=1; } \
/internal error:/ { printf "\033[1m"; out=1; } \
/^[^[]/ || out { print; printf "\033[0;0m"; out=0; } \
END { printf "%d error(s); %d warning(s).\n", e, w; } \
'
endef
define _go
touch .cqueue \
&& ( test -s .cqueue || echo "Nothing to be done for \`$@'." ) \
&& echo "$(JAVA_HEAP_SIZE) $(JAVA_STACK_SIZE)" \ \
&& CLASSPATH="$(RATER_CLASSPATH):rater/src/dslc.jar" \
$(JAVA) -Xmx$(JAVA_HEAP_SIZE) -Xss$(JAVA_STACK_SIZE) \
com.lovullo.dslc.DslCompiler < .cqueue 2>&1 \
| $(saneout); \
exit $${PIPESTATUS[0]}; \
@>.cqueue
endef
.NOTPARALLEL:
SHELL = /bin/bash -O extglob
# these files will never be deleted when Make considers them to be intermediate
# (e.g. when building summary pages), since they are still needed or take a
# while to build
.SECONDARY: %.js %.xml %.xmle %.xmlo
all: program-data-copy
program-ui-immediate:
@>.cqueue
@$(MAKE) --no-print-directory -f Makefile.2 program-ui-immediate
@$(MAKE) program-data-copy
@$(_go)
program-ui: standalones ui/package.js ui/Program.js program-ui-immediate
program-ui-immediate: ui/html/index.phtml
program-data-copy:
@>.cqueue
@$(MAKE) --no-print-directory -f Makefile.2 standalones program-ui c1map
@$(_go)
# Note the `$()' here to prevent Automake from inlining this file---it is
# to be generated when imports change, which can be at any time.
include $()suppliers.mk
summary-html: $(dest_summary_html) ;
%.html: %.js
$(TAME) summary $*.xmle $@
standalones: $(dest_standalone)
%.xmle: %.xmlo
$(TAME) link $< $@
%.js: %.xmle
$(TAME) standalone $< $@
# C1 XML (specific recipes are in suppliers.mk)
c1map: $(dest_c1map)
%.dot: %.xmlo
$(TAME) dot $< $@
%.dote: %.xmle
$(TAME) dot $< $@
%.svg: %.dote
dot -Tsvg "$<" > "$@"
%.svg: %.dot
dot -Tsvg "$<" > "$@"
%.xml: %.dat
rater/tools/tdat2xml $< > $@
%.xml: %.typelist
rater/tame/build-aux/list2typedef $(*F) < $< > $@
%.csvo: %.csvm
rater/tools/csvm2csv $< > $@
%.csvo: %.csvi
rater/tools/csvi $< > $@
%.csvo: %.csv
cp $< $@
%.xml: %.csvo
rater/tools/csv2xml $< > $@
version: .version.xml
.version.xml: FORCE
git log HEAD^.. -1 --pretty=format:'<version>%h</version>' > .version.xml
ui/program.expanded.xml: ui/program.xml
$(TAME) progui-expand $< $@
ui/Program.js: ui/program.expanded.xml ui/package.js
$(TAME) progui-class $< $@ include-path=../../../ui/
ui/html/index.phtml: ui/program.expanded.xml
$(TAME) progui-html $< $@ out-path=./
ui/package-dfns.xmlo: ui/package-dfns.xml
ui/package-dfns.xml: ui/program.expanded.xml
$(TAME) progui-pkg $< $@
ui/package-map.xmlo: ui/package-map.xml
ui/package-map.xml: ui/program.expanded.xml ui/package-dfns.xml
$(TAME) progui-pkg-map $< $@
# for the time being, this does not depend on clean-rate-tables because $(ant) will
specs:
$(MAKE) -C doc/specs
# for the time being, this does not depend on clean-rate-tables because ant will
# run it
clean:
find -L $(path_suppliers) $(path_map) $(path_c1map) common/ rater/core rater/lv \( \
-name '*.xmlo' \
-o -name '*.xmle' \
-o -name '*.js' \
-o -name '*.html' \
-o -name '*.dep' \
-o -name '*.tmp' \
-o -name '*.php' \
\) -exec rm -v {} \;
rm -rf $(path_ui)/package-dfns.* \
$(path_ui)/package-map.* \
$(path_ui)/program.expanded.xml \
$(path_ui)/include.js \
$(path_ui)/Program.js \
$(path_ui)/html
find . -path '*/tables/*.csvm' -o -path '*/territories/*.dat' \
| sed 's/\.csvm$$/\.xml/; s/\.dat$$/\.xml/' \
| xargs rm -fv
# generates a Makefile that will properly build all package dependencies; note
# that territory and rate packages also have includes; see top of this file for
# an explanation
suppliers.mk:
$(ant) pkg-dep
mv $(path_ui)/program.dep $(path_ui)/package-dfns.dep
./rater/tame/build-aux/gen-make common/ $(path_suppliers)/ $(path_dsl)/ $(path_map)/ $(path_ui)/ >$@
./rater/tame/build-aux/gen-c1make $(path_c1map)/*.xml >>$@
program-data-copy: standalones program-ui c1map .version.xml
mkdir -p "$(path_lv)/src/node/program/rater/programs/@program@"
mkdir -p "$(path_lv)/src/node/program/classify"
mkdir -p "$(path_lv)/src/node/program/ui/custom"
@ -124,7 +206,7 @@ program-data-copy:
ant -f "$(path_lv)/build.xml" js-mod-order
# TODO: merge this and the above
lvroot: prepare
lvroot: summary-html
mkdir -p "$(path_lvroot)/src/node/program/rater/programs/@program@"
mkdir -p "$(path_lvroot)/src/node/program/classify"
mkdir -p "$(path_lvroot)/src/node/program/ui/custom"
@ -155,28 +237,18 @@ intralov-root: summary-html
ln -fL $(path_dsl)/scripts/*.js "$(path_intralov_root)/rater/scripts/"
ln -fL $(path_suppliers)/*.{html,js} "$(path_intralov_root)/suppliers"
# because of the crazy wildcard target below, we want to ignore
# some Automake-generated stuff
%.am:
%.m4:
%.ac:
%: prepare
@if [[ "$@" != [Mm]akefile ]]; then \
$(MAKE) --no-print-directory -f Makefile.2 $@; \
$(_go); \
fi
clean:
$(MAKE) --no-print-directory -f Makefile.2 clean
prepare: FORCE
@>.cqueue
test: check
check-am: standalones ui/package.js
@$(path_dsl)/build-aux/progtest-runner $(path_suppliers) $(path_tests)
@$(path_dsl)/build-aux/progtest-runner ui/package.xml $(path_tests)/ui
kill-tamed: tamed-die
tamed-die:
$(TAME) --kill
me-a-sandwich:
@test $$EUID -eq 0 \
&& echo 'You actually ran me as root? Are you insane!?' \
|| echo 'Make it yourself.'
FORCE: ;

View File

@ -75,8 +75,7 @@ c1recipe()
)
echo "$dir/$base.php: $file $includes"
echo -e '\t@echo "c1map $< $@" >> .cqueue'
echo -e '\t@touch $@'
echo -e '\t$(TAME) c1map $< $@'
}

View File

@ -54,16 +54,8 @@ resolv-path()
# rule for building
[ -z "$GEN_MAKE" ] && {
echo "%.xmlo:: %.tmp"
echo -e "\t@rm -f \$@ \$<"
[ -n "$xmlo_cmd" ] \
&& echo -e "\t$xmlo_cmd" \
|| echo -e "\ttouch \$@"
echo "%.xmlo:: %.xml | prexmlo"
[ -n "$xmlo_cmd" ] \
&& echo -e "\t$xmlo_cmd" \
|| echo -e "\ttouch \$@"
echo "%.xmlo: %.xml"
echo -e '\t$(TAME) compile $< $@'
export GEN_MAKE="$( pwd )/$0"
exec "$GEN_MAKE" "$@"
@ -119,6 +111,8 @@ until [ $# -eq 0 ]; do (
# recurse on every subdirectory
for p in */; do
[ "$p" == ./ -o "$p" == ../ ] && continue
[ "$p" == node_modules/ -o "$p" == tame/ ] && continue
[ ! -d "$p" ] || ( cd "$OLDPWD" && "$GEN_MAKE" "$path/$p" ) || {
echo "fatal: failed to recurse on $( pwd )/$path/$p" >&2
exit 1

View File

@ -33,13 +33,10 @@ AM_INIT_AUTOMAKE([foreign])
AC_ARG_VAR([JAVA], [The Java executable])
AC_ARG_VAR([ANT], [Apache Ant])
AC_ARG_VAR([DSLC_JAR], [Path to DSL Compiler JAR])
AC_ARG_VAR([TAME], [Path to TAME])
AC_ARG_VAR([TAME], [The TAME compiler])
AC_ARG_VAR([RATER_CLASSPATH], [DSL Compiler Saxon class path])
AC_ARG_VAR([PROGUI_TEST_PATH], [Path to JavaScript tests for Program UI])
# Required version of TAME
AC_SUBST([tame_needed_ver], [1.0.0])
# Auto-discover Java and Ant paths
AC_CHECK_PROGS(JAVA, [java])
AC_CHECK_PROGS(ANT, [ant])
@ -64,34 +61,18 @@ AS_IF([test ! "$DSLC_JAR"],
# TAME is the compiler (whereas dslc invokes it, keeps things in memory, etc)
AS_IF([test ! "$TAME"],
[AC_CHECK_FILE([$CALCROOT/tame],
[AC_SUBST([TAME], [$CALCROOT/tame])],
[AC_CHECK_FILE([$CALCROOT/tame/bin/tame],
[AC_SUBST([TAME], [$CALCROOT/tame/bin/tame])],
[AC_MSG_ERROR(
[TAME not found])])],
[])
AC_MSG_CHECKING([TAME version])
AC_SUBST_FILE([tame_version])
tame_version=$( cat "$TAME/VERSION" )
# We get subtle errors or potential compiler bugs if the TAME version is
# incorrect; check for >= the required version
AS_VERSION_COMPARE([$tame_version], [$tame_needed_ver],
[
AC_MSG_RESULT([$tame_version])
AC_MSG_ERROR([TAME version $tame_needed_ver or greater required])
],
[AC_MSG_RESULT([$tame_version])],
[AC_MSG_RESULT([$tame_version (>$tame_needed_ver)])])
# @program@ in *.in files will be replaced with the program name provided by AC_INIT
AC_SUBST([program], AC_PACKAGE_NAME)
# Final files to be output by `configure'. The path before the colon is the
# destination name; after the colon is the source.
AC_CONFIG_FILES(Makefile:m4_defn(`calc_root')/build-aux/Makefile.in
Makefile.2:m4_defn(`calc_root')/build-aux/Makefile.2.in)
AC_CONFIG_FILES(Makefile:m4_defn(`calc_root')/build-aux/Makefile.in)
# Generate configure script
AC_OUTPUT

View File

@ -40,6 +40,7 @@ AC_SUBST(REV, m4_argn(3, ver_split))
AC_SUBST(SUFFIX, m4_argn(4, ver_split))
AC_ARG_VAR([JAVA], [The Java executable])
AC_ARG_VAR([JAVA_OPTS], [Java options])
AC_CHECK_PROGS(JAVA, [java])
AC_ARG_VAR([SAXON_CP], [Saxon class path])
@ -52,7 +53,16 @@ AS_IF(test ! -d "$HOXSL",
AC_MSG_ERROR([hoxsl path '$HOXSL' does not exist!]))
AC_MSG_RESULT(found)
# BC with RATER_CLASSPATH
DSLC_CLASSPATH="${DSLC_CLASSPATH:-$RATER_CLASSPATH}"
AC_SUBST(DSLC_CLASSPATH, [$DSLC_CLASSPATH])
AC_SUBST([AUTOGENERATED],
["THIS FILE IS AUTOGENERATED! DO NOT MODIFY! See *.in."])
AC_CONFIG_FILES([Makefile doc/Makefile src/init.xsl VERSION])
AC_CONFIG_FILES([bin/dslc],
[chmod +x bin/dslc])
AC_OUTPUT

View File

@ -27,7 +27,7 @@ stylesheets := $(shell find "$(path_src)" \
stexi := $(stylesheets:.xsl=.texi)
info_TEXINFOS = tame.texi
tame_TEXINFOS = todo.texi license.texi $(stexi) tame.css
tame_TEXINFOS = about.texi todo.texi license.texi $(stexi) tame.css
MAKEINFOHTML=$(MAKEINFO) --html --css-include tame.css

193
doc/about.texi 100644
View File

@ -0,0 +1,193 @@
@c This document is part of the TAME manual.
@c Copyright (C) 2018 R-T Specialty, LLC.
@c Permission is granted to copy, distribute and/or modify this document
@c under the terms of the GNU Free Documentation License, Version 1.3 or
@c any later version published by the Free Software Foundation; with no
@c Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
@c A copy of the license is included in the section entitled ``GNU Free
@c Documentation License''.
@node About TAME
@chapter About TAME
@tame{} is The Adaptive Metalanguage,
a programming language and system of tools designed to aid in the
development; understanding; and maintenance of systems performing
numerous calculations on a complex graph of dependencies;
conditions; and a large number of inputs.
This system was developed at R-T Specialty@footnote{
Formerly LoVullo Associates.}
to handle the complexity of comparative insurance rating systems.
It is a domain-specific language@tie{}(DSL) that itself encourages,
through the use of templates,
the creation of sub-DSLs.
@tame{} itself is at heart a calculator@mdash{
}processing only numerical input and output@mdash{
}driven by quantifiers as predicates.
Calculations and quantifiers are written declaratively without concern
for order of execution.
The system has powerful dependency resolution and data flow capabilities.
@tame{} consists of a macro processor (implementing a metalanguage);
numerous compilers for various targets
(JavaScript, HTML documentation and debugging environment, LaTeX,
and others);
linkers; and supporting tools.
The input grammar is XML,
and the majority of the project
(including the macro processor, compilers, and linkers)
is written in XSLT.@footnote{
There is a reason for that odd choice;
until an explanation is provided,
know that someone is perverted enough to implement a full
compiler in XSLT.}
@menu
* Getting Started:: Getting started from a source repository checkout.
* Manual Compilation:: How to compile a source file by hand.
* Compiling With Make:: Using the Makefile (recommended).
@end menu
@node Getting Started
@section Getting Started
To get started,
make sure Saxon version@tie{}9 or later is available and its path
set as @var{SAXON_CP};
that the path to hoxsl is set via @var{HOXSL};
and then run the @samp{bootstrap} script:
@float Figure, f:bootstrap
@example
$ export SAXON_CP=/path/to/saxon9he.jar
$ export HOXSL=/path/to/hoxsl/root
$ ./boostrap
@end example
@caption{Bootstrapping TAME in a source repository checkout}
@end float
@node Manual Compilation
@section Manual Compilation
@emph{Note: TAME is usually controlled through a Makefile;
@pxref{Compiling With Make} to avoid manual compilation
steps.}
@tame{} is controlled through the program in @command{bin/tame}.
When run,
it first spawns a daemon @command{bin/tamed} if it is not already
running.
@command{tamed} is needed to keep the JVM and compiled XSLT templates
in memory,
otherwise each file would incur a steep startup penalty.
@todo{Document commands.
Most developers do not build files directly,
so this is not essential yet.}
@float Figure, f:compile-ex
@example
$ bin/tame compile src/foo.xml src/foo.xmlo
$ bin/tame link src/foo.xmlo src/foo.xmle
$ bin/tame standalone src/foo.xmle src/foo.js
$ bin/tame summary src/foo.xmle src/foo.html
@end example
@caption{Compiling a JavaScript executable and Summary Page}
@end float
To kill the daemon,
pass @samp{--kill} to either @file{bin/tame} or @file{bin/tamed}.
For additional options and environment variables that influence
operation,
pass @samp{--help} to either command.
@node Compiling With Make
@section Compiling With Make
TAME can generate a @url{https://gnu.org/software/make,GNU Makefile}
for you using @url{https://gnu.org/software/automake,Automake} and
@url{https://gnu.org/softeware/autoconf,Autoconf}.
This greatly simplifies building projects by automatically building
all dependencies as needed,
and only when they have changed.@footnote{@c
When their modification timestamps change, specifically.}
The Makefile is generated by a @file{configure} script,
which itself generated by Autoconf using @file{configure.ac} in the
project root:
@float Figure, f:configure-ac
@example
AC_INIT([PROJECT_NAME], [0.0.0], [contact@@email])
m4_define(`calc_root', rater)
m4_include([rater/build-aux/m4/calcdsl.m4])
@end example
@caption{Example @file{configure.ac} in project root.}
@end float
By convention,
TAME is usually available as a submodule under @file{rater/}.
This confusing naming convention may change in the future.
Then, to generate the @file{Makefile}:
@float Figure, f:configure
@example
$ autoreconf -fvi
$ ./configure SAXON_CP=/path/to/saxon9he.jar
@end example
@caption{Invoking @file{configure} to generate @file{Makefile}.}
@end float
@todo{Add more sections.}
@menu
* Common Targets:: Common Makefile targets.
@end menu
@node Common Targets
@subsection Common Targets
A @dfn{target} is something that can be built.
Usually it is a specific file (e.g. @file{foo.js}),
but it can also be a command (also called a @dfn{phony target}).
Here are the most common phony targets that may be useful:
@table @samp
@item all
This is the default target (just type @samp{make}).
Build the UI and all suppliers.
Does not build the Summary Pages,
as they are considered to be debugging tools.
@item summary-html
Build all Summary Pages for programs in @file{suppliers/}.
This is equivalent to building each @file{suppliers/*.html} target
manually.
@item check
@item test
Run test cases in @file{test/}.
@item standalones
Build JavaScript executables for each program in @file{suppliers/}.
This is a dependency of @samp{summary-html}.
@item tamed-die
@item kill-tamed
Kill running tamed for effective user, if any
(@pxref{Manual Compilation}).
@item clean
Delete all file targets.
This may be necessary when upgrading TAME,
for example,
to rebuild all files using the new version.
@end table

View File

@ -1,6 +1,6 @@
\input texinfo
@c This document is part of the TAME manual.
@c Copyright (C) 2015, 2016 R-T Specialty, LLC.
@c Copyright (C) 2015, 2016, 2018 R-T Specialty, LLC.
@c Permission is granted to copy, distribute and/or modify this document
@c under the terms of the GNU Free Documentation License, Version 1.3 or
@c any later version published by the Free Software Foundation; with no
@ -19,7 +19,7 @@
@copying
This manual is for TAME, version @value{VERSION}.
Copyright @copyright{} 2015, 2016 R-T Specialty, LLC.
Copyright @copyright{} 2015, 2016, 2018 R-T Specialty, LLC.
@quotation
Permission is granted to copy, distribute and/or modify this document
@ -51,6 +51,7 @@ Free Documentation License".
@end ifnottex
@menu
* About TAME:: History of TAME and how to use it
* Preprocessor:: Metaprogramming system
* Dependency Graph:: Dependency processing and flow analysis
* Symbol Table:: Lookup table for all objects
@ -97,6 +98,7 @@ TAME
@definfoenclose math,\(,\)
@end ifhtml
@include about.texi
@node Preprocessor
@chapter Preprocessor

6
rater/README.md 100644
View File

@ -0,0 +1,6 @@
# Compatibility Directory
This directory exists for compatibility with earlier build scripts and path
assumptions before TAME was extracted into its own repository. A full
transition will remove this directory.

1
rater/c1map 120000
View File

@ -0,0 +1 @@
../src/current/c1map

1
rater/c1map.xsl 120000
View File

@ -0,0 +1 @@
../src/current/c1map.xsl

1
rater/calc.xsd 120000
View File

@ -0,0 +1 @@
../src/current/calc.xsd

View File

@ -0,0 +1 @@
../src/current/compile.xsl

1
rater/compiler 120000
View File

@ -0,0 +1 @@
../src/current/compiler

1
rater/dot.xsl 120000
View File

@ -0,0 +1 @@
../src/current/dot.xsl

1
rater/include 120000
View File

@ -0,0 +1 @@
../src/current/include/

1
rater/link.xsl 120000
View File

@ -0,0 +1 @@
../src/current/link.xsl

1987
rater/rater.xsd 100644

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
../src/current/standalone.xsl

View File

@ -0,0 +1 @@
../src/current/summary.xsl

1
rater/tame 120000
View File

@ -0,0 +1 @@
../

View File

@ -1380,8 +1380,7 @@
<xsl:function name="eseq:expand-node" as="node()*"
override="yes">
<xsl:function name="eseq:expand-node" as="node()*">
<xsl:param name="node" as="node()" />
<xsl:apply-templates mode="preproc:macros"

View File

@ -2,8 +2,9 @@
dslc_src := $(wildcard com/lovullo/dslc/*.java)
dslc_bin := $(dslc_src:.java=.class)
.PHONY: dslc clean
.PHONY: all all-nodoc dslc clean
all: dslc
dslc: dslc.jar
%.class: %.java

View File

@ -69,17 +69,10 @@ public class DslCompiler
HashMap<String,String> params
) throws Exception
{
if ( cmd.equals( "validate" ) )
// validate before compilation
if ( cmd.equals( "compile" ) )
{
_xsd.validate( doc );
return;
}
else if ( cmd.equals( "rm" ) )
{
// remove file (purposely uncaught)
( new File( src ) ).delete();
return;
}
if ( dest.equals( "" ) )
@ -105,12 +98,17 @@ public class DslCompiler
new StreamResult( new File( dest ) ),
params
);
// TODO: more unique identifier
System.err.println( "DONE 0 " + dest );
}
catch ( Exception e )
{
// delete the output file; it's garbage
destfile.delete();
System.err.println( "DONE 1 " + dest );
// be verbose and unprofessional.
throw e;
}
@ -290,7 +288,8 @@ public class DslCompiler
private static void compileSrc( _DslCompiler dslc, String cmdline ) throws Exception
{
System.err.println( cmdline );
System.err.printf( "COMMAND " + cmdline + "\n" );
String[] args = cmdline.split( " " );
String dest = "";