/* l2xixref.c   Interpeter X-referencing  */
/* BASED ON: xref.c  (unaltered except for common names) */

#include <stdio.h>
#include "l2xicmon.h"
#include "l2xiscan.h"
#include "l2xisymt.h"

#define DEBUG 0

#define MAX_LINENUMS_PER_LINE 10

/* line number item and list header */
typedef struct linenum_item {
  struct linenum_item *next;
  int line_number;
} LINENUM_ITEM, *LINENUM_ITEM_PTR;

typedef struct {
  LINENUM_ITEM_PTR first_linenum;
  LINENUM_ITEM_PTR last_linenum;
} LINENUM_HEADER, *LINENUM_HEADER_PTR;

/* EXTERNALS */

extern int line_number;
extern TOKEN_CODE token;
extern char word_string[];
extern SYMTAB_NODE_PTR symtab_root;


/***************************************************************************/
/* main(argc, argv()  loop to process identifiers, then print xref         */
/*          call as: xref infile                                           */

main(argc, argv)
int argc;
char *argv[];
{
  SYMTAB_NODE_PTR np;             /* ptr to symtab entry */
  LINENUM_HEADER_PTR hp;          /* ptr to line item list header */

  if (DEBUG) {
    fprintf(stderr, "\n ****Starting program xref\nCalling init_scanner\n");
    fflush(stderr);
  }

  init_scanner(argv[1]);

  if (DEBUG) {
    fprintf(stderr, "Returned from init_scanner\nProcessing tokens\n");
    fflush(stderr);
  }

  /* process tokens until end of file */
  do {
    get_token();
    if (token == END_OF_FILE) break;
    if (token == IDENTIFIER) {
      /* put identifier into symtab if not there, and record the */
      /* line number in the symtab entry */
      np = search_symtab(word_string, symtab_root);
      if (np == NULL) {
        np = enter_symtab(word_string, &symtab_root);
        hp = alloc_struct(LINENUM_HEADER);
        hp->first_linenum = hp->last_linenum = NULL;
        np->info = (char *) hp;
      }
      record_line_number(np, line_number);
    }
  } while (token != PERIOD); /* end do */

  if (DEBUG) {
    fprintf(stderr, "Finished token processing\nCalling print_xref\n\n");
    fflush(stderr);
  }

  /* print the xref listing */
  printf("\n\nCross-Reference");
  printf(  "\n---------------\n");
  print_xref(symtab_root);

  if (DEBUG) {
    fprintf(stderr, "\n\nReturned from print_xref\nCalling quit_scanner\n");
    fflush(stderr);
  }

  quit_scanner();

  if (DEBUG) {
    fprintf(stderr, "Returned from quit_scanner\n***That's all\n\n");
    fflush(stderr);
  }

}                                                              /* end main */
/***************************************************************************/



/***************************************************************************/
/* record_line_number(np, number) Record a line number into the            */
/*                                symtab entry                             */

record_line_number(np, number)
SYMTAB_NODE_PTR np;                  /* ptr to symtab entry */
int number;                          /* line number */
{
  LINENUM_ITEM_PTR ip;               /* ptr to line item */
  LINENUM_HEADER_PTR hp;               /* ptr to line item list header */

  /* create a new line number item */
  ip = alloc_struct(LINENUM_ITEM);
  ip->line_number = number;
  ip->next = NULL;

  /* link it to the list */
  hp = (LINENUM_HEADER_PTR) np->info;
  if (hp->first_linenum == NULL) hp->first_linenum = hp->last_linenum = ip;
  else {
    (hp->last_linenum)->next = ip;
    hp->last_linenum = ip;
  }

}                                                /* end record_line_number */
/***************************************************************************/



/***************************************************************************/
/* print_xref(np) Print x-refed names and line numbers in alpha order      */

print_xref(np)
SYMTAB_NODE_PTR np;               /* pointer to subtree */
{
  int n;
  LINENUM_ITEM_PTR ip;            /* ptr to line item */
  LINENUM_HEADER_PTR hp;          /* ptr to line item list header */

  if (np == NULL) return;

  /* print the left subtree */
  print_xref(np->left);

  /* then print the root of the subtree with at most MAX_LINENUMS_PER_LINE */
  printf("\n%-16s   ", np->name);
  n = strlen(np->name) > 16 ? 0 : MAX_LINENUMS_PER_LINE;
  hp = (LINENUM_HEADER_PTR) np->info;
  for (ip = hp->first_linenum; ip != NULL; ip = ip->next) {
    if (n == 0) {
      printf("\n%-16s   ", " ");
      n = MAX_LINENUMS_PER_LINE;
    }
    printf(" %4d", ip->line_number);
    --n;
  }
  printf("\n");

  /* now print the right subtree */
  print_xref(np->right);

}                                                        /* end print_xref */
/***************************************************************************/



/***************************************************************************/
/* ()  */
/*

()
{


} /* end */
/***************************************************************************/



/***************************************************************************/
/* ()  */
/*

()
{


} /* end */
/***************************************************************************/



/***************************************************************************/
/* ()  */
/*

()
{


} /* end */
/***************************************************************************/