xref: /dflybsd-src/contrib/binutils-2.34/gas/depend.c (revision b52ef7118d1621abed722c5bbbd542210290ecef)
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