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