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