/*
 * Copyright (C) 2000-2002 ASANO Masahiro
 */

#ifndef CRASH_H
#define CRASH_H

#include <stdio.h>
#include <setjmp.h>
#include "def.h"

#define	APPNAME	"mcrash"

extern char *symname;
extern char *physname;
extern int quiet;
extern int noprompt;
extern FILE *fp;	/* output device */

struct statement {
	enum st_type {
		SIMPLE, IF_CONVENTION, WHILE
	} st_type;
	struct statement *next, *ext1, *ext2;
	char line[1];		/* 1 for '\0' */
};

#define	MAXARGS	100
extern int argcnt;
extern char *args[MAXARGS];
extern char usage[];

extern addr_t xaddr[MAXARGS];
extern int xaddr_ptr;

extern const char *except_message;
extern char except_message_buf[];
extern jmp_buf *except_jmpbuf;
#define TRY	{\
	jmp_buf _jmpbuf_cur, *_jmpbuf_sv = except_jmpbuf;\
	except_jmpbuf = &_jmpbuf_cur;\
	if (setjmp(_jmpbuf_cur) == 0)
#define CATCH	else
#define ENDTRY	except_jmpbuf = _jmpbuf_sv;}
#define THROW(s)	(except_message = s, longjmp(*except_jmpbuf, 1))
#define THROWF(f,s)	(sprintf(except_message_buf,f,s), except_message = except_message_buf, longjmp(*except_jmpbuf, 1))
#define THROWF2(f,s,s2)	(sprintf(except_message_buf,f,s,s2), except_message = except_message_buf, longjmp(*except_jmpbuf, 1))

typedef struct commandtable {
	char *name;			/* command name */
	addr_t (*func)();		/* pointer to function */
	char *args;			/* description of argument */
	char *help;			/* help message */
} commandtable_t;
extern const commandtable_t **commandtable,
	*commandtable_base[], *commandtable_vers[], *commandtable_arch[], *commandtable_xfs[];
const int ncmdtable_base, ncmdtable_vers, ncmdtable_arch, ncmdtable_xfs;

typedef struct aliastable {
	char *keyin;
	char *alias;
	int keyin_sz;
	int alias_sz;
} aliastable_t;
extern struct aliastable *aliastable;
extern const char *initial_alias[];
extern int aliastable_size;

typedef struct variabletable {
	char *name;
	char *value;
	int name_sz;
	int value_sz;
} variabletable_t;
extern int variabletable_size;
extern struct variabletable *variabletable;
extern void setvariable();

typedef struct functiontable {
	char *name;
	int name_sz;
	struct statement *stmt;
} functiontable_t;
extern struct functiontable *functiontable;
extern const char *initial_function[];
extern int functiontable_size;

extern int sigpiped;

extern char PS1[], PS2[], *prompt;
extern char *get_line();
extern char *(*input_function)();
#define	setprompt(p)	(prompt = (p))
#define setinputfunc(p)	(input_function = (p))

struct statement *translate();
#define	G_EOF	1
#define	G_INTR	2
#define	G_ERROR	3

#define ARGHIST	64
extern int arghist_ptr;
extern char *arghist_buf[ARGHIST];

extern struct statement *allocstmt();
extern void freestmt();
extern int run_command();

extern int sizeof_func();

#ifndef	LIST_HEAD_DEFINED
/* Because of the struct "list_head" defined between "#ifdef __KERNEL__" block
   in Linux 2.2.16 */
struct list_head {
#if 0
	addr_t next, prev;
#else
	struct list_head *next, *prev;
#endif
};
#endif /*LIST_HEAD_DEFINED*/

#define	GETADDR(x)	if (x##_addr == 0 && (x##_addr = searchaddr_bysym(#x)) == 0) { THROW(#x " not found"); }

#endif /*CRASH_H*/
