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

#ifndef _COMMAND_H
#define _COMMAND_H

#include <hash.h>

#define MIN_STACK	   2048
#define MAX_CS_RECURSE	   128
#define COMMENT_CHAR	   ';'
#define GSYMTABSIZE	   256

#define findgsym(s)	   ((GSYM *)findhash(SymbolTab, s, GSYMTABSIZE))

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

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

/* defines for 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_FUNC    3	/* CMPTR function */

#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				  */

/*
 * Each symbol is like this with a node on the front
 */
typedef struct {
    BYTE	    sym_Type;
    VALUE	    sym_Value;
} SYM;

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

/*
 * global symbol
 */
typedef struct {
    HASHNODE	    gs_Node;
    SYM		    gs_Sym;
} GSYM;

/*
 * local symbol
 */
typedef struct {
    struct Node	    ls_Node;
    SYM		    ls_Sym;
} LSYM;

/*
 * context structure for each command string that is resolved
 * it didn't seem wise to use hash tables for local variables(?)
 */
typedef struct {
    BOOL	    cs_Args;
    LONG	    cs_Argc;
    VALUE	   *cs_Argv;
    struct List	    cs_Locals;
} CS;

/*
 * 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_Type = VTF_STRING, RES.val_Value.String = s
#define setnumres(n) RES.val_Type = VTF_NUMBER, RES.val_Value.Number = n

#endif /* _COMMAND_H */
