/***********************************
  (C) Copyright 1993; dit/upm
   Distributed under the conditions stated in the
   TOPO General Public License (see file LICENSE)
 ***********************************
 * $Log: dltg.c,v $
 * Revision 1.1  1993/09/30  14:30:46  lotos
 * Initial revision
 *
 ***********************************/

#ifndef lint
static char rcsid[]= "$Id: dltg.c,v 1.1 1993/09/30 14:30:46 lotos Exp $";
#endif

# include "tbil.hh"
# include "cast.hh"

# include "colours.h"
# define c_tree 101

# include "nodes2c.c"

typedef CLR_TYPE (*CLR_FUNC) ();
void putAST ();

TIOCOLOURS iocolours [] = {		/* io driver */
# include "colours.c"
  "tree",   c_tree,   (CLR_FUNC) restore, putAST, NULL, NULL,
  OTHERS
  };

ST* SymbolTable= NULL;
IAT* grnl= NULL;
AT* ATable= NULL;

char progname[]= "dltg";
int flaga= 0;
int flagd= 0;
int flags= 0;
int flagt= 0;
int flagplus[1024];
int flagplusi= 0;
int depth= -1;
char* fl= NULL;
FILE* flp= NULL;
char filename[BUFSIZ];
int errcnt= 0;

PRIVATE void my_dr_node ();
PRIVATE void my_it_tree ();
PRIVATE void my_drn_tree ();

CLR_TYPE
eval ()
{
  (void) fprintf (stderr,"Who called this?");
  exit (1);
}

void
putL (fp, val)
     FILE* fp;
     CLR_TYPE val;
{
  int i= (int) val;

  if (i < 0) {
    ++errcnt;
    (void) fprintf (stderr, "%s: LL underflow: %d\n", progname, i);
    (void) fprintf (fp, "%d[### LL underflow %%%%%%]", i);
    return;
  }
  else if (i >= SymbolTable->size) {
    ++errcnt;
    (void) fprintf (stderr, "%s: LL overflow: %d\n", progname, i);
    (void) fprintf (fp, "%d[### LL overflow %%%%%%]", i);
    return;
  }
  (void) fprintf (fp, "%s", SymbolTable->data[i]);
}

void
putG (fp, val)
     FILE* fp;
     CLR_TYPE val;
{
  int* p;
  int i= (int) val;

  if (i < 0) {
    ++errcnt;
    (void) fprintf (stderr, "%s: GL underflow: %d\n", progname, i);
    (void) fprintf (fp, "%d[### GL underflow %%%%%%]", i);
    return;
  }
  else if (i >= grnl->size) {
    ++errcnt;
    (void) fprintf (stderr, "%s: GL overflow: %d\n", progname, i);
    (void) fprintf (fp, "%d[### GL overflow %%%%%%]", i);
    return;
  }
  for (p= grnl->data[i]; *p != 0; p++)
    (void) fprintf (fp, " %d", *p);
}

void
putN (fp, val)
    FILE* fp;
    CLR_TYPE val;
{
  int* where;

  where= (int*) val;
  (void) fprintf (fp, "%d ", where[0]);
  putL (fp, (CLR_TYPE) where[1]);
}

void
putid (fp, val)
    FILE* fp;
    CLR_TYPE val;
{
  (void) fprintf (fp, "%d", (int) val);
  if (flaga && ATable != NULL) {
    TNODE *nodep;
    TIOCOLOURS bakHWclr[2];
    int i= (int) val;

    if (i < 1) {
      ++errcnt;
      (void) fprintf (stderr, "%s: ATable underflow: %d\n", progname, i);
      (void) fprintf (fp, "%d[### ATable underflow %%%%%%]", i);
      return;
    }
    else if (i >= ATable->size) {
      ++errcnt;
      (void) fprintf (stderr, "%s: ATable overflow: %d\n", progname, i);
      (void) fprintf (fp, "%d[### ATable overflow %%%%%%]", i);
      return;
    }
    nodep= new_node(0);
    (void) fprintf (fp, " => ");
    bakHWclr[0].put= HWclr[0].put;
    bakHWclr[1].put= HWclr[1].put;
    HWclr[0].put= putint;
    HWclr[1].put= putL;
    nodep->value0= ATable->data[i].value0;
    nodep->value1= ATable->data[i].value1;
    nodep->attrs= ATable->data[i].attrs;
    putattrs (fp, nodep);
    nodep->value0= 0;
    nodep->value1= 0;
    nodep->attrs= NULL;
    HWclr[0].put= bakHWclr[0].put;
    HWclr[1].put= bakHWclr[1].put;
    kill_tree(nodep);
  }
}

void
putAST (val)
     CLR_TYPE val;
{
  (void) putc ('\n', stdout);
  dr_tree ((TNODE*) val);
}

void
putdots ()
{
  (void) printf ("...");
}

void
help ()
{
  (void) fprintf (stderr, "usage: %s [-s] [-d] [-a] [-t] [+#] [-depth] [file]\n", progname);
  (void) fprintf (stderr, "    -s  prints symbolic node type\n");
  (void) fprintf (stderr, "    -d  skips LL, GL, and ATable\n");
  (void) fprintf (stderr, "        and expands GL and LL at seat\n");
  (void) fprintf (stderr, "    -a  idem, expanding ATable too\n");
  (void) fprintf (stderr, "    -t  dumps ATable\n");
  (void) fprintf (stderr, "    -t# dumps entrys # from ATable\n");
  (void) fprintf (stderr, "    +#  dumps entry # in ATable\n");
  exit (1);
}

main (argc, argv)
     int argc;
     char* argv[];
{
  TNODE* tree;
  int i, j;

  for (i= 1; i < argc; ++i) {
    if (argv[i][0] == '-') {
      switch (argv[i][1]) {
      case '0': case '1': case '2': case '3': case '4':
      case '5': case '6': case '7': case '8': case '9':
	for (j= 2; argv[i][j] != '\0'; ++j)
	  if (argv[i][j] < '0' || argv[i][j] > '9') help ();
	depth= atoi (&argv[i][1]);
	break;
      case 's':
	if (argv[i][2] != '\0') help ();
	flags= 1;
	break;
      case 'd':
	if (argv[i][2] != '\0') help ();
	flagd= 1;
	break;
      case 'a':
	if (argv[i][2] != '\0') help ();
	flaga= 1; flagd= 1;
	break;
      case 't':
	if (argv[i][2] == '\0')
	  flagt= -1;
	else
	  switch (argv[i][2]) {
	  case '1':
	    flagt= 1;
	    break;
	  case '2': case 't':
	    flagt= 2;
	    break;
	  case '3': case 's':
	    flagt= 3;
	    break;
	  case '4': case 'o':
	    flagt= 4;
	    break;
	  case '5': case 'p':
	    flagt= 5;
	    break;
	  case '6': case 'g':
	    flagt= 6;
	    break;
	  case '7': case 'v':
	    flagt= 7;
	    break;
	  default:
	    help ();
	  }
	break;
      default:
	help ();
      }
    }
    else if (argv[i][0] == '+') {
      for (j= 1; argv[i][j] != '\0'; ++j)
	if (argv[i][j] < '0' || argv[i][j] > '9') help ();
      if (j == 1) help ();
      flagplus[flagplusi++]= atoi (&argv[i][1]);
    }
    else if (fl == NULL)
      fl= argv[i];
    else
      help ();
  }
  if (fl == NULL)
    flp= stdin;
  else if ((flp= fopen (fl, "r")) == NULL) {
    (void) fprintf (stderr, "%s: could not open %s\n", progname, fl);
    exit (1);
  }

  cast_init (iocolours);
  if ((tree= restore (flp)) == NULL) {
    (void) fprintf (stderr, "%s: could not load source CAST\n", progname);
    exit (1);
  }
  
  SymbolTable= (ST*) find_attr (c_ll, tree)->value;
  grnl= (IAT*) find_attr (c_grnl, tree)->value;
  if (find_attr (c_at, tree) != NULL)
    ATable= (AT*) find_attr (c_at, tree)->value;

  if (flagd) {
    name2clr ("LL")->put= putdots;
    name2clr ("GL")->put= putdots;
    name2clr ("ATable")->put= putdots;
    name2clr ("L")->put= putL;
    name2clr ("N")->put= putN;
    HWclr[0].put= putG;
  }
  
  if (flagt) {
    TNODE *nodep;

    if (ATable == NULL) {
      (void) fprintf (stderr, "%s: no ATable available!\n", progname);
      exit (1);
    }
    nodep= new_node(0);
    HWclr[0].put= putint;
    HWclr[1].put= putL;
    for (i= 1; i < ATable->size; i++) {
      if (flagt < 0 || flagt == (int)ATable->data[i].value0) {
	(void) printf ("%3d => ", i);
	nodep->value0= ATable->data[i].value0;
	nodep->value1= ATable->data[i].value1;
	nodep->attrs= ATable->data[i].attrs;
	putattrs (stdout, nodep);
      }
    }
    exit (0);
  }
  if (flagplusi == 0)
    my_drn_tree (tree, depth);
  else {
    int it;
    TNODE *nodep;

    if (ATable == NULL) {
      (void) fprintf (stderr, "%s: no ATable available!\n", progname);
      exit (1);
    }
    nodep= new_node(0);
    HWclr[0].put= putint;
    HWclr[1].put= putL;
    for (i= 0; i < flagplusi; i++) {
      it= flagplus[i];
      if (it < 1 || ATable->size <= it) {
	++errcnt;
	(void) fprintf (stderr, "%s: ATable[1..%d]\n", progname, ATable->size);
      }
      else {
	(void) printf ("%3d => ", it);
	nodep->value0= ATable->data[it].value0;
	nodep->value1= ATable->data[it].value1;
	nodep->attrs= ATable->data[it].attrs;
	putattrs (stdout, nodep);
      }
    }
  }

  if (errcnt > 0)
    exit (1);
  else
    exit (0);

  return 0;
}

/****  functions from cast  ****/

PRIVATE void
my_dr_node (nodep)
     TNODE*  nodep;
{
  if (nodep) {
    if (flags)
      (void) printf ("<%s>", ndtab[MININDEX+nodep->type]);
    else
      (void) printf ("<%d>", nodep->type);
    putattrs (stdout, nodep);
  }
}

PRIVATE void
my_it_tree (indent, nodep, deep)
     int indent;
     TNODE* nodep;
     int deep;
{
  int i;
  
  if (nodep != NULL && deep != 0) {
    for (i= indent; i > 0; i--)
      (void) fprintf (stdout, "  ");
    my_dr_node (nodep);
    my_it_tree (indent+1, nodep->sons,     deep-1);
    my_it_tree (indent,   nodep->brothers, deep);
  }
}

PRIVATE void
my_drn_tree (tree, deep)
     TNODE* tree;
     int deep;
{
  my_dr_node (tree);
  my_it_tree (1, tree->sons, deep-1);
}
