/* Copyright (c) 1993 Stephen F. White */

#ifdef PROTO
extern void	gettimeofday(struct timeval *tp, struct timezone *tzp);
#endif

typedef struct timeval Timeval;

typedef struct Event Event;

struct Event {	
    int		msgid;		/* current message id */
    int		age;		/* current message's age */
    int		ticks;		/* current task's ticks */
    Objid	player;		/* current player */
    Objid       this;		/* object to which message was sent */
    Object     *on;		/* object on which method is located */
    Objid	caller;		/* object which sent the message */
    List       *args;		/* arguments to message */
    Method     *m;		/* method which was being executed */

      /* the following fields are used when the method gets blocked */
    enum { BL_MESSAGE, BL_LOCK, BL_TIMER, BL_SYS_MESSAGE, BL_DEAD }
				blocked_on;
				/* what the method is blocked on */
    Timeval	timeout_at;	/* time at which message should time out */
    int		blocked_msgid;	/* message for which MESSAGE event is waiting */
    Objid	blocked_objid;	/* object to which MESSAGE event was sent */
    String     *msg;		/* if sent to remote, text of message */
    Timeval	retry_at;	/* absolute time to retry at */
    int		retry_interval;	/* relative msec on next retry */

    String     *lock;		/* name of lock which LOCK is blocked on */

    int		sp;		/* stack pointer */
    int		pc;		/* program counter */
    Var	        stack[STACK_SIZE];	/* the stack */
    int         nvars;		/* and how many of them */
    int		last_opcode;	/* useful for error recovery */
    Event      *prev;		/* previous event in queue */
    Event      *next;		/* next event in queue */
};

/*
 * Execution globals
 */

extern Event	 	 frame;		/* the currently executing frame */
extern enum state	 ex_state;	/* execution state */
extern Var		 ex_retval;	/* return value (set by op_return()) */
extern Object		*this;		/* this object, may be 0 */

/*
 * from execute.c
 */

extern void		 push(Var v);
extern Var		 pop(void);
extern Var		 pop_args(int num);	/* pop an argument list */
extern void		 pushn(long i);	/* push an integer onto the stack */
extern void		 pushpc(int i);	/* push the PC onto the stack */
extern void		 raise(Error e);	/* raise an error */
extern void		 send_raise(List *raise_args);	/* send the raise msg */
extern Error		 call_verb(int msgid, int age, int ticks, Objid player,
				   Objid from, Objid to, List *args);
extern Method		*find_method(Object *o, const char *name);
extern void		 send_message_and_block(Objid from, Objid to,
					    String *msg, List *args, Objid on);
extern void		 resume_method_return(Event *e, Var retval);
extern void		 resume_method_raise(Event *e, List *raise_args);
extern void		 resume_method_halt(Event *e);
extern void		 resume_method(Event *e);
extern String		*add_traceback_header(String *str, Error e);
extern List		*make_raise_args(Error e);
extern Timeval		 timer_sub(Timeval t1, Timeval t2);
extern Timeval		 timer_addmsec(Timeval t, int msec);

/*
 * from message.c
 */
extern Error	send_message(int msgid, int age, int ticks, Objid player,
    Objid from, Objid to, String *message, List *args, Event *e, Objid on);
extern void		 event_add(Event *e);
extern void		 event_rm(Event *e);

/*
 * Prototypes for all the opcodes
 */

extern void	op_numpush(void), op_strpush(void), op_objpush(void),
		op_errpush(void), op_listpush(void), op_errpush(void),
		op_pushpc(void), op_if(void), op_elseif(void), op_null(void),
		op_for(void), op_forrng(void), op_while(void), op_do(void),
		op_dowhile(void), op_break(void), op_continue(void),
		op_add(void), op_sub(void), op_mul(void), op_div(void),
		op_mod(void), op_negate(void), op_message(void),
		op_message_expr(void), op_and(void), op_or(void),
		op_not(void), op_index(void), op_subset(void),
		op_lsubset(void), op_rsubset(void), op_gt(void), op_lt(void),
		op_ge(void), op_le(void), op_eq(void), op_ne(void),
		op_echo(void), op_echo_file(void), op_clone(void),
		op_destroy(void), op_chparents(void), op_time(void),
		op_ctime(void), op_in(void), op_explode(void),
		op_strsub(void), op_psub(void), op_random(void), op_pop(void),
		op_pad(void), op_setadd(void), op_setremove(void),
		op_listinsert(void), op_listappend(void), op_listdelete(void),
		op_listassign(void), op_asgnlvar(void), op_asgngvar(void),
		op_asgngvarexpr(void), op_getlvar(void), op_getgvar(void),
		op_getgvarexpr(void), op_parents(void), op_this(void),
		op_player(void), op_caller(void), op_args(void),
		op_setplayer(void), op_return(void), op_stop(void),
		op_abort(void), op_crypt(void), op_checkmem(void),
		op_cache_stats(void), op_lock(void), op_unlock(void),
		op_at(void), op_tostr(void), op_tonum(void), op_toobj(void),
		op_toerr(void), op_typeof(void), op_lengthof(void),
		op_serverof(void), op_servername(void), op_servers(void),
		op_verbs(void), op_vars(void), op_methods(void),
		op_verb(void),  op_rmverb(void), op_rmmethod(void),
		op_rmvar(void), op_program(void), op_compile(void),
		op_find_method(void), op_spew_method(void),
		op_list_method(void), op_decompile(void), op_hasparent(void),
		op_objsize(void), op_match(void), op_match_full(void),
		op_shutdown(void), op_dump(void), op_boot(void),
		op_writelog(void), op_raise(void), op_pass(void),
		op_sleep(void), op_ps(void), op_kill(void);