Back to index

cell-binutils  2.17cvs20070401
depend.c
Go to the documentation of this file.
00001 /* depend.c - Handle dependency tracking.
00002    Copyright 1997, 1998, 2000, 2001, 2003 Free Software Foundation, Inc.
00003 
00004    This file is part of GAS, the GNU Assembler.
00005 
00006    GAS is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2, or (at your option)
00009    any later version.
00010 
00011    GAS is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with GAS; see the file COPYING.  If not, write to the Free
00018    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
00019    02110-1301, USA.  */
00020 
00021 #include "as.h"
00022 
00023 /* The file to write to, or NULL if no dependencies being kept.  */
00024 static char * dep_file = NULL;
00025 
00026 struct dependency
00027   {
00028     char * file;
00029     struct dependency * next;
00030   };
00031 
00032 /* All the files we depend on.  */
00033 static struct dependency * dep_chain = NULL;
00034 
00035 /* Current column in output file.  */
00036 static int column = 0;
00037 
00038 static int quote_string_for_make (FILE *, char *);
00039 static void wrap_output (FILE *, char *, int);
00040 
00041 /* Number of columns allowable.  */
00042 #define MAX_COLUMNS 72
00043 
00044 /* Start saving dependencies, to be written to FILENAME.  If this is
00045    never called, then dependency tracking is simply skipped.  */
00046 
00047 void
00048 start_dependencies (char *filename)
00049 {
00050   dep_file = filename;
00051 }
00052 
00053 /* Noticed a new filename, so try to register it.  */
00054 
00055 void
00056 register_dependency (char *filename)
00057 {
00058   struct dependency *dep;
00059 
00060   if (dep_file == NULL)
00061     return;
00062 
00063   for (dep = dep_chain; dep != NULL; dep = dep->next)
00064     {
00065       if (!strcmp (filename, dep->file))
00066        return;
00067     }
00068 
00069   dep = (struct dependency *) xmalloc (sizeof (struct dependency));
00070   dep->file = xstrdup (filename);
00071   dep->next = dep_chain;
00072   dep_chain = dep;
00073 }
00074 
00075 /* Quote a file name the way `make' wants it, and print it to FILE.
00076    If FILE is NULL, do no printing, but return the length of the
00077    quoted string.
00078 
00079    This code is taken from gcc with only minor changes.  */
00080 
00081 static int
00082 quote_string_for_make (FILE *file, char *src)
00083 {
00084   char *p = src;
00085   int i = 0;
00086 
00087   for (;;)
00088     {
00089       char c = *p++;
00090 
00091       switch (c)
00092        {
00093        case '\0':
00094        case ' ':
00095        case '\t':
00096          {
00097            /* GNU make uses a weird quoting scheme for white space.
00098               A space or tab preceded by 2N+1 backslashes represents
00099               N backslashes followed by space; a space or tab
00100               preceded by 2N backslashes represents N backslashes at
00101               the end of a file name; and backslashes in other
00102               contexts should not be doubled.  */
00103            char *q;
00104 
00105            for (q = p - 1; src < q && q[-1] == '\\'; q--)
00106              {
00107               if (file)
00108                 putc ('\\', file);
00109               i++;
00110              }
00111          }
00112          if (!c)
00113            return i;
00114          if (file)
00115            putc ('\\', file);
00116          i++;
00117          goto ordinary_char;
00118 
00119        case '$':
00120          if (file)
00121            putc (c, file);
00122          i++;
00123          /* Fall through.  This can mishandle things like "$(" but
00124             there's no easy fix.  */
00125        default:
00126        ordinary_char:
00127          /* This can mishandle characters in the string "\0\n%*?[\\~";
00128             exactly which chars are mishandled depends on the `make' version.
00129             We know of no portable solution for this;
00130             even GNU make 3.76.1 doesn't solve the problem entirely.
00131             (Also, '\0' is mishandled due to our calling conventions.)  */
00132          if (file)
00133            putc (c, file);
00134          i++;
00135          break;
00136        }
00137     }
00138 }
00139 
00140 /* Append some output to the file, keeping track of columns and doing
00141    wrapping as necessary.  */
00142 
00143 static void
00144 wrap_output (FILE *f, char *string, int spacer)
00145 {
00146   int len = quote_string_for_make (NULL, string);
00147 
00148   if (len == 0)
00149     return;
00150 
00151   if (column
00152       && (MAX_COLUMNS
00153          - 1 /* spacer */
00154          - 2 /* ` \'   */
00155          < column + len))
00156     {
00157       fprintf (f, " \\\n ");
00158       column = 0;
00159       if (spacer == ' ')
00160        spacer = '\0';
00161     }
00162 
00163   if (spacer == ' ')
00164     {
00165       putc (spacer, f);
00166       ++column;
00167     }
00168 
00169   quote_string_for_make (f, string);
00170   column += len;
00171 
00172   if (spacer == ':')
00173     {
00174       putc (spacer, f);
00175       ++column;
00176     }
00177 }
00178 
00179 /* Print dependency file.  */
00180 
00181 void
00182 print_dependencies (void)
00183 {
00184   FILE *f;
00185   struct dependency *dep;
00186 
00187   if (dep_file == NULL)
00188     return;
00189 
00190   f = fopen (dep_file, FOPEN_WT);
00191   if (f == NULL)
00192     {
00193       as_warn (_("can't open `%s' for writing"), dep_file);
00194       return;
00195     }
00196 
00197   column = 0;
00198   wrap_output (f, out_file_name, ':');
00199   for (dep = dep_chain; dep != NULL; dep = dep->next)
00200     wrap_output (f, dep->file, ' ');
00201 
00202   putc ('\n', f);
00203 
00204   if (fclose (f))
00205     as_warn (_("can't close `%s'"), dep_file);
00206 }