xref: /openbsd-src/gnu/usr.bin/binutils/gprof/source.c (revision a4afd6dad3fba28f80e70208181c06c482259988)
1 /*
2  * Keeps track of source files.
3  */
4 #include "gprof.h"
5 #include "libiberty.h"
6 #include "search_list.h"
7 #include "source.h"
8 
9 #define EXT_ANNO "-ann"		/* postfix of annotated files */
10 
11 /*
12  * Default option values:
13  */
14 bool create_annotation_files = FALSE;
15 
16 Search_List src_search_list =
17 {0, 0};
18 Source_File *first_src_file = 0;
19 
20 
21 Source_File *
22 DEFUN (source_file_lookup_path, (path), const char *path)
23 {
24   Source_File *sf;
25 
26   for (sf = first_src_file; sf; sf = sf->next)
27     {
28       if (strcmp (path, sf->name) == 0)
29 	{
30 	  break;
31 	}
32     }
33   if (!sf)
34     {
35       /* create a new source file descriptor: */
36 
37       sf = (Source_File *) xmalloc (sizeof (*sf));
38       memset (sf, 0, sizeof (*sf));
39       sf->name = xstrdup (path);
40       sf->next = first_src_file;
41       first_src_file = sf;
42     }
43   return sf;
44 }
45 
46 
47 Source_File *
48 DEFUN (source_file_lookup_name, (filename), const char *filename)
49 {
50   const char *fname;
51   Source_File *sf;
52   /*
53    * The user cannot know exactly how a filename will be stored in
54    * the debugging info (e.g., ../include/foo.h
55    * vs. /usr/include/foo.h).  So we simply compare the filename
56    * component of a path only:
57    */
58   for (sf = first_src_file; sf; sf = sf->next)
59     {
60       fname = strrchr (sf->name, '/');
61       if (fname)
62 	{
63 	  ++fname;
64 	}
65       else
66 	{
67 	  fname = sf->name;
68 	}
69       if (strcmp (filename, fname) == 0)
70 	{
71 	  break;
72 	}
73     }
74   return sf;
75 }
76 
77 
78 FILE *
79 DEFUN (annotate_source, (sf, max_width, annote, arg),
80        Source_File * sf AND int max_width
81        AND void (*annote) PARAMS ((char *buf, int w, int l, void *arg))
82        AND void *arg)
83 {
84   static bool first_file = TRUE;
85   int i, line_num, nread;
86   bool new_line;
87   char buf[8192];
88   char fname[PATH_MAX];
89   char *annotation, *name_only;
90   FILE *ifp, *ofp;
91   Search_List_Elem *sle = src_search_list.head;
92 
93   /*
94    * Open input file.  If open fails, walk along search-list until
95    * open succeeds or reaching end of list:
96    */
97   strcpy (fname, sf->name);
98   if (sf->name[0] == '/')
99     {
100       sle = 0;			/* don't use search list for absolute paths */
101     }
102   name_only = 0;
103   while (TRUE)
104     {
105       DBG (SRCDEBUG, printf ("[annotate_source]: looking for %s, trying %s\n",
106 			     sf->name, fname));
107       ifp = fopen (fname, FOPEN_RB);
108       if (ifp)
109 	{
110 	  break;
111 	}
112       if (!sle && !name_only)
113 	{
114 	  name_only = strrchr (sf->name, '/');
115 	  if (name_only)
116 	    {
117 	      /* try search-list again, but this time with name only: */
118 	      ++name_only;
119 	      sle = src_search_list.head;
120 	    }
121 	}
122       if (sle)
123 	{
124 	  strcpy (fname, sle->path);
125 	  strcat (fname, "/");
126 	  if (name_only)
127 	    {
128 	      strcat (fname, name_only);
129 	    }
130 	  else
131 	    {
132 	      strcat (fname, sf->name);
133 	    }
134 	  sle = sle->next;
135 	}
136       else
137 	{
138 	  if (errno == ENOENT)
139 	    {
140 	      fprintf (stderr, "%s: could not locate `%s'\n",
141 		       whoami, sf->name);
142 	    }
143 	  else
144 	    {
145 	      perror (sf->name);
146 	    }
147 	  return 0;
148 	}
149     }
150 
151   ofp = stdout;
152   if (create_annotation_files)
153     {
154       /* try to create annotated source file: */
155       const char *filename;
156 
157       /* create annotation files in the current working directory: */
158       filename = strrchr (sf->name, '/');
159       if (filename)
160 	{
161 	  ++filename;
162 	}
163       else
164 	{
165 	  filename = sf->name;
166 	}
167 
168       strcpy (fname, filename);
169       strcat (fname, EXT_ANNO);
170       ofp = fopen (fname, "w");
171       if (!ofp)
172 	{
173 	  perror (fname);
174 	  return 0;
175 	}
176     }
177 
178   /*
179    * Print file names if output goes to stdout and there are
180    * more than one source file:
181    */
182   if (ofp == stdout)
183     {
184       if (first_file)
185 	{
186 	  first_file = FALSE;
187 	}
188       else
189 	{
190 	  fputc ('\n', ofp);
191 	}
192       if (first_output)
193 	{
194 	  first_output = FALSE;
195 	}
196       else
197 	{
198 	  fprintf (ofp, "\f\n");
199 	}
200       fprintf (ofp, "*** File %s:\n", sf->name);
201     }
202 
203   annotation = xmalloc (max_width + 1);
204   line_num = 1;
205   new_line = TRUE;
206   while ((nread = fread (buf, 1, sizeof (buf), ifp)) > 0)
207     {
208       for (i = 0; i < nread; ++i)
209 	{
210 	  if (new_line)
211 	    {
212 	      (*annote) (annotation, max_width, line_num, arg);
213 	      fputs (annotation, ofp);
214 	      ++line_num;
215 	      new_line = FALSE;
216 	    }
217 	  new_line = (buf[i] == '\n');
218 	  fputc (buf[i], ofp);
219 	}
220     }
221   free (annotation);
222   return ofp;
223 }
224