
/*
 * COMMAND.H
 * (c) 1992 J.Harper
 */

#include "hash.h"

#define	MIN_STACK	   2048
#define	MAX_MAC_RECURSE	   16
#define	COMMENT_CHAR	   ';'

/*
 * This	structure is the base of all argument/result communication between
 * commands.
 */
typedef	struct VALUE
{
    union
    {
	STRPTR		 String;
	LONG		 Number;
	VOID		*Generic;	/* use to init either */
    }		     val_Value;
    BYTE	     val_Type;
} VALUE;

/* command function */
typedef	VALUE *(*CMPTR)(LONG, VALUE *);

/*
 * Each	symbol in the hashtable	is like	this
 */
typedef	struct SYMBOL
{
    HASHNODE	     sym_Node;
    BYTE	     sym_SymType;
    BYTE	     sym_ValType;
    union
    {
	CMPTR		 Func;
	STRPTR		 String;
	LONG		 Number;
	VOID		*Generic;   /* use this	to initialize all types	*/
    }		     sym_Value;
} SYMBOL;

/* defines for sym_SymType */
#define	STF_COMMAND 1	/* command (or macro) to execute */
#define	STF_GLOBAL  2	/* variable (can be a command :-) */

/* defines for sym_ValType */
#define	VTF_FUNC    3	/* CMPTR function */

/* the rest can	also be	in val_Type */
#define	VTF_NONE    0	/* no value! */
#define	VTF_ANY	    VTF_NONE	/* synonym for template	checking */
#define	VTF_STRING  1	/* AllocVec()'ed string */
#define	VTF_NUMBER  2	/* LONG	value */

#define	VTF_BREAK   4	/* signifies that we broke out of the last string */
			/* not a value - only ever found in result of the */
			/* (break) command. (bit of a hack really).	  */
			/* The number of strings to break from is put into*/
			/* val_Value.Number				  */
/*
 * context structure for each macro that is evaluated.
 * it didn't seem wise to use hash tables for local variables(?)
 */
typedef	struct MACCONTEXT
{
    LONG	     mc_Argc;
    VALUE	    *mc_Argv;
    struct List	     mc_Locals;
} MACCONTEXT;

/*
 * this	is what	local symbols look like, they can only be numbers or
 * strings
 */
typedef	struct LOCALSYM
{
    struct Node	     l_Node;	/* name	in ln_Name */
    VALUE	     l_Value;
} LOCALSYM;

/*
 * Macros for checking command templates
 *
 * they	are used at the	start of a command's function, they return TRUE
 * if the template was satisfied.
 *
 * ie,
 *  if(TPLATE2(VTF_STRING, VTF_NUMBER))
 */
#define	TPLATE1(a)	 templatecmd(argc, argv, a)
#define	TPLATE2(a,b)	 templatecmd(argc, argv, a | (b	<< 2))
#define	TPLATE3(a,b,c)	 templatecmd(argc, argv, a | (b	<< 2) |	(c << 4))
#define	TPLATE4(a,b,c,d) templatecmd(argc, argv, a | (b	<< 2) |	(c << 4) | (d << 6))

/*
 * how to get args, ie,	(ARG1.val_Value.String)
 */
#define	RES    argv[0]
#define	ARG1   argv[1]
#define	ARG2   argv[2]
#define	ARG3   argv[3]
#define	ARG4   argv[4]
#define	ARG(x) argv[x]

/*
 * how to return stuff (note: (s) MUST have been savestring()'ed)
 */
#define	setstrres(s) { RES.val_Value.String = s; RES.val_Type =	VTF_STRING; }
#define	setnumres(n) { RES.val_Value.Number = n; RES.val_Type =	VTF_NUMBER; }
#define	setnores()   { RES.val_Type = VTF_NONE;	}
#define	returnstr(s) { setstrres(s); return(&RES); }
#define	returnnum(n) { setnumres(n); return(&RES); }
#define	returnno()   { setnores(); return(&RES); }

