depend.c revision 77298
1145522Sdarrenr/* depend.c - Handle dependency tracking. 2145522Sdarrenr Copyright (C) 1997, 1998 Free Software Foundation, Inc. 353642Sguido 4255332Scy This file is part of GAS, the GNU Assembler. 553642Sguido 680482Sdarrenr GAS is free software; you can redistribute it and/or modify 753642Sguido it under the terms of the GNU General Public License as published by 8145522Sdarrenr the Free Software Foundation; either version 2, or (at your option) 9145522Sdarrenr any later version. 10145522Sdarrenr 11145522Sdarrenr GAS is distributed in the hope that it will be useful, 12145522Sdarrenr but WITHOUT ANY WARRANTY; without even the implied warranty of 1392685Sdarrenr MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1453642Sguido GNU General Public License for more details. 1553642Sguido 1653642Sguido You should have received a copy of the GNU General Public License 1753642Sguido along with GAS; see the file COPYING. If not, write to the Free 1853642Sguido Software Foundation, 59 Temple Place - Suite 330, Boston, MA 19145522Sdarrenr 02111-1307, USA. */ 2053642Sguido 2153642Sguido#include "as.h" 22255332Scy 23255332Scy/* The file to write to, or NULL if no dependencies being kept. */ 24255332Scystatic char *dep_file = NULL; 2553642Sguido 26145522Sdarrenrstruct dependency { 27145522Sdarrenr char *file; 28145522Sdarrenr struct dependency *next; 29145522Sdarrenr}; 30145522Sdarrenr 31145522Sdarrenr/* All the files we depend on. */ 3253642Sguidostatic struct dependency *dep_chain = NULL; 33145522Sdarrenr 3453642Sguido/* Current column in output file. */ 3553642Sguidostatic int column = 0; 3653642Sguido 3753642Sguidostatic int quote_string_for_make PARAMS ((FILE *, char *)); 3853642Sguidostatic void wrap_output PARAMS ((FILE *, char *, int)); 39145522Sdarrenr 4053642Sguido/* Number of columns allowable. */ 4153642Sguido#define MAX_COLUMNS 72 4253642Sguido 43145522Sdarrenr/* Start saving dependencies, to be written to FILENAME. If this is 4453642Sguido never called, then dependency tracking is simply skipped. */ 45145522Sdarrenr 4653642Sguidovoid 4753642Sguidostart_dependencies (filename) 48145522Sdarrenr char *filename; 49145522Sdarrenr{ 5053642Sguido dep_file = filename; 5153642Sguido} 5253642Sguido 5353642Sguido/* Noticed a new filename, so try to register it. */ 5453642Sguido 5553642Sguidovoid 5653642Sguidoregister_dependency (filename) 5753642Sguido char *filename; 58255332Scy{ 59173181Sdarrenr struct dependency *dep; 6053642Sguido 6153642Sguido if (dep_file == NULL) 6253642Sguido return; 6353642Sguido 6453642Sguido for (dep = dep_chain; dep != NULL; dep = dep->next) 65145522Sdarrenr { 66145522Sdarrenr if (!strcmp (filename, dep->file)) 67145522Sdarrenr return; 68255332Scy } 69255332Scy 70255332Scy dep = (struct dependency *) xmalloc (sizeof (struct dependency)); 71255332Scy dep->file = xstrdup (filename); 7253642Sguido dep->next = dep_chain; 7353642Sguido dep_chain = dep; 7453642Sguido} 7553642Sguido 7653642Sguido/* Quote a file name the way `make' wants it, and print it to FILE. 7753642Sguido If FILE is NULL, do no printing, but return the length of the 7853642Sguido quoted string. 79249266Sglebius 80249266Sglebius This code is taken from gcc with only minor changes. */ 81249266Sglebius 82145522Sdarrenrstatic int 8353642Sguidoquote_string_for_make (file, src) 84145522Sdarrenr FILE *file; 8553642Sguido char *src; 8653642Sguido{ 8753642Sguido char *p = src; 88145522Sdarrenr int i = 0; 8953642Sguido for (;;) 9053642Sguido { 9153642Sguido char c = *p++; 92145522Sdarrenr switch (c) 9380482Sdarrenr { 9453642Sguido case '\0': 95145522Sdarrenr case ' ': 9653642Sguido case '\t': 9753642Sguido { 98145522Sdarrenr /* GNU make uses a weird quoting scheme for white space. 99145522Sdarrenr A space or tab preceded by 2N+1 backslashes represents 100145522Sdarrenr N backslashes followed by space; a space or tab 101145522Sdarrenr preceded by 2N backslashes represents N backslashes at 10253642Sguido the end of a file name; and backslashes in other 10353642Sguido contexts should not be doubled. */ 10453642Sguido char *q; 10553642Sguido for (q = p - 1; src < q && q[-1] == '\\'; q--) 10653642Sguido { 10753642Sguido if (file) 10853642Sguido putc ('\\', file); 10953642Sguido i++; 11053642Sguido } 11153642Sguido } 11253642Sguido if (!c) 113145522Sdarrenr return i; 11453642Sguido if (file) 11553642Sguido putc ('\\', file); 11653642Sguido i++; 11753642Sguido goto ordinary_char; 11853642Sguido 11953642Sguido case '$': 12053642Sguido if (file) 121145522Sdarrenr putc (c, file); 12253642Sguido i++; 12353642Sguido /* Fall through. This can mishandle things like "$(" but 12453642Sguido there's no easy fix. */ 12553642Sguido default: 126145522Sdarrenr ordinary_char: 12753642Sguido /* This can mishandle characters in the string "\0\n%*?[\\~"; 12880482Sdarrenr exactly which chars are mishandled depends on the `make' version. 12980482Sdarrenr We know of no portable solution for this; 130172776Sdarrenr even GNU make 3.76.1 doesn't solve the problem entirely. 13180482Sdarrenr (Also, '\0' is mishandled due to our calling conventions.) */ 13253642Sguido if (file) 13353642Sguido putc (c, file); 134255332Scy i++; 135255332Scy break; 136255332Scy } 137255332Scy } 138255332Scy} 139255332Scy 140255332Scy/* Append some output to the file, keeping track of columns and doing 14153642Sguido wrapping as necessary. */ 142255332Scy 143170268Sdarrenrstatic void 144255332Scywrap_output (f, string, spacer) 145170268Sdarrenr FILE *f; 146170268Sdarrenr char *string; 147170268Sdarrenr int spacer; 148255332Scy{ 149255332Scy int len = quote_string_for_make (NULL, string); 150255332Scy 151255332Scy if (len == 0) 152255332Scy return; 153255332Scy 154255332Scy if (column 155255332Scy && (MAX_COLUMNS 156255332Scy - 1 /* spacer */ 157255332Scy - 2 /* ` \' */ 158255332Scy < column + len)) 159255332Scy { 160255332Scy fprintf (f, " \\\n "); 161255332Scy column = 0; 162255332Scy if (spacer == ' ') 163255332Scy spacer = '\0'; 164255332Scy } 165255332Scy 166255332Scy if (spacer == ' ') 167255332Scy { 168255332Scy putc (spacer, f); 169255332Scy ++column; 170255332Scy } 171255332Scy 172255332Scy quote_string_for_make (f, string); 173255332Scy column += len; 174255332Scy 175255332Scy if (spacer == ':') 176255332Scy { 177255332Scy putc (spacer, f); 178255332Scy ++column; 179255332Scy } 180255332Scy} 181255332Scy 182255332Scy/* Print dependency file. */ 183255332Scy 184255332Scyvoid 185255332Scyprint_dependencies () 186255332Scy{ 187255332Scy FILE *f; 188255332Scy struct dependency *dep; 189255332Scy 190255332Scy if (dep_file == NULL) 191255332Scy return; 192255332Scy 193255332Scy f = fopen (dep_file, "w"); 194255332Scy if (f == NULL) 195255332Scy { 196255332Scy as_warn (_("Can't open `%s' for writing"), dep_file); 197255332Scy return; 198255332Scy } 199255332Scy 200255332Scy column = 0; 201255332Scy wrap_output (f, out_file_name, ':'); 202255332Scy for (dep = dep_chain; dep != NULL; dep = dep->next) 203255332Scy wrap_output (f, dep->file, ' '); 204255332Scy 205255332Scy putc ('\n', f); 206255332Scy 207255332Scy if (fclose (f)) 208255332Scy as_warn (_("Can't close `%s'"), dep_file); 209255332Scy} 210255332Scy