/****************************************************************************
	Kalkulon - A programmable calculator for programmers

	This file is part of the Kalkulon core.
	
	If you find this source code useful, your are encouraged to use it in your own projects.
	Please give me credit!

	COPYRIGHT by Juergen Holetzeck 2003 - 2008
	e-mail:		contact@kalkulon.de
	homepage:	www.kalkulon.de
****************************************************************************/


// fnlist.cpp: Implementierung der Klasse fnlist.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include <math.h>
#include <sstream>

#include "fnlist_impl.h"
#include "fnlist_internal.h"
#include "math1.h"
#include "commands.h"

using namespace Kalkulon;

namespace Kalkulon{
static const fn_list_item_t mylist[] =
{
//  use alphabetical for later optimization!
//  name        type                function pointer
	{	"Back",		DO_FP_DO,			(void *) cmd::Back		},
	{	"Beep",		FP_DOUBLE_DOUBLE,	(void *) cmd::Beep		},
	{	"ClearAll", DO_FP_EVAL,			(void *) cmd::ClearAll	},    
	{	"Erase",	DO_FP_DO_DO,		(void *) cmd::Erase1	},    
	{	"Erase",	DO_FP_DO_DO_DO,		(void *) cmd::Erase2	},    
	{	"Error",	FP_STRING,			(void *) cmd::Error		},    
	{	"Eval",     DO_FP_EVAL_STRING,  (void *) cmd::Eval		},    
	{	"Exec",		FP_STRING,			(void *) cmd::Exec1		},    
	{	"Exec",		FP_STRING_STRING,	(void *) cmd::Exec2		},    
	{	"Fold",		DO_FP_EVAL_DO_DO_DO,(void *) cmd::Fold		},    
	{	"FoldList",	DO_FP_EVAL_DO_DO_DO,(void *) cmd::FoldList	},    
	{	"ForEach",	DO_FP_EVAL_DO_DO,	(void *) cmd::ForEach1	},    
	{	"ForEach",	DO_FP_EVAL_DO_DO_DO,(void *) cmd::ForEach2	},    
	{	"Front",	DO_FP_DO,			(void *) cmd::Front		},    
	{	"FullForm", DO_FP_DO,			(void *) cmd::FullForm	},    
	{	"GetTicks", FP_VOID  ,			(void *) cmd::GetTicks	},    
	{	"Insert",	DO_FP_DO_DO_DO,		(void *) cmd::Insert	},    
	{	"LinePos",	DO_FP_DO_DO,		(void *) cmd::LinePos	},    
	{	"Load",		FP_EVAL_STRING,		(void *) cmd::Load		},    
	{	"Print",	DO_FP_EVAL_DO,		(void *) cmd::Print		},    
	{	"PrintLn",	FP_EVAL,			(void *) cmd::PrintLn0	},    
	{	"PrintLn",	DO_FP_EVAL_DO,		(void *) cmd::PrintLn1	},    
	{	"PopBack",	DO_FP_DO,			(void *) cmd::PopBack	},    
	{	"PopFront", DO_FP_DO,			(void *) cmd::PopFront	},    
	{	"PushBack",	DO_FP_DO_DO,		(void *) cmd::PushBack	},    
	{	"PushFront",DO_FP_DO_DO,		(void *) cmd::PushFront	},	
	{	"ReadBinData",	DO_FP_DO,		(void *) cmd::ReadBinData0	},	
	{	"ReadBinData",	DO_FP_DO_DO_DO,	(void *) cmd::ReadBinData1	},	
	{	"ReadData",	DO_FP_DO,		    (void *) cmd::ReadData		},
	{	"Replace",  DO_FP_DO_DO_DO,		(void *) cmd::Replace		},		
	{	"SetBinFormat", STRING_FP_VOID,	(void *) cmd::SetBinFormat	},	
	{	"SetNumFormat", STRING_FP_STRING,(void *) cmd::SetNumFormat	},	
	{	"SetHexFormat", STRING_FP_VOID,	(void *) cmd::SetHexFormat	},
	{	"SetRecursionLimit", FP_INT,	(void *) cmd::SetRecursionLimit },
	{	"SetSciFormat", STRING_FP_VOID,	(void *) cmd::SetSciFormat	},	
	{	"SetStdFormat", STRING_FP_VOID,	(void *) cmd::SetStdFormat	},	
	{	"Size",		FP_DO,				(void *) cmd::Size			},			
	{	"Sprintf",  STRING_FP_STRING_DO,(void *) cmd::Sprintf		},		
	{	"Sub",		DO_FP_DO_DO,		(void *) cmd::Sub1			},			
	{	"Sub",		DO_FP_DO_DO_DO,		(void *) cmd::Sub2			},			
	{	"Table",    DO_FP_EVAL_DO_DO,	(void *) cmd::Table1		},		
	{	"Table",    DO_FP_EVAL_DO_DO_DO,(void *) cmd::Table2		},		
	{	"Table",    DO_FP_EVAL_DO_DO_DO_DO,(void *) cmd::Table3		},	
	{	"Type",		FP_DO,				(void *) cmd::Type			},			
	{	"Version",	DO_FP_EVAL,			(void *) cmd::Version		},		
	{	"WriteBinData", DO_FP_DO_DO,	(void *) cmd::WriteBinData	},	
	{	"WriteData",DO_FP_DO_DO,	    (void *) cmd::WriteData		},	
   	{	"abs",		FP_DOUBLE,			(void *) (double (*) (double)) fabs	},
	{	"acos",		FP_DOUBLE,			(void *) (double (*) (double)) acos	},
	{	"asin",		FP_DOUBLE,			(void *) (double (*) (double)) asin	},
	{	"atan",		FP_DOUBLE,			(void *) (double (*) (double)) atan	},
	{	"ceil",		FP_DOUBLE,			(void *) (double (*) (double)) ceil	},
	{	"cos",		FP_DOUBLE,			(void *) (double (*) (double)) cos	},
	{	"cosh",		FP_DOUBLE,			(void *) (double (*) (double)) cosh	},
	{	"exp",		FP_DOUBLE,			(void *) (double (*) (double)) exp	},
	{	"floor",	FP_DOUBLE,			(void *) (double (*) (double)) floor},
	{	"fmod",		FP_DOUBLE_DOUBLE,   (void *) (double (*) (double, double)) fmod},
	{	"fp",		FP_DOUBLE,			(void *) (double (*) (double)) math::fp	},
	{	"ip",		FP_DOUBLE,			(void *) (double (*) (double)) math::ip	},
	{	"ld",		FP_DOUBLE,			(void *) (double (*) (double)) math::ld	},
	{	"ln",		FP_DOUBLE,			(void *) (double (*) (double)) log		},
	{	"log",		FP_DOUBLE,			(void *) (double (*) (double)) log10	},
	{	"max",		FP_DOUBLE_DOUBLE,   (void *) (double (*) (double, double)) math::max},
	{	"min",		FP_DOUBLE_DOUBLE,   (void *) (double (*) (double, double)) math::min},
	{	"pow",		FP_DOUBLE_DOUBLE,	(void *) (double (*) (double, double)) pow},
	{	"rand",		FP_VOID,			(void *) math::rand},
	{	"sign",		FP_DOUBLE,			(void *) (double (*) (double)) math::sign},
	{	"sin",		FP_DOUBLE,			(void *) (double (*) (double)) sin	},
	{	"sinh",		FP_DOUBLE,			(void *) (double (*) (double)) sinh	},
	{	"sqrt",		FP_DOUBLE,			(void *) (double (*) (double)) sqrt	},
	{	"srand",	FP_VOID,			(void *) math::srand				},
	{	"tan",		FP_DOUBLE,			(void *) (double (*) (double)) tan	},
	{	"tanh",		FP_DOUBLE,			(void *) (double (*) (double)) tanh	}
};


const fn_list_t fn_list =
{
	mylist,
	sizeof(mylist)/sizeof(mylist[0])
};

std::string fnListItemToString(const fn_list_item_t &fn)
{
  std::ostringstream os;
  os << fn;
  return os.str();
}

}


std::ostream& operator<< (std::ostream& out, const fn_list_item_t& fn)
{
  out << fn.name << '(';
  switch(fn.type)
  {
  case FP_DOUBLE:
  case FP_INT:
    out << "x";
    break;
  case DO_FP_EVAL_DO:
  case FP_DO:
  case DO_FP_DO:
    out << "arg";
    break;
  case FP_DOUBLE_DOUBLE:
  case FP_INT_INT:
  case FP_INT_DOUBLE:
  case FP_DOUBLE_INT:
    out << "x0, x1";
    break;
  case DO_FP_EVAL_DO_DO:
  case DO_FP_DO_DO:
    out << "arg0, arg1";
    break;
  case FP_DOUBLE_DOUBLE_DOUBLE:
  case FP_INT_INT_INT:
    out << "x0, x1, x2";
    break;
  case DO_FP_EVAL_DO_DO_DO:
  case DO_FP_DO_DO_DO:
    out << "arg0, arg1, arg2";
    break;
  case FP_DOUBLE_DOUBLE_DOUBLE_DOUBLE:
  case FP_INT_INT_INT_INT:
    out << "x0, x1, x2, x3";
    break;
  case DO_FP_EVAL_DO_DO_DO_DO:
    out << "arg0, arg1, arg2, arg3";
    break;
  case FP_STRING:
  case DO_FP_EVAL_STRING:
  case FP_EVAL_STRING:
  case STRING_FP_STRING:
    out << "str";
    break;
  case FP_STRING_STRING:
    out << "str0, str1";
    break;
  case STRING_FP_STRING_DO:
    out << "str, arg";
    break;
  }


  out << ')';
  return out;
}

