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