/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 *
 * tree.h -- public definitions for tree module
 *
 * the parse tree is made up of struct node's.  the struct is
 * a "variant record" with a type, the filename and line number
 * related to the node, and then type-specific node data.
 */

#ifndef	_ESC_COMMON_TREE_H
#define	_ESC_COMMON_TREE_H

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#ifdef	__cplusplus
extern "C" {
#endif

struct node {
	enum nodetype {
		T_NOTHING = 1000,	/* used to keep going on error cases */
		T_NAME,			/* identifiers, sometimes chained */
		T_GLOBID,		/* globals (e.g. $a) */
		T_EVENT,		/* class@path{expr} */
		T_ENGINE,		/* upset threshold engine (e.g. SERD) */
		T_ASRU,			/* ASRU declaration */
		T_FRU,			/* FRU declaration */
		T_TIMEVAL,		/* num w/time suffix (ns internally) */
		T_NUM,			/* num (ull internally) */
		T_QUOTE,		/* quoted string */
		T_FUNC,			/* func(arglist) */
		T_NVPAIR,		/* name=value pair in decl */
		T_ASSIGN,		/* assignment statement */
		T_CONDIF,		/* a and T_CONDELSE in (a ? b : c ) */
		T_CONDELSE,		/* lists b and c in (a ? b : c ) */
		T_NOT,			/* boolean ! operator */
		T_AND,			/* boolean && operator */
		T_OR,			/* boolean || operator */
		T_EQ,			/* boolean == operator */
		T_NE,			/* boolean != operator */
		T_SUB,			/* integer - operator */
		T_ADD,			/* integer + operator */
		T_MUL,			/* integer * operator */
		T_DIV,			/* integer / operator */
		T_MOD,			/* integer % operator */
		T_LT,			/* boolean < operator */
		T_LE,			/* boolean <= operator */
		T_GT,			/* boolean > operator */
		T_GE,			/* boolean >= operator */
		T_BITAND,		/* bitwise & operator */
		T_BITOR,		/* bitwise | operator */
		T_BITXOR,		/* bitwise ^ operator */
		T_BITNOT,		/* bitwise ~ operator */
		T_LSHIFT,		/* bitwise << operator */
		T_RSHIFT,		/* bitwise >> operator */
		T_ARROW,		/* lhs (N)->(K) rhs */
		T_LIST,			/* comma-separated list */
		T_FAULT,		/* fault declaration */
		T_UPSET,		/* upset declaration */
		T_DEFECT,		/* defect declaration */
		T_ERROR,		/* error declaration */
		T_EREPORT,		/* ereport declaration */
		T_SERD,			/* SERD engine declaration */
		T_STAT,			/* STAT engine declaration */
		T_PROP,			/* prop statement */
		T_MASK,			/* mask statement */
		T_CONFIG		/* config statement */
	} t;

	/*
	 * regardless of the type of node, filename and line number
	 * information from the original .esc file is tracked here.
	 */
	const char *file;
	int line;

	/*
	 * the variant part of a struct node...
	 */
	union {
		struct {
			/*
			 * info kept for T_NAME, used in several ways:
			 *
			 *	1 for simple variable names.
			 *		example: j
			 *
			 *	2 for event class names, with component
			 *	  names chained together via the "next"
			 *	  pointers.
			 *		example: fault.fan.broken
			 *
			 *	3 for component pathnames, with component
			 *	  names chained together via the "next"
			 *	  pointers and iterators or instance numbers
			 *	  attached via the "child" pointers.
			 *		example: sysboard[0]/cpu[n]
			 *
			 * case 3 is the most interesting.
			 *	- if child is set, there's an iterator
			 *	- if child is a T_NAME, it is x[j] or x<j> and
			 *	  iterator type tells you vertical or horizontal
			 *	- if child is a T_NUM, it is x[0] or x<0> or
			 *	  x0 and iterator type tells you which one
			 *	- if cp pointer is set, then we recently
			 *	  matched it to a config cache entry and one
			 *	  can ignore child for now because it still
			 *	  represents the *pattern* you're matching.
			 *	  cp represents what you matched.  ptree()
			 *	  knows that if cp is set, to print that number
			 *	  instead of following child.
			 *
			 * when T_NAME nodes are chained:
			 * the "last" pointer takes you to the end of the
			 * chain, but only the first component's last pointer
			 * is kept up to date.  it is used to determine
			 * where to append newly-created T_NAME nodes (see
			 * tree_name_append()).
			 */
			const char *s;		/* the name itself */

			struct node *child;
			struct node *next;
			struct node *last;

			/* opaque pointer used during config matching */
			struct config *cp;

			enum nametype {
				N_UNSPEC,
				N_FAULT,
				N_UPSET,
				N_DEFECT,
				N_ERROR,
				N_EREPORT,
				N_SERD,
				N_STAT
			} t:3;
			enum itertype {
				IT_NONE,
				IT_VERTICAL,
				IT_HORIZONTAL,
				IT_ENAME
			} it:2;
			unsigned childgen:1;	/* child was auto-generated */
		} name;

		struct {
			/*
			 * info kept for T_GLOBID
			 */
			const char *s;		/* the name itself */
		} globid;

		/*
		 * info kept for T_TIMEVAL and T_NUM
		 *
		 * timevals are kept in nanoseconds.
		 */
		unsigned long long ull;

		struct {
			/*
			 * info kept for T_QUOTE
			 */
			const char *s;		/* the quoted string */
		} quote;

		struct {
			/*
			 * info kept for T_FUNC
			 */
			const char *s;		/* name of function */
			struct node *arglist;
		} func;

		struct {
			/*
			 * info kept for T_PROP and T_MASK statements
			 * as well as declarations for:
			 *	T_FAULT
			 *	T_UPSET
			 *	T_DEFECT
			 *	T_ERROR
			 *	T_EREPORT
			 *	T_ASRU
			 *	T_FRU
			 *	T_CONFIG
			 */
			struct node *np;
			struct node *nvpairs;	/* for declarations */
			struct lut *lutp;	/* for declarations */
			struct node *next;	/* for Props & Masks lists */
			struct node *expr;	/* for if statements */
			unsigned char flags;	/* see STMT_ flags below */
		} stmt;			/* used for stmt */

		struct {
			/*
			 * info kept for T_EVENT
			 */
			struct node *ename;	/* event class name */
			struct node *epname;	/* component path name */
			struct node *eexprlist;	/* constraint expression */
			struct node *declp;	/* event declaration */
		} event;

		struct {
			/*
			 * info kept for T_ARROW
			 */
			struct node *lhs;	/* left side of arrow */
			struct node *rhs;	/* right side of arrow */
			struct node *nnp;	/* N value */
			struct node *knp;	/* K value */
			struct node *prop;	/* arrow is part of this prop */
		} arrow;

		struct {
			/*
			 * info kept for everything else (T_ADD, T_LIST, etc.)
			 */
			struct node *left;
			struct node *right;
		} expr;
	} u;
};

/* flags we keep with stmts */
#define	STMT_REF	0x01	/* declared item is referenced */
#define	STMT_CYMARK	0x02	/* declared item is marked for cycle check */
#define	STMT_CYCLE	0x04	/* cycle detected and already reported */

#define	TIMEVAL_EVENTUALLY (1000000000ULL*60*60*24*365*100)	/* 100 years */

void tree_init(void);
void tree_fini(void);
struct node *newnode(enum nodetype t, const char *file, int line);
void tree_free(struct node *root);
struct node *tree_root(struct node *np);
struct node *tree_nothing(void);
struct node *tree_expr(enum nodetype t, struct node *left, struct node *right);
struct node *tree_event(struct node *ename, struct node *epname,
    struct node *eexprlist);
struct node *tree_if(struct node *expr, struct node *stmts,
    const char *file, int line);
struct node *tree_name(const char *s, enum itertype it,
    const char *file, int line);
struct node *tree_iname(const char *s, const char *file, int line);
struct node *tree_globid(const char *s, const char *file, int line);
struct node *tree_name_append(struct node *np1, struct node *np2);
struct node *tree_name_repairdash(struct node *np1, const char *s);
struct node *tree_name_iterator(struct node *np1, struct node *np2);
struct node *tree_timeval(const char *s, const char *suffix,
    const char *file, int line);
struct node *tree_num(const char *s, const char *file, int line);
struct node *tree_quote(const char *s, const char *file, int line);
struct node *tree_func(const char *s, struct node *np,
    const char *file, int line);
struct node *tree_pname(struct node *np);
struct node *tree_arrow(struct node *lhs, struct node *nnp, struct node *knp,
    struct node *rhs);
struct lut *tree_s2np_lut_add(struct lut *root, const char *s, struct node *np);
struct node *tree_s2np_lut_lookup(struct lut *root, const char *s);
struct lut *tree_name2np_lut_add(struct lut *root,
    struct node *namep, struct node *np);
struct node *tree_name2np_lut_lookup(struct lut *root, struct node *namep);
struct node *tree_name2np_lut_lookup_name(struct lut *root, struct node *namep);
struct lut *tree_event2np_lut_add(struct lut *root,
    struct node *enp, struct node *np);
struct node *tree_event2np_lut_lookup(struct lut *root, struct node *enp);
struct node *tree_event2np_lut_lookup_event(struct lut *root,
    struct node *enp);
struct node *tree_decl(enum nodetype t, struct node *enp, struct node *nvpairs,
    const char *file, int line);
struct node *tree_stmt(enum nodetype t, struct node *np,
    const char *file, int line);
void tree_report();
int tree_namecmp(struct node *np1, struct node *np2);
int tree_eventcmp(struct node *np1, struct node *np2);

struct lut *Faults;
struct lut *Upsets;
struct lut *Defects;
struct lut *Errors;
struct lut *Ereports;
struct lut *Ereportenames;
struct lut *SERDs;
struct lut *STATs;
struct lut *ASRUs;
struct lut *FRUs;
struct lut *Configs;
struct node *Props;
struct node *Lastprops;
struct node *Masks;
struct node *Lastmasks;
struct node *Problems;
struct node *Lastproblems;

#ifdef	__cplusplus
}
#endif

#endif	/* _ESC_COMMON_TREE_H */