| git.druid.rocks | index | druid520 | nscc | src/ | nscc.sh |
src/nscc.sh
#!/bin/sh
# nscc -- the nsc compiler driver. nsc (notsuckyc) is a strict,
# explicit c89-like variant with no floats, no structs, no libc, no
# macros, and no implicit anything -- see docs/nsc.btft for the language.
#
# this script is deliberately just glue: it finds its own directory,
# puts the jcplib/ perl modules on PERL5LIB, and runs the eight
# stages (jlex0 -> jparse1 -> jscope2 -> jtype3 -> jdesugar4 ->
# jlower5 -> jselect6 -> jalloc7 -> jemit8), each reading the last
# one's output and writing its own (each stage is its own mini
# pipeline of in -- preproc -- proc -- out). stages run against
# per-stage files in a temp dir: posix sh has no pipefail, so one big
# pipe would let an upstream stage's failure disappear behind the
# last stage's exit code -- with set -e and one file per stage, every
# stage's failure stops the build with its own err: message. -j
# writes the intermediates next to the input (foo.toks.j0 ... foo.s)
# instead of the temp dir, for eyeballing a failed compile. -s makes
# jemit8 emit our own _start (no crt1/libc needed: the binary is
# freestanding) and, on netbsd, the .note.netbsd.ident section --
# the os and version are detected here with uname -s/-r (NSCC_OS and
# NSCC_OSVER in the environment override the detection, for
# cross-compiling).
#
# usage: nscc [-j] [-s] [-o out.s] [-h] foo.c
# output goes to stdout unless -o names a file.
set -e
usage() {
echo "usage: nscc [-j] [-s] [-o out.s] [-h] foo.c" >&2
echo "compiles nsc source into x86_64 (no gnu extensions) att asm." >&2
echo "-j write each stage's intermediate next to foo.c." >&2
echo "-s emit our own _start (freestanding, no crt1) and" >&2
echo " the platform note when on netbsd." >&2
echo "-o FILE write the .s to FILE instead of stdout." >&2
exit ${1:-0}
}
d=$(dirname "$0")
case "$d" in
/*) ;;
*) d=$(CDPATH= cd -- "$d" && pwd) ;;
esac
export PERL5LIB="$d${PERL5LIB:+:$PERL5LIB}"
jflag=0
sflag=0
out=
in=
while [ $# -gt 0 ]; do
case "$1" in
-h|--help) usage 0 ;;
-j) jflag=1 ;;
-s) sflag=1 ;;
-o) shift; [ -n "${1:-}" ] || usage 1; out=$1 ;;
-*) echo "err: unknown flag $1." >&2; usage 1 ;;
*) [ -z "$in" ] || { echo "err: exactly one input file." >&2; usage 1; }; in=$1 ;;
esac
shift
done
[ -n "$in" ] || { echo "err: no input file." >&2; usage 1; }
[ -f "$in" ] || { echo "err: $in: no such file." >&2; exit 1; }
export NSCC_FILE="$in"
# -s: build the target header that rides at the top of the lir (and
# everything after it): "target freestanding os=<uname -s>", plus
# " osver=<uname -r>" on netbsd. the IRs stay self-describing (no
# env plumbing into jemit8), and A/B tests stay pure diffs.
# NSCC_OS/NSCC_OSVER override the detection when already in the
# environment (cross-compiling).
hdr=
if [ "$sflag" = 1 ]; then
os="${NSCC_OS:-$(uname -s)}"
hdr="target freestanding os=$os"
if [ "$os" = "NetBSD" ]; then
hdr="$hdr osver=${NSCC_OSVER:-$(uname -r)}"
fi
fi
if [ "$jflag" = 1 ]; then
"$d/jlex0" < "$in" > "$in.toks.j0"
"$d/jparse1" < "$in.toks.j0" > "$in.cst.j1"
"$d/jscope2" < "$in.cst.j1" > "$in.ast.j2"
"$d/jtype3" < "$in.ast.j2" > "$in.tast.j3"
"$d/jdesugar4" < "$in.tast.j3" > "$in.cast.j4"
if [ -n "$hdr" ]; then
{ printf '%s\n' "$hdr"; cat "$in.cast.j4"; } | "$d/jlower5" > "$in.lir.j5"
else
"$d/jlower5" < "$in.cast.j4" > "$in.lir.j5"
fi
"$d/jselect6" < "$in.lir.j5" > "$in.mir0.j6"
"$d/jalloc7" < "$in.mir0.j6" > "$in.mir1.j7"
if [ -n "$out" ]; then
"$d/jemit8" < "$in.mir1.j7" > "$out"
else
"$d/jemit8" < "$in.mir1.j7" > "$in.s"
fi
exit 0
fi
tmp=$(mktemp -d "${TMPDIR:-/tmp}/nscc.XXXXXX") || exit 1
trap 'rm -rf "$tmp"' EXIT
"$d/jlex0" < "$in" > "$tmp/0"
"$d/jparse1" < "$tmp/0" > "$tmp/1"
"$d/jscope2" < "$tmp/1" > "$tmp/2"
"$d/jtype3" < "$tmp/2" > "$tmp/3"
if [ -n "$hdr" ]; then
{ printf '%s\n' "$hdr"; "$d/jdesugar4" < "$tmp/3"; } > "$tmp/4"
else
"$d/jdesugar4" < "$tmp/3" > "$tmp/4"
fi
"$d/jlower5" < "$tmp/4" > "$tmp/5"
"$d/jselect6" < "$tmp/5" > "$tmp/6"
"$d/jalloc7" < "$tmp/6" > "$tmp/7"
if [ -n "$out" ]; then
"$d/jemit8" < "$tmp/7" > "$out"
else
"$d/jemit8" < "$tmp/7"
fi