#!/bin/sh
# atheme-services: A collection of minimalist IRC services
# mkhooktypes.sh: Code generator for type-safe hooks.
#
# Copyright (c) 2009 Atheme Project (http://www.atheme.org)
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

if [ "$#" != 1 ]; then
	echo "Usage: $0 specfile >hfile" >&2
	exit 64
fi

echo "/* Generated by $0 from $1, do not edit! */"
echo "/* Type checking for hook functions */"
echo
while read hook type; do
	case $hook:$type in
	[#]*|:)
		continue
		;;
	*:void)
		echo "#define hook_call_$hook() hook_call_event(\"$hook\", NULL)"
		# Still require a dummy void * function parameter here.
		echo "#define hook_add_$hook(f) hook_add_hook(\"$hook\", f)"
		echo "#define hook_add_first_$hook(f) hook_add_hook_first(\"$hook\", f)"
		echo "#define hook_del_$hook(f) hook_del_hook(\"$hook\", f)"
		;;
	*)
		echo "#define hook_call_$hook(x) hook_call_event(\"$hook\", ENSURE_TYPE(x, $type))"
		echo "#define hook_add_$hook(f) hook_add_hook(\"$hook\", (void (*)(void *))ENSURE_TYPE(f, void (*)($type)))"
		echo "#define hook_add_first_$hook(f) hook_add_hook_first(\"$hook\", (void (*)(void *))ENSURE_TYPE(f, void (*)($type)))"
		echo "#define hook_del_$hook(f) hook_del_hook(\"$hook\", (void (*)(void *))ENSURE_TYPE(f, void (*)($type)))"
		;;
	esac
done < "$1"
