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