#!/bin/sh

##########################################################################
#
#This script is used to create API C source file for Aubit libraraies
#to be loaded at run-time using dlopen() function call.
#
#
#
#
#
#
##########################################################################

#Get settings
if [ "$AUBITDIR" = "" ]
then
	AUBITDIR=../..
fi


. $AUBITDIR/etc/aubitrc


if [ $# -lt 1 -o "$1" = "--help" ]
then
	echo "Creates run-time loadable library API definition source code "
    echo " "
	echo "Usage:   dlmagic <SpecFile> [<APIName>] [<EnvVar>] > <APIname>.c"
	echo "  SpecFile - contains specifications for the API"
	echo "  APIName - API name (will be overwritten by LIBRARY tag if declared"
	echo "      in SpecFile)"
	echo "  EnvVar - Environment variable to read (will be overwritten by"
	echo "      VARIABLE tag if declared in the SpecFile)"
    echo " "
    echo "Example: "
    echo "  dlmagic sqlapi.spec SQL SQLTYPE > API_SQL.c "
    echo " "
	echo "SpecFile file format:"
	echo "  func-name param-type param-name ... -> returns"
	echo "  line beginning with * is a comment"
	echo "  line beginning with # or / is included in the output Eg #define //comment etc"
    echo " "
    echo "Example input File :"
    echo "	LIBRARY TEST"
    echo "	VARIABLE VTEST"
    echo "	* This is a comment - Note - there are no spaces for void* int* etc."
    echo "	pdf_rep_print void* rep,int a,int s,int right_margin -> int*"
    echo "	disp_fields int n int attr ... -> int"
    echo " "

	exit 0
fi

specfile=$1

if [ "$2" == "-h" ]
then
	MAKE_HEADER=1
else
	if [ "$2" == "-H" ]
	then
		MAKE_HEADER=2
	else
		lib=$2
		env=$3
	fi
fi

lib_prefix=
api_prefix=

if grep LIBRARY $specfile > /dev/null
then
	lib=`$AWK '/^LIBRARY /{print $2}' $specfile`
fi

if grep VARIABLE $specfile > /dev/null
then
	env=`$AWK '/^VARIABLE /{print $2}' $specfile`
fi

#if you want prefix to be added to API function names
if grep API_PREFIX $specfile > /dev/null
then
	api_prefix=`$AWK '/^API_PREFIX /{print $2}' $specfile`
fi

#if you want prefix to be added to LIB functions calls
if grep LIB_PREFIX $specfile > /dev/null
then
	lib_prefix=`$AWK '/^LIB_PREFIX /{print $2}' $specfile`
fi

#name of the headers file to be refgerenced with #include
if grep HEADER_FILE $specfile > /dev/null
then
	HEADER_FILE=`$AWK '/^HEADER_FILE /{print $2}' $specfile`
fi



#echo "/* Library=$lib env=$env */"

if [ "$MAKE_HEADER" = "1" -o "$MAKE_HEADER" = "2" ]
then
	if  [ $MAKE_HEADER = "2" ]
	then
		use_prefix=1
	else
		use_prefix=0
	fi

	$AWK -v use_prefix=$use_prefix -v lib="$lib" -v env="$env" -v lib_prefix="$lib_prefix" -v api_prefix="$api_prefix" -v HEADER_FILE="$HEADER_FILE" '
	BEGIN {
		FS="[ \t,]+"
		print ""
		print "/*"
		print " * lib=" lib " env=" env " lib_prefix=" lib_prefix " api_prefix=" api_prefix
		print " * @file"
		print " * Function prototypes"
		print " *"
		print " * This file was created from .spec file of same name, using dlmagic script"
		print " * - if you need to edit it, edit .spec file instad, and use [make filename.h]"
		print " * to re-create it."
		print " *"
		print " * @todo See if the functions are static"
		print " * or to be externally seen"
		print " */"
		print ""
		print "/*******************************************************************"
		print "* (c) 1997-2005 Aubit Computing Ltd."
		print "*"
		print "*"
		print "********************************************************************/"
		print ""
		print "/*"
		print "====================================================================="
		print "                    Functions prototypes"
		print "====================================================================="
		print "*/"
		print ""
	if (use_prefix==0) {
		print "#ifndef __" lib "_H__"
		print "#define __" lib "_H__"
	} else {
		print "#ifndef __" lib "_LIB_H__"
		print "#define __" lib "_LIB_H__"
	}
print "#ifdef __cplusplus"
print "extern \"C\""
print "{"
print "#endif"
		print ""
	}
	/^LIBRARY / {next}
	/^VARIABLE / {next}
	/^HEADER_FILE / {next}
	/^MULTILOAD_LIBRARY/ {next}
	/^API_PREFIX / {next}
	/^LIB_PREFIX / {next}
	/^MAP / { map[$2]=$3; next}
	/^#/ {print
		next
	}
	/^\// {print
		next
	}
    /^extern/ {print
		next
	}
	/^\/\*/ {print
		next
	}
	/^ \*/ {print
		next
	}
	/^\*\// {print
		next
	}
	/^$/ {next}
	/^\*/ {next	}
	/^[ 	]*$/ {next}
	{
	fname=$1
	rtype="void"

	c=0
	for (a=2;a<=NF;a++) 
	{
		if ($a==" "||$a=="\t"||$a==",") continue;
		param_type[c]=$a
		if (param_type[c]=="->")
		{
			param_type[c]=""
			a++
			rtype=$a
			break
		}

		if (param_type[c]=="...")
		{
			param_name[c]=""
			a++
			c++
			break
		}


		a++
		param_name[c]=$a
		c++;
	}

    if (c==0)
    {
		param_name[c]=""
		param_type[c]="void"
        c++
    }


	if (use_prefix==0) {
		printf rtype " " api_prefix fname "("
	} else {
		printf rtype " " lib_prefix fname "("
	}
	va_start=""
	args=""
	for (b=0;b<c;b++)
	{
		printf("%s %s",param_type[b],param_name[b]);
		
		if (param_type[b]=="...")
		{
			va_start=last;
			args=args ",&ap"
		}
		else
		{
			args=args "," param_name[b]
		}

		last=param_name[b]
		
		if (b<c-1)
		{
			printf(",");
		}
	}
	args=substr(args,2)
	print ");"
	print ""
	}
	' < $specfile
	echo "#ifdef __cplusplus"
	echo "}"
	echo "#endif"
	echo "#endif  /* #ifdef __" lib "_H__  */"
	echo ""

    exit 0
fi


$AWK -v lib="$lib" -v env="$env" -v lib_prefix="$lib_prefix" -v api_prefix="$api_prefix" -v HEADER_FILE="$HEADER_FILE" '

function ring(rtype) {
if (rtype=="char*") { print "A4GL_debug(\"Returning (%s)\",rval);"; return;}
if (rtype=="void*") { print "A4GL_debug(\"Returning (%p)\",rval);"; return;}
if (rtype=="int") { print "A4GL_debug(\"Returning '%d'\",rval);"; return;}
print "A4GL_debug(\"Returning Unknown '%p'\",rval);"
}
function ping(rtype,name) {
if (rtype=="char*")  return "(%s)"
if (rtype=="char")  return "(%c)"
if (rtype=="void*")  return "%p"
if (rtype=="va_list*")  return "%p"
if (rtype=="int") return "%d"
return "%p" 
#print "Unknown type : " rtype > "dlmagic.log"
}


BEGIN {
FS="[ 	,]+"
print "/*"
print " * lib=" lib " env=" env " lib_prefix=" lib_prefix " api_prefix=" api_prefix
print " * @file"
print " * File definition"
print " *"
print " * This file was created from .spec file of same name, using dlmagic script"
print " * - if you need to edit it, edit .spec file instad, and use [make filename.c]"
print " * to re-create it."
print " *"
print " * @todo Add Doxygen comments to file"
print " * @todo Take the prototypes here declared. See if the functions are static"
print " * or to be externally seen"
print " * @todo Doxygen comments to add to functions"
print " */"
print ""
print "/*******************************************************************"
print "* (c) 1997-2005 Aubit Computing Ltd."
print "*"
print "*"
print "********************************************************************/"
print ""
print ""
print "#include \"a4gl_libaubit4gl_int.h\""
print ""
print "static void *libptr=0;"
print "static int (*func)();"
#print "static double (*func_d)();"
#print "void *A4GL_find_func(void *p,char *s);"
print "int A4GLself" lib "_initlib (void);"
print "void A4GLself" lib "_clrlibptr (void);"
print ""
print "/**"
print " * Library init function."
print " *"
print " * @todo : explain ussage and parameters."
print " * @return ."
print " */"
print ""
print "void A4GLself" lib "_clrlibptr (void) {"
print "    libptr=(void *)0;"
print "}"
print ""
print "int A4GLself" lib "_initlib (void) {"
print "  libptr=(void *)1;"
print "  return " lib_prefix "A4GLself" lib "_initlib();"

print "}"
print ""
print ""
}
/^LIBRARY / {next}
/^VARIABLE / {next}
/^HEADER_FILE / {next}
/^MULTILOAD_LIBRARY/ {next}
/^API_PREFIX / {next}
/^LIB_PREFIX / {next}
/MAP / { map[$2]=$3; next}
/^#/ {print
	next
}
/^\// {print
	next
}
/^extern/ {print
	next
}
/^ \*/ {print
	next
}
/^\*\// {print
	next
}
/^\*/ {next}
/^$/ {next}

/^[ 	]*$/ {next}
{
fname=$1
call_fname=$1
rtype="void"

c=0
for (a=2;a<=NF;a++) {

param_type[c]=$a
if (param_type[c]=="->") {
	param_type[c]=""
	a++
	rtype=$a
	break
}

if (param_type[c]=="...") {
	param_name[c]=""
    call_fname="internal_"fname
	a++
	c++
	break
}


a++
param_name[c]=$a
c++;
}


#THIS SHOULD BE PART OF .spec file
#print ""
#print "/**"
#print " * API call function for xyz ."
#print " *"
#print " * @todo : explain ussage and parameters."
#print " * @param xyz Explain me..."
#print " * @return xyz Explain me..."
#print " */"
#print ""

printf rtype " " api_prefix fname "("
va_start=""
args=""
debug_args="Call to " rtype " " api_prefix fname "("

for (b=0;b<c;b++) {
	printf("%s %s",param_type[b],param_name[b]);
	if (param_type[b]=="...") {
		va_start=last;
		args=args ",&ap"
		if (b) debug_args=debug_args "," 
		debug_args=debug_args ping("va_list*",param_name[b]);
	} else {
		if (b) debug_args=debug_args "," 
		debug_args=debug_args ping(param_type[b],param_name[b])
		args=args "," param_name[b]
	}
	last=param_name[b]
	if (b<c-1) {
		printf(",");
	}
}
args=substr(args,2)
print ") {"
if (va_start!="") {print "va_list ap;"}
if (rtype!="void") {
	print rtype " rval;"
}

print "   if (libptr==0) A4GLself" lib "_initlib();"
if (map[call_fname]) cfname=map[call_fname];
else cfname=call_fname;


fname=lib_prefix cfname

if (va_start!="") {
	print "   va_start(ap," va_start ");"
}

if (rtype=="void")
	print fname " (" args ");"
else {
	print "   rval=(" rtype ")" fname "(" args ");"
	print "return rval;"
}

print "}"
print ""

}' < $specfile


exit

