#ifdef WIN
#pragma warning (disable: 4786) // disable warning for STL maps
#pragma warning (disable: 4018) // disable warning for comparing signed and unsigned
#endif /* WIN */

#include <stdarg.h>
#include "dpuserType.h"
#include "../dpuser_utils.h"
#include "utils.h"

std::list<FuncProcInfo> funcProcOrder;

int indexBase = 1;

// in most cases the lvalue from a typeCon is copied to dvalue
// and convalue is converted to typeDbl. In functions.cpp und procedures.cpp
// the arguments-check will fail therefore. So before calling any functions
// in these two files, purify_typeCon() has to be applied to conValues with typeCon
void purify_typeCon(conValue &c)
{
	if (c.dvalue == (double)c.lvalue) {
		c.type = typeCon;
		c.dvalue = 0.0;
	}
}

int findProc(dpString &name) {
	int i, which = -1;
	
	for (i = 0; i < procs.size(); i++) {
		if (procs[i].name == name) which = i;
	}
	if (which == -1) {
		throw dpuserTypeException("Unknown procedure\n");
	}
	return which;
}

void checkProcArgs(dpString name) {
	findProc(name);
}

void checkProcArgs(dpString name, dpuserType &arg0) {
	int which;

	which = findProc(name);
	if (!(arg0.type & procs[which].args[0]))
		throw dpuserTypeException("First argument is of wrong type\n");
}

void checkProcArgs(dpString name, dpuserType &arg0, dpuserType &arg1) {
	int which;

	which = findProc(name);
	if (!(arg0.type & procs[which].args[0]))
		throw dpuserTypeException("First argument is of wrong type\n");
	if (!(arg1.type & procs[which].args[1]))
		throw dpuserTypeException("Second argument is of wrong type\n");
}

void checkProcArgs(dpString name, dpuserType &arg0, dpuserType &arg1, dpuserType &arg2) {
	int which;

	which = findProc(name);
	if (!(arg0.type & procs[which].args[0]))
		throw dpuserTypeException("First argument is of wrong type\n");
	if (!(arg1.type & procs[which].args[1]))
		throw dpuserTypeException("Second argument is of wrong type\n");
	if (!(arg2.type & procs[which].args[2]))
		throw dpuserTypeException("Third argument is of wrong type\n");
}

void checkProcArgs(dpString name, dpuserType &arg0, dpuserType &arg1, dpuserType &arg2, dpuserType &arg3) {
	int which;

	which = findProc(name);
	if (!(arg0.type & procs[which].args[0]))
		throw dpuserTypeException("First argument is of wrong type\n");
	if (!(arg1.type & procs[which].args[1]))
		throw dpuserTypeException("Second argument is of wrong type\n");
	if (!(arg2.type & procs[which].args[2]))
		throw dpuserTypeException("Third argument is of wrong type\n");
	if (!(arg3.type & procs[which].args[3]))
		throw dpuserTypeException("Forth argument is of wrong type\n");
}

void checkProcArgs(dpString name, dpuserType &arg0, dpuserType &arg1, dpuserType &arg2, dpuserType &arg3, dpuserType &arg4) {
	int which;

	which = findProc(name);
	if (!(arg0.type & procs[which].args[0]))
		throw dpuserTypeException("First argument is of wrong type\n");
	if (!(arg1.type & procs[which].args[1]))
		throw dpuserTypeException("Second argument is of wrong type\n");
	if (!(arg2.type & procs[which].args[2]))
		throw dpuserTypeException("Third argument is of wrong type\n");
	if (!(arg3.type & procs[which].args[3]))
		throw dpuserTypeException("Forth argument is of wrong type\n");
	if (!(arg4.type & procs[which].args[4]))
		throw dpuserTypeException("Fifth argument is of wrong type\n");
}

void checkProcArgs(dpString name, dpuserType &arg0, dpuserType &arg1, dpuserType &arg2, dpuserType &arg3, dpuserType &arg4, dpuserType &arg5) {
	int which;

	which = findProc(name);
	if (!(arg0.type & procs[which].args[0]))
		throw dpuserTypeException("First argument is of wrong type\n");
	if (!(arg1.type & procs[which].args[1]))
		throw dpuserTypeException("Second argument is of wrong type\n");
	if (!(arg2.type & procs[which].args[2]))
		throw dpuserTypeException("Third argument is of wrong type\n");
	if (!(arg3.type & procs[which].args[3]))
		throw dpuserTypeException("Forth argument is of wrong type\n");
	if (!(arg4.type & procs[which].args[4]))
		throw dpuserTypeException("Fifth argument is of wrong type\n");
	if (!(arg5.type & procs[which].args[5]))
		throw dpuserTypeException("Sixth argument is of wrong type\n");
}

void checkProcArgs(dpString name, dpuserType &arg0, dpuserType &arg1, dpuserType &arg2, dpuserType &arg3, dpuserType &arg4, dpuserType &arg5, dpuserType &arg6) {
	int which;

	which = findProc(name);
	if (!(arg0.type & procs[which].args[0]))
		throw dpuserTypeException("First argument is of wrong type\n");
	if (!(arg1.type & procs[which].args[1]))
		throw dpuserTypeException("Second argument is of wrong type\n");
	if (!(arg2.type & procs[which].args[2]))
		throw dpuserTypeException("Third argument is of wrong type\n");
	if (!(arg3.type & procs[which].args[3]))
		throw dpuserTypeException("Forth argument is of wrong type\n");
	if (!(arg4.type & procs[which].args[4]))
		throw dpuserTypeException("Fifth argument is of wrong type\n");
	if (!(arg5.type & procs[which].args[5]))
		throw dpuserTypeException("Sixth argument is of wrong type\n");
	if (!(arg6.type & procs[which].args[6]))
		throw dpuserTypeException("Seventh argument is of wrong type\n");
}

void checkProcArgs(dpString name, dpuserType &arg0, dpuserType &arg1, dpuserType &arg2, dpuserType &arg3, dpuserType &arg4, dpuserType &arg5, dpuserType &arg6, dpuserType &arg7) {
	int which;

	which = findProc(name);
	if (!(arg0.type & procs[which].args[0]))
		throw dpuserTypeException("First argument is of wrong type\n");
	if (!(arg1.type & procs[which].args[1]))
		throw dpuserTypeException("Second argument is of wrong type\n");
	if (!(arg2.type & procs[which].args[2]))
		throw dpuserTypeException("Third argument is of wrong type\n");
	if (!(arg3.type & procs[which].args[3]))
		throw dpuserTypeException("Forth argument is of wrong type\n");
	if (!(arg4.type & procs[which].args[4]))
		throw dpuserTypeException("Fifth argument is of wrong type\n");
	if (!(arg5.type & procs[which].args[5]))
		throw dpuserTypeException("Sixth argument is of wrong type\n");
	if (!(arg6.type & procs[which].args[6]))
		throw dpuserTypeException("Seventh argument is of wrong type\n");
	if (!(arg7.type & procs[which].args[7]))
		throw dpuserTypeException("Eighth argument is of wrong type\n");
}

void checkProcArgs(dpString name, dpuserType &arg0, dpuserType &arg1, dpuserType &arg2, dpuserType &arg3, dpuserType &arg4, dpuserType &arg5, dpuserType &arg6, dpuserType &arg7, dpuserType &arg8) {
	int which;

	which = findProc(name);
	if (!(arg0.type & procs[which].args[0]))
		throw dpuserTypeException("First argument is of wrong type\n");
	if (!(arg1.type & procs[which].args[1]))
		throw dpuserTypeException("Second argument is of wrong type\n");
	if (!(arg2.type & procs[which].args[2]))
		throw dpuserTypeException("Third argument is of wrong type\n");
	if (!(arg3.type & procs[which].args[3]))
		throw dpuserTypeException("Forth argument is of wrong type\n");
	if (!(arg4.type & procs[which].args[4]))
		throw dpuserTypeException("Fifth argument is of wrong type\n");
	if (!(arg5.type & procs[which].args[5]))
		throw dpuserTypeException("Sixth argument is of wrong type\n");
	if (!(arg6.type & procs[which].args[6]))
		throw dpuserTypeException("Seventh argument is of wrong type\n");
	if (!(arg7.type & procs[which].args[7]))
		throw dpuserTypeException("Eighth argument is of wrong type\n");
	if (!(arg8.type & procs[which].args[8]))
		throw dpuserTypeException("Ninth argument is of wrong type\n");
}

void checkProcArgs(dpString name, dpuserType &arg0, dpuserType &arg1, dpuserType &arg2, dpuserType &arg3, dpuserType &arg4, dpuserType &arg5, dpuserType &arg6, dpuserType &arg7, dpuserType &arg8, dpuserType &arg9) {
	int which;

	which = findProc(name);
	if (!(arg0.type & procs[which].args[0]))
		throw dpuserTypeException("First argument is of wrong type\n");
	if (!(arg1.type & procs[which].args[1]))
		throw dpuserTypeException("Second argument is of wrong type\n");
	if (!(arg2.type & procs[which].args[2]))
		throw dpuserTypeException("Third argument is of wrong type\n");
	if (!(arg3.type & procs[which].args[3]))
		throw dpuserTypeException("Forth argument is of wrong type\n");
	if (!(arg4.type & procs[which].args[4]))
		throw dpuserTypeException("Fifth argument is of wrong type\n");
	if (!(arg5.type & procs[which].args[5]))
		throw dpuserTypeException("Sixth argument is of wrong type\n");
	if (!(arg6.type & procs[which].args[6]))
		throw dpuserTypeException("Seventh argument is of wrong type\n");
	if (!(arg7.type & procs[which].args[7]))
		throw dpuserTypeException("Eighth argument is of wrong type\n");
	if (!(arg8.type & procs[which].args[8]))
		throw dpuserTypeException("Ninth argument is of wrong type\n");
	if (!(arg9.type & procs[which].args[9]))
		throw dpuserTypeException("Tenth argument is of wrong type\n");
}

void checkProcArgs(dpString name, dpuserType &arg0, dpuserType &arg1, dpuserType &arg2, dpuserType &arg3, dpuserType &arg4, dpuserType &arg5, dpuserType &arg6, dpuserType &arg7, dpuserType &arg8, dpuserType &arg9, dpuserType &arg10) {
	int which;

	which = findProc(name);
	if (!(arg0.type & procs[which].args[0]))
		throw dpuserTypeException("First argument is of wrong type\n");
	if (!(arg1.type & procs[which].args[1]))
		throw dpuserTypeException("Second argument is of wrong type\n");
	if (!(arg2.type & procs[which].args[2]))
		throw dpuserTypeException("Third argument is of wrong type\n");
	if (!(arg3.type & procs[which].args[3]))
		throw dpuserTypeException("Forth argument is of wrong type\n");
	if (!(arg4.type & procs[which].args[4]))
		throw dpuserTypeException("Fifth argument is of wrong type\n");
	if (!(arg5.type & procs[which].args[5]))
		throw dpuserTypeException("Sixth argument is of wrong type\n");
	if (!(arg6.type & procs[which].args[6]))
		throw dpuserTypeException("Seventh argument is of wrong type\n");
	if (!(arg7.type & procs[which].args[7]))
		throw dpuserTypeException("Eighth argument is of wrong type\n");
	if (!(arg8.type & procs[which].args[8]))
		throw dpuserTypeException("Ninth argument is of wrong type\n");
	if (!(arg9.type & procs[which].args[9]))
		throw dpuserTypeException("Tenth argument is of wrong type\n");
	if (!(arg10.type & procs[which].args[10]))
		throw dpuserTypeException("Eleventh argument is of wrong type\n");
}

void checkProcArgs(dpString name, dpuserType &arg0, dpuserType &arg1, dpuserType &arg2, dpuserType &arg3, dpuserType &arg4, dpuserType &arg5, dpuserType &arg6, dpuserType &arg7, dpuserType &arg8, dpuserType &arg9, dpuserType &arg10, dpuserType &arg11) {
	int which;

	which = findProc(name);
	if (!(arg0.type & procs[which].args[0]))
		throw dpuserTypeException("First argument is of wrong type\n");
	if (!(arg1.type & procs[which].args[1]))
		throw dpuserTypeException("Second argument is of wrong type\n");
	if (!(arg2.type & procs[which].args[2]))
		throw dpuserTypeException("Third argument is of wrong type\n");
	if (!(arg3.type & procs[which].args[3]))
		throw dpuserTypeException("Forth argument is of wrong type\n");
	if (!(arg4.type & procs[which].args[4]))
		throw dpuserTypeException("Fifth argument is of wrong type\n");
	if (!(arg5.type & procs[which].args[5]))
		throw dpuserTypeException("Sixth argument is of wrong type\n");
	if (!(arg6.type & procs[which].args[6]))
		throw dpuserTypeException("Seventh argument is of wrong type\n");
	if (!(arg7.type & procs[which].args[7]))
		throw dpuserTypeException("Eighth argument is of wrong type\n");
	if (!(arg8.type & procs[which].args[8]))
		throw dpuserTypeException("Ninth argument is of wrong type\n");
	if (!(arg9.type & procs[which].args[9]))
		throw dpuserTypeException("Tenth argument is of wrong type\n");
	if (!(arg10.type & procs[which].args[10]))
		throw dpuserTypeException("Eleventh argument is of wrong type\n");
	if (!(arg11.type & procs[which].args[11]))
		throw dpuserTypeException("Twelfth argument is of wrong type\n");
}

void checkProcArgs(dpString name, dpuserType &arg0, dpuserType &arg1, dpuserType &arg2, dpuserType &arg3, dpuserType &arg4, dpuserType &arg5, dpuserType &arg6, dpuserType &arg7, dpuserType &arg8, dpuserType &arg9, dpuserType &arg10, dpuserType &arg11, dpuserType &arg12) {
	int which;

	which = findProc(name);
	if (!(arg0.type & procs[which].args[0]))
		throw dpuserTypeException("First argument is of wrong type\n");
	if (!(arg1.type & procs[which].args[1]))
		throw dpuserTypeException("Second argument is of wrong type\n");
	if (!(arg2.type & procs[which].args[2]))
		throw dpuserTypeException("Third argument is of wrong type\n");
	if (!(arg3.type & procs[which].args[3]))
		throw dpuserTypeException("Forth argument is of wrong type\n");
	if (!(arg4.type & procs[which].args[4]))
		throw dpuserTypeException("Fifth argument is of wrong type\n");
	if (!(arg5.type & procs[which].args[5]))
		throw dpuserTypeException("Sixth argument is of wrong type\n");
	if (!(arg6.type & procs[which].args[6]))
		throw dpuserTypeException("Seventh argument is of wrong type\n");
	if (!(arg7.type & procs[which].args[7]))
		throw dpuserTypeException("Eighth argument is of wrong type\n");
	if (!(arg8.type & procs[which].args[8]))
		throw dpuserTypeException("Ninth argument is of wrong type\n");
	if (!(arg9.type & procs[which].args[9]))
		throw dpuserTypeException("Tenth argument is of wrong type\n");
	if (!(arg10.type & procs[which].args[10]))
		throw dpuserTypeException("Eleventh argument is of wrong type\n");
	if (!(arg11.type & procs[which].args[11]))
		throw dpuserTypeException("Twelfth argument is of wrong type\n");
	if (!(arg12.type & procs[which].args[12]))
		throw dpuserTypeException("Thirteenth argument is of wrong type\n");
}

void checkProcArgs(dpString name, dpuserType &arg0, dpuserType &arg1, dpuserType &arg2, dpuserType &arg3, dpuserType &arg4, dpuserType &arg5, dpuserType &arg6, dpuserType &arg7, dpuserType &arg8, dpuserType &arg9, dpuserType &arg10, dpuserType &arg11, dpuserType &arg12, dpuserType &arg13) {
	int which;

	which = findProc(name);
	if (!(arg0.type & procs[which].args[0]))
		throw dpuserTypeException("First argument is of wrong type\n");
	if (!(arg1.type & procs[which].args[1]))
		throw dpuserTypeException("Second argument is of wrong type\n");
	if (!(arg2.type & procs[which].args[2]))
		throw dpuserTypeException("Third argument is of wrong type\n");
	if (!(arg3.type & procs[which].args[3]))
		throw dpuserTypeException("Forth argument is of wrong type\n");
	if (!(arg4.type & procs[which].args[4]))
		throw dpuserTypeException("Fifth argument is of wrong type\n");
	if (!(arg5.type & procs[which].args[5]))
		throw dpuserTypeException("Sixth argument is of wrong type\n");
	if (!(arg6.type & procs[which].args[6]))
		throw dpuserTypeException("Seventh argument is of wrong type\n");
	if (!(arg7.type & procs[which].args[7]))
		throw dpuserTypeException("Eighth argument is of wrong type\n");
	if (!(arg8.type & procs[which].args[8]))
		throw dpuserTypeException("Ninth argument is of wrong type\n");
	if (!(arg9.type & procs[which].args[9]))
		throw dpuserTypeException("Tenth argument is of wrong type\n");
	if (!(arg10.type & procs[which].args[10]))
		throw dpuserTypeException("Eleventh argument is of wrong type\n");
	if (!(arg11.type & procs[which].args[11]))
		throw dpuserTypeException("Twelfth argument is of wrong type\n");
	if (!(arg12.type & procs[which].args[12]))
		throw dpuserTypeException("Thirteenth argument is of wrong type\n");
	if (!(arg13.type & procs[which].args[13]))
		throw dpuserTypeException("Fourteenth argument is of wrong type\n");
}

int Dpuser2cUtils::whichFunc = -1;
//Alex
void Dpuser2cUtils::checkFuncArgs(dpString name) {
	int i;
	whichFunc = -1;	
	
	for (i = 0; i < funcs.size(); i++)
		if (funcs[i].name == name) whichFunc = i;
	if (whichFunc == -1) {
		throw dpuserTypeException("Unknown function\n");
	}
}

//Alex
void Dpuser2cUtils::checkFuncArgs(dpString name, dpuserType &arg0) {
	checkFuncArgs(name);

	if (!(arg0.type & funcs[whichFunc].args[0]))
		throw dpuserTypeException("First argument is of wrong type\n");
}

//Alex
void Dpuser2cUtils::checkFuncArgs(dpString name, dpuserType &arg0, dpuserType &arg1) {
	checkFuncArgs(name, arg0);

	if (!(arg1.type & funcs[whichFunc].args[1]))
		throw dpuserTypeException("Second argument is of wrong type\n");
}

//Alex
void Dpuser2cUtils::checkFuncArgs(dpString name, dpuserType &arg0, dpuserType &arg1, dpuserType &arg2) {
	checkFuncArgs(name, arg0, arg1);

	if (!(arg2.type & funcs[whichFunc].args[2]))
		throw dpuserTypeException("Third argument is of wrong type\n");
}

//Alex
void Dpuser2cUtils::checkFuncArgs(dpString name, dpuserType &arg0, dpuserType &arg1, dpuserType &arg2, dpuserType &arg3) {
	checkFuncArgs(name, arg0, arg1, arg2);

	if (!(arg3.type & funcs[whichFunc].args[3]))
		throw dpuserTypeException("Forth argument is of wrong type\n");
}

//Alex
void Dpuser2cUtils::checkFuncArgs(dpString name, dpuserType &arg0, dpuserType &arg1, dpuserType &arg2, dpuserType &arg3, dpuserType &arg4) {
	checkFuncArgs(name, arg0, arg1, arg2, arg3);

	if (!(arg4.type & funcs[whichFunc].args[4]))
		throw dpuserTypeException("Fifth argument is of wrong type\n");
}

//Alex
void Dpuser2cUtils::checkFuncArgs(dpString name, dpuserType &arg0, dpuserType &arg1, dpuserType &arg2, dpuserType &arg3, dpuserType &arg4, dpuserType &arg5) {
	checkFuncArgs(name, arg0, arg1, arg2, arg3, arg4);

	if (!(arg5.type & funcs[whichFunc].args[5]))
		throw dpuserTypeException("Sixth argument is of wrong type\n");
}

//Alex
void Dpuser2cUtils::checkFuncArgs(dpString name, dpuserType &arg0, dpuserType &arg1, dpuserType &arg2, dpuserType &arg3, dpuserType &arg4, dpuserType &arg5, dpuserType &arg6) {
	checkFuncArgs(name, arg0, arg1, arg2, arg3, arg4, arg5);

	if (!(arg6.type & funcs[whichFunc].args[6]))
		throw dpuserTypeException("Seventh argument is of wrong type\n");
}

//Alex
void Dpuser2cUtils::checkFuncArgs(dpString name, dpuserType &arg0, dpuserType &arg1, dpuserType &arg2, dpuserType &arg3, dpuserType &arg4, dpuserType &arg5, dpuserType &arg6, dpuserType &arg7) {
	checkFuncArgs(name, arg0, arg1, arg2, arg3, arg4, arg5, arg6);

	if (!(arg7.type & funcs[whichFunc].args[7]))
		throw dpuserTypeException("Eighth argument is of wrong type\n");
}

//Alex
void Dpuser2cUtils::checkFuncArgs(dpString name, dpuserType &arg0, dpuserType &arg1, dpuserType &arg2, dpuserType &arg3, dpuserType &arg4, dpuserType &arg5, dpuserType &arg6, dpuserType &arg7, dpuserType &arg8) {
	checkFuncArgs(name, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);

	if (!(arg8.type & funcs[whichFunc].args[8]))
		throw dpuserTypeException("Ninth argument is of wrong type\n");
}

//Alex
void Dpuser2cUtils::checkFuncArgs(dpString name, dpuserType &arg0, dpuserType &arg1, dpuserType &arg2, dpuserType &arg3, dpuserType &arg4, dpuserType &arg5, dpuserType &arg6, dpuserType &arg7, dpuserType &arg8, dpuserType &arg9) {
	checkFuncArgs(name, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);

	if (!(arg9.type & funcs[whichFunc].args[9]))
		throw dpuserTypeException("Tenth argument is of wrong type\n");
}

//Alex
void Dpuser2cUtils::checkFuncArgs(dpString name, dpuserType &arg0, dpuserType &arg1, dpuserType &arg2, dpuserType &arg3, dpuserType &arg4, dpuserType &arg5, dpuserType &arg6, dpuserType &arg7, dpuserType &arg8, dpuserType &arg9, dpuserType &arg10) {
	checkFuncArgs(name, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);

	if (!(arg10.type & funcs[whichFunc].args[10]))
		throw dpuserTypeException("Eleventh argument is of wrong type\n");
}

//Alex
void Dpuser2cUtils::checkFuncArgs(dpString name, dpuserType &arg0, dpuserType &arg1, dpuserType &arg2, dpuserType &arg3, dpuserType &arg4, dpuserType &arg5, dpuserType &arg6, dpuserType &arg7, dpuserType &arg8, dpuserType &arg9, dpuserType &arg10, dpuserType &arg11)
 {
	checkFuncArgs(name, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);

	if (!(arg11.type & funcs[whichFunc].args[11]))
		throw dpuserTypeException("Twelfth argument is of wrong type\n");
}
