/***********************************************
 (C) Copyright 1992-1993; dit/upm
   Distributed under the conditions stated in the
   EPS General Public License (see file LICENSE)
 ***********************************************
 $Log: colours.c,v $
 * Revision 2.6  1993/06/15  11:03:24  eps
 * is a LINTLIBRARY
 *
 * Revision 2.5  1993/01/12  16:35:41  eps
 * portability issues
 *
 * Revision 2.4  1992/01/14  15:43:51  eps
 * distribution issues
 *
 * Revision 2.3  92/01/14  15:26:59  eps
 * adapt to case independent cast
 *
 * Revision 2.2  91/04/10  10:02:01  eps
 * new function todoi
 *
 * Revision 2.1  90/10/30  08:44:40  eps
 * plenty of small fixes:
 * visit, new classes, integrated tree traversal for evaluation, ...
 *
 * Revision 1.7  90/06/04  11:53:17  eps
 * adclr fixed to cope with nodes without previous colours
 *
 * Revision 1.6  90/05/10  20:24:57  eps
 * remove colours.hh
 *
 * Revision 1.5  90/05/10  18:14:40  eps
 * speed up adclr ()
 *
 * Revision 1.4  90/03/16  16:50:29  eps
 * third argument dropped, it was always identical to fourth
 *
 * Revision 1.3  90/02/19  19:22:31  eps
 * include fdclr, optimized for negative colours
 * drop ptclr, and lfclr
 *
 * Revision 1.2  90/01/29  14:56:51  eps
 * fixing license details
 *
 * Revision 1.1  90/01/25  19:53:30  eps
 * Initial revision
 *
 **********************************************/

/* LINTLIBRARY */

#ifndef lint
static char rcsid[]= "$Id: colours.c,v 2.6 1993/06/15 11:03:24 eps Exp $";
#endif

# include <stdio.h>
# include "rag.hh"

# define pos(n) (n < 0 ? -n : n)

typedef CLR_TYPE  (*PFI)();

PRIVATE void
crash (tool, c, n, r, msg)
     char* tool;
     int c;			/* colour type */
     TNODE* n;			/* node */
     int r;			/* semantic rule */
     char* msg;
{
  (void) fprintf (stderr,
		  "%s:colour %d (%s):rule %d:%s\n",
		  tool,
		  c, type2clr(pos(c))->keyword,
		  r,
		  msg);
  if (n != NULL) {
    (void) fprintf (stderr, "node ...\n");
    dr_node (n);
    if (gt_ft (n) != NULL) {
      (void) fprintf (stderr, "father ... sons\n");
      drn_tree (gt_ft (n), 3);
    }
    else {
      (void) fprintf (stderr, "[no father] ... sons\n");
      drn_tree (n, 2);
    }
  }
  exit (1);
}

PUBLIC CLR_TYPE
fdclr (c, node, nrs)
     int c;
     TNODE* node;
     int nrs;
{
  TATTR* attr;
  CLR_TYPE val;

  if (node == NULL)
    crash ("fdclr", c, node, nrs, "null node");
  for (attr= node->attrs; attr != NULL; attr= attr->next)
    if ((attr->atype == c) || (-attr->atype == c))
      break;
  if (attr == NULL)
    crash ("fdclr", c, node, nrs, "no such colour");
  if (attr->atype > 0)
    return attr->value;
  if (attr->value == NULL)
    crash ("fdclr", c, node, nrs, "circular definition!");
  val= attr->value;
  attr->value= NULL;		/* to check circularities !! */
  attr->value= val= eval ((int) val, node);
  attr->atype= c;
  return val;
}

PUBLIC	void
adclr (c, node, nrs)
     int c;
     TNODE* node;
     int nrs;
{
  TATTR* attr;
  TATTR* last;

  if (node == NULL)
    crash ("adclr", c, node, nrs, "null node");
  if (node->attrs == NULL) {
    attr= new_attr ();
    node->attrs= attr;
  }
  else {
    for (attr= node->attrs; attr != NULL; attr= attr->next)
      if ((attr->atype == c) || (-attr->atype == c))
	crash ("adclr", c, node, nrs, "already exists");
      else
	last= attr;
    attr= new_attr ();
    last->next= attr;
  }
  attr->atype= c;
  attr->value= (CLR_TYPE) nrs;
  attr->next= NULL;
}

PUBLIC void
heval (r, h)
     TNODE* r;
     TNODE* h[];
{
  register int i, class;

  class= (int) r->value1;
  for (i= 1; i < 33; i++)
    h[i]= NULL;
  if (class == 0)
    h[1]= r->sons;
  else {
    r= r->sons;
    for (i= 0; i < 32 && r != NULL; i++)
      if (class & (1 << i)) {
	h[i+1]= r;
	r= r->brothers;
      }
      else
	h[i+1]= NULL;
  }
}

PUBLIC void
todoi (r, i)
     TNODE* r;
     int i;
{
  register TATTR* a;
  CLR_TYPE val;
  int c;

  for (; r != NULL; r= r->brothers) {
    if (r->sons)
      todoi (r->sons, i);
    for (a= r->attrs; a != NULL; a= a->next)
      if ((c= a->atype) < 0 && ragphase[-c] == i) {
	if (a->value == NULL)
	  crash ("todo", -c, r, -1, "circular definition!");
	val= a->value;
	a->value= NULL;            /* to check circularities !! */
	a->value= eval ((int) val, r);
	a->atype= -c;
      }
  }
}

PUBLIC void
todo (r)
     TNODE* r;
{
  register TATTR* a;
  CLR_TYPE val;
  int c;

  for (; r != NULL; r= r->brothers) {
    if (r->sons)
      todo (r->sons);
    for (a= r->attrs; a != NULL; a= a->next)
      if ((c= a->atype) < 0) {
	if (a->value == NULL)
	  crash ("todo", -c, r, -1, "circular definition!");
	val= a->value;
	a->value= NULL;            /* to check circularities !! */
	a->value= eval ((int) val, r);
	a->atype= -c;
      }
  }
}

