xref: /dflybsd-src/contrib/gcc-8.0/libcpp/mkdeps.c (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
1*38fd1498Szrj /* Dependency generator for Makefile fragments.
2*38fd1498Szrj    Copyright (C) 2000-2018 Free Software Foundation, Inc.
3*38fd1498Szrj    Contributed by Zack Weinberg, Mar 2000
4*38fd1498Szrj 
5*38fd1498Szrj This program is free software; you can redistribute it and/or modify it
6*38fd1498Szrj under the terms of the GNU General Public License as published by the
7*38fd1498Szrj Free Software Foundation; either version 3, or (at your option) any
8*38fd1498Szrj later version.
9*38fd1498Szrj 
10*38fd1498Szrj This program is distributed in the hope that it will be useful,
11*38fd1498Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of
12*38fd1498Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13*38fd1498Szrj GNU General Public License for more details.
14*38fd1498Szrj 
15*38fd1498Szrj You should have received a copy of the GNU General Public License
16*38fd1498Szrj along with this program; see the file COPYING3.  If not see
17*38fd1498Szrj <http://www.gnu.org/licenses/>.
18*38fd1498Szrj 
19*38fd1498Szrj  In other words, you are welcome to use, share and improve this program.
20*38fd1498Szrj  You are forbidden to forbid anyone else to use, share and improve
21*38fd1498Szrj  what you give them.   Help stamp out software-hoarding!  */
22*38fd1498Szrj 
23*38fd1498Szrj #include "config.h"
24*38fd1498Szrj #include "system.h"
25*38fd1498Szrj #include "mkdeps.h"
26*38fd1498Szrj 
27*38fd1498Szrj /* Keep this structure local to this file, so clients don't find it
28*38fd1498Szrj    easy to start making assumptions.  */
29*38fd1498Szrj struct deps
30*38fd1498Szrj {
31*38fd1498Szrj   const char **targetv;
32*38fd1498Szrj   unsigned int ntargets;	/* number of slots actually occupied */
33*38fd1498Szrj   unsigned int targets_size;	/* amt of allocated space - in words */
34*38fd1498Szrj 
35*38fd1498Szrj   const char **depv;
36*38fd1498Szrj   unsigned int ndeps;
37*38fd1498Szrj   unsigned int deps_size;
38*38fd1498Szrj 
39*38fd1498Szrj   const char **vpathv;
40*38fd1498Szrj   size_t *vpathlv;
41*38fd1498Szrj   unsigned int nvpaths;
42*38fd1498Szrj   unsigned int vpaths_size;
43*38fd1498Szrj };
44*38fd1498Szrj 
45*38fd1498Szrj static const char *munge (const char *);
46*38fd1498Szrj 
47*38fd1498Szrj /* Given a filename, quote characters in that filename which are
48*38fd1498Szrj    significant to Make.  Note that it's not possible to quote all such
49*38fd1498Szrj    characters - e.g. \n, %, *, ?, [, \ (in some contexts), and ~ are
50*38fd1498Szrj    not properly handled.  It isn't possible to get this right in any
51*38fd1498Szrj    current version of Make.  (??? Still true?  Old comment referred to
52*38fd1498Szrj    3.76.1.)  */
53*38fd1498Szrj 
54*38fd1498Szrj static const char *
munge(const char * filename)55*38fd1498Szrj munge (const char *filename)
56*38fd1498Szrj {
57*38fd1498Szrj   int len;
58*38fd1498Szrj   const char *p, *q;
59*38fd1498Szrj   char *dst, *buffer;
60*38fd1498Szrj 
61*38fd1498Szrj   for (p = filename, len = 0; *p; p++, len++)
62*38fd1498Szrj     {
63*38fd1498Szrj       switch (*p)
64*38fd1498Szrj 	{
65*38fd1498Szrj 	case ' ':
66*38fd1498Szrj 	case '\t':
67*38fd1498Szrj 	  /* GNU make uses a weird quoting scheme for white space.
68*38fd1498Szrj 	     A space or tab preceded by 2N+1 backslashes represents
69*38fd1498Szrj 	     N backslashes followed by space; a space or tab
70*38fd1498Szrj 	     preceded by 2N backslashes represents N backslashes at
71*38fd1498Szrj 	     the end of a file name; and backslashes in other
72*38fd1498Szrj 	     contexts should not be doubled.  */
73*38fd1498Szrj 	  for (q = p - 1; filename <= q && *q == '\\';  q--)
74*38fd1498Szrj 	    len++;
75*38fd1498Szrj 	  len++;
76*38fd1498Szrj 	  break;
77*38fd1498Szrj 
78*38fd1498Szrj 	case '$':
79*38fd1498Szrj 	  /* '$' is quoted by doubling it.  */
80*38fd1498Szrj 	  len++;
81*38fd1498Szrj 	  break;
82*38fd1498Szrj 
83*38fd1498Szrj 	case '#':
84*38fd1498Szrj 	  /* '#' is quoted with a backslash.  */
85*38fd1498Szrj 	  len++;
86*38fd1498Szrj 	  break;
87*38fd1498Szrj 	}
88*38fd1498Szrj     }
89*38fd1498Szrj 
90*38fd1498Szrj   /* Now we know how big to make the buffer.  */
91*38fd1498Szrj   buffer = XNEWVEC (char, len + 1);
92*38fd1498Szrj 
93*38fd1498Szrj   for (p = filename, dst = buffer; *p; p++, dst++)
94*38fd1498Szrj     {
95*38fd1498Szrj       switch (*p)
96*38fd1498Szrj 	{
97*38fd1498Szrj 	case ' ':
98*38fd1498Szrj 	case '\t':
99*38fd1498Szrj 	  for (q = p - 1; filename <= q && *q == '\\';  q--)
100*38fd1498Szrj 	    *dst++ = '\\';
101*38fd1498Szrj 	  *dst++ = '\\';
102*38fd1498Szrj 	  break;
103*38fd1498Szrj 
104*38fd1498Szrj 	case '$':
105*38fd1498Szrj 	  *dst++ = '$';
106*38fd1498Szrj 	  break;
107*38fd1498Szrj 
108*38fd1498Szrj 	case '#':
109*38fd1498Szrj 	  *dst++ = '\\';
110*38fd1498Szrj 	  break;
111*38fd1498Szrj 
112*38fd1498Szrj 	default:
113*38fd1498Szrj 	  /* nothing */;
114*38fd1498Szrj 	}
115*38fd1498Szrj       *dst = *p;
116*38fd1498Szrj     }
117*38fd1498Szrj 
118*38fd1498Szrj   *dst = '\0';
119*38fd1498Szrj   return buffer;
120*38fd1498Szrj }
121*38fd1498Szrj 
122*38fd1498Szrj /* If T begins with any of the partial pathnames listed in d->vpathv,
123*38fd1498Szrj    then advance T to point beyond that pathname.  */
124*38fd1498Szrj static const char *
apply_vpath(struct deps * d,const char * t)125*38fd1498Szrj apply_vpath (struct deps *d, const char *t)
126*38fd1498Szrj {
127*38fd1498Szrj   if (d->vpathv)
128*38fd1498Szrj     {
129*38fd1498Szrj       unsigned int i;
130*38fd1498Szrj       for (i = 0; i < d->nvpaths; i++)
131*38fd1498Szrj 	{
132*38fd1498Szrj 	  if (!filename_ncmp (d->vpathv[i], t, d->vpathlv[i]))
133*38fd1498Szrj 	    {
134*38fd1498Szrj 	      const char *p = t + d->vpathlv[i];
135*38fd1498Szrj 	      if (!IS_DIR_SEPARATOR (*p))
136*38fd1498Szrj 		goto not_this_one;
137*38fd1498Szrj 
138*38fd1498Szrj 	      /* Do not simplify $(vpath)/../whatever.  ??? Might not
139*38fd1498Szrj 		 be necessary. */
140*38fd1498Szrj 	      if (p[1] == '.' && p[2] == '.' && IS_DIR_SEPARATOR (p[3]))
141*38fd1498Szrj 		goto not_this_one;
142*38fd1498Szrj 
143*38fd1498Szrj 	      /* found a match */
144*38fd1498Szrj 	      t = t + d->vpathlv[i] + 1;
145*38fd1498Szrj 	      break;
146*38fd1498Szrj 	    }
147*38fd1498Szrj 	not_this_one:;
148*38fd1498Szrj 	}
149*38fd1498Szrj     }
150*38fd1498Szrj 
151*38fd1498Szrj   /* Remove leading ./ in any case.  */
152*38fd1498Szrj   while (t[0] == '.' && IS_DIR_SEPARATOR (t[1]))
153*38fd1498Szrj     {
154*38fd1498Szrj       t += 2;
155*38fd1498Szrj       /* If we removed a leading ./, then also remove any /s after the
156*38fd1498Szrj 	 first.  */
157*38fd1498Szrj       while (IS_DIR_SEPARATOR (t[0]))
158*38fd1498Szrj 	++t;
159*38fd1498Szrj     }
160*38fd1498Szrj 
161*38fd1498Szrj   return t;
162*38fd1498Szrj }
163*38fd1498Szrj 
164*38fd1498Szrj /* Public routines.  */
165*38fd1498Szrj 
166*38fd1498Szrj struct deps *
deps_init(void)167*38fd1498Szrj deps_init (void)
168*38fd1498Szrj {
169*38fd1498Szrj   return XCNEW (struct deps);
170*38fd1498Szrj }
171*38fd1498Szrj 
172*38fd1498Szrj void
deps_free(struct deps * d)173*38fd1498Szrj deps_free (struct deps *d)
174*38fd1498Szrj {
175*38fd1498Szrj   unsigned int i;
176*38fd1498Szrj 
177*38fd1498Szrj   if (d->targetv)
178*38fd1498Szrj     {
179*38fd1498Szrj       for (i = 0; i < d->ntargets; i++)
180*38fd1498Szrj 	free ((void *) d->targetv[i]);
181*38fd1498Szrj       free (d->targetv);
182*38fd1498Szrj     }
183*38fd1498Szrj 
184*38fd1498Szrj   if (d->depv)
185*38fd1498Szrj     {
186*38fd1498Szrj       for (i = 0; i < d->ndeps; i++)
187*38fd1498Szrj 	free ((void *) d->depv[i]);
188*38fd1498Szrj       free (d->depv);
189*38fd1498Szrj     }
190*38fd1498Szrj 
191*38fd1498Szrj   if (d->vpathv)
192*38fd1498Szrj     {
193*38fd1498Szrj       for (i = 0; i < d->nvpaths; i++)
194*38fd1498Szrj 	free ((void *) d->vpathv[i]);
195*38fd1498Szrj       free (d->vpathv);
196*38fd1498Szrj       free (d->vpathlv);
197*38fd1498Szrj     }
198*38fd1498Szrj 
199*38fd1498Szrj   free (d);
200*38fd1498Szrj }
201*38fd1498Szrj 
202*38fd1498Szrj /* Adds a target T.  We make a copy, so it need not be a permanent
203*38fd1498Szrj    string.  QUOTE is true if the string should be quoted.  */
204*38fd1498Szrj void
deps_add_target(struct deps * d,const char * t,int quote)205*38fd1498Szrj deps_add_target (struct deps *d, const char *t, int quote)
206*38fd1498Szrj {
207*38fd1498Szrj   if (d->ntargets == d->targets_size)
208*38fd1498Szrj     {
209*38fd1498Szrj       d->targets_size = d->targets_size * 2 + 4;
210*38fd1498Szrj       d->targetv = XRESIZEVEC (const char *, d->targetv, d->targets_size);
211*38fd1498Szrj     }
212*38fd1498Szrj 
213*38fd1498Szrj   t = apply_vpath (d, t);
214*38fd1498Szrj   if (quote)
215*38fd1498Szrj     t = munge (t);  /* Also makes permanent copy.  */
216*38fd1498Szrj   else
217*38fd1498Szrj     t = xstrdup (t);
218*38fd1498Szrj 
219*38fd1498Szrj   d->targetv[d->ntargets++] = t;
220*38fd1498Szrj }
221*38fd1498Szrj 
222*38fd1498Szrj /* Sets the default target if none has been given already.  An empty
223*38fd1498Szrj    string as the default target in interpreted as stdin.  The string
224*38fd1498Szrj    is quoted for MAKE.  */
225*38fd1498Szrj void
deps_add_default_target(struct deps * d,const char * tgt)226*38fd1498Szrj deps_add_default_target (struct deps *d, const char *tgt)
227*38fd1498Szrj {
228*38fd1498Szrj   /* Only if we have no targets.  */
229*38fd1498Szrj   if (d->ntargets)
230*38fd1498Szrj     return;
231*38fd1498Szrj 
232*38fd1498Szrj   if (tgt[0] == '\0')
233*38fd1498Szrj     deps_add_target (d, "-", 1);
234*38fd1498Szrj   else
235*38fd1498Szrj     {
236*38fd1498Szrj #ifndef TARGET_OBJECT_SUFFIX
237*38fd1498Szrj # define TARGET_OBJECT_SUFFIX ".o"
238*38fd1498Szrj #endif
239*38fd1498Szrj       const char *start = lbasename (tgt);
240*38fd1498Szrj       char *o = (char *) alloca (strlen (start)
241*38fd1498Szrj                                  + strlen (TARGET_OBJECT_SUFFIX) + 1);
242*38fd1498Szrj       char *suffix;
243*38fd1498Szrj 
244*38fd1498Szrj       strcpy (o, start);
245*38fd1498Szrj 
246*38fd1498Szrj       suffix = strrchr (o, '.');
247*38fd1498Szrj       if (!suffix)
248*38fd1498Szrj         suffix = o + strlen (o);
249*38fd1498Szrj       strcpy (suffix, TARGET_OBJECT_SUFFIX);
250*38fd1498Szrj 
251*38fd1498Szrj       deps_add_target (d, o, 1);
252*38fd1498Szrj     }
253*38fd1498Szrj }
254*38fd1498Szrj 
255*38fd1498Szrj void
deps_add_dep(struct deps * d,const char * t)256*38fd1498Szrj deps_add_dep (struct deps *d, const char *t)
257*38fd1498Szrj {
258*38fd1498Szrj   t = munge (apply_vpath (d, t));  /* Also makes permanent copy.  */
259*38fd1498Szrj 
260*38fd1498Szrj   if (d->ndeps == d->deps_size)
261*38fd1498Szrj     {
262*38fd1498Szrj       d->deps_size = d->deps_size * 2 + 8;
263*38fd1498Szrj       d->depv = XRESIZEVEC (const char *, d->depv, d->deps_size);
264*38fd1498Szrj     }
265*38fd1498Szrj   d->depv[d->ndeps++] = t;
266*38fd1498Szrj }
267*38fd1498Szrj 
268*38fd1498Szrj void
deps_add_vpath(struct deps * d,const char * vpath)269*38fd1498Szrj deps_add_vpath (struct deps *d, const char *vpath)
270*38fd1498Szrj {
271*38fd1498Szrj   const char *elem, *p;
272*38fd1498Szrj   char *copy;
273*38fd1498Szrj   size_t len;
274*38fd1498Szrj 
275*38fd1498Szrj   for (elem = vpath; *elem; elem = p)
276*38fd1498Szrj     {
277*38fd1498Szrj       for (p = elem; *p && *p != ':'; p++);
278*38fd1498Szrj       len = p - elem;
279*38fd1498Szrj       copy = XNEWVEC (char, len + 1);
280*38fd1498Szrj       memcpy (copy, elem, len);
281*38fd1498Szrj       copy[len] = '\0';
282*38fd1498Szrj       if (*p == ':')
283*38fd1498Szrj 	p++;
284*38fd1498Szrj 
285*38fd1498Szrj       if (d->nvpaths == d->vpaths_size)
286*38fd1498Szrj 	{
287*38fd1498Szrj 	  d->vpaths_size = d->vpaths_size * 2 + 8;
288*38fd1498Szrj 	  d->vpathv = XRESIZEVEC (const char *, d->vpathv, d->vpaths_size);
289*38fd1498Szrj 	  d->vpathlv = XRESIZEVEC (size_t, d->vpathlv, d->vpaths_size);
290*38fd1498Szrj 	}
291*38fd1498Szrj       d->vpathv[d->nvpaths] = copy;
292*38fd1498Szrj       d->vpathlv[d->nvpaths] = len;
293*38fd1498Szrj       d->nvpaths++;
294*38fd1498Szrj     }
295*38fd1498Szrj }
296*38fd1498Szrj 
297*38fd1498Szrj void
deps_write(const struct deps * d,FILE * fp,unsigned int colmax)298*38fd1498Szrj deps_write (const struct deps *d, FILE *fp, unsigned int colmax)
299*38fd1498Szrj {
300*38fd1498Szrj   unsigned int size, i, column;
301*38fd1498Szrj 
302*38fd1498Szrj   column = 0;
303*38fd1498Szrj   if (colmax && colmax < 34)
304*38fd1498Szrj     colmax = 34;
305*38fd1498Szrj 
306*38fd1498Szrj   for (i = 0; i < d->ntargets; i++)
307*38fd1498Szrj     {
308*38fd1498Szrj       size = strlen (d->targetv[i]);
309*38fd1498Szrj       column += size;
310*38fd1498Szrj       if (i)
311*38fd1498Szrj 	{
312*38fd1498Szrj 	  if (colmax && column > colmax)
313*38fd1498Szrj 	    {
314*38fd1498Szrj 	      fputs (" \\\n ", fp);
315*38fd1498Szrj 	      column = 1 + size;
316*38fd1498Szrj 	    }
317*38fd1498Szrj 	  else
318*38fd1498Szrj 	    {
319*38fd1498Szrj 	      putc (' ', fp);
320*38fd1498Szrj 	      column++;
321*38fd1498Szrj 	    }
322*38fd1498Szrj 	}
323*38fd1498Szrj       fputs (d->targetv[i], fp);
324*38fd1498Szrj     }
325*38fd1498Szrj 
326*38fd1498Szrj   putc (':', fp);
327*38fd1498Szrj   column++;
328*38fd1498Szrj 
329*38fd1498Szrj   for (i = 0; i < d->ndeps; i++)
330*38fd1498Szrj     {
331*38fd1498Szrj       size = strlen (d->depv[i]);
332*38fd1498Szrj       column += size;
333*38fd1498Szrj       if (colmax && column > colmax)
334*38fd1498Szrj 	{
335*38fd1498Szrj 	  fputs (" \\\n ", fp);
336*38fd1498Szrj 	  column = 1 + size;
337*38fd1498Szrj 	}
338*38fd1498Szrj       else
339*38fd1498Szrj 	{
340*38fd1498Szrj 	  putc (' ', fp);
341*38fd1498Szrj 	  column++;
342*38fd1498Szrj 	}
343*38fd1498Szrj       fputs (d->depv[i], fp);
344*38fd1498Szrj     }
345*38fd1498Szrj   putc ('\n', fp);
346*38fd1498Szrj }
347*38fd1498Szrj 
348*38fd1498Szrj void
deps_phony_targets(const struct deps * d,FILE * fp)349*38fd1498Szrj deps_phony_targets (const struct deps *d, FILE *fp)
350*38fd1498Szrj {
351*38fd1498Szrj   unsigned int i;
352*38fd1498Szrj 
353*38fd1498Szrj   for (i = 1; i < d->ndeps; i++)
354*38fd1498Szrj     {
355*38fd1498Szrj       putc ('\n', fp);
356*38fd1498Szrj       fputs (d->depv[i], fp);
357*38fd1498Szrj       putc (':', fp);
358*38fd1498Szrj       putc ('\n', fp);
359*38fd1498Szrj     }
360*38fd1498Szrj }
361*38fd1498Szrj 
362*38fd1498Szrj /* Write out a deps buffer to a file, in a form that can be read back
363*38fd1498Szrj    with deps_restore.  Returns nonzero on error, in which case the
364*38fd1498Szrj    error number will be in errno.  */
365*38fd1498Szrj 
366*38fd1498Szrj int
deps_save(struct deps * deps,FILE * f)367*38fd1498Szrj deps_save (struct deps *deps, FILE *f)
368*38fd1498Szrj {
369*38fd1498Szrj   unsigned int i;
370*38fd1498Szrj 
371*38fd1498Szrj   /* The cppreader structure contains makefile dependences.  Write out this
372*38fd1498Szrj      structure.  */
373*38fd1498Szrj 
374*38fd1498Szrj   /* The number of dependences.  */
375*38fd1498Szrj   if (fwrite (&deps->ndeps, sizeof (deps->ndeps), 1, f) != 1)
376*38fd1498Szrj       return -1;
377*38fd1498Szrj   /* The length of each dependence followed by the string.  */
378*38fd1498Szrj   for (i = 0; i < deps->ndeps; i++)
379*38fd1498Szrj     {
380*38fd1498Szrj       size_t num_to_write = strlen (deps->depv[i]);
381*38fd1498Szrj       if (fwrite (&num_to_write, sizeof (size_t), 1, f) != 1)
382*38fd1498Szrj           return -1;
383*38fd1498Szrj       if (fwrite (deps->depv[i], num_to_write, 1, f) != 1)
384*38fd1498Szrj           return -1;
385*38fd1498Szrj     }
386*38fd1498Szrj 
387*38fd1498Szrj   return 0;
388*38fd1498Szrj }
389*38fd1498Szrj 
390*38fd1498Szrj /* Read back dependency information written with deps_save into
391*38fd1498Szrj    the deps buffer.  The third argument may be NULL, in which case
392*38fd1498Szrj    the dependency information is just skipped, or it may be a filename,
393*38fd1498Szrj    in which case that filename is skipped.  */
394*38fd1498Szrj 
395*38fd1498Szrj int
deps_restore(struct deps * deps,FILE * fd,const char * self)396*38fd1498Szrj deps_restore (struct deps *deps, FILE *fd, const char *self)
397*38fd1498Szrj {
398*38fd1498Szrj   unsigned int i, count;
399*38fd1498Szrj   size_t num_to_read;
400*38fd1498Szrj   size_t buf_size = 512;
401*38fd1498Szrj   char *buf;
402*38fd1498Szrj 
403*38fd1498Szrj   /* Number of dependences.  */
404*38fd1498Szrj   if (fread (&count, 1, sizeof (count), fd) != sizeof (count))
405*38fd1498Szrj     return -1;
406*38fd1498Szrj 
407*38fd1498Szrj   buf = XNEWVEC (char, buf_size);
408*38fd1498Szrj 
409*38fd1498Szrj   /* The length of each dependence string, followed by the string.  */
410*38fd1498Szrj   for (i = 0; i < count; i++)
411*38fd1498Szrj     {
412*38fd1498Szrj       /* Read in # bytes in string.  */
413*38fd1498Szrj       if (fread (&num_to_read, 1, sizeof (size_t), fd) != sizeof (size_t))
414*38fd1498Szrj 	{
415*38fd1498Szrj 	  free (buf);
416*38fd1498Szrj 	  return -1;
417*38fd1498Szrj 	}
418*38fd1498Szrj       if (buf_size < num_to_read + 1)
419*38fd1498Szrj 	{
420*38fd1498Szrj 	  buf_size = num_to_read + 1 + 127;
421*38fd1498Szrj 	  buf = XRESIZEVEC (char, buf, buf_size);
422*38fd1498Szrj 	}
423*38fd1498Szrj       if (fread (buf, 1, num_to_read, fd) != num_to_read)
424*38fd1498Szrj 	{
425*38fd1498Szrj 	  free (buf);
426*38fd1498Szrj 	  return -1;
427*38fd1498Szrj 	}
428*38fd1498Szrj       buf[num_to_read] = '\0';
429*38fd1498Szrj 
430*38fd1498Szrj       /* Generate makefile dependencies from .pch if -nopch-deps.  */
431*38fd1498Szrj       if (self != NULL && filename_cmp (buf, self) != 0)
432*38fd1498Szrj         deps_add_dep (deps, buf);
433*38fd1498Szrj     }
434*38fd1498Szrj 
435*38fd1498Szrj   free (buf);
436*38fd1498Szrj   return 0;
437*38fd1498Szrj }
438