1*fae548d3Szrj /* depend.c - Handle dependency tracking.
2*fae548d3Szrj Copyright (C) 1997-2020 Free Software Foundation, Inc.
3*fae548d3Szrj
4*fae548d3Szrj This file is part of GAS, the GNU Assembler.
5*fae548d3Szrj
6*fae548d3Szrj GAS is free software; you can redistribute it and/or modify
7*fae548d3Szrj it under the terms of the GNU General Public License as published by
8*fae548d3Szrj the Free Software Foundation; either version 3, or (at your option)
9*fae548d3Szrj any later version.
10*fae548d3Szrj
11*fae548d3Szrj GAS is distributed in the hope that it will be useful,
12*fae548d3Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of
13*fae548d3Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*fae548d3Szrj GNU General Public License for more details.
15*fae548d3Szrj
16*fae548d3Szrj You should have received a copy of the GNU General Public License
17*fae548d3Szrj along with GAS; see the file COPYING. If not, write to the Free
18*fae548d3Szrj Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
19*fae548d3Szrj 02110-1301, USA. */
20*fae548d3Szrj
21*fae548d3Szrj #include "as.h"
22*fae548d3Szrj #include "filenames.h"
23*fae548d3Szrj
24*fae548d3Szrj /* The file to write to, or NULL if no dependencies being kept. */
25*fae548d3Szrj static char * dep_file = NULL;
26*fae548d3Szrj
27*fae548d3Szrj struct dependency
28*fae548d3Szrj {
29*fae548d3Szrj char * file;
30*fae548d3Szrj struct dependency * next;
31*fae548d3Szrj };
32*fae548d3Szrj
33*fae548d3Szrj /* All the files we depend on. */
34*fae548d3Szrj static struct dependency * dep_chain = NULL;
35*fae548d3Szrj
36*fae548d3Szrj /* Current column in output file. */
37*fae548d3Szrj static int column = 0;
38*fae548d3Szrj
39*fae548d3Szrj static int quote_string_for_make (FILE *, const char *);
40*fae548d3Szrj static void wrap_output (FILE *, const char *, int);
41*fae548d3Szrj
42*fae548d3Szrj /* Number of columns allowable. */
43*fae548d3Szrj #define MAX_COLUMNS 72
44*fae548d3Szrj
45*fae548d3Szrj /* Start saving dependencies, to be written to FILENAME. If this is
46*fae548d3Szrj never called, then dependency tracking is simply skipped. */
47*fae548d3Szrj
48*fae548d3Szrj void
start_dependencies(char * filename)49*fae548d3Szrj start_dependencies (char *filename)
50*fae548d3Szrj {
51*fae548d3Szrj dep_file = filename;
52*fae548d3Szrj }
53*fae548d3Szrj
54*fae548d3Szrj /* Noticed a new filename, so try to register it. */
55*fae548d3Szrj
56*fae548d3Szrj void
register_dependency(const char * filename)57*fae548d3Szrj register_dependency (const char *filename)
58*fae548d3Szrj {
59*fae548d3Szrj struct dependency *dep;
60*fae548d3Szrj
61*fae548d3Szrj if (dep_file == NULL)
62*fae548d3Szrj return;
63*fae548d3Szrj
64*fae548d3Szrj for (dep = dep_chain; dep != NULL; dep = dep->next)
65*fae548d3Szrj {
66*fae548d3Szrj if (!filename_cmp (filename, dep->file))
67*fae548d3Szrj return;
68*fae548d3Szrj }
69*fae548d3Szrj
70*fae548d3Szrj dep = XNEW (struct dependency);
71*fae548d3Szrj dep->file = xstrdup (filename);
72*fae548d3Szrj dep->next = dep_chain;
73*fae548d3Szrj dep_chain = dep;
74*fae548d3Szrj }
75*fae548d3Szrj
76*fae548d3Szrj /* Quote a file name the way `make' wants it, and print it to FILE.
77*fae548d3Szrj If FILE is NULL, do no printing, but return the length of the
78*fae548d3Szrj quoted string.
79*fae548d3Szrj
80*fae548d3Szrj This code is taken from gcc with only minor changes. */
81*fae548d3Szrj
82*fae548d3Szrj static int
quote_string_for_make(FILE * file,const char * src)83*fae548d3Szrj quote_string_for_make (FILE *file, const char *src)
84*fae548d3Szrj {
85*fae548d3Szrj const char *p = src;
86*fae548d3Szrj int i = 0;
87*fae548d3Szrj
88*fae548d3Szrj for (;;)
89*fae548d3Szrj {
90*fae548d3Szrj char c = *p++;
91*fae548d3Szrj
92*fae548d3Szrj switch (c)
93*fae548d3Szrj {
94*fae548d3Szrj case '\0':
95*fae548d3Szrj case ' ':
96*fae548d3Szrj case '\t':
97*fae548d3Szrj {
98*fae548d3Szrj /* GNU make uses a weird quoting scheme for white space.
99*fae548d3Szrj A space or tab preceded by 2N+1 backslashes represents
100*fae548d3Szrj N backslashes followed by space; a space or tab
101*fae548d3Szrj preceded by 2N backslashes represents N backslashes at
102*fae548d3Szrj the end of a file name; and backslashes in other
103*fae548d3Szrj contexts should not be doubled. */
104*fae548d3Szrj const char *q;
105*fae548d3Szrj
106*fae548d3Szrj for (q = p - 1; src < q && q[-1] == '\\'; q--)
107*fae548d3Szrj {
108*fae548d3Szrj if (file)
109*fae548d3Szrj putc ('\\', file);
110*fae548d3Szrj i++;
111*fae548d3Szrj }
112*fae548d3Szrj }
113*fae548d3Szrj if (!c)
114*fae548d3Szrj return i;
115*fae548d3Szrj if (file)
116*fae548d3Szrj putc ('\\', file);
117*fae548d3Szrj i++;
118*fae548d3Szrj goto ordinary_char;
119*fae548d3Szrj
120*fae548d3Szrj case '$':
121*fae548d3Szrj if (file)
122*fae548d3Szrj putc (c, file);
123*fae548d3Szrj i++;
124*fae548d3Szrj /* Fall through. */
125*fae548d3Szrj /* This can mishandle things like "$(" but there's no easy fix. */
126*fae548d3Szrj default:
127*fae548d3Szrj ordinary_char:
128*fae548d3Szrj /* This can mishandle characters in the string "\0\n%*?[\\~";
129*fae548d3Szrj exactly which chars are mishandled depends on the `make' version.
130*fae548d3Szrj We know of no portable solution for this;
131*fae548d3Szrj even GNU make 3.76.1 doesn't solve the problem entirely.
132*fae548d3Szrj (Also, '\0' is mishandled due to our calling conventions.) */
133*fae548d3Szrj if (file)
134*fae548d3Szrj putc (c, file);
135*fae548d3Szrj i++;
136*fae548d3Szrj break;
137*fae548d3Szrj }
138*fae548d3Szrj }
139*fae548d3Szrj }
140*fae548d3Szrj
141*fae548d3Szrj /* Append some output to the file, keeping track of columns and doing
142*fae548d3Szrj wrapping as necessary. */
143*fae548d3Szrj
144*fae548d3Szrj static void
wrap_output(FILE * f,const char * string,int spacer)145*fae548d3Szrj wrap_output (FILE *f, const char *string, int spacer)
146*fae548d3Szrj {
147*fae548d3Szrj int len = quote_string_for_make (NULL, string);
148*fae548d3Szrj
149*fae548d3Szrj if (len == 0)
150*fae548d3Szrj return;
151*fae548d3Szrj
152*fae548d3Szrj if (column
153*fae548d3Szrj && (MAX_COLUMNS
154*fae548d3Szrj - 1 /* spacer */
155*fae548d3Szrj - 2 /* ` \' */
156*fae548d3Szrj < column + len))
157*fae548d3Szrj {
158*fae548d3Szrj fprintf (f, " \\\n ");
159*fae548d3Szrj column = 0;
160*fae548d3Szrj if (spacer == ' ')
161*fae548d3Szrj spacer = '\0';
162*fae548d3Szrj }
163*fae548d3Szrj
164*fae548d3Szrj if (spacer == ' ')
165*fae548d3Szrj {
166*fae548d3Szrj putc (spacer, f);
167*fae548d3Szrj ++column;
168*fae548d3Szrj }
169*fae548d3Szrj
170*fae548d3Szrj quote_string_for_make (f, string);
171*fae548d3Szrj column += len;
172*fae548d3Szrj
173*fae548d3Szrj if (spacer == ':')
174*fae548d3Szrj {
175*fae548d3Szrj putc (spacer, f);
176*fae548d3Szrj ++column;
177*fae548d3Szrj }
178*fae548d3Szrj }
179*fae548d3Szrj
180*fae548d3Szrj /* Print dependency file. */
181*fae548d3Szrj
182*fae548d3Szrj void
print_dependencies(void)183*fae548d3Szrj print_dependencies (void)
184*fae548d3Szrj {
185*fae548d3Szrj FILE *f;
186*fae548d3Szrj struct dependency *dep;
187*fae548d3Szrj
188*fae548d3Szrj if (dep_file == NULL)
189*fae548d3Szrj return;
190*fae548d3Szrj
191*fae548d3Szrj f = fopen (dep_file, FOPEN_WT);
192*fae548d3Szrj if (f == NULL)
193*fae548d3Szrj {
194*fae548d3Szrj as_warn (_("can't open `%s' for writing"), dep_file);
195*fae548d3Szrj return;
196*fae548d3Szrj }
197*fae548d3Szrj
198*fae548d3Szrj column = 0;
199*fae548d3Szrj wrap_output (f, out_file_name, ':');
200*fae548d3Szrj for (dep = dep_chain; dep != NULL; dep = dep->next)
201*fae548d3Szrj wrap_output (f, dep->file, ' ');
202*fae548d3Szrj
203*fae548d3Szrj putc ('\n', f);
204*fae548d3Szrj
205*fae548d3Szrj if (fclose (f))
206*fae548d3Szrj as_warn (_("can't close `%s'"), dep_file);
207*fae548d3Szrj }
208