depend.c revision 60484
1210389Sgabor/* depend.c - Handle dependency tracking. 2210389Sgabor Copyright (C) 1997, 1998 Free Software Foundation, Inc. 3210389Sgabor 4210389Sgabor This file is part of GAS, the GNU Assembler. 5210389Sgabor 6210389Sgabor GAS is free software; you can redistribute it and/or modify 7210389Sgabor it under the terms of the GNU General Public License as published by 8210389Sgabor the Free Software Foundation; either version 2, or (at your option) 9210389Sgabor any later version. 10210389Sgabor 11210389Sgabor GAS is distributed in the hope that it will be useful, 12210389Sgabor but WITHOUT ANY WARRANTY; without even the implied warranty of 13210389Sgabor MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14210389Sgabor GNU General Public License for more details. 15210389Sgabor 16210389Sgabor You should have received a copy of the GNU General Public License 17210389Sgabor along with GAS; see the file COPYING. If not, write to the Free 18210389Sgabor Software Foundation, 59 Temple Place - Suite 330, Boston, MA 19210389Sgabor 02111-1307, USA. */ 20210389Sgabor 21210389Sgabor#include "as.h" 22210389Sgabor 23210389Sgabor/* The file to write to, or NULL if no dependencies being kept. */ 24210389Sgaborstatic char *dep_file = NULL; 25210389Sgabor 26210389Sgaborstruct dependency 27210389Sgabor{ 28210389Sgabor char *file; 29210389Sgabor struct dependency *next; 30210389Sgabor}; 31210389Sgabor 32210389Sgabor/* All the files we depend on. */ 33210389Sgaborstatic struct dependency *dep_chain = NULL; 34210389Sgabor 35210389Sgabor/* Current column in output file. */ 36210389Sgaborstatic int column = 0; 37210389Sgabor 38210389Sgaborstatic int quote_string_for_make PARAMS ((FILE *, char *)); 39210389Sgaborstatic void wrap_output PARAMS ((FILE *, char *, int)); 40210389Sgabor 41210389Sgabor/* Number of columns allowable. */ 42210389Sgabor#define MAX_COLUMNS 72 43210389Sgabor 44210389Sgabor 45210389Sgabor 46210389Sgabor/* Start saving dependencies, to be written to FILENAME. If this is 47210389Sgabor never called, then dependency tracking is simply skipped. */ 48210389Sgabor 49210389Sgaborvoid 50210389Sgaborstart_dependencies (filename) 51210389Sgabor char *filename; 52210389Sgabor{ 53210389Sgabor dep_file = filename; 54210389Sgabor} 55210389Sgabor 56210389Sgabor/* Noticed a new filename, so try to register it. */ 57210389Sgabor 58210389Sgaborvoid 59210389Sgaborregister_dependency (filename) 60210389Sgabor char *filename; 61210389Sgabor{ 62210389Sgabor struct dependency *dep; 63210389Sgabor 64210389Sgabor if (dep_file == NULL) 65210389Sgabor return; 66210389Sgabor 67210389Sgabor for (dep = dep_chain; dep != NULL; dep = dep->next) 68210389Sgabor { 69210389Sgabor if (! strcmp (filename, dep->file)) 70210389Sgabor return; 71210389Sgabor } 72210389Sgabor 73210389Sgabor dep = (struct dependency *) xmalloc (sizeof (struct dependency)); 74210389Sgabor dep->file = xstrdup (filename); 75210389Sgabor dep->next = dep_chain; 76210389Sgabor dep_chain = dep; 77210389Sgabor} 78210389Sgabor 79210389Sgabor/* Quote a file name the way `make' wants it, and print it to FILE. 80210389Sgabor If FILE is NULL, do no printing, but return the length of the 81210389Sgabor quoted string. 82210389Sgabor 83210389Sgabor This code is taken from gcc with only minor changes. */ 84210389Sgabor 85210389Sgaborstatic int 86210389Sgaborquote_string_for_make (file, src) 87210389Sgabor FILE *file; 88210389Sgabor char *src; 89210389Sgabor{ 90210389Sgabor char *p = src; 91210389Sgabor int i = 0; 92210389Sgabor for (;;) 93210389Sgabor { 94210389Sgabor char c = *p++; 95210389Sgabor switch (c) 96210389Sgabor { 97210389Sgabor case '\0': 98210389Sgabor case ' ': 99210389Sgabor case '\t': 100210389Sgabor { 101210389Sgabor /* GNU make uses a weird quoting scheme for white space. 102210389Sgabor A space or tab preceded by 2N+1 backslashes represents 103210389Sgabor N backslashes followed by space; a space or tab 104210389Sgabor preceded by 2N backslashes represents N backslashes at 105210389Sgabor the end of a file name; and backslashes in other 106210389Sgabor contexts should not be doubled. */ 107210389Sgabor char *q; 108210389Sgabor for (q = p - 1; src < q && q[-1] == '\\'; q--) 109210389Sgabor { 110210389Sgabor if (file) 111210389Sgabor putc ('\\', file); 112210389Sgabor i++; 113210389Sgabor } 114210389Sgabor } 115210389Sgabor if (!c) 116210389Sgabor return i; 117210389Sgabor if (file) 118210389Sgabor putc ('\\', file); 119210389Sgabor i++; 120210389Sgabor goto ordinary_char; 121210389Sgabor 122210389Sgabor case '$': 123210389Sgabor if (file) 124210389Sgabor putc (c, file); 125210389Sgabor i++; 126210389Sgabor /* Fall through. This can mishandle things like "$(" but 127210389Sgabor there's no easy fix. */ 128210389Sgabor default: 129210389Sgabor ordinary_char: 130210389Sgabor /* This can mishandle characters in the string "\0\n%*?[\\~"; 131210389Sgabor exactly which chars are mishandled depends on the `make' version. 132210389Sgabor We know of no portable solution for this; 133210389Sgabor even GNU make 3.76.1 doesn't solve the problem entirely. 134210389Sgabor (Also, '\0' is mishandled due to our calling conventions.) */ 135210389Sgabor if (file) 136210389Sgabor putc (c, file); 137210389Sgabor i++; 138210389Sgabor break; 139210389Sgabor } 140210389Sgabor } 141210389Sgabor} 142210389Sgabor 143210389Sgabor/* Append some output to the file, keeping track of columns and doing 144210389Sgabor wrapping as necessary. */ 145210389Sgabor 146210389Sgaborstatic void 147210389Sgaborwrap_output (f, string, spacer) 148210389Sgabor FILE *f; 149210389Sgabor char *string; 150210389Sgabor int spacer; 151210389Sgabor{ 152210389Sgabor int len = quote_string_for_make (NULL, string); 153210389Sgabor 154210389Sgabor if (len == 0) 155210389Sgabor return; 156210389Sgabor 157210389Sgabor if (column && MAX_COLUMNS - 1 /*spacer*/ - 2 /*` \'*/ < column + len) 158210389Sgabor { 159210389Sgabor fprintf (f, " \\\n "); 160210389Sgabor column = 0; 161210389Sgabor if (spacer == ' ') 162210389Sgabor spacer = '\0'; 163 } 164 165 if (spacer == ' ') 166 { 167 putc (spacer, f); 168 ++column; 169 } 170 171 quote_string_for_make (f, string); 172 column += len; 173 174 if (spacer == ':') 175 { 176 putc (spacer, f); 177 ++column; 178 } 179} 180 181/* Print dependency file. */ 182 183void 184print_dependencies () 185{ 186 FILE *f; 187 struct dependency *dep; 188 189 if (dep_file == NULL) 190 return; 191 192 f = fopen (dep_file, "w"); 193 if (f == NULL) 194 { 195 as_warn (_("Can't open `%s' for writing"), dep_file); 196 return; 197 } 198 199 column = 0; 200 wrap_output (f, out_file_name, ':'); 201 for (dep = dep_chain; dep != NULL; dep = dep->next) 202 wrap_output (f, dep->file, ' '); 203 204 putc ('\n', f); 205 206 if (fclose (f)) 207 as_warn (_("Can't close `%s'"), dep_file); 208} 209