| 1 | /* depend.c - Handle dependency tracking.
 | 
|---|
| 2 |    Copyright 1997, 1998, 2000, 2001 Free Software Foundation, Inc.
 | 
|---|
| 3 | 
 | 
|---|
| 4 |    This file is part of GAS, the GNU Assembler.
 | 
|---|
| 5 | 
 | 
|---|
| 6 |    GAS is free software; you can redistribute it and/or modify
 | 
|---|
| 7 |    it under the terms of the GNU General Public License as published by
 | 
|---|
| 8 |    the Free Software Foundation; either version 2, or (at your option)
 | 
|---|
| 9 |    any later version.
 | 
|---|
| 10 | 
 | 
|---|
| 11 |    GAS is distributed in the hope that it will be useful,
 | 
|---|
| 12 |    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
| 13 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
| 14 |    GNU General Public License for more details.
 | 
|---|
| 15 | 
 | 
|---|
| 16 |    You should have received a copy of the GNU General Public License
 | 
|---|
| 17 |    along with GAS; see the file COPYING.  If not, write to the Free
 | 
|---|
| 18 |    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 | 
|---|
| 19 |    02111-1307, USA.  */
 | 
|---|
| 20 | 
 | 
|---|
| 21 | #include "as.h"
 | 
|---|
| 22 | 
 | 
|---|
| 23 | /* The file to write to, or NULL if no dependencies being kept.  */
 | 
|---|
| 24 | static char * dep_file = NULL;
 | 
|---|
| 25 | 
 | 
|---|
| 26 | struct dependency
 | 
|---|
| 27 |   {
 | 
|---|
| 28 |     char * file;
 | 
|---|
| 29 |     struct dependency * next;
 | 
|---|
| 30 |   };
 | 
|---|
| 31 | 
 | 
|---|
| 32 | /* All the files we depend on.  */
 | 
|---|
| 33 | static struct dependency * dep_chain = NULL;
 | 
|---|
| 34 | 
 | 
|---|
| 35 | /* Current column in output file.  */
 | 
|---|
| 36 | static int column = 0;
 | 
|---|
| 37 | 
 | 
|---|
| 38 | static int quote_string_for_make PARAMS ((FILE *, char *));
 | 
|---|
| 39 | static void wrap_output PARAMS ((FILE *, char *, int));
 | 
|---|
| 40 | 
 | 
|---|
| 41 | /* Number of columns allowable.  */
 | 
|---|
| 42 | #define MAX_COLUMNS 72
 | 
|---|
| 43 |  | 
|---|
| 44 | 
 | 
|---|
| 45 | /* Start saving dependencies, to be written to FILENAME.  If this is
 | 
|---|
| 46 |    never called, then dependency tracking is simply skipped.  */
 | 
|---|
| 47 | 
 | 
|---|
| 48 | void
 | 
|---|
| 49 | start_dependencies (filename)
 | 
|---|
| 50 |      char *filename;
 | 
|---|
| 51 | {
 | 
|---|
| 52 |   dep_file = filename;
 | 
|---|
| 53 | }
 | 
|---|
| 54 | 
 | 
|---|
| 55 | /* Noticed a new filename, so try to register it.  */
 | 
|---|
| 56 | 
 | 
|---|
| 57 | void
 | 
|---|
| 58 | register_dependency (filename)
 | 
|---|
| 59 |      char *filename;
 | 
|---|
| 60 | {
 | 
|---|
| 61 |   struct dependency *dep;
 | 
|---|
| 62 | 
 | 
|---|
| 63 |   if (dep_file == NULL)
 | 
|---|
| 64 |     return;
 | 
|---|
| 65 | 
 | 
|---|
| 66 |   for (dep = dep_chain; dep != NULL; dep = dep->next)
 | 
|---|
| 67 |     {
 | 
|---|
| 68 |       if (!strcmp (filename, dep->file))
 | 
|---|
| 69 |         return;
 | 
|---|
| 70 |     }
 | 
|---|
| 71 | 
 | 
|---|
| 72 |   dep = (struct dependency *) xmalloc (sizeof (struct dependency));
 | 
|---|
| 73 |   dep->file = xstrdup (filename);
 | 
|---|
| 74 |   dep->next = dep_chain;
 | 
|---|
| 75 |   dep_chain = dep;
 | 
|---|
| 76 | }
 | 
|---|
| 77 | 
 | 
|---|
| 78 | /* Quote a file name the way `make' wants it, and print it to FILE.
 | 
|---|
| 79 |    If FILE is NULL, do no printing, but return the length of the
 | 
|---|
| 80 |    quoted string.
 | 
|---|
| 81 | 
 | 
|---|
| 82 |    This code is taken from gcc with only minor changes.  */
 | 
|---|
| 83 | 
 | 
|---|
| 84 | static int
 | 
|---|
| 85 | quote_string_for_make (file, src)
 | 
|---|
| 86 |      FILE *file;
 | 
|---|
| 87 |      char *src;
 | 
|---|
| 88 | {
 | 
|---|
| 89 |   char *p = src;
 | 
|---|
| 90 |   int i = 0;
 | 
|---|
| 91 | 
 | 
|---|
| 92 |   for (;;)
 | 
|---|
| 93 |     {
 | 
|---|
| 94 |       char c = *p++;
 | 
|---|
| 95 | 
 | 
|---|
| 96 |       switch (c)
 | 
|---|
| 97 |         {
 | 
|---|
| 98 |         case '\0':
 | 
|---|
| 99 |         case ' ':
 | 
|---|
| 100 |         case '\t':
 | 
|---|
| 101 |           {
 | 
|---|
| 102 |             /* GNU make uses a weird quoting scheme for white space.
 | 
|---|
| 103 |                A space or tab preceded by 2N+1 backslashes represents
 | 
|---|
| 104 |                N backslashes followed by space; a space or tab
 | 
|---|
| 105 |                preceded by 2N backslashes represents N backslashes at
 | 
|---|
| 106 |                the end of a file name; and backslashes in other
 | 
|---|
| 107 |                contexts should not be doubled.  */
 | 
|---|
| 108 |             char *q;
 | 
|---|
| 109 | 
 | 
|---|
| 110 |             for (q = p - 1; src < q && q[-1] == '\\'; q--)
 | 
|---|
| 111 |               {
 | 
|---|
| 112 |                 if (file)
 | 
|---|
| 113 |                   putc ('\\', file);
 | 
|---|
| 114 |                 i++;
 | 
|---|
| 115 |               }
 | 
|---|
| 116 |           }
 | 
|---|
| 117 |           if (!c)
 | 
|---|
| 118 |             return i;
 | 
|---|
| 119 |           if (file)
 | 
|---|
| 120 |             putc ('\\', file);
 | 
|---|
| 121 |           i++;
 | 
|---|
| 122 |           goto ordinary_char;
 | 
|---|
| 123 | 
 | 
|---|
| 124 |         case '$':
 | 
|---|
| 125 |           if (file)
 | 
|---|
| 126 |             putc (c, file);
 | 
|---|
| 127 |           i++;
 | 
|---|
| 128 |           /* Fall through.  This can mishandle things like "$(" but
 | 
|---|
| 129 |              there's no easy fix.  */
 | 
|---|
| 130 |         default:
 | 
|---|
| 131 |         ordinary_char:
 | 
|---|
| 132 |           /* This can mishandle characters in the string "\0\n%*?[\\~";
 | 
|---|
| 133 |              exactly which chars are mishandled depends on the `make' version.
 | 
|---|
| 134 |              We know of no portable solution for this;
 | 
|---|
| 135 |              even GNU make 3.76.1 doesn't solve the problem entirely.
 | 
|---|
| 136 |              (Also, '\0' is mishandled due to our calling conventions.)  */
 | 
|---|
| 137 |           if (file)
 | 
|---|
| 138 |             putc (c, file);
 | 
|---|
| 139 |           i++;
 | 
|---|
| 140 |           break;
 | 
|---|
| 141 |         }
 | 
|---|
| 142 |     }
 | 
|---|
| 143 | }
 | 
|---|
| 144 | 
 | 
|---|
| 145 | /* Append some output to the file, keeping track of columns and doing
 | 
|---|
| 146 |    wrapping as necessary.  */
 | 
|---|
| 147 | 
 | 
|---|
| 148 | static void
 | 
|---|
| 149 | wrap_output (f, string, spacer)
 | 
|---|
| 150 |      FILE *f;
 | 
|---|
| 151 |      char *string;
 | 
|---|
| 152 |      int spacer;
 | 
|---|
| 153 | {
 | 
|---|
| 154 |   int len = quote_string_for_make (NULL, string);
 | 
|---|
| 155 | 
 | 
|---|
| 156 |   if (len == 0)
 | 
|---|
| 157 |     return;
 | 
|---|
| 158 | 
 | 
|---|
| 159 |   if (column
 | 
|---|
| 160 |       && (MAX_COLUMNS
 | 
|---|
| 161 |           - 1 /* spacer */
 | 
|---|
| 162 |           - 2 /* ` \'   */
 | 
|---|
| 163 |           < column + len))
 | 
|---|
| 164 |     {
 | 
|---|
| 165 |       fprintf (f, " \\\n ");
 | 
|---|
| 166 |       column = 0;
 | 
|---|
| 167 |       if (spacer == ' ')
 | 
|---|
| 168 |         spacer = '\0';
 | 
|---|
| 169 |     }
 | 
|---|
| 170 | 
 | 
|---|
| 171 |   if (spacer == ' ')
 | 
|---|
| 172 |     {
 | 
|---|
| 173 |       putc (spacer, f);
 | 
|---|
| 174 |       ++column;
 | 
|---|
| 175 |     }
 | 
|---|
| 176 | 
 | 
|---|
| 177 |   quote_string_for_make (f, string);
 | 
|---|
| 178 |   column += len;
 | 
|---|
| 179 | 
 | 
|---|
| 180 |   if (spacer == ':')
 | 
|---|
| 181 |     {
 | 
|---|
| 182 |       putc (spacer, f);
 | 
|---|
| 183 |       ++column;
 | 
|---|
| 184 |     }
 | 
|---|
| 185 | }
 | 
|---|
| 186 | 
 | 
|---|
| 187 | /* Print dependency file.  */
 | 
|---|
| 188 | 
 | 
|---|
| 189 | void
 | 
|---|
| 190 | print_dependencies ()
 | 
|---|
| 191 | {
 | 
|---|
| 192 |   FILE *f;
 | 
|---|
| 193 |   struct dependency *dep;
 | 
|---|
| 194 | 
 | 
|---|
| 195 |   if (dep_file == NULL)
 | 
|---|
| 196 |     return;
 | 
|---|
| 197 | 
 | 
|---|
| 198 |   f = fopen (dep_file, FOPEN_WT);
 | 
|---|
| 199 |   if (f == NULL)
 | 
|---|
| 200 |     {
 | 
|---|
| 201 |       as_warn (_("can't open `%s' for writing"), dep_file);
 | 
|---|
| 202 |       return;
 | 
|---|
| 203 |     }
 | 
|---|
| 204 | 
 | 
|---|
| 205 |   column = 0;
 | 
|---|
| 206 |   wrap_output (f, out_file_name, ':');
 | 
|---|
| 207 |   for (dep = dep_chain; dep != NULL; dep = dep->next)
 | 
|---|
| 208 |     wrap_output (f, dep->file, ' ');
 | 
|---|
| 209 | 
 | 
|---|
| 210 |   putc ('\n', f);
 | 
|---|
| 211 | 
 | 
|---|
| 212 |   if (fclose (f))
 | 
|---|
| 213 |     as_warn (_("can't close `%s'"), dep_file);
 | 
|---|
| 214 | }
 | 
|---|