depend.c revision 38889
1260684Skaiw/* depend.c - Handle dependency tracking. 2260684Skaiw Copyright (C) 1997, 1998 Free Software Foundation, Inc. 3260684Skaiw 4260684Skaiw This file is part of GAS, the GNU Assembler. 5260684Skaiw 6260684Skaiw GAS is free software; you can redistribute it and/or modify 7260684Skaiw it under the terms of the GNU General Public License as published by 8260684Skaiw the Free Software Foundation; either version 2, or (at your option) 9260684Skaiw any later version. 10260684Skaiw 11260684Skaiw GAS is distributed in the hope that it will be useful, 12260684Skaiw but WITHOUT ANY WARRANTY; without even the implied warranty of 13260684Skaiw MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14260684Skaiw GNU General Public License for more details. 15260684Skaiw 16260684Skaiw You should have received a copy of the GNU General Public License 17260684Skaiw along with GAS; see the file COPYING. If not, write to the Free 18260684Skaiw Software Foundation, 59 Temple Place - Suite 330, Boston, MA 19260684Skaiw 02111-1307, USA. */ 20260684Skaiw 21260684Skaiw#include "as.h" 22260684Skaiw 23260684Skaiw/* The file to write to, or NULL if no dependencies being kept. */ 24260684Skaiwstatic char *dep_file = NULL; 25260684Skaiw 26260684Skaiwstruct dependency 27260684Skaiw{ 28260684Skaiw char *file; 29260684Skaiw struct dependency *next; 30260684Skaiw}; 31260684Skaiw 32260684Skaiw/* All the files we depend on. */ 33260684Skaiwstatic struct dependency *dep_chain = NULL; 34260684Skaiw 35260684Skaiw/* Current column in output file. */ 36260684Skaiwstatic int column = 0; 37260684Skaiw 38260684Skaiwstatic int quote_string_for_make PARAMS ((FILE *, char *)); 39260684Skaiwstatic void wrap_output PARAMS ((FILE *, char *, int)); 40260684Skaiw 41260684Skaiw/* Number of columns allowable. */ 42260684Skaiw#define MAX_COLUMNS 72 43260684Skaiw 44260684Skaiw 45260684Skaiw 46260684Skaiw/* Start saving dependencies, to be written to FILENAME. If this is 47260684Skaiw never called, then dependency tracking is simply skipped. */ 48260684Skaiw 49260684Skaiwvoid 50260684Skaiwstart_dependencies (filename) 51260684Skaiw char *filename; 52260684Skaiw{ 53260684Skaiw dep_file = filename; 54260684Skaiw} 55260684Skaiw 56260684Skaiw/* Noticed a new filename, so try to register it. */ 57260684Skaiw 58260684Skaiwvoid 59260684Skaiwregister_dependency (filename) 60260684Skaiw char *filename; 61260684Skaiw{ 62260684Skaiw struct dependency *dep; 63260684Skaiw 64260684Skaiw if (dep_file == NULL) 65260684Skaiw return; 66260684Skaiw 67260684Skaiw for (dep = dep_chain; dep != NULL; dep = dep->next) 68260684Skaiw { 69260684Skaiw if (! strcmp (filename, dep->file)) 70260684Skaiw return; 71260684Skaiw } 72260684Skaiw 73260684Skaiw dep = (struct dependency *) xmalloc (sizeof (struct dependency)); 74260684Skaiw dep->file = xstrdup (filename); 75260684Skaiw dep->next = dep_chain; 76260684Skaiw dep_chain = dep; 77260684Skaiw} 78260684Skaiw 79260684Skaiw/* Quote a file name the way `make' wants it, and print it to FILE. 80260684Skaiw If FILE is NULL, do no printing, but return the length of the 81260684Skaiw quoted string. 82260684Skaiw 83260684Skaiw This code is taken from gcc with only minor changes. */ 84260684Skaiw 85260684Skaiwstatic int 86260684Skaiwquote_string_for_make (file, src) 87260684Skaiw FILE *file; 88260684Skaiw char *src; 89260684Skaiw{ 90260684Skaiw char *p = src; 91260684Skaiw int i = 0; 92260684Skaiw for (;;) 93260684Skaiw { 94260684Skaiw char c = *p++; 95260684Skaiw switch (c) 96260684Skaiw { 97260684Skaiw case '\0': 98260684Skaiw case ' ': 99260684Skaiw case '\t': 100260684Skaiw { 101260684Skaiw /* GNU make uses a weird quoting scheme for white space. 102260684Skaiw A space or tab preceded by 2N+1 backslashes represents 103260684Skaiw N backslashes followed by space; a space or tab 104260684Skaiw preceded by 2N backslashes represents N backslashes at 105260684Skaiw the end of a file name; and backslashes in other 106260684Skaiw contexts should not be doubled. */ 107260684Skaiw char *q; 108260684Skaiw for (q = p - 1; src < q && q[-1] == '\\'; q--) 109260684Skaiw { 110260684Skaiw if (file) 111260684Skaiw putc ('\\', file); 112260684Skaiw i++; 113260684Skaiw } 114260684Skaiw } 115260684Skaiw if (!c) 116260684Skaiw return i; 117260684Skaiw if (file) 118260684Skaiw putc ('\\', file); 119260684Skaiw i++; 120260684Skaiw goto ordinary_char; 121260684Skaiw 122260684Skaiw case '$': 123260684Skaiw if (file) 124260684Skaiw putc (c, file); 125260684Skaiw i++; 126260684Skaiw /* Fall through. This can mishandle things like "$(" but 127260684Skaiw there's no easy fix. */ 128260684Skaiw default: 129260684Skaiw ordinary_char: 130260684Skaiw /* This can mishandle characters in the string "\0\n%*?[\\~"; 131260684Skaiw exactly which chars are mishandled depends on the `make' version. 132260684Skaiw We know of no portable solution for this; 133260684Skaiw even GNU make 3.76.1 doesn't solve the problem entirely. 134260684Skaiw (Also, '\0' is mishandled due to our calling conventions.) */ 135260684Skaiw if (file) 136260684Skaiw putc (c, file); 137260684Skaiw i++; 138260684Skaiw break; 139260684Skaiw } 140260684Skaiw } 141260684Skaiw} 142260684Skaiw 143/* Append some output to the file, keeping track of columns and doing 144 wrapping as necessary. */ 145 146static void 147wrap_output (f, string, spacer) 148 FILE *f; 149 char *string; 150 int spacer; 151{ 152 int len = quote_string_for_make (NULL, string); 153 154 if (len == 0) 155 return; 156 157 if (column && MAX_COLUMNS - 1 /*spacer*/ - 2 /*` \'*/ < column + len) 158 { 159 fprintf (f, " \\\n "); 160 column = 0; 161 if (spacer == ' ') 162 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