* SDCPP synchronized with GCC CPP release version 4.1.1,
[fw/sdcc] / support / cpp2 / libcpp / mkdeps.c
1 /* Dependency generator for Makefile fragments.
2    Copyright (C) 2000, 2001, 2003 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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
41 static const char *munge (const char *);
42
43 /* Given a filename, quote characters in that filename which are
44    significant to Make.  Note that it's not possible to quote all such
45    characters - e.g. \n, %, *, ?, [, \ (in some contexts), and ~ are
46    not properly handled.  It isn't possible to get this right in any
47    current version of Make.  (??? Still true?  Old comment referred to
48    3.76.1.)  */
49
50 static const char *
51 munge (const char *filename)
52 {
53   int len;
54   const char *p, *q;
55   char *dst, *buffer;
56
57   for (p = filename, len = 0; *p; p++, len++)
58     {
59       switch (*p)
60         {
61         case ' ':
62         case '\t':
63           /* GNU make uses a weird quoting scheme for white space.
64              A space or tab preceded by 2N+1 backslashes represents
65              N backslashes followed by space; a space or tab
66              preceded by 2N backslashes represents N backslashes at
67              the end of a file name; and backslashes in other
68              contexts should not be doubled.  */
69           for (q = p - 1; filename <= q && *q == '\\';  q--)
70             len++;
71           len++;
72           break;
73
74         case '$':
75           /* '$' is quoted by doubling it.  */
76           len++;
77           break;
78         }
79     }
80
81   /* Now we know how big to make the buffer.  */
82   buffer = xmalloc (len + 1);
83
84   for (p = filename, dst = buffer; *p; p++, dst++)
85     {
86       switch (*p)
87         {
88         case ' ':
89         case '\t':
90           for (q = p - 1; filename <= q && *q == '\\';  q--)
91             *dst++ = '\\';
92           *dst++ = '\\';
93           break;
94
95         case '$':
96           *dst++ = '$';
97           break;
98
99         default:
100           /* nothing */;
101         }
102       *dst = *p;
103     }
104
105   *dst = '\0';
106   return buffer;
107 }
108
109 /* Public routines.  */
110
111 struct deps *
112 deps_init (void)
113 {
114   struct deps *d = xmalloc (sizeof (struct deps));
115
116   /* Allocate space for the vectors only if we need it.  */
117
118   d->targetv = 0;
119   d->depv = 0;
120
121   d->ntargets = 0;
122   d->targets_size = 0;
123   d->ndeps = 0;
124   d->deps_size = 0;
125
126   return d;
127 }
128
129 void
130 deps_free (struct deps *d)
131 {
132   unsigned int i;
133
134   if (d->targetv)
135     {
136       for (i = 0; i < d->ntargets; i++)
137         free ((void *) d->targetv[i]);
138       free (d->targetv);
139     }
140
141   if (d->depv)
142     {
143       for (i = 0; i < d->ndeps; i++)
144         free ((void *) d->depv[i]);
145       free (d->depv);
146     }
147
148   free (d);
149 }
150
151 /* Adds a target T.  We make a copy, so it need not be a permanent
152    string.  QUOTE is true if the string should be quoted.  */
153 void
154 deps_add_target (struct deps *d, const char *t, int quote)
155 {
156   if (d->ntargets == d->targets_size)
157     {
158       d->targets_size = d->targets_size * 2 + 4;
159       d->targetv = xrealloc (d->targetv,
160                              d->targets_size * sizeof (const char *));
161     }
162
163   if (quote)
164     t = munge (t);  /* Also makes permanent copy.  */
165   else
166     t = xstrdup (t);
167
168   d->targetv[d->ntargets++] = t;
169 }
170
171 /* Sets the default target if none has been given already.  An empty
172    string as the default target in interpreted as stdin.  The string
173    is quoted for MAKE.  */
174 void
175 deps_add_default_target (cpp_reader *pfile, const char *tgt)
176 {
177   struct deps *d = pfile->deps;
178
179   /* Only if we have no targets.  */
180   if (d->ntargets)
181     return;
182
183   if (tgt[0] == '\0')
184     deps_add_target (d, "-", 1);
185   else
186     {
187 #ifndef TARGET_OBJECT_SUFFIX
188 # define TARGET_OBJECT_SUFFIX ".o"
189 #endif
190       const char *start = lbasename (tgt);
191       char *o;
192       char *suffix;
193       const char *obj_ext;
194
195       if (NULL == CPP_OPTION (pfile, obj_ext))
196         obj_ext = TARGET_OBJECT_SUFFIX;
197       else if (CPP_OPTION (pfile, obj_ext)[0] != '.')
198         {
199           char *t = alloca (strlen (CPP_OPTION (pfile, obj_ext)) + 2);
200           t[0] = '.';
201           strcpy (&t[1], CPP_OPTION (pfile, obj_ext));
202           obj_ext = t;
203         }
204       else
205         obj_ext = CPP_OPTION (pfile, obj_ext);
206
207       o = (char *) alloca (strlen (start) + strlen (obj_ext) + 1);
208
209       strcpy (o, start);
210
211       suffix = strrchr (o, '.');
212       if (!suffix)
213         suffix = o + strlen (o);
214       strcpy (suffix, obj_ext);
215
216       deps_add_target (d, o, 1);
217     }
218 }
219
220 void
221 deps_add_dep (struct deps *d, const char *t)
222 {
223   t = munge (t);  /* Also makes permanent copy.  */
224
225   if (d->ndeps == d->deps_size)
226     {
227       d->deps_size = d->deps_size * 2 + 8;
228       d->depv = xrealloc (d->depv, d->deps_size * sizeof (const char *));
229     }
230   d->depv[d->ndeps++] = t;
231 }
232
233 void
234 deps_write (const struct deps *d, FILE *fp, unsigned int colmax)
235 {
236   unsigned int size, i, column;
237
238   column = 0;
239   if (colmax && colmax < 34)
240     colmax = 34;
241
242   for (i = 0; i < d->ntargets; i++)
243     {
244       size = strlen (d->targetv[i]);
245       column += size;
246       if (colmax && column > colmax)
247         {
248           fputs (" \\\n ", fp);
249           column = 1 + size;
250         }
251       if (i)
252         {
253           putc (' ', fp);
254           column++;
255         }
256       fputs (d->targetv[i], fp);
257     }
258
259   putc (':', fp);
260   putc (' ', fp);
261   column += 2;
262
263   for (i = 0; i < d->ndeps; i++)
264     {
265       size = strlen (d->depv[i]);
266       column += size;
267       if (colmax && column > colmax)
268         {
269           fputs (" \\\n ", fp);
270           column = 1 + size;
271         }
272       if (i)
273         {
274           putc (' ', fp);
275           column++;
276         }
277       fputs (d->depv[i], fp);
278     }
279   putc ('\n', fp);
280 }
281
282 void
283 deps_phony_targets (const struct deps *d, FILE *fp)
284 {
285   unsigned int i;
286
287   for (i = 1; i < d->ndeps; i++)
288     {
289       putc ('\n', fp);
290       fputs (d->depv[i], fp);
291       putc (':', fp);
292       putc ('\n', fp);
293     }
294 }
295
296 /* Write out a deps buffer to a file, in a form that can be read back
297    with deps_restore.  Returns nonzero on error, in which case the
298    error number will be in errno.  */
299
300 int
301 deps_save (struct deps *deps, FILE *f)
302 {
303   unsigned int i;
304
305   /* The cppreader structure contains makefile dependences.  Write out this
306      structure.  */
307
308   /* The number of dependences.  */
309   if (fwrite (&deps->ndeps, sizeof (deps->ndeps), 1, f) != 1)
310       return -1;
311   /* The length of each dependence followed by the string.  */
312   for (i = 0; i < deps->ndeps; i++)
313     {
314       size_t num_to_write = strlen (deps->depv[i]);
315       if (fwrite (&num_to_write, sizeof (size_t), 1, f) != 1)
316           return -1;
317       if (fwrite (deps->depv[i], num_to_write, 1, f) != 1)
318           return -1;
319     }
320
321   return 0;
322 }
323
324 /* Read back dependency information written with deps_save into
325    the deps buffer.  The third argument may be NULL, in which case
326    the dependency information is just skipped, or it may be a filename,
327    in which case that filename is skipped.  */
328
329 int
330 deps_restore (struct deps *deps, FILE *fd, const char *self)
331 {
332   unsigned int i, count;
333   size_t num_to_read;
334   size_t buf_size = 512;
335   char *buf = xmalloc (buf_size);
336
337   /* Number of dependences.  */
338   if (fread (&count, 1, sizeof (count), fd) != sizeof (count))
339     return -1;
340
341   /* The length of each dependence string, followed by the string.  */
342   for (i = 0; i < count; i++)
343     {
344       /* Read in # bytes in string.  */
345       if (fread (&num_to_read, 1, sizeof (size_t), fd) != sizeof (size_t))
346         return -1;
347       if (buf_size < num_to_read + 1)
348         {
349           buf_size = num_to_read + 1 + 127;
350           buf = xrealloc (buf, buf_size);
351         }
352       if (fread (buf, 1, num_to_read, fd) != num_to_read)
353         return -1;
354       buf[num_to_read] = '\0';
355
356       /* Generate makefile dependencies from .pch if -nopch-deps.  */
357       if (self != NULL && strcmp (buf, self) != 0)
358         deps_add_dep (deps, buf);
359     }
360
361   free (buf);
362   return 0;
363 }