depend.c revision 89857
138889Sjdp/* depend.c - Handle dependency tracking. 289857Sobrien Copyright 1997, 1998, 2000, 2001 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 1838889Sjdp Software Foundation, 59 Temple Place - Suite 330, Boston, MA 1938889Sjdp 02111-1307, 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 3838889Sjdpstatic int quote_string_for_make PARAMS ((FILE *, char *)); 3938889Sjdpstatic void wrap_output PARAMS ((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 4838889Sjdpstart_dependencies (filename) 4938889Sjdp char *filename; 5038889Sjdp{ 5138889Sjdp dep_file = filename; 5238889Sjdp} 5338889Sjdp 5438889Sjdp/* Noticed a new filename, so try to register it. */ 5538889Sjdp 5638889Sjdpvoid 5738889Sjdpregister_dependency (filename) 5838889Sjdp char *filename; 5938889Sjdp{ 6038889Sjdp struct dependency *dep; 6138889Sjdp 6238889Sjdp if (dep_file == NULL) 6338889Sjdp return; 6438889Sjdp 6538889Sjdp for (dep = dep_chain; dep != NULL; dep = dep->next) 6638889Sjdp { 6777298Sobrien if (!strcmp (filename, dep->file)) 6838889Sjdp return; 6938889Sjdp } 7038889Sjdp 7138889Sjdp dep = (struct dependency *) xmalloc (sizeof (struct dependency)); 7238889Sjdp dep->file = xstrdup (filename); 7338889Sjdp dep->next = dep_chain; 7438889Sjdp dep_chain = dep; 7538889Sjdp} 7638889Sjdp 7738889Sjdp/* Quote a file name the way `make' wants it, and print it to FILE. 7838889Sjdp If FILE is NULL, do no printing, but return the length of the 7938889Sjdp quoted string. 8038889Sjdp 8138889Sjdp This code is taken from gcc with only minor changes. */ 8238889Sjdp 8338889Sjdpstatic int 8438889Sjdpquote_string_for_make (file, src) 8538889Sjdp FILE *file; 8638889Sjdp char *src; 8738889Sjdp{ 8838889Sjdp char *p = src; 8938889Sjdp int i = 0; 9089857Sobrien 9138889Sjdp for (;;) 9238889Sjdp { 9338889Sjdp char c = *p++; 9489857Sobrien 9538889Sjdp switch (c) 9638889Sjdp { 9738889Sjdp case '\0': 9838889Sjdp case ' ': 9938889Sjdp case '\t': 10038889Sjdp { 10138889Sjdp /* GNU make uses a weird quoting scheme for white space. 10238889Sjdp A space or tab preceded by 2N+1 backslashes represents 10338889Sjdp N backslashes followed by space; a space or tab 10438889Sjdp preceded by 2N backslashes represents N backslashes at 10538889Sjdp the end of a file name; and backslashes in other 10638889Sjdp contexts should not be doubled. */ 10738889Sjdp char *q; 10889857Sobrien 10977298Sobrien for (q = p - 1; src < q && q[-1] == '\\'; q--) 11038889Sjdp { 11138889Sjdp if (file) 11238889Sjdp putc ('\\', file); 11338889Sjdp i++; 11438889Sjdp } 11538889Sjdp } 11638889Sjdp if (!c) 11738889Sjdp return i; 11838889Sjdp if (file) 11938889Sjdp putc ('\\', file); 12038889Sjdp i++; 12138889Sjdp goto ordinary_char; 12277298Sobrien 12338889Sjdp case '$': 12438889Sjdp if (file) 12538889Sjdp putc (c, file); 12638889Sjdp i++; 12738889Sjdp /* Fall through. This can mishandle things like "$(" but 12838889Sjdp there's no easy fix. */ 12938889Sjdp default: 13038889Sjdp ordinary_char: 13138889Sjdp /* This can mishandle characters in the string "\0\n%*?[\\~"; 13238889Sjdp exactly which chars are mishandled depends on the `make' version. 13338889Sjdp We know of no portable solution for this; 13438889Sjdp even GNU make 3.76.1 doesn't solve the problem entirely. 13538889Sjdp (Also, '\0' is mishandled due to our calling conventions.) */ 13638889Sjdp if (file) 13738889Sjdp putc (c, file); 13838889Sjdp i++; 13938889Sjdp break; 14038889Sjdp } 14138889Sjdp } 14238889Sjdp} 14338889Sjdp 14438889Sjdp/* Append some output to the file, keeping track of columns and doing 14538889Sjdp wrapping as necessary. */ 14638889Sjdp 14738889Sjdpstatic void 14838889Sjdpwrap_output (f, string, spacer) 14938889Sjdp FILE *f; 15038889Sjdp char *string; 15138889Sjdp int spacer; 15238889Sjdp{ 15338889Sjdp int len = quote_string_for_make (NULL, string); 15438889Sjdp 15538889Sjdp if (len == 0) 15638889Sjdp return; 15738889Sjdp 15877298Sobrien if (column 15977298Sobrien && (MAX_COLUMNS 16077298Sobrien - 1 /* spacer */ 16177298Sobrien - 2 /* ` \' */ 16277298Sobrien < column + len)) 16338889Sjdp { 16438889Sjdp fprintf (f, " \\\n "); 16538889Sjdp column = 0; 16638889Sjdp if (spacer == ' ') 16738889Sjdp spacer = '\0'; 16838889Sjdp } 16938889Sjdp 17038889Sjdp if (spacer == ' ') 17138889Sjdp { 17238889Sjdp putc (spacer, f); 17338889Sjdp ++column; 17438889Sjdp } 17538889Sjdp 17638889Sjdp quote_string_for_make (f, string); 17738889Sjdp column += len; 17838889Sjdp 17938889Sjdp if (spacer == ':') 18038889Sjdp { 18138889Sjdp putc (spacer, f); 18238889Sjdp ++column; 18338889Sjdp } 18438889Sjdp} 18538889Sjdp 18638889Sjdp/* Print dependency file. */ 18738889Sjdp 18838889Sjdpvoid 18938889Sjdpprint_dependencies () 19038889Sjdp{ 19138889Sjdp FILE *f; 19238889Sjdp struct dependency *dep; 19338889Sjdp 19438889Sjdp if (dep_file == NULL) 19538889Sjdp return; 19638889Sjdp 19789857Sobrien f = fopen (dep_file, FOPEN_WT); 19838889Sjdp if (f == NULL) 19938889Sjdp { 20089857Sobrien as_warn (_("can't open `%s' for writing"), dep_file); 20138889Sjdp return; 20238889Sjdp } 20338889Sjdp 20438889Sjdp column = 0; 20538889Sjdp wrap_output (f, out_file_name, ':'); 20638889Sjdp for (dep = dep_chain; dep != NULL; dep = dep->next) 20738889Sjdp wrap_output (f, dep->file, ' '); 20838889Sjdp 20938889Sjdp putc ('\n', f); 21038889Sjdp 21138889Sjdp if (fclose (f)) 21289857Sobrien as_warn (_("can't close `%s'"), dep_file); 21338889Sjdp} 214