Listing 2
#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]<I>,</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") == O) { strcpy(caller_name, &toks[O] [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 [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"); } /* End of File */