// -------------------------------------------------------------------------
// Citadel: Script.H
//
// Structs, unions, and enums used by the script interpretter.


#include "cwindows.h"
#include "timer.h"

// data types
enum VariableTypeE
	{
	TYPE_NONE,		TYPE_INT,		TYPE_UINT,		TYPE_LONG,
	TYPE_ULONG, 	TYPE_BOOL,

	TYPE_STRING_MIN = 6,		// 2 bytes (1 char + end)
	TYPE_STRING_MAX = 260,		// 256 bytes (255 chars + end)


	BY_REF = 0x8000,			// By reference
	};


// commands
enum CommandTypeE
	{
	CMD_UNK,

	// math
	CMD_ADD,	CMD_SUB,	CMD_MUL,	CMD_DIV,	CMD_MOD,	CMD_ASGN,

	// looping and branching
	CMD_EXIT,	CMD_WHILE,	CMD_WHILENOT,	CMD_WEND,	CMD_DO, 	CMD_LOOP,
	CMD_LOOPNOT,	CMD_GOTO,	CMD_LABEL,	CMD_RET,	CMD_CALL,	CMD_RUN,
	CMD_CHAIN,

	// conditional
	CMD_IF, 	CMD_IFNOT,	CMD_ELSE,	CMD_ENDIF,

	// comparison
	CMD_EQ, 	CMD_GT, 	CMD_LT, 	CMD_NE, 	CMD_GE, 	CMD_LE,

	// strings
	CMD_STRB,	CMD_STRU,	CMD_STRL,	CMD_STRC,	CMD_STRS,	CMD_STRE,
	CMD_STRPR,	CMD_STRPL,

	// Boolean
	CMD_AND,	CMD_OR, 	CMD_XOR,
	};

#define MAXARGS 5

union cmdData
	{
	strList *sl;				// if cmd takes more than one parameter
	char *str;					// if cmd takes one parameter
	};

struct scriptCommandRecord
	{
	scriptCommandRecord *next;
	int line;					// line number in .CSF file
	CommandTypeE type;			// type of command
	void *ptr;					// For speedy stuff.
	ulong time; 				// For profiler.
	ulong runCounter;			// For profiler.
	cmdData c;					// command's parameters
	};

union varTypes
	{
	int i;						// value of INT
	uint ui;					// value of UINT
	long l; 					// value of LONG
	ulong ul;					// value of ULONG
	Bool b; 					// value of Bool
	char *string;				// ptr to value of STR
	};

struct scriptVariables
	{
	scriptVariables *next;
	label name; 				// name of variable
	int type;					// type of variable
	varTypes v; 				// value of variable
	};

enum LoopTypeE
	{
	LOOP_NONE,

	LOOP_WHILE, 	LOOP_WHILENOT,		LOOP_DO
	};

struct scriptLoops
	{
	scriptLoops *next;
	LoopTypeE LoopType; 			// type of loop
	scriptCommandRecord *where; 	// where to loop to
	};


struct scriptFunctionList
	{
	scriptFunctionList *next;

	label name; 					// name of function
	VariableTypeE rett; 			// type function returns

	// argument types
	VariableTypeE argt[MAXARGS];

	// argument names
	label argn[MAXARGS];

	// argument data
	scriptVariables *argv[MAXARGS];

	// the ones that are being referenced
	scriptVariables *byref[MAXARGS];

	scriptVariables *vars;			// local variables
	scriptCommandRecord *cmds;		// commands of function

	scriptLoops *loopInfo;			// any active loops
	};

struct scriptCallList
	{
	scriptCallList *next;

	scriptFunctionList *oldFunc;	// function to return to
	scriptCommandRecord *oldCmd;	// command to return to
	};

enum
	{
	S_GVAR, 	S_LVAR, 	S_ADD,		S_SUB,		S_MUL,		S_DIV,
	S_MOD,		S_ASGN, 	S_STR,		S_WHILE,	S_WHILENOT, S_WEND,
	S_DO,		S_LOOP, 	S_LOOPNOT,	S_IF,		S_IFNOT,	S_ELSE,
	S_ENDIF,	S_GOTO, 	S_LABEL,	S_FUNC, 	S_RET,		S_ENDFUNC,
	S_CALL, 	S_RUN,		S_CHAIN,	S_EQ,		S_GT,		S_LT,
	S_NE,		S_GE,		S_LE,		S_EXIT, 	S_AND,		S_OR,
	S_XOR,		S_VERSION,

	S_NUM
	};


extern discardable *ScriptDData;			// all script discardable data
#define getscrmsg(xxx) ((char **) ScriptDData->next->next->aux)[xxx]

// Debugging stuff
struct Breakpoints
	{
	Breakpoints *next;
	int LineNum;
	};

struct ScriptInfoS
	{
	CITWINDOW *DebuggingWindow, *WWindow, *SourceWindow;
	Bool Debug, Pause;
	Bool oldSystemDebug, SingleStep;
	Breakpoints *BPoints;

	scriptVariables lastResult; 		// _RESULT of last cmd/func
	char wowza[256];					// string _RESULT

	scriptVariables *gvBase;			// our global variables
	scriptFunctionList *sfBase; 		// our functions
	scriptCallList *callList;			// whete to #RETurn

	char Name[81];						// name of current script

	scriptCommandRecord *curCmd;		// command in execution
	scriptFunctionList *curFunc;		// function in execution

	FILE *UsrFile[5];					// script user files
	Message *UsrMsg;					// script message.

	LogEntry *UsrUsr;					// script user.
	Bool UseCU; 						// If using TI()CurrentUser.

	strList *dupCheck;					// script user.
	directoryinfo *Files;				// script directory.

	Bool Error;

	scriptVariables byval;				// For returning BYVAL params
	char tmpstr[20];					// For numeric->string evals

	Timer CmdTimer;
	scriptCommandRecord *LastCmd;

	Bool ToRet; 						// Back to Citadel

	Bool ReadAplOnExit; 				// Should we?

	void (*DeinitScript)(ScriptInfoS *si);
	};

extern ScriptInfoS *CurScript;

void DebuggingMsg(const char *Msg);
Bool RemoveWatch(const char *Expr);
Bool AddWatch(const char *Expr);
void ToggleWatch(const char *Expr);
