//***************************************************************************
//
//								ENVIRON.H
//
//***************************************************************************

#ifndef ABLENV_H
#define ABLENV_H

#include <stdio.h>

#ifndef DABLENV_H
	#include "dablenv.h"
#endif

#include "ablgen.h"

#ifndef ABLSYMT_H
	#include "ablsymt.h"
#endif

#ifndef ABLEXEC_H
	#include "ablexec.h"
#endif

#ifndef DABLDBUG_H
	#include "dabldbug.h"
#endif

#ifndef DFILE_H
	#include "dfile.h"
#endif
namespace ABL
{

//***************************************************************************

	typedef struct _SourceFile
	{
		char          fileName[MAXLEN_FILENAME];
		unsigned char     fileNumber;
		FilePtr         filePtr;
		long          lineNumber;
	} SourceFile;

//---------------------------------------------------------------------------

#define	MAX_USER_FILES			6
#define MAX_USER_FILE_LINES		50
#define	MAX_USER_FILE_LINELEN	200
#if 0
class UserFile
{

public:

	long          handle;
	bool          inUse;
	char          fileName[MAXLEN_FILENAME];
	Stuff::MemoryStream *stream;
	long          numLines;
	long          totalLines;
	char          lines[MAX_USER_FILE_LINES][MAX_USER_FILE_LINELEN];

	static UserFile    *files[MAX_USER_FILES];

public:
/*
	void* operator new (size_t mySize);

	void operator delete (void* us);
*/	

	void init (void)
	{
		handle = -1;
		inUse = false;
		fileName[0] = NULL;
		stream = NULL;
		numLines = 0;
		totalLines = 0;
		for (long i = 0; i < MAX_USER_FILE_LINES; i++)
			lines[i][0] = NULL;
	}

	UserFile (void)
	{
		init();
	}

	void destroy (void);

	~UserFile (void)
	{
		destroy();
	}

	void dump (void);

	void close (void);

	long open (Stuff::MemoryStream *stream);

	void write (char* s);

	static void setup (void);

	static void cleanup (void);

	static UserFile *getNewFile (void);
};
#endif
//---------------------------------------------------------------------------

#define	MAX_ABLMODULE_NAME	25
#define	MAX_SOURCE_FILES	256			// per module
#define	MAX_LIBRARIES_USED	25			// per module

	typedef struct
	{
		char          name[128];
		long          size;
	} VariableInfo;

	typedef struct
	{
		char          name[128];
		long          codeSegmentSize;
	} RoutineInfo;

	typedef struct
	{
		char          name[128];
		char          fileName[128];
		long          numStaticVars;
		long          totalSizeStaticVars;
		VariableInfo      largestStaticVar;
		long          totalCodeSegmentSize;
		long          numRoutines;
		RoutineInfo       routineInfo[128];
	} ModuleInfo;

	typedef struct
	{
		char*         fileName;
		SymTableNodePtr     moduleIdPtr;
		long          numSourceFiles;
		char**          sourceFiles;
		long          numLibrariesUsed;
		ABLModulePtr*     librariesUsed;
		long          numStaticVars;
		long*         sizeStaticVars;
		long          totalSizeStaticVars;
		long          numInstances;
	} ModuleEntry;

	typedef ModuleEntry* ModuleEntryPtr;

	class ABLModule
	{

	private:

		long          id;
		char          name[MAX_ABLMODULE_NAME];
		long          handle;
		StackItemPtr      staticData;
		StackItem       returnVal;
		bool          initCalled;
		WatchManagerPtr     watchManager;
		BreakPointManagerPtr  breakPointManager;
		SymTableNodePtr curState;
		bool          trace;
		bool          step;
		bool          traceEntry;
		bool          traceExit;

		//static long				numModules;

	public:

//		void* operator new (size_t mySize);
//		void operator delete (void* us);

		void init (void)
		{
			id = -1;
			name[0] = NULL;
			handle = -1;
			staticData = NULL;
			initCalled = false;
			watchManager = NULL;
			breakPointManager = NULL;
			curState = NULL;
			trace = false;
			step = false;
			traceEntry = false;
			traceExit = false;
		}

		SymTableNodePtr GetCurState() const
		{
			return(curState);
		}

		ABLModule (void)
		{
			init();
		}
		reset (void);

		long init (long moduleHandle);

	void write (MemoryStream *stream);

	void read (MemoryStream *stream);

		long getId (void)
		{
			return(id);
		}

		void SwitchStates (const char *name);

		long getHandle (void)
		{
			return(handle);
		}

		StackItemPtr getStaticData (void)
		{
			return(staticData);
		}

		void setInitCalled (bool called)
		{
			initCalled = called;
		}

		bool getInitCalled (void)
		{
			return(initCalled);
		}

		char* getName (void)
		{
			return(name);
		}

		void setName (char* _name);

		WatchManagerPtr getWatchManager (void)
		{
			return(watchManager);
		}

		BreakPointManagerPtr getBreakPointManager (void)
		{
			return(breakPointManager);
		}

		void setTrace (bool _trace)
		{
			trace = _trace;
			traceEntry = _trace;
			traceExit = _trace;
		}

		bool getTrace (void)
		{
			return(trace);
		}

		void setStep (bool _step)
		{
			step = _step;
		}

		bool getStep (void)
		{
			return(step);
		}

		long execute (ABLParamPtr paramList = NULL);
		long execute (ABLParamPtr moduleParamList, SymTableNodePtr functionIdPtr);

		SymTableNodePtr findSymbol (char* symbolName, SymTableNodePtr curFunction = NULL, bool searchLibraries = false);

		SymTableNodePtr findFunction (char* functionName, bool searchLibraries = false);

		char* getSourceFile (long fileNumber);

		char* getSourceDirectory (long fileNumber, char* directory);

		void getInfo (ModuleInfo* moduleInfo);

		float getReal (void)
		{
			return(returnVal.real);
		}

		long getInteger (void)
		{
			return(returnVal.integer);
		}

		long setStaticInteger (char* name, long value);

		long getStaticInteger (char* name);

		long setStaticReal (char* name, float value);

		float getStaticReal (char* name);

		long setStaticIntegerArray (char* name, long size, long* values);

		long getStaticIntegerArray (char* name, long size, long* values);

		long setStaticRealArray (char* name, long size, float* values);

		long getStaticRealArray (char* name, long size, float* values);

		void destroy (void);

		~ABLModule (void)
		{
			destroy();
		}

	};

//*************************************************************************

	void initModuleRegistry (long maxModules);
	void destroyModuleRegistry (void);
	void initLibraryRegistry (long maxLibraries);
	void destroyLibraryRegistry (void);

//***************************************************************************
}
#endif
