]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gas/depend.c
19990502 sourceware import
[thirdparty/binutils-gdb.git] / gas / depend.c
1 /* depend.c - Handle dependency tracking.
2 Copyright (C) 1997, 1998 Free Software Foundation, Inc.
3
4 This file is part of GAS, the GNU Assembler.
5
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to the Free
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
20
21 #include "as.h"
22
23 /* The file to write to, or NULL if no dependencies being kept. */
24 static char *dep_file = NULL;
25
26 struct dependency
27 {
28 char *file;
29 struct dependency *next;
30 };
31
32 /* All the files we depend on. */
33 static struct dependency *dep_chain = NULL;
34
35 /* Current column in output file. */
36 static int column = 0;
37
38 static int quote_string_for_make PARAMS ((FILE *, char *));
39 static void wrap_output PARAMS ((FILE *, char *, int));
40
41 /* Number of columns allowable. */
42 #define MAX_COLUMNS 72
43
44 \f
45
46 /* Start saving dependencies, to be written to FILENAME. If this is
47 never called, then dependency tracking is simply skipped. */
48
49 void
50 start_dependencies (filename)
51 char *filename;
52 {
53 dep_file = filename;
54 }
55
56 /* Noticed a new filename, so try to register it. */
57
58 void
59 register_dependency (filename)
60 char *filename;
61 {
62 struct dependency *dep;
63
64 if (dep_file == NULL)
65 return;
66
67 for (dep = dep_chain; dep != NULL; dep = dep->next)
68 {
69 if (! strcmp (filename, dep->file))
70 return;
71 }
72
73 dep = (struct dependency *) xmalloc (sizeof (struct dependency));
74 dep->file = xstrdup (filename);
75 dep->next = dep_chain;
76 dep_chain = dep;
77 }
78
79 /* Quote a file name the way `make' wants it, and print it to FILE.
80 If FILE is NULL, do no printing, but return the length of the
81 quoted string.
82
83 This code is taken from gcc with only minor changes. */
84
85 static int
86 quote_string_for_make (file, src)
87 FILE *file;
88 char *src;
89 {
90 char *p = src;
91 int i = 0;
92 for (;;)
93 {
94 char c = *p++;
95 switch (c)
96 {
97 case '\0':
98 case ' ':
99 case '\t':
100 {
101 /* GNU make uses a weird quoting scheme for white space.
102 A space or tab preceded by 2N+1 backslashes represents
103 N backslashes followed by space; a space or tab
104 preceded by 2N backslashes represents N backslashes at
105 the end of a file name; and backslashes in other
106 contexts should not be doubled. */
107 char *q;
108 for (q = p - 1; src < q && q[-1] == '\\'; q--)
109 {
110 if (file)
111 putc ('\\', file);
112 i++;
113 }
114 }
115 if (!c)
116 return i;
117 if (file)
118 putc ('\\', file);
119 i++;
120 goto ordinary_char;
121
122 case '$':
123 if (file)
124 putc (c, file);
125 i++;
126 /* Fall through. This can mishandle things like "$(" but
127 there's no easy fix. */
128 default:
129 ordinary_char:
130 /* This can mishandle characters in the string "\0\n%*?[\\~";
131 exactly which chars are mishandled depends on the `make' version.
132 We know of no portable solution for this;
133 even GNU make 3.76.1 doesn't solve the problem entirely.
134 (Also, '\0' is mishandled due to our calling conventions.) */
135 if (file)
136 putc (c, file);
137 i++;
138 break;
139 }
140 }
141 }
142
143 /* Append some output to the file, keeping track of columns and doing
144 wrapping as necessary. */
145
146 static void
147 wrap_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
183 void
184 print_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 }