/**************************************************************
 *       drawkrnl.c - LBM Interpreter Kernel Drawing Functions
 **************************************************************/
/***********************************************
 (C) Copyright 1993-1994; dit/upm
   Distributed under the conditions stated in the
   TOPO General Public License (see file LICENSE)
 ***********************************************
 $Log: drawkrnl.c,v $
 * Revision 1.3  1994/11/14  11:24:16  lotos
 * avoid name collision
 *
 * Revision 1.2  1994/10/17  16:40:43  lotos
 * cosmetics
 *
 * Revision 1.1  1993/10/16  10:52:38  lotos
 * Initial revision
 *
 **********************************************
 $Id: drawkrnl.c,v 1.3 1994/11/14 11:24:16 lotos Exp $
 **********************************************/

#include "swbus.h"

#define NODE 0
#define LBM  1

PRIVATE int indlvl = 0;

PRIVATE void
fprintblnks (fp)
  FILE *fp;
{
  int i = 0;

  for ( ; i < indlvl; i++)
    (void)fprintf (fp, "   ");
}

PRIVATE void
fdraw_lbm_node (fp, S, r)
  FILE  *fp;
  spe   S;
  TNODE *r;
{
  int     id;
  TNODE   *h[MAX_TNODES], *aux;
  INTlist gl1, gl2, vl;

  assert (r != NULL);

  h[0] = r;
  switch (lbm_node_type (S, r)) {
  case _let_exp_1 :
    (void)fprintf (fp, "LET ");
    fdraw_lbm_node (fp, S, gt_fs (r));
    (void)fprintf (fp, " IN\n");
    break;
  case _var_choice_exp_1 :
    myheval (h[0], h);

    break;
  case _gate_choice_exp_1 :
  case _par_exp_full_synch_1 :
  case _par_exp_inter_1 :
  case _par_exp_expli_1 :

    fatal_error ("Tree bad transformed", __FILE__, __LINE__);

    break;
  case _hiding_exp_1 :
    (void)fprintf (fp, "HIDE ");
    fdraw_gatelist (fp, S, (INTlist)takeclr (c_gate_decl, r));
    (void)fprintf (fp, " IN\n");

    break;
  case _enable_exp_1 :
    (void)fprintf (fp, ">> ");
    if (find_attr (c_var_list, r) != NULL) {
      (void)fprintf (fp, "ACCEPT ");
      for (vl = (INTlist)takeclr (c_var_list, r);
	   vl != NULL;
	   vl = INTtail (vl)) {
	(void)fprintf (fp, "%s : %s", l2s (S, INThead (vl)),
		       l2s (S, id2sort (S, (CLR_TYPE)INThead (vl))));
	if (INTtail (vl) != NULL)
	  (void)fprintf (fp, ", ");
      }
      (void)fprintf (fp, " IN");
    }
    (void)fprintf (fp, "\n");
    break;
  case _disable_exp_1 :
    (void)fprintf (fp, "[>\n");

    break;
  case _parallel_full_synch_1 :
    (void)fprintf (fp, "||\n");

    break;
  case _parallel_interleaving_1 :
    (void)fprintf (fp, "|||\n");

    break;
  case _parallel_explicit_1 :
    (void)fprintf (fp, "|[");
    fdraw_gatelist (fp, S, (INTlist)takeclr (c_gate_list, r));
    (void)fprintf (fp, "]|\n");

    break;
  case _choice_exp_1 :
    (void)fprintf (fp, "[]\n");

    break;
  case _guard_exp_1 :
    myheval (h[0], h);
    (void)fprintf (fp, "[");
    fdraw_lbm_node (fp, S, h[1]);
    (void)fprintf (fp, " = ");
    fdraw_lbm_node (fp, S, h[2]);
    (void)fprintf (fp, "] ->\n");

    break;
  case _external_offer_1 :
    myheval (h[0], h);
    (void)fprintf (fp, "%s ", l2s (S, (int)takeclr (c_gate_id, r)));
    if (h[1] != NULL) {
      for (aux = gt_fs (h[1]); aux != NULL; aux = gt_rb (aux)) {
	if (aux->type == tvar_id) {
	  (void)fprintf (fp, "? ");
	  fdraw_lbm_node (fp, S, aux);
	}
	else {
	  (void)fprintf (fp, "! ");
	  fdraw_lbm_node (fp, S, aux);
	}
	(void)fprintf (fp, " ");
      }
    }
    if (h[2] != NULL) {
      (void)fprintf (fp, "[");
      fdraw_lbm_node (fp, S, gt_fs (h[2]));
      (void)fprintf (fp, " = ");
      fdraw_lbm_node (fp, S, gt_rb (gt_fs (h[2])));
      (void)fprintf (fp, "]");
    }
    (void)fprintf (fp, ";\n");

    break;
  case _internal_action_1 :
    (void)fprintf (fp, "i ;\n");

    break;
  case _stop_exp_1 :
    (void)fprintf (fp, "stop\n");

    break;
  case _exit_exp_1 :
    myheval (h[0], h);
    (void)fprintf (fp, "exit");
    if (h[1] != NULL) {
      (void)fprintf (fp, " (");
      for (aux = gt_fs (h[1]); aux != NULL; aux = gt_rb (aux)) {
	if (aux->type == tvalue_exp)
	  fdraw_lbm_node (fp, S, aux);
	else
	  (void)fprintf (fp, "ANY %s", l2s (S, takeclr (c_sort, aux)));
	if (gt_rb (aux) != NULL)
	  (void)fprintf (fp, ", ");
      }
      (void)fprintf (fp, ")");
    }
    (void)fprintf (fp, "\n");

    break;
  case _BUT_instantiation_1 :
    myheval (h[0], h);
    (void)fprintf (fp, "%s ", l2s (S, (int)takeclr (c_BUT_number, r)));
    if (find_attr (c_gate_list, r) != NULL) {
      (void)fprintf (fp, "[");
      fdraw_gatelist (fp, S, (INTlist)takeclr (c_gate_list, r));
      (void)fprintf (fp, "] ");
    }
    if (h[1] != NULL) {
      (void)fprintf (fp, "(");
      for (aux = gt_fs (h[1]); aux != NULL; aux = gt_rb (aux)) {
	fdraw_lbm_node (fp, S, aux);
	if (gt_rb (aux) != NULL)
	  (void)fprintf (fp, ", ");
      }
      (void)fprintf (fp, ")");
    }
    (void)fprintf (fp, "\n");

    break;
  case _relabel_1 :
    (void)fprintf (fp, "[");
    for (gl1 = (INTlist)takeclr (c_gate_list, r),
	 gl2 = (INTlist)takeclr (c_gate_decl, r);
	 (gl1 != NULL) && (gl2 != NULL);
	 gl1 = INTtail (gl1), gl2 = INTtail (gl2)) {
      (void)fprintf (fp, "%s/%s",
		     l2s (S, INThead (gl1)),
		     l2s (S, INThead (gl2)));
      if (INTtail (gl1) != NULL)
	(void)fprintf (fp, ", ");
    }
    (void)fprintf (fp, "]\n");

    break;
  case _ident_equation_list_1 :
    for (r = gt_fs (r); r != NULL; r = gt_rb (r)) {
      fdraw_lbm_node (fp, S, r);
      if (gt_rb (r) != NULL)
	(void)fprintf (fp, ", ");
    }
    break;
  case _ident_equation_1 :
    vl = (INTlist)takeclr (c_var_list, r);
    fdraw_varlist (fp, S, vl);
    (void)fprintf (fp, " : %s",
		   l2s (S, id2sort (S, (CLR_TYPE)INThead (vl))));
    (void)fprintf (fp, " = ");
    fdraw_lbm_node (fp, S, gt_fs (r));
    break;
  case _var_id_1 :
    (void)fprintf (fp, "%s", l2s (S, takeclr (c_var_id, r)));
    break;
  case _value_exp_1 :
    id = (int)takeclr (c_idref, r);
    if (idclass (S, id) == TOPN)   /* operation */
      if (IsInfix (r)) {
	fdraw_lbm_node (fp, S, gt_fs (r));
	(void)fprintf (fp, " %s ", l2s (S, id));
	fdraw_lbm_node (fp, S, gt_rb (gt_fs (r)));
      }
      else {
	(void)fprintf (fp, "%s", l2s (S, id));
	if (gt_fs (r) != NULL) {
	  (void)fprintf (fp, " (");
	  for (aux = gt_fs (r); aux != NULL; aux = gt_rb (aux)) {
	    fdraw_lbm_node (fp, S, aux);
	    if (gt_rb (aux) != NULL)
	      (void)fprintf (fp, ", ");
	  }
	  (void)fprintf (fp, ")");
	}
      }
    else                        /* variable */
      (void)fprintf (fp, "%s", l2s (S, id));
    break;
  default :
    fatal_error ("Wrong node", __FILE__, __LINE__);
  }
}

PRIVATE void
fdraw_lbm (fp, S, r)
  FILE  *fp;
  spe   S;
  TNODE *r;
{
  if (r == NULL) {
    /* It may happen after the evolution of an "exit" */
    /* Arbitrarily, a SPECIFICATION EXITED will be printed. */
    (void)fprintf (fp, "SPECIFICATION EXITED\n");
  }
  else
    fdraw_lbm_node (fp, S, r);
}

PRIVATE void
fdraw_environ (fp, S, env)
  FILE    *fp;
  spe     S;
  xnviron env;
{
  int i;

  (void)fprintf (fp, "(");
  for (i = 0; i < env->size; i++) {
    (void)fprintf (fp, "%s [%s]",
		   l2s (S, env->data[i*2]), getvname (env->data[i*2+1]));
    if (i+1 < env->size)
      (void)fprintf (fp, ", ");
  }
  (void)fprintf (fp, ")");
}

PRIVATE void
fdraw_kt_node (fp, S, kt)
  FILE  *fp;
  spe   S;
  krnlt kt;
{
  gtelist gl1;
  gtelist gl2;
  char    *ast;

  ast = (kt->xto != NOCHOOSEN) ? "*" : "";

  switch (kt->class) {
  case LUNDEFINED : /* Non stable */
    (void)fprintf (fp, "UNSTABLE %s", ast);
    break;
  case LSTOP :
    (void)fprintf (fp, "STOP %s", ast);
    break;
  case LINTERNAL :
    (void)fprintf (fp, "i %s;", ast);
    break;
  case LACTION :
    (void)fprintf (fp, "%s %s;", l2s (S, kt->g), ast);
    break;
  case LEXIT :
    (void)fprintf (fp, "EXIT %s", ast);
    break;

    /* NON TERMINALS */

  case LCHOICE :
    (void)fprintf (fp, "[] %s", ast);
    break;
  case LFULL_SYNC :
    (void)fprintf (fp, "|| %s", ast);
    break;
  case LINTERLEAVING :
    (void)fprintf (fp, "||| %s", ast);
    break;
  case LSYNC :
    (void)fprintf (fp, "|[");
    fdraw_gatelist (fp, S, kt->gtes);
    (void)fprintf (fp, "]| %s", ast);
    break;
  case LDISABLING :
    (void)fprintf (fp, "[> %s", ast);
    break;
  case LENABLING :
    (void)fprintf (fp, ">> %s", ast);
    break;
  case LHIDE :
    (void)fprintf (fp, "HIDE ");
    fdraw_gatelist (fp, S, kt->gtes);
    (void)fprintf (fp, " IN %s", ast);
    break;
  case LRELABEL :
  case LINSTANTIATION :
    if (kt->rlb != NULL) {
      (void)fprintf (fp, "[ ");
      for (gl1 = kt->rlb->actual, gl2 = kt->rlb->formal;
	   (gl1 != NULL) && (gl2 != NULL);
	   gl1 = INTtail (gl1), gl2 = INTtail (gl2))
	(void)fprintf (fp, "%s/%s ",
		       l2s (S, INThead (gl1)),
		       l2s (S, INThead (gl2)));
      (void)fprintf (fp, "] %s", ast);
    }
    break;
    default :
      fatal_error ("There no exist such kind of node",
		   __FILE__, __LINE__);
  }
  if (kt->env != NULL)
    fdraw_environ (fp, S, kt->env);
  (void)fprintf (fp, "\n");
}

PRIVATE void
fdrawktnode (fp, S, kt, class)
  FILE  *fp;
  spe   S;
  krnlt kt;
  int   class;
{
  fprintblnks (fp);

  if (class == NODE)
    fdraw_kt_node (fp, S, kt);
  else
    fdraw_lbm (fp, S, kt->lb);
}

PRIVATE void
print_guards_lets (fp, S, r)
  FILE  *fp;
  spe   S;
  TNODE *r;
{
  if (r != NULL) {
    /* It may happen after the evolution of an "exit" */
    if (gt_ft (r) != NULL) {
      switch (lbm_node_type (S, gt_ft (r))) {
      case _let_exp_1 :
      case _guard_exp_1 :
	print_guards_lets (fp, S, gt_ft (r));
	fprintblnks (fp);
	fdraw_lbm (fp, S, gt_ft (r));
	break;
      }
    }
  }
}

PRIVATE void
fdraw_krnlt (fp, S, kt, class)
  FILE  *fp;
  krnlt kt;
  spe   S;
  int   class;
{
  indlvl++;
  if (class == LBM) {
    print_guards_lets (fp, S, kt->lb);
  }
  if ((kt->son1 != NULL) && (kt->son2 != NULL)) {
    fdraw_krnlt (fp, S, kt->son1, class);
    fdrawktnode (fp, S, kt, class);
    fdraw_krnlt (fp, S, kt->son2, class);
  }
  else if ((kt->son1 == NULL) && (kt->son2 == NULL)) {
    fdrawktnode (fp, S, kt, class);
  }
  else if (kt->son1 != NULL) {
    fdrawktnode (fp, S, kt, class);
    fdraw_krnlt (fp, S, kt->son1, class);
  }
  else fatal_error ("Tree bad built: son2 exists, and son1 is NULL",
		    __FILE__, __LINE__);
  indlvl--;
}

PRIVATE void
draw_krnlt (S, kt)
  spe   S;
  krnlt kt;
{
  fdraw_krnlt (stdout, S, kt, NODE);
}

PUBLIC void
fdraw_kt (fp, S, kt)
  FILE  *fp;
  spe   S;
  krnlt kt;
{
  fdraw_krnlt (fp, S, kt, NODE);
}

PUBLIC void
draw_kt (S, kt)
  spe   S;
  krnlt kt;
{
  fdraw_krnlt (stdout, S, kt, NODE);
}

/* Next two function token from "omdrast.c" */
/* adapted by Gabriel Huecas */

PRIVATE void
my_dr_node (fp, S, r)
  FILE  *fp;
  spe   S;
  TNODE *r;
{
  if (r) {
    (void)fprintf (fp, "<%s>", l2s (S, (int)takeclr (c_BUT_number, r)));
    putattrs (fp, r);
  }
}

PRIVATE void
my_it_tree (fp, S, indent, r, deep)
  FILE  *fp;
  spe   S;
  int   indent;
  TNODE *r;
  int   deep;
{
  int i;

  if (r != NULL && deep != 0) {
    for (i= indent; i > 0; i--)
      (void)fprintf (fp, "  ");
    my_dr_node (fp, S, r);
    my_it_tree (fp, S, indent+1, gt_fs (r), deep-1);
    my_it_tree (fp, S, indent,   gt_rb (r), deep);
  }
}

PUBLIC void
fdraw_hierarchy (fp, S, Hp)
  FILE  *fp;
  spe   S;
  TNODE *Hp;
{
  assert (S != NULL);
  my_it_tree (fp, S, 0, Hp, -1);
}

PUBLIC void
draw_hierarchy (S, Hp)
  spe   S;
  TNODE *Hp;
{
  fdraw_hierarchy (stdout, S, Hp);
}

PUBLIC void
fdraw_proclist (fp, S, pl)
  FILE     *fp;
  spe      S;
  proclist pl;
{
  for (; pl != NULL; pl = INTtail (pl))
    (void)fprintf (fp, "%s (%d)\n",
		   procinstname (S, INThead (pl)), INThead (pl));
}

PUBLIC void
draw_proclist (S, pl)
  spe      S;
  proclist pl;
{
  fdraw_proclist (stdout, S, pl);
}

PUBLIC void
fdraw_state (fp, S)
  FILE *fp;
  spe  S;
{
  assert (S != NULL);
  fdraw_krnlt (fp, S, S->kt, LBM);
}

PUBLIC void
draw_state (S)
  spe  S;
{
  fdraw_state (stdout, S);
}

PUBLIC void
fdraw_proc_state (fp, S, pi)
  FILE *fp;
  spe  S;
  proc pi;
{
  assert (S != NULL);
  fdraw_krnlt (fp, S, search_pi_kt (pi, S->kt), LBM);
}

PUBLIC void
draw_proc_state (S, pi)
  spe  S;
  proc pi;
{
  fdraw_proc_state (stdout, S, pi);
}
