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