#define MAX_PAD 28

char *malloc();
#define NEW(type) ((type *) malloc(sizeof(type)))

struct _name_chain {
  struct _name_chain *link;
  char *name;
  char *short_name;
  char *file_name; } ;

struct _def_chain {
  struct _def_chain *link;
  char *name;
  struct _call_chain {
    struct _call_chain *link;
    char *name; } *calls; };

typedef struct _name_chain NAME_CHAIN;
typedef struct _def_chain DEF_CHAIN;
typedef struct _call_chain CALL_CHAIN;

static NAME_CHAIN *names;
static DEF_CHAIN *defs;
static char *last;
static char name_buffer[256];

yywrap () /* what to do when the input to the scanner finishes! */
{
 return (1);
}

main()
{
 DEF_CHAIN *dcp;
 CALL_CHAIN *ccp;
 NAME_CHAIN *ncp;
 int column;

 defs = 0;
 last = 0;
 names = 0;

 yylex();
 
 /* Now go through the functions and find their source files */

 for (dcp=defs;dcp;dcp=dcp->link)
  { 

    printf ("%s", dcp->name);

    for (ncp=names;ncp;ncp=ncp->link)
     { 
       if (strcmp (dcp->name, ncp->short_name) == 0)
	  break;
     }
    column = strlen(dcp->name);
    while (column++ < MAX_PAD)
       putchar (' ');
    if (ncp)
       printf (" @ %s\n", ncp->file_name);
    else
       printf (" @ *\n");
       
    /* and print the functions that call them */

    for (ccp=dcp->calls;ccp;ccp=ccp->link)
     { printf("   %s\n",ccp->name);
     }
    if (dcp->link)
     { printf ("\n\n");
     }
   }
}

caller(fxn)
char *fxn;
{
 NAME_CHAIN *name_p;
 char *cp;

 if (last)
  { free(last);
  }
 last = malloc(strlen(fxn)+1);
 strcpy(last,fxn);
 
 /* See if the name is on the name list */

 for (name_p=names; name_p; name_p=name_p->link)
  { 
    if (strcmp(name_p->name,fxn) == 0)
       break;
  }

 /* If it isn't, put it oin the list */

 if (! name_p)
  { 
    name_p = NEW(NAME_CHAIN);
    name_p->link = names;
    names = name_p;
    
    name_p->name = malloc (strlen(fxn)+1);

    strcpy (name_buffer, fxn);
    cp = (char *) index(name_buffer, ' ');
    *cp = '\0';
    name_p->short_name = malloc (strlen(name_buffer)+1);

    strcpy (name_p->name, fxn);
    strcpy (name_p->short_name, name_buffer);
    
    cp = (char *) index(++cp, ':');
    while (isspace (*++cp));
    name_p->file_name = malloc (strlen(cp)+1);
    strcpy (name_p->file_name, cp);
  }
}

called(fxn)
char *fxn;
{
 DEF_CHAIN *dcp;
 CALL_CHAIN *ccp;

 for (dcp=defs;dcp;dcp=dcp->link)
  { if (strcmp(dcp->name,fxn) == 0)
     { break;
     }
  }
 if (! dcp)
  { dcp = NEW(DEF_CHAIN);
    dcp->link = defs;
    defs = dcp;

    dcp->name = malloc(strlen(fxn)+1);
    strcpy(dcp->name,fxn);
    dcp->calls = 0;
  }
 for (ccp=dcp->calls;ccp;ccp=ccp->link)
  { if (strcmp(ccp->name,last) == 0)
     { return;
     }
  }
 ccp = NEW(CALL_CHAIN);
 ccp->link = dcp->calls;
 dcp->calls = ccp;
 ccp->name = malloc(strlen(last)+1);
 strcpy(ccp->name,last);
}
