#ifndef support_HH
#define support_HH

#define PUBLIC
#define PRIVATE static

/***********************************************************************
     "support.hh": generic SUPPORT functions.
***********************************************************************/

/***********************************
  (C) Copyright 1992-1993; dit/upm
   Distributed under the conditions stated in the
   TOPO General Public License (see file LICENSE)
 ***********************************
 $Log: support.desc,v $
 * Revision 1.4  1994/11/08  13:48:48  lotos
 * ported to djgpp
 *
 * Revision 1.3  1993/03/29  18:14:34  lotos
 * constructor verification
 *
 * Revision 1.2  1993/03/24  17:45:23  lotos
 * new option -s
 *
 * Revision 1.1  1993/03/18  11:14:24  lotos
 * Initial revision
 *
 ***********************************/

#include "rag.hh"
#include "nodes.h"
#include "grc.h"


/*
 *** Symbol table handling functions ***
 */

typedef struct
{ char *name;
  int type;
} tSYM;		/* symbol type */

/* sorts a symbol table (last element must be { NULL, 0 }) */

void	sort_sym ();

/* finds a symbol in a sorted symbol table */

int	find_sym ();


/*
 *** Node queue manipulation functions ***
 */

typedef struct NDlink
{ struct NDlink *next;
  struct NDlink *prev;
  TNODE *data;
} *NDlink;

typedef struct
{ struct NDlink mark;
  NDlink first;
  NDlink last;
} *NDqueue;

/* creates a new queue */

NDqueue	NQcreate ();

/* provides the first element of a queue (or NULL if none) */

#define NQfirst(queue)						\
	  eval_if((queue) != NULL &&				\
		  (queue)->first != NULL,			\
		  (queue)->first->next == NULL? NULL		\
					      : (queue)->first)

/* provides the next element of a queue (or NULL if none) */

#define NQnext(link)						\
	  eval_if((link) != NULL &&				\
		  (link)->next != NULL,				\
		  (link)->next->next == NULL? NULL		\
					    : (link)->next)

/* provides the previous element of a queue (or NULL if none) */

#define NQprev(link)						\
	  eval_if((link) != NULL &&				\
		  (link)->prev != NULL,				\
		  (link)->prev->prev == NULL? NULL		\
					    : (link)->prev)

/* provides the value of a queue element */

#define NQdata(link)						\
	  eval_if((link) != NULL &&				\
		  (link)->next != NULL &&			\
		  (link)->data != NULL,				\
		  (link)->data)

/* locates an element in the queue and returns it (or NULL if not found) */

NDlink	NQfind ();

/* adds a new element to an existing queue and returns it */

NDlink	NQadd ();

/* removes an element in a queue */

void	NQrm ();

/* duplicates a queue */

NDqueue	NQdup ();

/* destroys an already existent queue */

void	NQdestroy ();

/* TIOCOLOURS entry */

#define IO_NQ	NULL, NULL, NULL, NULL

/* draws a queue in a file */

void	NQdraw ();


/*
 *** Basic data and functions for using EPS ***
 */

#include "colours.h"
#define c_opns		100	/* operations of a sort */
#define c_antv		101	/* annotation value */
#define c_init		102	/* initialization done? */
#define c_accept	104	/* accepted annotation list */
#define c_reject	105	/* rejected annotation list */
#define c_remain	106	/* remaining annotation list */
#define c_insert	107	/* inserting annotation list */

#ifndef support_IMP
extern	TIOCOLOURS iocolours[];
#else
	TIOCOLOURS iocolours[]= {
#include "colours.c"
				 "opns",   c_opns,   IO_IT,
				 "antv",   c_antv,   IO_str,
				 "init",   c_init,   IO_int,
				 "accept", c_accept, IO_NQ,
				 "reject", c_reject, IO_NQ,
				 "remain", c_remain, IO_NQ,
				 "insert", c_insert, IO_NQ,
				 NULL,     others,   IO_ign
			       };
#endif

/* possible values of "idclass" attribute */
#define spec_id		 1
#define type_id		 2
#define sort_id		 3
#define opn_id		 4
#define proc_id		 5
#define gate_id		 6
#define value_id	 7

#ifndef support_IMP
extern	TNODE *SpecTree;
#else
	TNODE *SpecTree= NULL;
#endif

#ifndef support_IMP
extern	TNODE *TpltTree;
#else
	TNODE *TpltTree= NULL;
#endif

typedef struct
{ int *all;
  int *begin;
  int *sort;
  int *opn;
  int *end;
} tSPEC_DECL;	/* specification declaration information structure */

/* specification declaration information */
#ifndef support_IMP
extern	tSPEC_DECL SpecDecl;
#else
	tSPEC_DECL SpecDecl= { NULL, NULL, NULL, NULL, NULL };
#endif

extern ST *SymbolTable;		/* symbol table */
#ifndef support_IMP
extern	HT HashTable;
#else
	HT HashTable= NULL;
#endif

#ifndef support_IMP
extern	AT *ATable;
#else
	AT *ATable= NULL;
#endif

#ifndef support_IMP
extern	int errorcount;
#else
	int errorcount= 0;
#endif


TNODE *	bast ();

/* sets a drawing function */

void	set_draw ();

/* draws a node */

void	draw_node ();

/* draws a tree */

void	draw_tree ();


/*
 *** General functions for handling specification tables ***
 */

/* is a specification table initialized? */

#define is_stbl_init(name)	((name) != NULL)

/* returns a pointer to a specification table */

#define stbl_ptr(name)	eval_if(is_stbl_init(name), name)

/* is an element in a specification table? */

#define is_stbl_entry(name, ndx)	\
	 (is_stbl_init(name) &&		\
	  0 <= (ndx) &&			\
	  (ndx) < (name)->size)

/* returns the size of a specification table */

#define stbl_size(name) \
	  eval_if(is_stbl_init(name), (name)->size)

/* returns an element in a specification table */

#define stbl_entry(name, ndx) \
	  eval_if(is_stbl_entry(name, ndx), (name)->data + ndx)


/*
 *** General functions for handling attributes ***
 */

/* provides the value of an attribute */

CLR_TYPE _attr_value();

#ifndef NDEBUG
#  define attr_value(nodep, attr_name, attr_type) \
	    ((attr_type) _attr_value(nodep, attr_name))
#else
#  define attr_value(nodep, attr_name, attr_type) \
	    ((attr_type) find_attr((attr_name), (nodep))->value)
#endif

/* provides the value of a hardwired attribute */

#define HWattr_value(nodep, attr_pos, attr_type) \
	  eval_if((nodep) != NULL, (attr_type) (nodep)->attr_pos)

/* provides the value of first hardwired attribute */

#define HWattr0_value(nodep, attr_type) \
	  HWattr_value(nodep, value0, attr_type)

/* provides the value of second hardwired attribute */

#define HWattr1_value(nodep, attr_type) \
	  HWattr_value(nodep, value1, attr_type)

/* provides the value of an attribute, or else "not_found_value" */

CLR_TYPE _find_attr_value();

#define find_attr_value(nodep, attr_name, attr_type, not_found_value)  \
	  ((attr_type) _find_attr_value(nodep, attr_name,	       \
					(CLR_TYPE) (not_found_value)))

/* adds an attribute and its value */

void _add_attr_value();

#ifndef NDEBUG
#  define add_attr_value(nodep, attr_name, attr_value) \
	    _add_attr_value(nodep, attr_name, (CLR_TYPE) (attr_value))
#else
#  define add_attr_value(nodep, attr_name, attr_value)		\
	    ((void) (add_attr((attr_name), (nodep))->value=	\
		       (CLR_TYPE) (attr_value)))
#endif

/* adds the value of a hardwired attribute */

#define add_HWattr_value(nodep, attr_pos, attr_value)		\
	  eval_if((nodep) != NULL && (nodep)->attr_pos == NULL,	\
		  (void) ((nodep)->attr_pos=			\
			    (CLR_TYPE) (attr_value)))

/* adds the value of first hardwired attribute */

#define add_HWattr0_value(nodep, attr_value) \
	  add_HWattr_value(nodep, value0, attr_value)

/* adds the value of second hardwired attribute */

#define add_HWattr1_value(nodep, attr_value) \
	  add_HWattr_value(nodep, value1, attr_value)

/* removes an attribute and its value */

void _del_attr_value();

#ifndef NDEBUG
#  define del_attr_value(nodep, attr_name) \
	    _del_attr_value(nodep, attr_name)
#else
#  define del_attr_value(nodep, attr_name) \
	    free_attr(take_attr((attr_name), (nodep)))
#endif

/* removes an attribute, if any, and its value */

void _fdel_attr_value();

#define fdel_attr_value(nodep, attr_name) \
	  _fdel_attr_value(nodep, attr_name)

/* like "attr_value()", but for attribute table */

CLR_TYPE _AT_attr_value();

#ifndef NDEBUG
#  define AT_attr_value(ndx, attr_name, attr_type) \
	    ((attr_type) _AT_attr_value(ndx, attr_name))
#else
#  define AT_attr_value(ndx, attr_name, attr_type) \
	    ((attr_type) ATfind(ATable, ndx, attr_name)->value)
#endif

/* like "HWattr_value()", but for attribute table */

#define AT_HWattr_value(ndx, attr_pos, attr_type)		\
	  eval_if(is_stbl_entry(ATable, ndx),			\
		  (attr_type) ATable->data[ndx].attr_pos)

/* like "HWattr0_value()", but for attribute table */

#define AT_HWattr0_value(ndx, attr_type) \
	  AT_HWattr_value(ndx, value0, attr_type)

/* like "HWattr1_value()", but for attribute table */

#define AT_HWattr1_value(ndx, attr_type) \
	  AT_HWattr_value(ndx, value1, attr_type)

/* like "find_attr_value()", but for attribute table */

CLR_TYPE _AT_find_attr_value();

#define AT_find_attr_value(ndx, attr_name, attr_type, not_found_value) \
	  ((attr_type) _AT_find_attr_value(ndx, attr_name,	       \
					   (CLR_TYPE)		       \
					   (not_found_value)))

/* like "add_attr_value()", but for attribute table */

void _AT_add_attr_value();

#ifndef NDEBUG
#  define AT_add_attr_value(ndx, attr_name, attr_value) \
	    _AT_add_attr_value(ndx, attr_name, (CLR_TYPE) (attr_value))
#else
#  define AT_add_attr_value(ndx, attr_name, attr_value)		\
	    ((void) (ATadd(ATable, ndx, attr_name)->value=	\
		       (CLR_TYPE) (attr_value)))
#endif

/* like "add_HWattr_value()", but for attribute table */

#define AT_add_HWattr_value(ndx, attr_pos, attr_value)		\
	  eval_if(is_stbl_entry(ATable, ndx) &&			\
		  stbl_entry(ATable, ndx)->attr_pos == NULL,	\
		  (void) (stbl_entry(ATable, ndx)->attr_pos=	\
			    (CLR_TYPE) (attr_value)))

/* like "add_HWattr0_value()", but for attribute table */

#define AT_add_HWattr0_value(ndx, attr_value) \
	  AT_add_HWattr_value(ndx, value0, attr_value)

/* like "add_HWattr1_value()", but for attribute table */

#define AT_add_HWattr1_value(ndx, attr_value) \
	  AT_add_HWattr_value(ndx, value1, attr_value)

/* like "del_attr_value()", but for attribute table */

void _AT_del_attr_value();

#ifndef NDEBUG
#  define AT_del_attr_value(ndx, attr_name) \
	    _AT_del_attr_value(ndx, attr_name)
#else
#  define AT_del_attr_value(ndx, attr_name) \
	    free_attr(ATtake(ATable, ndx, attr_name))
#endif

/* like "fdel_attr_value()", but for attribute table */

void _AT_fdel_attr_value();

#define AT_fdel_attr_value(ndx, attr_name) \
	  _AT_fdel_attr_value(ndx, attr_name)


/*
 *** Functions for handling specific attributes ***
 */

/* returns "at" attribute value */

#define ask_at(nodep)	attr_value(nodep, c_at, AT *)

/* returns "ll" attribute value */

#define ask_ll(nodep)	attr_value(nodep, c_ll, ST *)

/* returns "lexv" attribute value */

#define ask_lexv(nodep)	attr_value(nodep, c_lexv, int)

/* returns "lexv" attribute value (from attribute table) */

#define AT_ask_lexv(idn)	AT_HWattr1_value(idn, int)

/* returns "line" attribute value */

#define ask_line(nodep)	attr_value(nodep, c_line, int *)

/* returns "line" attribute value (from attribute table) */

#define AT_ask_line(idn)	AT_attr_value(idn, c_line, int *)

/* adds "line" attribute and its value */

#define add_line(nodep, val) \
	  add_attr_value(nodep, c_line, ALIN(void, val))

/* returns "idclass" attribute value (from attribute table) */

#define AT_ask_idclass(idn)	AT_HWattr0_value(idn, int)

/* returns "spec" attribute value */

#define ask_spec(nodep)	attr_value(nodep, c_spec, int)

/* returns "endspec" attribute value */

#define ask_endspec(nodep)	attr_value(nodep, c_endspec, int)

/* returns "cso" attribute value */

#define ask_cso(nodep)	attr_value(nodep, c_cso, int)

/* returns "cop" attribute value */

#define ask_cop(nodep)	attr_value(nodep, c_cop, int)

/* returns "cui" attribute value (from attribute table) */

#define AT_ask_cui(idn)	AT_find_attr_value(idn, c_cui, int, -1)

/* returns "infix" attribute value */

#define ask_infix(nodep)	find_attr_value(nodep, c_infix, int, -1)

/* returns "infix" attribute value (from attribute table) */

#define AT_ask_infix(idn)	AT_find_attr_value(idn, c_infix, int, -1)

/* returns "sort" attribute value (from attribute table) */

#define AT_ask_sort(idn)	AT_attr_value(idn, c_sort, int)

/* returns "opns" attribute value (from attribute table) */

#define AT_ask_opns(idn)	AT_attr_value(idn, c_opns, IT *)

/* adds "opns" attribute and its value */

#define AT_add_opns(idn, val) \
	  AT_add_attr_value(idn, c_opns, ALIN(void, val))

/* returns "sargl" attribute value (from attribute table) */

#define AT_ask_sargl(idn)	AT_attr_value(idn, c_sargl, INTlist)

/* returns "grn" attribute value */

#define ask_grn(nodep)	HWattr0_value(nodep, int)

/* adds "grn" attribute and its value */

#define add_grn(nodep, val)	add_HWattr0_value (nodep, val)

/* returns "antv" attribute value */

#define ask_antv(nodep)	find_attr_value(nodep, c_antv, char *, NULL)

/* adds "antv" attribute and its value */

#define add_antv(nodep, val) \
	  add_attr_value(nodep, c_antv, ALIN(void, val))

/* deletes "antv" attribute and its value */

#define del_antv(nodep)	fdel_attr_value(nodep, c_antv)

/* returns "accept" attribute value */

#define AT_ask_accept(idn)	AT_attr_value(idn, c_accept, NDqueue)

/* adds "accept" attribute and its value */

#define AT_add_accept(idn, val) \
	  AT_add_attr_value(idn, c_accept, ALIN(void, val))

/* returns "reject" attribute value */

#define AT_ask_reject(idn)	AT_attr_value(idn, c_reject, NDqueue)

/* adds "reject" attribute and its value */

#define AT_add_reject(idn, val) \
	  AT_add_attr_value(idn, c_reject, ALIN(void, val))

/* returns "remain" attribute value */

#define AT_ask_remain(idn)	AT_attr_value(idn, c_remain, NDqueue)

/* adds "remain" attribute and its value */

#define AT_add_remain(idn, val) \
	  AT_add_attr_value(idn, c_remain, ALIN(void, val))

/* returns "insert" attribute value */

#define AT_ask_insert(idn)	AT_attr_value(idn, c_insert, NDqueue)

/* adds "insert" attribute and its value */

#define AT_add_insert(idn, val) \
	  AT_add_attr_value(idn, c_insert, ALIN(void, val))

/* returns "Gannot" attribute value */

#define AT_ask_Gannot(idn)	AT_attr_value(idn, c_Gannot, IT *)

/* adds "Gannot" attribute and its value */

#define AT_add_Gannot(idn, val) \
	  AT_add_attr_value(idn, c_Gannot, ALIN(void, val))

/* returns "Gline" attribute value */

#define AT_ask_Gline(idn)	AT_attr_value(idn, c_Gline, IT *)

/* adds "Gline" attribute and its value */

#define AT_add_Gline(idn, val) \
	  AT_add_attr_value(idn, c_Gline, ALIN(void, val))


/*
 *** Functions to ask for specific pseudo-attributes ***
 */

/* returns "ident" pseudo-attribute value */

#define ident(nodep)	(*stbl_entry(SymbolTable, ask_lexv(nodep)))

/* returns "ident" pseudo-attribute value (from attribute table) */

#define AT_ident(idn)	(*stbl_entry(SymbolTable, AT_ask_lexv(idn)))

/* returns "nofile" pseudo-attribute value */

#define nofile(nodep)	(*stbl_entry(SymbolTable, ask_line(nodep)[1]))

/* returns "AT_nofile" pseudo-attribute value (from attribute table) */

#define AT_nofile(idn)	(*stbl_entry(SymbolTable, AT_ask_line(idn)[1]))

/* returns "noline" pseudo-attribute value */

#define noline(nodep)	(ask_line(nodep)[0])

/* returns "AT_noline" pseudo-attribute value (from attribute table) */

#define AT_noline(idn)	(AT_ask_line(idn)[0])


/*
 *** Annotation data and functions ***
 */

/* annotation class */
typedef enum { SYMBOLIC, EXTERNAL } tANNOT_CLASS;

#ifndef class
#  define CLASS class
#endif

typedef struct annot
{ char *name;
  int token;
  int node;
  int attr;
  struct
  { int begin;
    int sort;
    int opn;
    int end;
  } where;
  tANNOT_CLASS CLASS;
  struct
  { struct annot **item;
    int size;
  } group;
} tANNOT;	/* annotation information structure */

#ifdef CLASS
#  undef CLASS
#endif

/* annotation information list type */
typedef tANNOT tANNOT_LIST[];

/* annotation information list (you mustn't use it) */
#ifndef support_IMP
extern	tANNOT_LIST _annot_list;
#else
	tANNOT_LIST _annot_list= {
#include "annots.c"
				  { NULL, 0, 0, 0,
				    { FALSE, FALSE, FALSE, FALSE },
				    SYMBOLIC,
				    { NULL, 0 }
				  }
};
#endif

/* annotation information list size (you mustn't use it) */
#ifndef support_IMP
extern	int _annot_list_size;
#else
	int _annot_list_size= 0;
#endif

/* provides access to annotation information list */

#define annot_list(ndx)				\
	  eval_if(EVAL(ndx) >= 0 &&		\
		  EVAL(ndx) < _annot_list_size,	\
		  _annot_list + (ndx))

/* provides annotation information list size */

#define annot_list_size()			\
	  eval_if(_annot_list_size > 0,		\
		  _annot_list_size)

typedef struct
{ tANNOT **item;
  int last;
} tANNOT_INDEX;	/* annotation information index structure */

/* node index to annotation information (you mustn't use it) */
#ifndef support_IMP
extern	tANNOT_INDEX _annot_node;
#else
	tANNOT_INDEX _annot_node= { NULL, 0 };
#endif

/* indexes annotation information by node */

#define annot_node(type)				\
	  eval_if(EVAL(type) < 0 &&			\
		  EVAL(type) > _annot_node.last &&	\
		  _annot_node.item[type] != NULL,	\
		  _annot_node.item[type])

/* attribute index to annotation information (you mustn't use it) */
#ifndef support_IMP
extern	tANNOT_INDEX _annot_attr;
#else
	tANNOT_INDEX _annot_attr= { NULL, 0 };
#endif

/* indexes annotation information by attribute */

#define annot_attr(type)				\
	  eval_if(EVAL(type) > 0 &&			\
		  EVAL(type) < _annot_attr.last &&	\
		  _annot_attr.item[type] != NULL,	\
		  _annot_attr.item[type])


/*
 *** Support starting and stopping functions ***
 */

/* starts processing */

void	xtart ();

/* stops processing */

void	stop ();

#endif
