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