
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "c_calls.h"

void build_graph(LIST *fcn_list, const char *filename)

/*
Build a graph which shows the calling relationships of all fcns in
a C program by parsing the program's assembly language file.
*/

{
FILE      *input_file;
LINE      line;
TOKENS    toks;
char      *tp;
NAME      caller_name, called_name;
int       i;
LIST      caller_ptr = NULL, called_ptr;

if ((input_file = fopen(filename, "r")) == NULL)
     error("cannot open input file");

while (!feof(input_file))
     {
     fgets(line, sizeof(line), input_file);
     line[strlen(line) - 1] = '\0';  /* Remove \n from end of line. */

     memset(toks, 0, sizeof(toks));

     /* Extract the fields from the current line. */
     tp = strtok(line, "\t ");  /* Token separator is a tab or space. */

     for (i = 0; (i < MAX_TOKENS) && (tp != NULL); i++)
          {
          strcpy(toks[i], tp);
          tp = strtok(NULL, "\t ");  /* Get next token. */
          }

     i--;  /* i now points to last token on current line. */

     /* If current line is the start of a fcn... */
     if (stricmp(toks[1], "proc") == 0)
          {
          strcpy(caller_name, &toks[0][1]);

          /* Insert fcn into fcn list. */
          insert_cell(fcn_list, caller_name);

          /* Make the new fcn the calling fcn. */
          caller_ptr = find_cell(*fcn_list, caller_name);

          }

     /* If current line is a user-defined fcn call... */
     if ((stricmp(toks[0], "call") == 0) &&
         (toks[i][strlen(toks[i]) - 1] != '@') && (toks[i][1] != '_'))
          {
          strcpy(called_name, &toks[i][1]);

          /* Insert called fcn into the fcn list. */
          insert_cell(fcn_list, called_name);

          /* Record that the calling fcn is calling this fcn. */
          insert_cell(&caller_ptr->calls, called_name);

          /* Record that this fcn is called by the calling fcn. */
          called_ptr = find_cell(*fcn_list, called_name);
          insert_cell(&called_ptr->called_from, caller_name);
          }
     }

if (fclose(input_file) != 0)
     error("cannot close input file");
}
