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