Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 1 | /* Dependency generator for Makefile fragments. |
Richard Sandiford | 500f3ed | 2013-01-14 18:13:59 +0000 | [diff] [blame] | 2 | Copyright (C) 2000-2013 Free Software Foundation, Inc. |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 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 |
Jakub Jelinek | 748086b | 2009-04-09 17:00:19 +0200 | [diff] [blame] | 7 | Free Software Foundation; either version 3, or (at your option) any |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 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 |
Jakub Jelinek | 748086b | 2009-04-09 17:00:19 +0200 | [diff] [blame] | 16 | along with this program; see the file COPYING3. If not see |
| 17 | <http://www.gnu.org/licenses/>. |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 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 | |
Neil Booth | 03b9ab4 | 2001-01-04 10:25:55 +0000 | [diff] [blame] | 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; |
Zack Weinberg | c6e8380 | 2004-06-05 20:58:06 +0000 | [diff] [blame] | 38 | |
| 39 | const char **vpathv; |
| 40 | size_t *vpathlv; |
| 41 | unsigned int nvpaths; |
| 42 | unsigned int vpaths_size; |
Neil Booth | 03b9ab4 | 2001-01-04 10:25:55 +0000 | [diff] [blame] | 43 | }; |
| 44 | |
Andreas Jaeger | 0c20a65 | 2003-07-06 11:56:09 +0200 | [diff] [blame] | 45 | static const char *munge (const char *); |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 46 | |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 47 | /* Given a filename, quote characters in that filename which are |
| 48 | significant to Make. Note that it's not possible to quote all such |
| 49 | characters - e.g. \n, %, *, ?, [, \ (in some contexts), and ~ are |
| 50 | not properly handled. It isn't possible to get this right in any |
| 51 | current version of Make. (??? Still true? Old comment referred to |
| 52 | 3.76.1.) */ |
Andreas Jaeger | 0c20a65 | 2003-07-06 11:56:09 +0200 | [diff] [blame] | 53 | |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 54 | static const char * |
Andreas Jaeger | 0c20a65 | 2003-07-06 11:56:09 +0200 | [diff] [blame] | 55 | munge (const char *filename) |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 56 | { |
| 57 | int len; |
| 58 | const char *p, *q; |
| 59 | char *dst, *buffer; |
| 60 | |
| 61 | for (p = filename, len = 0; *p; p++, len++) |
| 62 | { |
| 63 | switch (*p) |
| 64 | { |
| 65 | case ' ': |
| 66 | case '\t': |
| 67 | /* GNU make uses a weird quoting scheme for white space. |
| 68 | A space or tab preceded by 2N+1 backslashes represents |
| 69 | N backslashes followed by space; a space or tab |
| 70 | preceded by 2N backslashes represents N backslashes at |
| 71 | the end of a file name; and backslashes in other |
| 72 | contexts should not be doubled. */ |
Zack Weinberg | e23c0ba | 2000-03-07 23:11:06 +0000 | [diff] [blame] | 73 | for (q = p - 1; filename <= q && *q == '\\'; q--) |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 74 | len++; |
| 75 | len++; |
| 76 | break; |
| 77 | |
| 78 | case '$': |
Neil Booth | a5a4ce3 | 2001-01-05 07:50:24 +0000 | [diff] [blame] | 79 | /* '$' is quoted by doubling it. */ |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 80 | len++; |
| 81 | break; |
Markus Milleder | 830465c | 2008-03-06 19:08:40 +0100 | [diff] [blame] | 82 | |
| 83 | case '#': |
| 84 | /* '#' is quoted with a backslash. */ |
| 85 | len++; |
| 86 | break; |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 87 | } |
| 88 | } |
| 89 | |
| 90 | /* Now we know how big to make the buffer. */ |
Gabriel Dos Reis | c3f829c | 2005-05-28 15:52:48 +0000 | [diff] [blame] | 91 | buffer = XNEWVEC (char, len + 1); |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 92 | |
| 93 | for (p = filename, dst = buffer; *p; p++, dst++) |
| 94 | { |
| 95 | switch (*p) |
| 96 | { |
| 97 | case ' ': |
| 98 | case '\t': |
Zack Weinberg | e23c0ba | 2000-03-07 23:11:06 +0000 | [diff] [blame] | 99 | for (q = p - 1; filename <= q && *q == '\\'; q--) |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 100 | *dst++ = '\\'; |
| 101 | *dst++ = '\\'; |
| 102 | break; |
| 103 | |
| 104 | case '$': |
| 105 | *dst++ = '$'; |
| 106 | break; |
| 107 | |
Markus Milleder | 830465c | 2008-03-06 19:08:40 +0100 | [diff] [blame] | 108 | case '#': |
| 109 | *dst++ = '\\'; |
| 110 | break; |
| 111 | |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 112 | default: |
| 113 | /* nothing */; |
| 114 | } |
| 115 | *dst = *p; |
| 116 | } |
| 117 | |
| 118 | *dst = '\0'; |
| 119 | return buffer; |
| 120 | } |
| 121 | |
Zack Weinberg | c6e8380 | 2004-06-05 20:58:06 +0000 | [diff] [blame] | 122 | /* If T begins with any of the partial pathnames listed in d->vpathv, |
| 123 | then advance T to point beyond that pathname. */ |
| 124 | static const char * |
| 125 | apply_vpath (struct deps *d, const char *t) |
| 126 | { |
| 127 | if (d->vpathv) |
| 128 | { |
| 129 | unsigned int i; |
| 130 | for (i = 0; i < d->nvpaths; i++) |
| 131 | { |
Kai Tietz | 4489800 | 2011-03-25 20:11:26 +0100 | [diff] [blame] | 132 | if (!filename_ncmp (d->vpathv[i], t, d->vpathlv[i])) |
Zack Weinberg | c6e8380 | 2004-06-05 20:58:06 +0000 | [diff] [blame] | 133 | { |
| 134 | const char *p = t + d->vpathlv[i]; |
| 135 | if (!IS_DIR_SEPARATOR (*p)) |
| 136 | goto not_this_one; |
| 137 | |
| 138 | /* Do not simplify $(vpath)/../whatever. ??? Might not |
| 139 | be necessary. */ |
| 140 | if (p[1] == '.' && p[2] == '.' && IS_DIR_SEPARATOR (p[3])) |
| 141 | goto not_this_one; |
| 142 | |
| 143 | /* found a match */ |
| 144 | t = t + d->vpathlv[i] + 1; |
| 145 | break; |
| 146 | } |
| 147 | not_this_one:; |
| 148 | } |
| 149 | } |
| 150 | |
| 151 | /* Remove leading ./ in any case. */ |
| 152 | while (t[0] == '.' && IS_DIR_SEPARATOR (t[1])) |
Tom Tromey | 67e6443 | 2007-01-30 15:50:00 +0000 | [diff] [blame] | 153 | { |
| 154 | t += 2; |
| 155 | /* If we removed a leading ./, then also remove any /s after the |
| 156 | first. */ |
| 157 | while (IS_DIR_SEPARATOR (t[0])) |
| 158 | ++t; |
| 159 | } |
Zack Weinberg | c6e8380 | 2004-06-05 20:58:06 +0000 | [diff] [blame] | 160 | |
| 161 | return t; |
| 162 | } |
| 163 | |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 164 | /* Public routines. */ |
| 165 | |
| 166 | struct deps * |
Andreas Jaeger | 0c20a65 | 2003-07-06 11:56:09 +0200 | [diff] [blame] | 167 | deps_init (void) |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 168 | { |
Gabriel Dos Reis | c3f829c | 2005-05-28 15:52:48 +0000 | [diff] [blame] | 169 | return XCNEW (struct deps); |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 170 | } |
| 171 | |
| 172 | void |
Andreas Jaeger | 0c20a65 | 2003-07-06 11:56:09 +0200 | [diff] [blame] | 173 | deps_free (struct deps *d) |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 174 | { |
| 175 | unsigned int i; |
Richard Kenner | 05bccae | 2000-03-07 11:41:32 +0000 | [diff] [blame] | 176 | |
Neil Booth | f7114e1 | 2001-01-06 00:15:29 +0000 | [diff] [blame] | 177 | if (d->targetv) |
| 178 | { |
| 179 | for (i = 0; i < d->ntargets; i++) |
Kaveh R. Ghazi | fad205f | 2003-06-16 21:41:10 +0000 | [diff] [blame] | 180 | free ((void *) d->targetv[i]); |
Neil Booth | f7114e1 | 2001-01-06 00:15:29 +0000 | [diff] [blame] | 181 | free (d->targetv); |
| 182 | } |
Richard Kenner | 05bccae | 2000-03-07 11:41:32 +0000 | [diff] [blame] | 183 | |
Neil Booth | f7114e1 | 2001-01-06 00:15:29 +0000 | [diff] [blame] | 184 | if (d->depv) |
| 185 | { |
| 186 | for (i = 0; i < d->ndeps; i++) |
Kaveh R. Ghazi | fad205f | 2003-06-16 21:41:10 +0000 | [diff] [blame] | 187 | free ((void *) d->depv[i]); |
Neil Booth | f7114e1 | 2001-01-06 00:15:29 +0000 | [diff] [blame] | 188 | free (d->depv); |
| 189 | } |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 190 | |
Zack Weinberg | c6e8380 | 2004-06-05 20:58:06 +0000 | [diff] [blame] | 191 | if (d->vpathv) |
| 192 | { |
| 193 | for (i = 0; i < d->nvpaths; i++) |
| 194 | free ((void *) d->vpathv[i]); |
| 195 | free (d->vpathv); |
| 196 | free (d->vpathlv); |
| 197 | } |
| 198 | |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 199 | free (d); |
| 200 | } |
| 201 | |
Neil Booth | a5a4ce3 | 2001-01-05 07:50:24 +0000 | [diff] [blame] | 202 | /* Adds a target T. We make a copy, so it need not be a permanent |
| 203 | string. QUOTE is true if the string should be quoted. */ |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 204 | void |
Andreas Jaeger | 0c20a65 | 2003-07-06 11:56:09 +0200 | [diff] [blame] | 205 | deps_add_target (struct deps *d, const char *t, int quote) |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 206 | { |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 207 | if (d->ntargets == d->targets_size) |
| 208 | { |
Neil Booth | f7114e1 | 2001-01-06 00:15:29 +0000 | [diff] [blame] | 209 | d->targets_size = d->targets_size * 2 + 4; |
Gabriel Dos Reis | c3f829c | 2005-05-28 15:52:48 +0000 | [diff] [blame] | 210 | d->targetv = XRESIZEVEC (const char *, d->targetv, d->targets_size); |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 211 | } |
Richard Kenner | 05bccae | 2000-03-07 11:41:32 +0000 | [diff] [blame] | 212 | |
Zack Weinberg | c6e8380 | 2004-06-05 20:58:06 +0000 | [diff] [blame] | 213 | t = apply_vpath (d, t); |
Neil Booth | a5a4ce3 | 2001-01-05 07:50:24 +0000 | [diff] [blame] | 214 | if (quote) |
| 215 | t = munge (t); /* Also makes permanent copy. */ |
| 216 | else |
| 217 | t = xstrdup (t); |
| 218 | |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 219 | d->targetv[d->ntargets++] = t; |
| 220 | } |
| 221 | |
Neil Booth | 03b9ab4 | 2001-01-04 10:25:55 +0000 | [diff] [blame] | 222 | /* Sets the default target if none has been given already. An empty |
Neil Booth | a5a4ce3 | 2001-01-05 07:50:24 +0000 | [diff] [blame] | 223 | string as the default target in interpreted as stdin. The string |
| 224 | is quoted for MAKE. */ |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 225 | void |
Andreas Jaeger | 0c20a65 | 2003-07-06 11:56:09 +0200 | [diff] [blame] | 226 | deps_add_default_target (struct deps *d, const char *tgt) |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 227 | { |
Neil Booth | 03b9ab4 | 2001-01-04 10:25:55 +0000 | [diff] [blame] | 228 | /* Only if we have no targets. */ |
| 229 | if (d->ntargets) |
| 230 | return; |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 231 | |
Neil Booth | 03b9ab4 | 2001-01-04 10:25:55 +0000 | [diff] [blame] | 232 | if (tgt[0] == '\0') |
Neil Booth | a5a4ce3 | 2001-01-05 07:50:24 +0000 | [diff] [blame] | 233 | deps_add_target (d, "-", 1); |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 234 | else |
Neil Booth | 03b9ab4 | 2001-01-04 10:25:55 +0000 | [diff] [blame] | 235 | { |
DJ Delorie | 45936a8 | 2001-04-19 16:28:05 -0400 | [diff] [blame] | 236 | #ifndef TARGET_OBJECT_SUFFIX |
| 237 | # define TARGET_OBJECT_SUFFIX ".o" |
Neil Booth | 03b9ab4 | 2001-01-04 10:25:55 +0000 | [diff] [blame] | 238 | #endif |
Andrew Cagney | 0821bff | 2001-08-03 15:42:25 +0000 | [diff] [blame] | 239 | const char *start = lbasename (tgt); |
Gabriel Dos Reis | c3f829c | 2005-05-28 15:52:48 +0000 | [diff] [blame] | 240 | char *o = (char *) alloca (strlen (start) |
| 241 | + strlen (TARGET_OBJECT_SUFFIX) + 1); |
Nathan Sidwell | 48ce6bb | 2001-02-12 14:06:22 +0000 | [diff] [blame] | 242 | char *suffix; |
Neil Booth | 03b9ab4 | 2001-01-04 10:25:55 +0000 | [diff] [blame] | 243 | |
Nathan Sidwell | 48ce6bb | 2001-02-12 14:06:22 +0000 | [diff] [blame] | 244 | strcpy (o, start); |
Andreas Jaeger | 0c20a65 | 2003-07-06 11:56:09 +0200 | [diff] [blame] | 245 | |
Nathan Sidwell | 48ce6bb | 2001-02-12 14:06:22 +0000 | [diff] [blame] | 246 | suffix = strrchr (o, '.'); |
| 247 | if (!suffix) |
| 248 | suffix = o + strlen (o); |
DJ Delorie | 45936a8 | 2001-04-19 16:28:05 -0400 | [diff] [blame] | 249 | strcpy (suffix, TARGET_OBJECT_SUFFIX); |
Andreas Jaeger | 0c20a65 | 2003-07-06 11:56:09 +0200 | [diff] [blame] | 250 | |
Neil Booth | a5a4ce3 | 2001-01-05 07:50:24 +0000 | [diff] [blame] | 251 | deps_add_target (d, o, 1); |
Neil Booth | 03b9ab4 | 2001-01-04 10:25:55 +0000 | [diff] [blame] | 252 | } |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 253 | } |
| 254 | |
| 255 | void |
Andreas Jaeger | 0c20a65 | 2003-07-06 11:56:09 +0200 | [diff] [blame] | 256 | deps_add_dep (struct deps *d, const char *t) |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 257 | { |
Zack Weinberg | c6e8380 | 2004-06-05 20:58:06 +0000 | [diff] [blame] | 258 | t = munge (apply_vpath (d, t)); /* Also makes permanent copy. */ |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 259 | |
| 260 | if (d->ndeps == d->deps_size) |
| 261 | { |
Neil Booth | fa6f74f | 2001-01-06 11:08:49 +0000 | [diff] [blame] | 262 | d->deps_size = d->deps_size * 2 + 8; |
Gabriel Dos Reis | c3f829c | 2005-05-28 15:52:48 +0000 | [diff] [blame] | 263 | d->depv = XRESIZEVEC (const char *, d->depv, d->deps_size); |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 264 | } |
| 265 | d->depv[d->ndeps++] = t; |
| 266 | } |
| 267 | |
| 268 | void |
Zack Weinberg | c6e8380 | 2004-06-05 20:58:06 +0000 | [diff] [blame] | 269 | deps_add_vpath (struct deps *d, const char *vpath) |
| 270 | { |
| 271 | const char *elem, *p; |
| 272 | char *copy; |
| 273 | size_t len; |
| 274 | |
| 275 | for (elem = vpath; *elem; elem = p) |
| 276 | { |
| 277 | for (p = elem; *p && *p != ':'; p++); |
| 278 | len = p - elem; |
Gabriel Dos Reis | c3f829c | 2005-05-28 15:52:48 +0000 | [diff] [blame] | 279 | copy = XNEWVEC (char, len + 1); |
Zack Weinberg | c6e8380 | 2004-06-05 20:58:06 +0000 | [diff] [blame] | 280 | memcpy (copy, elem, len); |
| 281 | copy[len] = '\0'; |
| 282 | if (*p == ':') |
| 283 | p++; |
| 284 | |
| 285 | if (d->nvpaths == d->vpaths_size) |
| 286 | { |
| 287 | d->vpaths_size = d->vpaths_size * 2 + 8; |
Gabriel Dos Reis | c3f829c | 2005-05-28 15:52:48 +0000 | [diff] [blame] | 288 | d->vpathv = XRESIZEVEC (const char *, d->vpathv, d->vpaths_size); |
| 289 | d->vpathlv = XRESIZEVEC (size_t, d->vpathlv, d->vpaths_size); |
Zack Weinberg | c6e8380 | 2004-06-05 20:58:06 +0000 | [diff] [blame] | 290 | } |
| 291 | d->vpathv[d->nvpaths] = copy; |
| 292 | d->vpathlv[d->nvpaths] = len; |
| 293 | d->nvpaths++; |
| 294 | } |
| 295 | } |
| 296 | |
| 297 | void |
Andreas Jaeger | 0c20a65 | 2003-07-06 11:56:09 +0200 | [diff] [blame] | 298 | deps_write (const struct deps *d, FILE *fp, unsigned int colmax) |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 299 | { |
| 300 | unsigned int size, i, column; |
| 301 | |
| 302 | column = 0; |
| 303 | if (colmax && colmax < 34) |
| 304 | colmax = 34; |
| 305 | |
| 306 | for (i = 0; i < d->ntargets; i++) |
| 307 | { |
| 308 | size = strlen (d->targetv[i]); |
| 309 | column += size; |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 310 | if (i) |
| 311 | { |
Ralf Wildenhues | d482a07 | 2008-02-27 21:42:23 +0000 | [diff] [blame] | 312 | if (colmax && column > colmax) |
| 313 | { |
| 314 | fputs (" \\\n ", fp); |
| 315 | column = 1 + size; |
| 316 | } |
| 317 | else |
| 318 | { |
| 319 | putc (' ', fp); |
| 320 | column++; |
| 321 | } |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 322 | } |
| 323 | fputs (d->targetv[i], fp); |
| 324 | } |
| 325 | |
| 326 | putc (':', fp); |
Ralf Wildenhues | d482a07 | 2008-02-27 21:42:23 +0000 | [diff] [blame] | 327 | column++; |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 328 | |
| 329 | for (i = 0; i < d->ndeps; i++) |
| 330 | { |
| 331 | size = strlen (d->depv[i]); |
| 332 | column += size; |
| 333 | if (colmax && column > colmax) |
| 334 | { |
| 335 | fputs (" \\\n ", fp); |
| 336 | column = 1 + size; |
| 337 | } |
Ralf Wildenhues | d482a07 | 2008-02-27 21:42:23 +0000 | [diff] [blame] | 338 | else |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 339 | { |
| 340 | putc (' ', fp); |
| 341 | column++; |
| 342 | } |
| 343 | fputs (d->depv[i], fp); |
| 344 | } |
| 345 | putc ('\n', fp); |
| 346 | } |
Andreas Jaeger | 0c20a65 | 2003-07-06 11:56:09 +0200 | [diff] [blame] | 347 | |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 348 | void |
Andreas Jaeger | 0c20a65 | 2003-07-06 11:56:09 +0200 | [diff] [blame] | 349 | deps_phony_targets (const struct deps *d, FILE *fp) |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 350 | { |
Richard Kenner | 05bccae | 2000-03-07 11:41:32 +0000 | [diff] [blame] | 351 | unsigned int i; |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 352 | |
| 353 | for (i = 1; i < d->ndeps; i++) |
| 354 | { |
Neil Booth | a5a4ce3 | 2001-01-05 07:50:24 +0000 | [diff] [blame] | 355 | putc ('\n', fp); |
Zack Weinberg | 49e6c08 | 2000-03-04 19:42:04 +0000 | [diff] [blame] | 356 | fputs (d->depv[i], fp); |
| 357 | putc (':', fp); |
| 358 | putc ('\n', fp); |
| 359 | } |
| 360 | } |
Geoffrey Keating | 17211ab | 2003-01-10 02:22:34 +0000 | [diff] [blame] | 361 | |
| 362 | /* Write out a deps buffer to a file, in a form that can be read back |
| 363 | with deps_restore. Returns nonzero on error, in which case the |
| 364 | error number will be in errno. */ |
| 365 | |
| 366 | int |
Andreas Jaeger | 0c20a65 | 2003-07-06 11:56:09 +0200 | [diff] [blame] | 367 | deps_save (struct deps *deps, FILE *f) |
Geoffrey Keating | 17211ab | 2003-01-10 02:22:34 +0000 | [diff] [blame] | 368 | { |
| 369 | unsigned int i; |
| 370 | |
| 371 | /* The cppreader structure contains makefile dependences. Write out this |
| 372 | structure. */ |
| 373 | |
| 374 | /* The number of dependences. */ |
| 375 | if (fwrite (&deps->ndeps, sizeof (deps->ndeps), 1, f) != 1) |
| 376 | return -1; |
| 377 | /* The length of each dependence followed by the string. */ |
| 378 | for (i = 0; i < deps->ndeps; i++) |
| 379 | { |
| 380 | size_t num_to_write = strlen (deps->depv[i]); |
| 381 | if (fwrite (&num_to_write, sizeof (size_t), 1, f) != 1) |
| 382 | return -1; |
| 383 | if (fwrite (deps->depv[i], num_to_write, 1, f) != 1) |
| 384 | return -1; |
| 385 | } |
| 386 | |
| 387 | return 0; |
| 388 | } |
| 389 | |
| 390 | /* Read back dependency information written with deps_save into |
| 391 | the deps buffer. The third argument may be NULL, in which case |
| 392 | the dependency information is just skipped, or it may be a filename, |
| 393 | in which case that filename is skipped. */ |
| 394 | |
| 395 | int |
Andreas Jaeger | 0c20a65 | 2003-07-06 11:56:09 +0200 | [diff] [blame] | 396 | deps_restore (struct deps *deps, FILE *fd, const char *self) |
Geoffrey Keating | 17211ab | 2003-01-10 02:22:34 +0000 | [diff] [blame] | 397 | { |
| 398 | unsigned int i, count; |
| 399 | size_t num_to_read; |
| 400 | size_t buf_size = 512; |
Tobias Burnus | 55e7f90 | 2012-10-15 22:08:57 +0200 | [diff] [blame] | 401 | char *buf; |
Geoffrey Keating | 17211ab | 2003-01-10 02:22:34 +0000 | [diff] [blame] | 402 | |
| 403 | /* Number of dependences. */ |
| 404 | if (fread (&count, 1, sizeof (count), fd) != sizeof (count)) |
| 405 | return -1; |
| 406 | |
Tobias Burnus | 55e7f90 | 2012-10-15 22:08:57 +0200 | [diff] [blame] | 407 | buf = XNEWVEC (char, buf_size); |
| 408 | |
Geoffrey Keating | 17211ab | 2003-01-10 02:22:34 +0000 | [diff] [blame] | 409 | /* The length of each dependence string, followed by the string. */ |
| 410 | for (i = 0; i < count; i++) |
| 411 | { |
| 412 | /* Read in # bytes in string. */ |
| 413 | if (fread (&num_to_read, 1, sizeof (size_t), fd) != sizeof (size_t)) |
Tobias Burnus | 55e7f90 | 2012-10-15 22:08:57 +0200 | [diff] [blame] | 414 | { |
| 415 | free (buf); |
| 416 | return -1; |
| 417 | } |
Geoffrey Keating | 17211ab | 2003-01-10 02:22:34 +0000 | [diff] [blame] | 418 | if (buf_size < num_to_read + 1) |
| 419 | { |
| 420 | buf_size = num_to_read + 1 + 127; |
Gabriel Dos Reis | c3f829c | 2005-05-28 15:52:48 +0000 | [diff] [blame] | 421 | buf = XRESIZEVEC (char, buf, buf_size); |
Geoffrey Keating | 17211ab | 2003-01-10 02:22:34 +0000 | [diff] [blame] | 422 | } |
| 423 | if (fread (buf, 1, num_to_read, fd) != num_to_read) |
Tobias Burnus | 55e7f90 | 2012-10-15 22:08:57 +0200 | [diff] [blame] | 424 | { |
| 425 | free (buf); |
| 426 | return -1; |
| 427 | } |
Geoffrey Keating | 17211ab | 2003-01-10 02:22:34 +0000 | [diff] [blame] | 428 | buf[num_to_read] = '\0'; |
| 429 | |
Andreas Jaeger | 0c20a65 | 2003-07-06 11:56:09 +0200 | [diff] [blame] | 430 | /* Generate makefile dependencies from .pch if -nopch-deps. */ |
Kai Tietz | 4489800 | 2011-03-25 20:11:26 +0100 | [diff] [blame] | 431 | if (self != NULL && filename_cmp (buf, self) != 0) |
Geoffrey Keating | 17211ab | 2003-01-10 02:22:34 +0000 | [diff] [blame] | 432 | deps_add_dep (deps, buf); |
| 433 | } |
| 434 | |
| 435 | free (buf); |
| 436 | return 0; |
| 437 | } |