#!/bin/sh
#---help---
# Usage:
#   $0 build [options]
#   $0 install [options]
#   $0 (-h | --help)
#
# Compile and install tree-sitter grammar as a .so library.  This script should
# be used in all tree-sitter grammar aports to simplify maintenance.
#
# Options:
#   -q <querydir> Location of directory with queries (.scm files) to be
#                 installed (defaults to $PWD/queries).
#
#   -s <srcdir>   Location of the source directory with grammar.json and C/C++
#                 sources (defaults to $PWD/src).
#
#   -n <name>     Name of the grammar (defaults to name specified in
#                 grammar.json converted to kebab-case).
#
# Environment variables:
#   CC, CXX, LD, CFLAGS, CXXFLAGS, LDFLAGS, DESTDIR, PREFIX
#---help---
set -eu

PROGNAME='abuild-tree-sitter'

: ${CC:="cc"}
: ${CFLAGS:=}
: ${CXX:="c++"}
: ${CXXFLAGS:=}
: ${LD:="ld"}
: ${LDFLAGS:=}
: ${DESTDIR:=}
: ${PREFIX:="/usr"}

: ${CFLAGS_BASE:="-fPIC -Wall -std=c99"}
: ${CXXFLAGS_BASE:="-fPIC -Wall -fno-exceptions"}
: ${LDFLAGS_BASE:="-shared"}


help() {
	local tag='#---help---'
	sed -n "/^$tag/,/^$tag/{/^$tag/d; s/^# \\?//; s/\$0/$PROGNAME/; p}" "$0"
}

die() {
	printf "$PROGNAME: %s\n" "$@" >&2
	exit 1
}

subcmd=
case "${1:-}" in
	'' | -h | --help) help; exit 0;;
	-*) die 'missing subcommand';;
	*) subcmd=$1; shift;;
esac

querydir='./queries'
srcdir='./src'
destdir=
name=
while getopts ':q:s:D:h' OPT; do
	case "$OPT" in
		q) querydir=$OPTARG;;
		s) srcdir=$OPTARG;;
		D) destdir=$OPTARG;;
		n) name=$OPTARG;;
		h) help; exit 0;;
		\?) die "unknown option: -$OPTARG";;
	esac
done
shift $((OPTIND - 1))

[ "$name" ] || name=$(jq -re '.name | gsub("_"; "-")' "$srcdir"/grammar.json)

case "$subcmd" in
build)
	cd "$srcdir"

	set -x
	$CC $CFLAGS_BASE $CFLAGS -c ./*.c
	if find -name '*.cc' | grep -q .; then
		$CXX $CXXFLAGS_BASE $CXXFLAGS -c ./*.cc
		$CXX $LDFLAGS_BASE $LDFLAGS -o $name.so ./*.o
	else
		$CC $LDFLAGS_BASE $LDFLAGS -o $name.so ./*.o
	fi
;;
install)
	set -x
	# Some programs expect grammar libs as <lang>.so in a specific
	# directory, some expect libtree-sitter-<lang>.so on the library path.
	install -D -m755 "$srcdir"/*.so -t "$DESTDIR$PREFIX"/lib/tree-sitter/
	ln -s tree-sitter/$name.so "$DESTDIR$PREFIX"/lib/libtree-sitter-$name.so

	if [ -d "$querydir" ]; then
		install -D -m755 "$querydir"/*.scm -t "$DESTDIR$PREFIX"/share/tree-sitter/queries/$name/
	fi
;;
*)
	die "invalid subcommand: $subcmd"
;;
esac
