OSDN Git Service

libcpp:
[pf3gnuchains/gcc-fork.git] / libcpp / mkdeps.c
1 /* Dependency generator for Makefile fragments.
2    Copyright (C) 2000, 2001, 2003, 2007, 2008 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 2, 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; if not, write to the Free Software
17 Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
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     }
84
85   /* Now we know how big to make the buffer.  */
86   buffer = XNEWVEC (char, len + 1);
87
88   for (p = filename, dst = buffer; *p; p++, dst++)
89     {
90       switch (*p)
91         {
92         case ' ':
93         case '\t':
94           for (q = p - 1; filename <= q && *q == '\\';  q--)
95             *dst++ = '\\';
96           *dst++ = '\\';
97           break;
98
99         case '$':
100           *dst++ = '$';
101           break;
102
103         default:
104           /* nothing */;
105         }
106       *dst = *p;
107     }
108
109   *dst = '\0';
110   return buffer;
111 }
112
113 /* If T begins with any of the partial pathnames listed in d->vpathv,
114    then advance T to point beyond that pathname.  */
115 static const char *
116 apply_vpath (struct deps *d, const char *t)
117 {
118   if (d->vpathv)
119     {
120       unsigned int i;
121       for (i = 0; i < d->nvpaths; i++)
122         {
123           if (!strncmp (d->vpathv[i], t, d->vpathlv[i]))
124             {
125               const char *p = t + d->vpathlv[i];
126               if (!IS_DIR_SEPARATOR (*p))
127                 goto not_this_one;
128
129               /* Do not simplify $(vpath)/../whatever.  ??? Might not
130                  be necessary. */
131               if (p[1] == '.' && p[2] == '.' && IS_DIR_SEPARATOR (p[3]))
132                 goto not_this_one;
133
134               /* found a match */
135               t = t + d->vpathlv[i] + 1;
136               break;
137             }
138         not_this_one:;
139         }
140     }
141
142   /* Remove leading ./ in any case.  */
143   while (t[0] == '.' && IS_DIR_SEPARATOR (t[1]))
144     {
145       t += 2;
146       /* If we removed a leading ./, then also remove any /s after the
147          first.  */
148       while (IS_DIR_SEPARATOR (t[0]))
149         ++t;
150     }
151
152   return t;
153 }
154
155 /* Public routines.  */
156
157 struct deps *
158 deps_init (void)
159 {
160   return XCNEW (struct deps);
161 }
162
163 void
164 deps_free (struct deps *d)
165 {
166   unsigned int i;
167
168   if (d->targetv)
169     {
170       for (i = 0; i < d->ntargets; i++)
171         free ((void *) d->targetv[i]);
172       free (d->targetv);
173     }
174
175   if (d->depv)
176     {
177       for (i = 0; i < d->ndeps; i++)
178         free ((void *) d->depv[i]);
179       free (d->depv);
180     }
181
182   if (d->vpathv)
183     {
184       for (i = 0; i < d->nvpaths; i++)
185         free ((void *) d->vpathv[i]);
186       free (d->vpathv);
187       free (d->vpathlv);
188     }
189
190   free (d);
191 }
192
193 /* Adds a target T.  We make a copy, so it need not be a permanent
194    string.  QUOTE is true if the string should be quoted.  */
195 void
196 deps_add_target (struct deps *d, const char *t, int quote)
197 {
198   if (d->ntargets == d->targets_size)
199     {
200       d->targets_size = d->targets_size * 2 + 4;
201       d->targetv = XRESIZEVEC (const char *, d->targetv, d->targets_size);
202     }
203
204   t = apply_vpath (d, t);
205   if (quote)
206     t = munge (t);  /* Also makes permanent copy.  */
207   else
208     t = xstrdup (t);
209
210   d->targetv[d->ntargets++] = t;
211 }
212
213 /* Sets the default target if none has been given already.  An empty
214    string as the default target in interpreted as stdin.  The string
215    is quoted for MAKE.  */
216 void
217 deps_add_default_target (struct deps *d, const char *tgt)
218 {
219   /* Only if we have no targets.  */
220   if (d->ntargets)
221     return;
222
223   if (tgt[0] == '\0')
224     deps_add_target (d, "-", 1);
225   else
226     {
227 #ifndef TARGET_OBJECT_SUFFIX
228 # define TARGET_OBJECT_SUFFIX ".o"
229 #endif
230       const char *start = lbasename (tgt);
231       char *o = (char *) alloca (strlen (start)
232                                  + strlen (TARGET_OBJECT_SUFFIX) + 1);
233       char *suffix;
234
235       strcpy (o, start);
236
237       suffix = strrchr (o, '.');
238       if (!suffix)
239         suffix = o + strlen (o);
240       strcpy (suffix, TARGET_OBJECT_SUFFIX);
241
242       deps_add_target (d, o, 1);
243     }
244 }
245
246 void
247 deps_add_dep (struct deps *d, const char *t)
248 {
249   t = munge (apply_vpath (d, t));  /* Also makes permanent copy.  */
250
251   if (d->ndeps == d->deps_size)
252     {
253       d->deps_size = d->deps_size * 2 + 8;
254       d->depv = XRESIZEVEC (const char *, d->depv, d->deps_size);
255     }
256   d->depv[d->ndeps++] = t;
257 }
258
259 void
260 deps_add_vpath (struct deps *d, const char *vpath)
261 {
262   const char *elem, *p;
263   char *copy;
264   size_t len;
265
266   for (elem = vpath; *elem; elem = p)
267     {
268       for (p = elem; *p && *p != ':'; p++);
269       len = p - elem;
270       copy = XNEWVEC (char, len + 1);
271       memcpy (copy, elem, len);
272       copy[len] = '\0';
273       if (*p == ':')
274         p++;
275
276       if (d->nvpaths == d->vpaths_size)
277         {
278           d->vpaths_size = d->vpaths_size * 2 + 8;
279           d->vpathv = XRESIZEVEC (const char *, d->vpathv, d->vpaths_size);
280           d->vpathlv = XRESIZEVEC (size_t, d->vpathlv, d->vpaths_size);
281         }
282       d->vpathv[d->nvpaths] = copy;
283       d->vpathlv[d->nvpaths] = len;
284       d->nvpaths++;
285     }
286 }
287
288 void
289 deps_write (const struct deps *d, FILE *fp, unsigned int colmax)
290 {
291   unsigned int size, i, column;
292
293   column = 0;
294   if (colmax && colmax < 34)
295     colmax = 34;
296
297   for (i = 0; i < d->ntargets; i++)
298     {
299       size = strlen (d->targetv[i]);
300       column += size;
301       if (i)
302         {
303           if (colmax && column > colmax)
304             {
305               fputs (" \\\n ", fp);
306               column = 1 + size;
307             }
308           else
309             {
310               putc (' ', fp);
311               column++;
312             }
313         }
314       fputs (d->targetv[i], fp);
315     }
316
317   putc (':', fp);
318   column++;
319
320   for (i = 0; i < d->ndeps; i++)
321     {
322       size = strlen (d->depv[i]);
323       column += size;
324       if (colmax && column > colmax)
325         {
326           fputs (" \\\n ", fp);
327           column = 1 + size;
328         }
329       else
330         {
331           putc (' ', fp);
332           column++;
333         }
334       fputs (d->depv[i], fp);
335     }
336   putc ('\n', fp);
337 }
338
339 void
340 deps_phony_targets (const struct deps *d, FILE *fp)
341 {
342   unsigned int i;
343
344   for (i = 1; i < d->ndeps; i++)
345     {
346       putc ('\n', fp);
347       fputs (d->depv[i], fp);
348       putc (':', fp);
349       putc ('\n', fp);
350     }
351 }
352
353 /* Write out a deps buffer to a file, in a form that can be read back
354    with deps_restore.  Returns nonzero on error, in which case the
355    error number will be in errno.  */
356
357 int
358 deps_save (struct deps *deps, FILE *f)
359 {
360   unsigned int i;
361
362   /* The cppreader structure contains makefile dependences.  Write out this
363      structure.  */
364
365   /* The number of dependences.  */
366   if (fwrite (&deps->ndeps, sizeof (deps->ndeps), 1, f) != 1)
367       return -1;
368   /* The length of each dependence followed by the string.  */
369   for (i = 0; i < deps->ndeps; i++)
370     {
371       size_t num_to_write = strlen (deps->depv[i]);
372       if (fwrite (&num_to_write, sizeof (size_t), 1, f) != 1)
373           return -1;
374       if (fwrite (deps->depv[i], num_to_write, 1, f) != 1)
375           return -1;
376     }
377
378   return 0;
379 }
380
381 /* Read back dependency information written with deps_save into
382    the deps buffer.  The third argument may be NULL, in which case
383    the dependency information is just skipped, or it may be a filename,
384    in which case that filename is skipped.  */
385
386 int
387 deps_restore (struct deps *deps, FILE *fd, const char *self)
388 {
389   unsigned int i, count;
390   size_t num_to_read;
391   size_t buf_size = 512;
392   char *buf = XNEWVEC (char, buf_size);
393
394   /* Number of dependences.  */
395   if (fread (&count, 1, sizeof (count), fd) != sizeof (count))
396     return -1;
397
398   /* The length of each dependence string, followed by the string.  */
399   for (i = 0; i < count; i++)
400     {
401       /* Read in # bytes in string.  */
402       if (fread (&num_to_read, 1, sizeof (size_t), fd) != sizeof (size_t))
403         return -1;
404       if (buf_size < num_to_read + 1)
405         {
406           buf_size = num_to_read + 1 + 127;
407           buf = XRESIZEVEC (char, buf, buf_size);
408         }
409       if (fread (buf, 1, num_to_read, fd) != num_to_read)
410         return -1;
411       buf[num_to_read] = '\0';
412
413       /* Generate makefile dependencies from .pch if -nopch-deps.  */
414       if (self != NULL && strcmp (buf, self) != 0)
415         deps_add_dep (deps, buf);
416     }
417
418   free (buf);
419   return 0;
420 }