diff options
author | Ken Raeburn <raeburn@cygnus> | 1995-02-07 22:34:18 +0000 |
---|---|---|
committer | Ken Raeburn <raeburn@cygnus> | 1995-02-07 22:34:18 +0000 |
commit | 5489fcc3d9dbb1f529dddb19b615e23d8ed59dc7 (patch) | |
tree | 1a79cfffd92f2afb67780dd7372c1759c49791aa /gprof/source.c | |
parent | 2559e01429d193b7957c106a6a8b0598476f9845 (diff) | |
download | gdb-5489fcc3d9dbb1f529dddb19b615e23d8ed59dc7.zip gdb-5489fcc3d9dbb1f529dddb19b615e23d8ed59dc7.tar.gz gdb-5489fcc3d9dbb1f529dddb19b615e23d8ed59dc7.tar.bz2 |
Lots of changes from David Mosberger-Tang; see ChangeLog and NOTES for details:
Alpha support.
Long options.
New file format to support more information; backwards compatibility.
Line-level profiling, on systems where bfd_find_nearest_line works.
Selective display of data.
Diffstat (limited to 'gprof/source.c')
-rw-r--r-- | gprof/source.c | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/gprof/source.c b/gprof/source.c new file mode 100644 index 0000000..7917bba --- /dev/null +++ b/gprof/source.c @@ -0,0 +1,186 @@ +/* + * Keeps track of source files. + */ +#include "gprof.h" +#include "libiberty.h" +#include "search_list.h" +#include "source.h" + +#define EXT_ANNO "-ann" /* postfix of annotated files */ + +/* + * Default option values: + */ +bool create_annotation_files = FALSE; + +Search_List src_search_list = {0, 0}; +Source_File *first_src_file = 0; + + +Source_File* +DEFUN(source_file_lookup_path, (path), const char *path) +{ + Source_File *sf; + + for (sf = first_src_file; sf; sf = sf->next) { + if (strcmp(path, sf->name) == 0) { + break; + } /* if */ + } /* for */ + if (!sf) { + /* create a new source file descriptor: */ + + sf = (Source_File*) xmalloc(sizeof(*sf)); + memset(sf, 0, sizeof(*sf)); + sf->name = strdup(path); + sf->next = first_src_file; + first_src_file = sf; + } /* if */ + return sf; +} /* source_file_lookup_path */ + + +Source_File* +DEFUN(source_file_lookup_name, (filename), const char *filename) +{ + const char *fname; + Source_File *sf; + /* + * The user cannot know exactly how a filename will be stored in + * the debugging info (e.g., ../include/foo.h + * vs. /usr/include/foo.h). So we simply compare the filename + * component of a path only: + */ + for (sf = first_src_file; sf; sf = sf->next) { + fname = strrchr(sf->name, '/'); + if (fname) { + ++fname; + } else { + fname = sf->name; + } /* if */ + if (strcmp(filename, fname) == 0) { + break; + } /* if */ + } /* for */ + return sf; +} /* source_file_lookup_name */ + + +FILE* +DEFUN(annotate_source, (sf, max_width, annote, arg), + Source_File *sf AND int max_width + AND void (*annote) PARAMS((char *buf, int w, int l, void *arg)) + AND void *arg) +{ + static bool first_file = TRUE; + int i, line_num, nread; + bool new_line; + char buf[8192]; + char fname[PATH_MAX]; + char *annotation, *name_only; + FILE *ifp, *ofp; + Search_List_Elem *sle = src_search_list.head; + + /* + * Open input file. If open fails, walk along search-list until + * open succeeds or reaching end of list: + */ + strcpy(fname, sf->name); + if (sf->name[0] == '/') { + sle = 0; /* don't use search list for absolute paths */ + } /* if */ + name_only = 0; + while (TRUE) { + DBG(SRCDEBUG, printf("[annotate_source]: looking for %s, trying %s\n", + sf->name, fname)); + ifp = fopen(fname, FOPEN_RB); + if (ifp) { + break; + } /* if */ + if (!sle && !name_only) { + name_only = strrchr(sf->name, '/'); + if (name_only) { + /* try search-list again, but this time with name only: */ + ++name_only; + sle = src_search_list.head; + } /* if */ + } /* if */ + if (sle) { + strcpy(fname, sle->path); + strcat(fname, "/"); + if (name_only) { + strcat(fname, name_only); + } else { + strcat(fname, sf->name); + } /* if */ + sle = sle->next; + } else { + if (errno == ENOENT) { + fprintf(stderr, "%s: could not locate `%s'\n", + whoami, sf->name); + } else { + perror(sf->name); + } /* if */ + return 0; + } /* if */ + } /* while */ + + ofp = stdout; + if (create_annotation_files) { + /* try to create annotated source file: */ + const char *filename; + + /* create annotation files in the current working directory: */ + filename = strrchr(sf->name, '/'); + if (filename) { + ++filename; + } else { + filename = sf->name; + } /* if */ + + strcpy(fname, filename); + strcat(fname, EXT_ANNO); + ofp = fopen(fname, "w"); + if (!ofp) { + perror(fname); + return 0; + } /* if */ + } /* if */ + + /* + * Print file names if output goes to stdout and there are + * more than one source file: + */ + if (ofp == stdout) { + if (first_file) { + first_file = FALSE; + } else { + fputc('\n', ofp); + } /* if */ + if (first_output) { + first_output = FALSE; + } else { + fprintf(ofp, "\f\n"); + } /* if */ + fprintf(ofp, "*** File %s:\n", sf->name); + } /* if */ + + annotation = xmalloc(max_width + 1); + line_num = 1; + new_line = TRUE; + while ((nread = fread(buf, 1, sizeof(buf), ifp)) > 0) { + for (i = 0; i < nread; ++i) { + if (new_line) { + (*annote)(annotation, max_width, line_num, arg); + fputs(annotation, ofp); + ++line_num; new_line = FALSE; + } /* if */ + new_line = (buf[i] == '\n'); + fputc(buf[i], ofp); + } /* for */ + } /* while */ + free(annotation); + return ofp; +} /* annotate_source */ + + /*** end of source.c ***/ |