// utf-8

/*	Copyright  (c)	Günter Woigk   2001-2003
  					mailto:kio@little-bat.de

	This file is free software

 	This program 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.  

 	Permission to use, copy, modify, distribute, and sell this software and
 	its documentation for any purpose is hereby granted without fee, provided
 	that the above copyright notice appear in all copies and that both that
 	copyright notice and this permission notice appear in supporting
 	documentation, and that the name of the copyright holder not be used
 	in advertising or publicity pertaining to distribution of the software
 	without specific, written prior permission. The copyright holder makes no
 	representations about the suitability of this software for any purpose.
 	It is provided "as is" without express or implied warranty.

 	THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 	INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 	EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 	CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 	DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 	TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 	PERFORMANCE OF THIS SOFTWARE.
*/


#ifndef _vscript_h_
#define _vscript_h_


#include "Stream.h"
#include "var/var.h"


/* ----	argv[] arguments -------------------------------
*/
extern	String		applName;
extern	bool		verbose;
extern	Stream*		stdStream[];	// real stdin/stdout/stderr
#define				stdinStream		stdStream[0]
#define				stdoutStream	stdStream[1]
#define				stderrStream	stdStream[2]



class VScript
{
/* ----	priorities for VScript::Value(…) ---------------
*/
enum
{ 	pAny = 0,		// whole expression: up to ')' or ','
	pAssign,		// = += -= /= *=
	pAcceptVoid,	// stop at pAssign; accept a proc returning no value => return v=NULL  (( used only by Execute() ))
	pSel,			// ?:
	pBoo,			// && ||
	pCmp, 			// comparisions
	pHash,			// concatenation
	pAdd, 			// add, sub
	pMul, 			// mul, div, rem
	pBit, 			// masking & | ^ 
	pRot, 			// rot/shift
	pUna			// unary operator:	 highest priority
};


/* ----	global and local variables hook ----
*/
	Var*		globals;		// vektor variable which contains all global variables
	Var*		locals;			// pointer to current local variables context; initially to globals
	Var*		proc;			// currently executed procedure


/* ----	input/output via streams -----------------------
*/
	#define		max_streams		100
	Stream*		std_io[max_streams];// closed stream defaults: stdin/stdout/stderr/no_io/...
	Stream*		io[max_streams];	// slots for open# streams...
	#define		stdin_stream	0	// stdin  from within the script  (as for 'get')
	#define		stdout_stream	1	// stdout from within the script  (as for 'put')
	#define		stderr_stream	2	// stderr from within the script  (as for 'log')
	uint		stream;				// current stream in i/o statement

		
/* ----	member functions ------------------------------
*/
	void		OpenStream		( cstr fname, int flags );
	void		CloseStream		( );
	uchar*		SetStream		( uchar* ip, uint dflt_stream, bool expectkomma=1 );
			
	void		PutNL			( )							{ io[stream]->PutNL();				}
	void		PutSpaces		( uint n )					{ io[stream]->PutSpaces(n);			}
	void		PutString		( cString& text )			{ io[stream]->PutString(text);		}
	void		PutChar			( UTF8Char s )				{ io[stream]->PutChar(s);			}
	void		PutChar			( UCS4Char s )				{ io[stream]->PutChar(s);			}
	String		GetString		( )							{ return io[stream]->GetString();	}
	UCS4Char	GetChar			( )							{ return io[stream]->GetChar(); 	}
	uint		WriteBinary		( const void* p, uint n )	{ return io[stream]->Write(p,n);	}
	uint		ReadBinary		( void* p,       uint n )	{ return io[stream]->Read(p,n); 	}

	
	uchar*		Expect			( uchar*ip, uchar token );
	uchar*		GetIdentifier	( uchar*ip, String& idf );
	bool 		TrapVarInUse	( Var* v );
	Var*		FindVar			( cString& name );
	
	void		GetCGIArguments	( );
	uchar*		Execute			( Var& proc, Var*& u, uchar* ip=NULL );

	uchar*		Value			( uchar*ip, Var*&v, int prio );
	uchar*		NumValue		( uchar*ip, Var*&v, int prio );
	uchar*		StrValue		( uchar*ip, Var*&v, int prio );
	uchar*		RefValue		( uchar*ip, Var*&v, int prio );
	uchar*		NumRefValue		( uchar*ip, Var*&v, int prio );
	uchar*		StrRefValue		( uchar*ip, Var*&v, int prio );
	uchar*		SingleArg		( uchar*ip, Var*&v );
	uchar*		SingleStrArg	( uchar*ip, Var*&v );
	uchar*		SingleNumArg	( uchar*ip, Var*&v );

				VScript			( const VScript& );		// prohibit
	VScript&	operator=		( const VScript& );		// prohibit

public:
				VScript			( );
				~VScript		( );

	void		Run				( cString& filename, Var*& v );
	void		RunScript		( cString& script, int argc, cstr argv[], Var*& v );
	void		RunShell		( );
	void		RunCalc			( cString& );
};

#endif

