depend.c revision 60484
1210389Sgabor/* depend.c - Handle dependency tracking.
2210389Sgabor   Copyright (C) 1997, 1998 Free Software Foundation, Inc.
3210389Sgabor
4210389Sgabor   This file is part of GAS, the GNU Assembler.
5210389Sgabor
6210389Sgabor   GAS is free software; you can redistribute it and/or modify
7210389Sgabor   it under the terms of the GNU General Public License as published by
8210389Sgabor   the Free Software Foundation; either version 2, or (at your option)
9210389Sgabor   any later version.
10210389Sgabor
11210389Sgabor   GAS is distributed in the hope that it will be useful,
12210389Sgabor   but WITHOUT ANY WARRANTY; without even the implied warranty of
13210389Sgabor   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14210389Sgabor   GNU General Public License for more details.
15210389Sgabor
16210389Sgabor   You should have received a copy of the GNU General Public License
17210389Sgabor   along with GAS; see the file COPYING.  If not, write to the Free
18210389Sgabor   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19210389Sgabor   02111-1307, USA.  */
20210389Sgabor
21210389Sgabor#include "as.h"
22210389Sgabor
23210389Sgabor/* The file to write to, or NULL if no dependencies being kept.  */
24210389Sgaborstatic char *dep_file = NULL;
25210389Sgabor
26210389Sgaborstruct dependency
27210389Sgabor{
28210389Sgabor  char *file;
29210389Sgabor  struct dependency *next;
30210389Sgabor};
31210389Sgabor
32210389Sgabor/* All the files we depend on.  */
33210389Sgaborstatic struct dependency *dep_chain = NULL;
34210389Sgabor
35210389Sgabor/* Current column in output file.  */
36210389Sgaborstatic int column = 0;
37210389Sgabor
38210389Sgaborstatic int quote_string_for_make PARAMS ((FILE *, char *));
39210389Sgaborstatic void wrap_output PARAMS ((FILE *, char *, int));
40210389Sgabor
41210389Sgabor/* Number of columns allowable.  */
42210389Sgabor#define MAX_COLUMNS 72
43210389Sgabor
44210389Sgabor
45210389Sgabor
46210389Sgabor/* Start saving dependencies, to be written to FILENAME.  If this is
47210389Sgabor   never called, then dependency tracking is simply skipped.  */
48210389Sgabor
49210389Sgaborvoid
50210389Sgaborstart_dependencies (filename)
51210389Sgabor     char *filename;
52210389Sgabor{
53210389Sgabor  dep_file = filename;
54210389Sgabor}
55210389Sgabor
56210389Sgabor/* Noticed a new filename, so try to register it.  */
57210389Sgabor
58210389Sgaborvoid
59210389Sgaborregister_dependency (filename)
60210389Sgabor     char *filename;
61210389Sgabor{
62210389Sgabor  struct dependency *dep;
63210389Sgabor
64210389Sgabor  if (dep_file == NULL)
65210389Sgabor    return;
66210389Sgabor
67210389Sgabor  for (dep = dep_chain; dep != NULL; dep = dep->next)
68210389Sgabor    {
69210389Sgabor      if (! strcmp (filename, dep->file))
70210389Sgabor	return;
71210389Sgabor    }
72210389Sgabor
73210389Sgabor  dep = (struct dependency *) xmalloc (sizeof (struct dependency));
74210389Sgabor  dep->file = xstrdup (filename);
75210389Sgabor  dep->next = dep_chain;
76210389Sgabor  dep_chain = dep;
77210389Sgabor}
78210389Sgabor
79210389Sgabor/* Quote a file name the way `make' wants it, and print it to FILE.
80210389Sgabor   If FILE is NULL, do no printing, but return the length of the
81210389Sgabor   quoted string.
82210389Sgabor
83210389Sgabor   This code is taken from gcc with only minor changes.  */
84210389Sgabor
85210389Sgaborstatic int
86210389Sgaborquote_string_for_make (file, src)
87210389Sgabor     FILE *file;
88210389Sgabor     char *src;
89210389Sgabor{
90210389Sgabor  char *p = src;
91210389Sgabor  int i = 0;
92210389Sgabor  for (;;)
93210389Sgabor    {
94210389Sgabor      char c = *p++;
95210389Sgabor      switch (c)
96210389Sgabor	{
97210389Sgabor	case '\0':
98210389Sgabor	case ' ':
99210389Sgabor	case '\t':
100210389Sgabor	  {
101210389Sgabor	    /* GNU make uses a weird quoting scheme for white space.
102210389Sgabor	       A space or tab preceded by 2N+1 backslashes represents
103210389Sgabor	       N backslashes followed by space; a space or tab
104210389Sgabor	       preceded by 2N backslashes represents N backslashes at
105210389Sgabor	       the end of a file name; and backslashes in other
106210389Sgabor	       contexts should not be doubled.  */
107210389Sgabor	    char *q;
108210389Sgabor	    for (q = p - 1; src < q && q[-1] == '\\';  q--)
109210389Sgabor	      {
110210389Sgabor		if (file)
111210389Sgabor		  putc ('\\', file);
112210389Sgabor		i++;
113210389Sgabor	      }
114210389Sgabor	  }
115210389Sgabor	  if (!c)
116210389Sgabor	    return i;
117210389Sgabor	  if (file)
118210389Sgabor	    putc ('\\', file);
119210389Sgabor	  i++;
120210389Sgabor	  goto ordinary_char;
121210389Sgabor
122210389Sgabor	case '$':
123210389Sgabor	  if (file)
124210389Sgabor	    putc (c, file);
125210389Sgabor	  i++;
126210389Sgabor	  /* Fall through.  This can mishandle things like "$(" but
127210389Sgabor	     there's no easy fix.  */
128210389Sgabor	default:
129210389Sgabor	ordinary_char:
130210389Sgabor	  /* This can mishandle characters in the string "\0\n%*?[\\~";
131210389Sgabor	     exactly which chars are mishandled depends on the `make' version.
132210389Sgabor	     We know of no portable solution for this;
133210389Sgabor	     even GNU make 3.76.1 doesn't solve the problem entirely.
134210389Sgabor	     (Also, '\0' is mishandled due to our calling conventions.)  */
135210389Sgabor	  if (file)
136210389Sgabor	    putc (c, file);
137210389Sgabor	  i++;
138210389Sgabor	  break;
139210389Sgabor	}
140210389Sgabor    }
141210389Sgabor}
142210389Sgabor
143210389Sgabor/* Append some output to the file, keeping track of columns and doing
144210389Sgabor   wrapping as necessary.  */
145210389Sgabor
146210389Sgaborstatic void
147210389Sgaborwrap_output (f, string, spacer)
148210389Sgabor     FILE *f;
149210389Sgabor     char *string;
150210389Sgabor     int spacer;
151210389Sgabor{
152210389Sgabor  int len = quote_string_for_make (NULL, string);
153210389Sgabor
154210389Sgabor  if (len == 0)
155210389Sgabor    return;
156210389Sgabor
157210389Sgabor  if (column && MAX_COLUMNS - 1 /*spacer*/ - 2 /*` \'*/ < column + len)
158210389Sgabor    {
159210389Sgabor      fprintf (f, " \\\n ");
160210389Sgabor      column = 0;
161210389Sgabor      if (spacer == ' ')
162210389Sgabor	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