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