Back to index

cell-binutils  2.17cvs20070401
source.c
Go to the documentation of this file.
00001 /* source.c - Keep track of source files.
00002 
00003    Copyright 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
00004 
00005    This file is part of GNU Binutils.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
00020    02110-1301, USA.  */
00021 
00022 #include "gprof.h"
00023 #include "libiberty.h"
00024 #include "filenames.h"
00025 #include "search_list.h"
00026 #include "source.h"
00027 
00028 #define EXT_ANNO "-ann"            /* Postfix of annotated files.  */
00029 
00030 /* Default option values.  */
00031 bfd_boolean create_annotation_files = FALSE;
00032 
00033 Search_List src_search_list = {0, 0};
00034 Source_File *first_src_file = 0;
00035 
00036 
00037 Source_File *
00038 source_file_lookup_path (const char *path)
00039 {
00040   Source_File *sf;
00041 
00042   for (sf = first_src_file; sf; sf = sf->next)
00043     {
00044       if (FILENAME_CMP (path, sf->name) == 0)
00045        break;
00046     }
00047 
00048   if (!sf)
00049     {
00050       /* Create a new source file descriptor.  */
00051       sf = (Source_File *) xmalloc (sizeof (*sf));
00052 
00053       memset (sf, 0, sizeof (*sf));
00054 
00055       sf->name = xstrdup (path);
00056       sf->next = first_src_file;
00057       first_src_file = sf;
00058     }
00059 
00060   return sf;
00061 }
00062 
00063 
00064 Source_File *
00065 source_file_lookup_name (const char *filename)
00066 {
00067   const char *fname;
00068   Source_File *sf;
00069 
00070   /* The user cannot know exactly how a filename will be stored in
00071      the debugging info (e.g., ../include/foo.h
00072      vs. /usr/include/foo.h).  So we simply compare the filename
00073      component of a path only.  */
00074   for (sf = first_src_file; sf; sf = sf->next)
00075     {
00076       fname = strrchr (sf->name, '/');
00077 
00078       if (fname)
00079        ++fname;
00080       else
00081        fname = sf->name;
00082 
00083       if (FILENAME_CMP (filename, fname) == 0)
00084        break;
00085     }
00086 
00087   return sf;
00088 }
00089 
00090 
00091 FILE *
00092 annotate_source (Source_File *sf, unsigned int max_width,
00093      void (*annote) (char *, unsigned int, int, void *),
00094      void *arg)
00095 {
00096   static bfd_boolean first_file = TRUE;
00097   int i, line_num, nread;
00098   bfd_boolean new_line;
00099   char buf[8192];
00100   char fname[PATH_MAX];
00101   char *annotation, *name_only;
00102   FILE *ifp, *ofp;
00103   Search_List_Elem *sle = src_search_list.head;
00104 
00105   /* Open input file.  If open fails, walk along search-list until
00106      open succeeds or reaching end of list.  */
00107   strcpy (fname, sf->name);
00108 
00109   if (IS_ABSOLUTE_PATH (sf->name))
00110     sle = 0;                /* Don't use search list for absolute paths.  */
00111 
00112   name_only = 0;
00113   while (TRUE)
00114     {
00115       DBG (SRCDEBUG, printf ("[annotate_source]: looking for %s, trying %s\n",
00116                           sf->name, fname));
00117 
00118       ifp = fopen (fname, FOPEN_RB);
00119       if (ifp)
00120        break;
00121 
00122       if (!sle && !name_only)
00123        {
00124          name_only = strrchr (sf->name, '/');
00125 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
00126          {
00127            char *bslash = strrchr (sf->name, '\\');
00128            if (name_only == NULL || (bslash != NULL && bslash > name_only))
00129              name_only = bslash;
00130            if (name_only == NULL && sf->name[0] != '\0' && sf->name[1] == ':')
00131              name_only = (char *)sf->name + 1;
00132          }
00133 #endif
00134          if (name_only)
00135            {
00136              /* Try search-list again, but this time with name only.  */
00137              ++name_only;
00138              sle = src_search_list.head;
00139            }
00140        }
00141 
00142       if (sle)
00143        {
00144          strcpy (fname, sle->path);
00145 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
00146          /* d:foo is not the same thing as d:/foo!  */
00147          if (fname[strlen (fname) - 1] == ':')
00148            strcat (fname, ".");
00149 #endif
00150          strcat (fname, "/");
00151 
00152          if (name_only)
00153            strcat (fname, name_only);
00154          else
00155            strcat (fname, sf->name);
00156 
00157          sle = sle->next;
00158        }
00159       else
00160        {
00161          if (errno == ENOENT)
00162            fprintf (stderr, _("%s: could not locate `%s'\n"),
00163                    whoami, sf->name);
00164          else
00165            perror (sf->name);
00166 
00167          return 0;
00168        }
00169     }
00170 
00171   ofp = stdout;
00172 
00173   if (create_annotation_files)
00174     {
00175       /* Try to create annotated source file.  */
00176       const char *filename;
00177 
00178       /* Create annotation files in the current working directory.  */
00179       filename = strrchr (sf->name, '/');
00180 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
00181        {
00182          char *bslash = strrchr (sf->name, '\\');
00183          if (filename == NULL || (bslash != NULL && bslash > filename))
00184            filename = bslash;
00185          if (filename == NULL && sf->name[0] != '\0' && sf->name[1] == ':')
00186            filename = sf->name + 1;
00187        }
00188 #endif
00189       if (filename)
00190        ++filename;
00191       else
00192        filename = sf->name;
00193 
00194       strcpy (fname, filename);
00195       strcat (fname, EXT_ANNO);
00196 #ifdef __MSDOS__
00197       {
00198        /* foo.cpp-ann can overwrite foo.cpp due to silent truncation of
00199           file names on 8+3 filesystems.  Their `stat' better be good...  */
00200        struct stat buf1, buf2;
00201 
00202        if (stat (filename, &buf1) == 0
00203            && stat (fname, &buf2) == 0
00204            && buf1.st_ino == buf2.st_ino)
00205          {
00206            char *dot = strrchr (fname, '.');
00207 
00208            if (dot)
00209              *dot = '\0';
00210            strcat (fname, ".ann");
00211          }
00212       }
00213 #endif
00214       ofp = fopen (fname, "w");
00215 
00216       if (!ofp)
00217        {
00218          perror (fname);
00219          return 0;
00220        }
00221     }
00222 
00223   /* Print file names if output goes to stdout
00224      and there are more than one source file.  */
00225   if (ofp == stdout)
00226     {
00227       if (first_file)
00228        first_file = FALSE;
00229       else
00230        fputc ('\n', ofp);
00231 
00232       if (first_output)
00233        first_output = FALSE;
00234       else
00235        fprintf (ofp, "\f\n");
00236 
00237       fprintf (ofp, _("*** File %s:\n"), sf->name);
00238     }
00239 
00240   annotation = xmalloc (max_width + 1);
00241   line_num = 1;
00242   new_line = TRUE;
00243 
00244   while ((nread = fread (buf, 1, sizeof (buf), ifp)) > 0)
00245     {
00246       for (i = 0; i < nread; ++i)
00247        {
00248          if (new_line)
00249            {
00250              (*annote) (annotation, max_width, line_num, arg);
00251              fputs (annotation, ofp);
00252              ++line_num;
00253              new_line = FALSE;
00254            }
00255 
00256          new_line = (buf[i] == '\n');
00257          fputc (buf[i], ofp);
00258        }
00259     }
00260 
00261   free (annotation);
00262   return ofp;
00263 }