typedef struct Field Field;
typedef struct Filter Filter;
typedef struct Msg Msg;
typedef struct Mux Mux;
typedef struct Proto Proto;

#define NetS(x) ((((uchar*)x)[0]<<8) | ((uchar*)x)[1])
#define Net3(x) ((((uchar*)x)[0]<<16) | (((uchar*)x)[1]<<8) | ((uchar*)x)[2])
#define NetL(x) ((((uchar*)x)[0]<<24) | (((uchar*)x)[1]<<16) | (((uchar*)x)[2]<<8) | ((uchar*)x)[3])

/*
 *  one per protocol module
 */
struct Proto
{
	char*	name;
	void	(*compile)(Filter*);
	int	(*filter)(Filter*, Msg*);
	int	(*seprint)(Msg*);
	Mux*	mux;
	char*	valfmt;
	Field*	field;
	int	(*framer)(int, uchar*, int);
};
extern Proto *protos[];

/*
 *  one per protocol module, pointed to by Proto.mux
 */
struct Mux
{
	char*	name;
	ulong	val;
	Proto*	pr;
};

/*
 *  a field defining a comparison filter
 */
struct Field
{
	char*	name;
	int	ftype;
	int	subop;
	char*	help;
};

/*
 *  the status of the current message walk
 */
struct Msg
{
	uchar	*ps;	/* packet ptr */
	uchar	*pe;	/* packet end */

	char	*p;	/* buffer start */
	char	*e;	/* buffer end */

	int	needroot;	/* pr is root, need to see in expression */
	Proto	*pr;	/* current/next protocol */	
};

enum
{
	Fnum,		/* just a number */
	Fether,		/* ethernet address */
	Fv4ip,		/* v4 ip address */
	Fv6ip,		/* v6 ip address */
	Fba,		/* byte array */
};

/*
 *  a node in the filter tree
 */
struct Filter {
	int	op;	/* token type */
	char	*s;	/* string */
	Filter	*l;
	Filter	*r;

	Proto	*pr;	/* next protocol;

	/* protocol specific */
	int	subop;
	ulong	param;
	union {
		ulong	ulv;
		vlong	vlv;
		uchar	a[32];
	};
};

extern void	yyinit(char*);
extern int	yyparse(void);
extern Filter*	newfilter(void);
extern void	compile_cmp(char*, Filter*, Field*);
extern void	demux(Mux*, ulong, ulong, Msg*, Proto*);
extern int	defaultframer(int, uchar*, int);

extern int Mflag;
extern int Nflag;
extern int dflag;
extern int Cflag;

typedef Filter *Filterptr;
#define YYSTYPE Filterptr
extern Filter *filter;
