138889Sjdp/* depend.c - Handle dependency tracking. 2218822Sdim Copyright 1997, 1998, 2000, 2001, 2003 Free Software Foundation, Inc. 338889Sjdp 438889Sjdp This file is part of GAS, the GNU Assembler. 538889Sjdp 638889Sjdp GAS is free software; you can redistribute it and/or modify 738889Sjdp it under the terms of the GNU General Public License as published by 838889Sjdp the Free Software Foundation; either version 2, or (at your option) 938889Sjdp any later version. 1038889Sjdp 1138889Sjdp GAS is distributed in the hope that it will be useful, 1238889Sjdp but WITHOUT ANY WARRANTY; without even the implied warranty of 1338889Sjdp MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1438889Sjdp GNU General Public License for more details. 1538889Sjdp 1638889Sjdp You should have received a copy of the GNU General Public License 1738889Sjdp along with GAS; see the file COPYING. If not, write to the Free 18218822Sdim Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 19218822Sdim 02110-1301, USA. */ 2038889Sjdp 2138889Sjdp#include "as.h" 2238889Sjdp 2338889Sjdp/* The file to write to, or NULL if no dependencies being kept. */ 2489857Sobrienstatic char * dep_file = NULL; 2538889Sjdp 2689857Sobrienstruct dependency 2789857Sobrien { 2889857Sobrien char * file; 2989857Sobrien struct dependency * next; 3089857Sobrien }; 3138889Sjdp 3238889Sjdp/* All the files we depend on. */ 3389857Sobrienstatic struct dependency * dep_chain = NULL; 3438889Sjdp 3538889Sjdp/* Current column in output file. */ 3638889Sjdpstatic int column = 0; 3738889Sjdp 38130561Sobrienstatic int quote_string_for_make (FILE *, char *); 39130561Sobrienstatic void wrap_output (FILE *, char *, int); 4038889Sjdp 4138889Sjdp/* Number of columns allowable. */ 4238889Sjdp#define MAX_COLUMNS 72 4338889Sjdp 4438889Sjdp/* Start saving dependencies, to be written to FILENAME. If this is 4538889Sjdp never called, then dependency tracking is simply skipped. */ 4638889Sjdp 4738889Sjdpvoid 48130561Sobrienstart_dependencies (char *filename) 4938889Sjdp{ 5038889Sjdp dep_file = filename; 5138889Sjdp} 5238889Sjdp 5338889Sjdp/* Noticed a new filename, so try to register it. */ 5438889Sjdp 5538889Sjdpvoid 56130561Sobrienregister_dependency (char *filename) 5738889Sjdp{ 5838889Sjdp struct dependency *dep; 5938889Sjdp 6038889Sjdp if (dep_file == NULL) 6138889Sjdp return; 6238889Sjdp 6338889Sjdp for (dep = dep_chain; dep != NULL; dep = dep->next) 6438889Sjdp { 6577298Sobrien if (!strcmp (filename, dep->file)) 6638889Sjdp return; 6738889Sjdp } 6838889Sjdp 6938889Sjdp dep = (struct dependency *) xmalloc (sizeof (struct dependency)); 7038889Sjdp dep->file = xstrdup (filename); 7138889Sjdp dep->next = dep_chain; 7238889Sjdp dep_chain = dep; 7338889Sjdp} 7438889Sjdp 7538889Sjdp/* Quote a file name the way `make' wants it, and print it to FILE. 7638889Sjdp If FILE is NULL, do no printing, but return the length of the 7738889Sjdp quoted string. 7838889Sjdp 7938889Sjdp This code is taken from gcc with only minor changes. */ 8038889Sjdp 8138889Sjdpstatic int 82130561Sobrienquote_string_for_make (FILE *file, char *src) 8338889Sjdp{ 8438889Sjdp char *p = src; 8538889Sjdp int i = 0; 8689857Sobrien 8738889Sjdp for (;;) 8838889Sjdp { 8938889Sjdp char c = *p++; 9089857Sobrien 9138889Sjdp switch (c) 9238889Sjdp { 9338889Sjdp case '\0': 9438889Sjdp case ' ': 9538889Sjdp case '\t': 9638889Sjdp { 9738889Sjdp /* GNU make uses a weird quoting scheme for white space. 9838889Sjdp A space or tab preceded by 2N+1 backslashes represents 9938889Sjdp N backslashes followed by space; a space or tab 10038889Sjdp preceded by 2N backslashes represents N backslashes at 10138889Sjdp the end of a file name; and backslashes in other 10238889Sjdp contexts should not be doubled. */ 10338889Sjdp char *q; 10489857Sobrien 10577298Sobrien for (q = p - 1; src < q && q[-1] == '\\'; q--) 10638889Sjdp { 10738889Sjdp if (file) 10838889Sjdp putc ('\\', file); 10938889Sjdp i++; 11038889Sjdp } 11138889Sjdp } 11238889Sjdp if (!c) 11338889Sjdp return i; 11438889Sjdp if (file) 11538889Sjdp putc ('\\', file); 11638889Sjdp i++; 11738889Sjdp goto ordinary_char; 11877298Sobrien 11938889Sjdp case '$': 12038889Sjdp if (file) 12138889Sjdp putc (c, file); 12238889Sjdp i++; 12338889Sjdp /* Fall through. This can mishandle things like "$(" but 12438889Sjdp there's no easy fix. */ 12538889Sjdp default: 12638889Sjdp ordinary_char: 12738889Sjdp /* This can mishandle characters in the string "\0\n%*?[\\~"; 12838889Sjdp exactly which chars are mishandled depends on the `make' version. 12938889Sjdp We know of no portable solution for this; 13038889Sjdp even GNU make 3.76.1 doesn't solve the problem entirely. 13138889Sjdp (Also, '\0' is mishandled due to our calling conventions.) */ 13238889Sjdp if (file) 13338889Sjdp putc (c, file); 13438889Sjdp i++; 13538889Sjdp break; 13638889Sjdp } 13738889Sjdp } 13838889Sjdp} 13938889Sjdp 14038889Sjdp/* Append some output to the file, keeping track of columns and doing 14138889Sjdp wrapping as necessary. */ 14238889Sjdp 14338889Sjdpstatic void 144130561Sobrienwrap_output (FILE *f, char *string, int spacer) 14538889Sjdp{ 14638889Sjdp int len = quote_string_for_make (NULL, string); 14738889Sjdp 14838889Sjdp if (len == 0) 14938889Sjdp return; 15038889Sjdp 15177298Sobrien if (column 15277298Sobrien && (MAX_COLUMNS 15377298Sobrien - 1 /* spacer */ 15477298Sobrien - 2 /* ` \' */ 15577298Sobrien < column + len)) 15638889Sjdp { 15738889Sjdp fprintf (f, " \\\n "); 15838889Sjdp column = 0; 15938889Sjdp if (spacer == ' ') 16038889Sjdp spacer = '\0'; 16138889Sjdp } 16238889Sjdp 16338889Sjdp if (spacer == ' ') 16438889Sjdp { 16538889Sjdp putc (spacer, f); 16638889Sjdp ++column; 16738889Sjdp } 16838889Sjdp 16938889Sjdp quote_string_for_make (f, string); 17038889Sjdp column += len; 17138889Sjdp 17238889Sjdp if (spacer == ':') 17338889Sjdp { 17438889Sjdp putc (spacer, f); 17538889Sjdp ++column; 17638889Sjdp } 17738889Sjdp} 17838889Sjdp 17938889Sjdp/* Print dependency file. */ 18038889Sjdp 18138889Sjdpvoid 182130561Sobrienprint_dependencies (void) 18338889Sjdp{ 18438889Sjdp FILE *f; 18538889Sjdp struct dependency *dep; 18638889Sjdp 18738889Sjdp if (dep_file == NULL) 18838889Sjdp return; 18938889Sjdp 19089857Sobrien f = fopen (dep_file, FOPEN_WT); 19138889Sjdp if (f == NULL) 19238889Sjdp { 19389857Sobrien as_warn (_("can't open `%s' for writing"), dep_file); 19438889Sjdp return; 19538889Sjdp } 19638889Sjdp 19738889Sjdp column = 0; 19838889Sjdp wrap_output (f, out_file_name, ':'); 19938889Sjdp for (dep = dep_chain; dep != NULL; dep = dep->next) 20038889Sjdp wrap_output (f, dep->file, ' '); 20138889Sjdp 20238889Sjdp putc ('\n', f); 20338889Sjdp 20438889Sjdp if (fclose (f)) 20589857Sobrien as_warn (_("can't close `%s'"), dep_file); 20638889Sjdp} 207