OSDN Git Service

* gnu/java/net/natPlainSocketImplPosix.cc (bind): Remove check for
[pf3gnuchains/gcc-fork.git] / libcpp / mkdeps.c
1 /* Dependency generator for Makefile fragments.
2    Copyright (C) 2000, 2001, 2003, 2007 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 (colmax && column > colmax)
302         {
303           fputs (" \\\n ", fp);
304           column = 1 + size;
305         }
306       if (i)
307         {
308           putc (' ', fp);
309           column++;
310         }
311       fputs (d->targetv[i], fp);
312     }
313
314   putc (':', fp);
315   putc (' ', fp);
316   column += 2;
317
318   for (i = 0; i < d->ndeps; i++)
319     {
320       size = strlen (d->depv[i]);
321       column += size;
322       if (colmax && column > colmax)
323         {
324           fputs (" \\\n ", fp);
325           column = 1 + size;
326         }
327       if (i)
328         {
329           putc (' ', fp);
330           column++;
331         }
332       fputs (d->depv[i], fp);
333     }
334   putc ('\n', fp);
335 }
336
337 void
338 deps_phony_targets (const struct deps *d, FILE *fp)
339 {
340   unsigned int i;
341
342   for (i = 1; i < d->ndeps; i++)
343     {
344       putc ('\n', fp);
345       fputs (d->depv[i], fp);
346       putc (':', fp);
347       putc ('\n', fp);
348     }
349 }
350
351 /* Write out a deps buffer to a file, in a form that can be read back
352    with deps_restore.  Returns nonzero on error, in which case the
353    error number will be in errno.  */
354
355 int
356 deps_save (struct deps *deps, FILE *f)
357 {
358   unsigned int i;
359
360   /* The cppreader structure contains makefile dependences.  Write out this
361      structure.  */
362
363   /* The number of dependences.  */
364   if (fwrite (&deps->ndeps, sizeof (deps->ndeps), 1, f) != 1)
365       return -1;
366   /* The length of each dependence followed by the string.  */
367   for (i = 0; i < deps->ndeps; i++)
368     {
369       size_t num_to_write = strlen (deps->depv[i]);
370       if (fwrite (&num_to_write, sizeof (size_t), 1, f) != 1)
371           return -1;
372       if (fwrite (deps->depv[i], num_to_write, 1, f) != 1)
373           return -1;
374     }
375
376   return 0;
377 }
378
379 /* Read back dependency information written with deps_save into
380    the deps buffer.  The third argument may be NULL, in which case
381    the dependency information is just skipped, or it may be a filename,
382    in which case that filename is skipped.  */
383
384 int
385 deps_restore (struct deps *deps, FILE *fd, const char *self)
386 {
387   unsigned int i, count;
388   size_t num_to_read;
389   size_t buf_size = 512;
390   char *buf = XNEWVEC (char, buf_size);
391
392   /* Number of dependences.  */
393   if (fread (&count, 1, sizeof (count), fd) != sizeof (count))
394     return -1;
395
396   /* The length of each dependence string, followed by the string.  */
397   for (i = 0; i < count; i++)
398     {
399       /* Read in # bytes in string.  */
400       if (fread (&num_to_read, 1, sizeof (size_t), fd) != sizeof (size_t))
401         return -1;
402       if (buf_size < num_to_read + 1)
403         {
404           buf_size = num_to_read + 1 + 127;
405           buf = XRESIZEVEC (char, buf, buf_size);
406         }
407       if (fread (buf, 1, num_to_read, fd) != num_to_read)
408         return -1;
409       buf[num_to_read] = '\0';
410
411       /* Generate makefile dependencies from .pch if -nopch-deps.  */
412       if (self != NULL && strcmp (buf, self) != 0)
413         deps_add_dep (deps, buf);
414     }
415
416   free (buf);
417   return 0;
418 }