/* ,file-id archive://[lord]/421/rx/dbug.c/1998-05-18
 */
/*	Copyright (C) 1997 Tom Lord
 * 
 * This program is provided to you under the terms of the Liberty Software
 * License.  You are NOT permitted to redistribute, modify, or use it
 * except in very specific ways described by that license.
 *
 * This software comes with NO WARRANTY.
 * 
 * You should have received a copy of the Liberty Software License
 * along with this software; see the file =LICENSE.  If not, write to
 * the Tom Lord, 1810 Francisco St. #2, Berkeley CA, 94703, USA.  
 */






#include <stdio.h>
#include <ctype.h>

#include "vu/bitset.h"
#include "vu/hashtab.h"
#include "vu/dstr.h"
#include "rexp.h"
#include "nfa.h"





#ifdef HAVE_POSITIONAL_ARRAY_INITS
#define AT(X) [X] =
#else
#define AT(X)
#endif

static char *node_type_names[] =
{
  AT(r_cset) "r_cset",
  AT(r_concat) "r_concat",
  AT(r_alternate) "r_alternate",
  AT(r_opt) "r_opt",
  AT(r_star) "r_star",
  AT(r_plus) "r_plus",
  AT(r_string) "r_string",
  AT(r_cut) "r_cut",

  AT(r_interval) "r_interval",
  AT(r_parens) "r_parens",
  AT(r_context) "r_context"
};

static void
print_cset (int cset_size, bitset cs)
{
  int x;
  if (!cs)
      printf ("nil");
  else
    {
      putchar ('[');
      for (x = 0; x < cset_size; ++x)
	if (bitset_member (cs, x))
	  {
	    if (isprint(x))
	      putchar (x);
	    else
	      printf ("\\0%o ", x);
	  }
      putchar (']');
    }
}

static void
print_string (struct dstring *s, char bracket)
{
  int x;
  if (!s && bracket)
    printf ("nil");
  else
    {
      if (bracket)
	putchar ('\"');
      for (x = 0; x < s->len; ++x)
	if (isprint(s->chr[x]))
	  putchar (s->chr[x]);
	else
	  printf ("\\0%o ", x);
      if (bracket)
	putchar ('\"');
    }
}    

static void
spaces (int n)
{
  while (n--)
    putchar (' ');
}


void
print_rexp (int cset_size, int indent, struct rx_exp_node * rexp)
{
  spaces (indent);
  if (!rexp)
    printf ("nil\n");
  else
    {
      printf ("Node %lx type %d (%s), iv=%d(%c), iv2=%d, len=%d obs=%d cs=",
	      (unsigned long) rexp, rexp->type, node_type_names[rexp->type],
	      rexp->intval,
	      ((   (0 <= rexp->intval)
		&& (256 > rexp->intval)
		&& isprint (rexp->intval))
	       ? rexp->intval
	       : ' '),
	      rexp->intval2,
	      rexp->len,
	      rexp->observed);
      print_cset (cset_size, rexp->cset);
      printf (" s=");
      print_string (&(rexp->cstr), 1);
      putchar ('\n');
      if (rexp->left || rexp->right)
	{
	  print_rexp (cset_size, indent + 2, rexp->left);
	  print_rexp (cset_size, indent + 2, rexp->right);
	}
    }
}

void
unparse_print_rexp (int cset_size, struct rx_exp_node * rexp)
{
  if (!rexp)
    return;
  else
    switch (rexp->type)
      {
      case r_cset:
	if (1 != bitset_population (cset_size, rexp->cset))
	  print_cset (cset_size, rexp->cset);
	else
	  {
	    int x;
	    bitset cs;
	    
	    cs = rexp->cset;
	    for (x = 0; x < cset_size; ++x)
	      if (bitset_member (cs, x))
		{
		  if (isprint(x))
		    putchar (x);
		  else
		    printf ("\\0%o ", x);
		}
	  }
	break;

      case r_string:
	print_string (&(rexp->cstr), 0);
	break;

      case r_parens:
	putchar ('(');
	unparse_print_rexp (cset_size, rexp->left);
	putchar (')');
	break;

      case r_context:
	putchar ('\\');
	putchar (rexp->intval);
	break;

      case r_cut:
	printf ("[[:cut %d:]]", rexp->intval);
	break;

      case r_concat:
	unparse_print_rexp (cset_size, rexp->left);
	unparse_print_rexp (cset_size, rexp->right);
	break;

      case r_alternate:
	unparse_print_rexp (cset_size, rexp->left);
	putchar ('|');
	unparse_print_rexp (cset_size, rexp->right);
	break;

      case r_star:
	unparse_print_rexp (cset_size, rexp->left);
	putchar ('*');
	break;

      case r_interval:
	unparse_print_rexp (cset_size, rexp->left);
	printf ("{%d,%d}", rexp->intval, rexp->intval2);
	break;
      }
}

static void
print_nfa_state (struct rx_nfa * rx, struct rx_nfa_state * state)
{
  struct rx_nfa_edge * e;
  printf ("state %d, state_label %d, is_start %d\n",
	  state->id, state->state_label, state->is_start);
  for (e = state->edges; e; e = e->next)
    {
      printf ("\tEdge %s to %d ",
	      (e->type == ne_cset
	       ? "cset"
	       : (e->type == ne_epsilon
		  ? "epsilon"
		  : "side effect")),
	      e->dest->id);
      if (e->type == ne_cset)
	print_cset (rx->local_cset_size, e->cset);
      else
	printf ("epsilon");
      putchar ('\n');
    }
}

void
print_nfa (struct rx_nfa * rx)
{
  struct rx_nfa_state * state;
  for (state = rx->nfa_states; state; state = state->next)
    print_nfa_state (rx, state);
}

