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