# include "align.h"
/* VAX VMS
# include <unixio>
*/
# include <stdio.h>

/* #define INC_COLUMNS */

  /* externals from slurp */
extern char nextchar();
extern char peekchar();
extern int fetchline();
extern void writeline();
extern void skip_to();
extern FILE *outstream;


/* externals from words */
extern void readword();
extern void initstore();

/* types */
struct tnode {
  word name;
  int branch, term, tri;
  struct tnode *mother, *daughters, *next;
  char tag[10];       /* text of tag held in charstore */
};

typedef struct tnode treenode;

/* error stuff */
int sinned   = FALSE;  /* error has occurred in run */
int error = FALSE;  /* error has occurred in current example */

FILE  *error_file;
char error_name[50];


void goof(s)
char *s;
{
  if (!sinned) {
    error_file = fopen(error_name,"w");
    sinned = TRUE;
  }	
  fprintf(stderr,"%s at line %d\n",s,linecount());
  fprintf(error_file,"%s at line %d\n",s,linecount);
  error = TRUE;
}

  

char delmark = '|';  /* delimiter */
int tagcount;        /* keeps track of tags */

/* strequ */
int strequ(s1,s2)
char *s1, *s2;
{
  if (strcmp(s1,s2) == 0)
    return(TRUE);
  else
    return(FALSE);
}

/* local node label & annotation-ending function */
static int endlabel(c)
char c;
{
 if (eoln() || c == delmark) {
   return(TRUE);
 }
 else
   return(FALSE);
}

/* local command-word ending function */
static int endcom(c)
char c;
{
  if (c == ' ' || c == delmark) {
    return(TRUE);
  }
  else
    return(FALSE);
}

/* adapted from K&R itoa */
void convert(n,s)
int n;
char s[];
{
  int i;

  i = 0;
  do {
    s[i++] = n % 26 + 'a';
  } while ((n /= 26) > 0);
  s[i] = '\0';
}

char grabchar()
{
char c;
  c = nextchar();
  if (c == '%') {
    fetchline();
    return(grabchar());
  } else
  return (c);
}

/* allocates nodespace, reads in info, etc. */
treenode *build_node()
{
  int go;

  treenode *node;
  word holder;
  char **pointer;

  pointer = &(holder.loc);
  node = (treenode *)malloc(sizeof(treenode));
  readword(&node->name,&go,endlabel,grabchar,FALSE);
  node->next = NULL;
  node->daughters = NULL;
  node->mother = NULL;
  node->tri = FALSE;
  node->term = TRUE;
  node->tag[0]='\0';
  while (go) {
    readword(&holder,&go,endcom,nextchar,FALSE);
    if (strequ(*pointer,"tri"))
      node->tri=TRUE;
    else
    if (strequ(*pointer,"tag")) {
      readword(&holder,&go,endcom,nextchar,FALSE);
      strcpy(node->tag,*pointer);
    }
  }

  if (node->tag[0] == '\0') {
    node->tag[0] = 'Z';
    convert(tagcount++,&(node->tag[1]));
  }
  return(node);
}

/* gets a node, assuming that the line the node is on is already read
   in */
treenode *get_node()
{
  int pos,dpos;

  treenode *node;

  advanceeoln_pos(&pos);
  if (eoln()) {
    goof("blank line in tree");
    fetchline();
    return(NULL);
  }
  node = build_node();
  fetchline();
  advanceeoln_pos(&dpos);
  if (dpos > pos) {
    get_daughters(node,dpos);
  }
  return(node);
}

get_daughters(node,dpos)
treenode *node;   /* node of which daughters are being read */
int dpos;         /* position where daughters are supposed to be */
{
  int pos;
  treenode *current;

  current = get_node();
  current->mother = node;
  node->daughters = current;
  node->term = FALSE;

  while (currentpos() == dpos && !error) { /* as long as we're getting daughters */
    current->next = get_node();
    current = current->next;
    current->mother = node;
  }
}

void show_tree(node, ind)
treenode *node;
int ind;
{
  int i;

  if (node != NULL) {
    for (i = 1; i<=ind; i++)
      putc(' ', outstream);
    fprintf(outstream,"%s\n",node->name.loc);
if (node->tri) printf("TRI\n");
printf("tag = %s\n",node->tag);
    for (node = node->daughters; node !=NULL; node=node->next)
      show_tree(node,ind+2);
  }
}



void write_tree(node, ind)
treenode *node;
int ind;
{
  int i;
  treenode *mother;

  if (node != NULL) {
    mother = node;
    for (i = 1; i<=ind; i++)    /* print indentation */
      putc(' ', outstream);
    if (node->term) {
      fprintf(outstream,"{\\tnode{%s}{%s}}",node->tag,node->name.loc);
    }
    else {
      fprintf(outstream,"{\\ntnode{%s}{%s},\n",node->tag,node->name.loc);
      for (node = node->daughters; node !=NULL; node=node->next)
	write_tree(node,ind+2);
/*
      for (i = 1; i<=ind; i++)
	putc(' ', outstream);
*/
      putc('}',outstream);
    };
    
    if (mother->next != NULL) fprintf(outstream,",\n");
/*
    else fprintf(outstream,"%\n");
  if (node->next != NULL && node->mother != NULL)
    putc(',',outstream);
  putc('\n',outstream);
*/
  }
}

void draw_lines(node)
treenode *node;
{
  int i;
  char *m;   /* mother & daughter tags */
  treenode *mother; /* mother */

  if (node != NULL) {
    mother = node;
    m = mother->tag;
    for (node = mother->daughters; node !=NULL; node=node->next) {
      if (node->tri)
	fprintf(outstream,"\\nodetriangle{%s}{%s}%%\n",m,node->tag);
      else
	fprintf(outstream,"\\nodeconnect{%s}{%s}%%\n",m,node->tag);
    }
    for (node = mother->daughters; node !=NULL; node=node->next)
      draw_lines(node);
  }
}


void free_tree(node)
treenode *node;
{

    if (node !=NULL) {
      for (node = node->daughters; node !=NULL; node=node->next)
	free_tree(node);
      free(node);
      node=NULL;
  }
}


void tree()
{
  treenode *node;

  delmark = '|';
  error = FALSE;
  tagcount = 0;

  init_store();
  fetchline();
  node=get_node();
  if (!matchstr(".]") && !error)
    goof("bad tree indentation");
  if (error) {
    fprintf(outstream,"\nBAD TREE\n");
    error = FALSE;
  }
  else {
    fprintf(outstream,"\\tree");
    write_tree(node,0);
    fprintf(outstream,"%%\n"),
    draw_lines(node);
  }
  free_tree(node);
}

void extendfilename(name,extension,result)
/* chris: fix parameter declarations */
char name[];
char extension[];
char result[];
{
  strcpy(result,name);
  strcat(result,extension);
}



main(argc, argv)
int argc;
char *argv[];

{

  char infile[200];
  char outfile[200];

  char c;

  /* chris - let it run as filter */
  if (argc < 2)
    {
      strcpy(infile, "stdin");
      strcpy(error_name, "trees.err");
    }
  else
    {
      extendfilename(argv[1],".txp",infile);
      extendfilename(argv[1],"_tx2.tex",outfile);
      extendfilename(argv[1],".err",error_name);
    }

/* VAX/VMS reading from logical `source', writing to logical `product'
  open_source("source");
  outstream = fopen("product","w");
*/

  if (open_source(infile)) {
    /* chris - letting it run as a filter still */
    if (argc < 2)
      outstream = stdout;
    else
      outstream = fopen(outfile,"w"); 
    while (fetchline()) {            /* as long as there's input */
      if (nextchar() == '.') {     
        if ((c = nextchar()) == '[') {   
	  tree();
        }
#ifdef INC_COLUMNS
        else
        if (c == '<') {
          columns();
        }
#endif
      }
      else {
        writeline();
      }
    }
  } else printf("file `%s' not found\n",infile);
  return(sinned);
}
