/* "CodeWorker":	a scripting language for parsing and generating text.

Copyright (C) 1996-1997, 1999-2004 Cédric Lemaire

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

To contact the author: codeworker@free.fr
*/

#ifdef WIN32
#pragma warning(disable : 4786)
#endif

#include "UtlException.h"
#include "DtaScriptVariable.h"

#ifdef CODEWORKER_DOT_NET
#	include "DOTNET.h"
#	include "CGCompiler.h"

#	define CW_STRING_TO_CHARARRAY(s) \
			const char* tc##s = NULL;\
			try {\
				tc##s = static_cast<const char*>(const_cast<void*>(static_cast<const void*>(System::Runtime::InteropServices::Marshal::StringToHGlobalAuto(s))));\
			} catch(System::ArgumentException* /*exceptArg*/) {\
			} catch(System::OutOfMemoryException* /*exceptOOM*/) {\
			}
#	define CW_FREE_CHARARRAY(s) System::Runtime::InteropServices::Marshal::FreeHGlobal(static_cast<System::IntPtr>(const_cast<void*>(static_cast<const void*>(tc##s))));


namespace CodeWorker {

	System::String* ParsingTree_var::getValue() {
		if (_pInternalNode == NULL) return NULL;
		const char* tcValue = _pInternalNode->getValue();
		if (tcValue == NULL) return NULL;
		return new System::String(tcValue);
	}

	void ParsingTree_var::setValue(ParsingTree_var* pValue) {
		if (_pInternalNode == NULL) throw UtlException("internal error: trying to set a value to an empty node");
		if (pValue->_pInternalNode == NULL) _pInternalNode->setValue((const char*) NULL);
		_pInternalNode->setValue(pValue->_pInternalNode->getValue());
	}


	ParsingTree_value::ParsingTree_value() {
		_pInternalNode = new DtaScriptVariable;
	}

	ParsingTree_value::ParsingTree_value(bool bValue) {
		_pInternalNode = new DtaScriptVariable;
		_pInternalNode->setValue(bValue);
	}

	ParsingTree_value::ParsingTree_value(int iValue) {
		_pInternalNode = new DtaScriptVariable;
		_pInternalNode->setValue(iValue);
	}

	ParsingTree_value::ParsingTree_value(double dValue) {
		_pInternalNode = new DtaScriptVariable;
		_pInternalNode->setValue(dValue);
	}

	ParsingTree_value::ParsingTree_value(System::String* tcValue) {
		CW_STRING_TO_CHARARRAY(tcValue);
		_pInternalNode = new DtaScriptVariable;
		_pInternalNode->setValue(tctcValue);
		CW_FREE_CHARARRAY(tcValue);
	}

	ParsingTree_value::ParsingTree_value(ParsingTree_var* pTree) {
		_pInternalNode = new DtaScriptVariable;
		setValue(pTree);
	}

	ParsingTree_value::~ParsingTree_value() {
		delete _pInternalNode;
	}


	CompiledCommonScript::CompiledCommonScript() : _pScript(NULL) {
		_pScript = __nogc new CGCompiledCommonScript;
	}

	CompiledCommonScript::~CompiledCommonScript() {
		delete _pScript;
	}

	void CompiledCommonScript::buildFromFile(System::String* pFilename) {
		CW_STRING_TO_CHARARRAY(pFilename);
		std::string sFilename = tcpFilename;
		CW_FREE_CHARARRAY(pFilename);
		_pScript->buildFromFile(sFilename);
	}

	void CompiledCommonScript::buildFromString(System::String* pText) {
		CW_STRING_TO_CHARARRAY(pText);
		std::string sScriptText = tcpText;
		CW_FREE_CHARARRAY(pText);
		_pScript->buildFromString(sScriptText);
	}

	void CompiledCommonScript::execute(ParsingTree_var* pContext) {
		_pScript->execute(pContext->_pInternalNode);
	}


	CompiledTemplateScript::CompiledTemplateScript(System::String* sFile) : _pScript(NULL) {
		CW_STRING_TO_CHARARRAY(sFile);
		std::string sFilename = tcsFile;
		CW_FREE_CHARARRAY(sFile);
		_pScript = new CGCompiledTemplateScript(sFilename);
	}

	CompiledTemplateScript::~CompiledTemplateScript() {
		delete _pScript;
	}


	void CompiledTemplateScript::generate(ParsingTree_var* pContext, System::String* sOutputFile) {
		CW_STRING_TO_CHARARRAY(sOutputFile);
		_pScript->generate(pContext->_pInternalNode, tcsOutputFile);
		CW_FREE_CHARARRAY(sOutputFile);
	}

	void CompiledTemplateScript::generateString(ParsingTree_var* pContext, System::String* sOutputText) {
		CW_STRING_TO_CHARARRAY(sOutputText);
		std::string sSTDText = tcsOutputText;
		_pScript->generateString(pContext->_pInternalNode, sSTDText);
		CW_FREE_CHARARRAY(sOutputText);
	}

	void CompiledTemplateScript::expand(ParsingTree_var* pContext, System::String* sOutputFile) {
		CW_STRING_TO_CHARARRAY(sOutputFile);
		_pScript->expand(pContext->_pInternalNode, tcsOutputFile);
		CW_FREE_CHARARRAY(sOutputFile);
	}


	CompiledBNFScript::CompiledBNFScript(System::String* sFile) : _pScript(NULL) {
		CW_STRING_TO_CHARARRAY(sFile);
		std::string sFilename = tcsFile;
		CW_FREE_CHARARRAY(sFile);
		_pScript = new CGCompiledBNFScript(sFilename);
	}

	CompiledBNFScript::~CompiledBNFScript() {
		delete _pScript;
	}

	void CompiledBNFScript::parse(ParsingTree_var* pContext, System::String* sParsedFile) {
		CW_STRING_TO_CHARARRAY(sParsedFile);
		_pScript->parse(pContext->_pInternalNode, tcsParsedFile);
		CW_FREE_CHARARRAY(sParsedFile);
	}

	void CompiledBNFScript::parseString(ParsingTree_var* pContext, System::String* sText) {
		CW_STRING_TO_CHARARRAY(sText);
		std::string sSTDText = tcsText;
		_pScript->parseString(pContext->_pInternalNode, sSTDText);
		CW_FREE_CHARARRAY(sText);
	}


	CompiledTranslationScript::CompiledTranslationScript(System::String* sFile) : _pScript(NULL) {
		CW_STRING_TO_CHARARRAY(sFile);
		std::string sFilename = tcsFile;
		CW_FREE_CHARARRAY(sFile);
		_pScript = new CGCompiledTranslationScript(sFilename);
	}

	CompiledTranslationScript::~CompiledTranslationScript() {
		delete _pScript;
	}

	void CompiledTranslationScript::translate(ParsingTree_var* pContext, System::String* sParsedFile, System::String* sOutputFile) {
		CW_STRING_TO_CHARARRAY(sParsedFile);
		CW_STRING_TO_CHARARRAY(sOutputFile);
		_pScript->translate(pContext->_pInternalNode, tcsParsedFile, tcsOutputFile);
		CW_FREE_CHARARRAY(sOutputFile);
		CW_FREE_CHARARRAY(sParsedFile);
	}

	System::String* CompiledTranslationScript::translateString(ParsingTree_var* pContext, System::String* sInputText) {
		CW_STRING_TO_CHARARRAY(sInputText);
		std::string sOutputText;
		_pScript->translateString(pContext->_pInternalNode, tcsInputText, sOutputText);
		CW_FREE_CHARARRAY(sInputText);
		return System::Runtime::InteropServices::Marshal::PtrToStringAuto(static_cast<System::IntPtr>(const_cast<void*>(static_cast<const void*>(sOutputText.c_str()))), sOutputText.size());
	}
}

namespace CodeWorker {
	public __gc class Main {
	public:
		static int initialize() {
			int iRetval = 0;
			try {
				__crt_dll_initialize();
			} catch(System::Exception* e) {
				System::Console::WriteLine(e);
				iRetval = 1;
			}
			return iRetval;
		}
		static int terminate() {
			int iRetval = 0;
			try {
				__crt_dll_terminate();
			} catch(System::Exception* e) {
				System::Console::WriteLine(e);
				iRetval = 1;
			}
			return iRetval;
		}
	};
}

BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpvReserved) {
	System::Console::WriteLine("CodeWorker::DllMain is called...");
	return TRUE;
}
#endif
