Home | History | Annotate | Line # | Download | only in libcpp
      1  1.1  mrg /* Dependency generator for Makefile fragments.
      2  1.1  mrg    Copyright (C) 2000-2022 Free Software Foundation, Inc.
      3  1.1  mrg    Contributed by Zack Weinberg, Mar 2000
      4  1.1  mrg 
      5  1.1  mrg This program is free software; you can redistribute it and/or modify it
      6  1.1  mrg under the terms of the GNU General Public License as published by the
      7  1.1  mrg Free Software Foundation; either version 3, or (at your option) any
      8  1.1  mrg later version.
      9  1.1  mrg 
     10  1.1  mrg This program is distributed in the hope that it will be useful,
     11  1.1  mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  1.1  mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  1.1  mrg GNU General Public License for more details.
     14  1.1  mrg 
     15  1.1  mrg You should have received a copy of the GNU General Public License
     16  1.1  mrg along with this program; see the file COPYING3.  If not see
     17  1.1  mrg <http://www.gnu.org/licenses/>.
     18  1.1  mrg 
     19  1.1  mrg  In other words, you are welcome to use, share and improve this program.
     20  1.1  mrg  You are forbidden to forbid anyone else to use, share and improve
     21  1.1  mrg  what you give them.   Help stamp out software-hoarding!  */
     22  1.1  mrg 
     23  1.1  mrg #include "config.h"
     24  1.1  mrg #include "system.h"
     25  1.1  mrg #include "mkdeps.h"
     26  1.1  mrg #include "internal.h"
     27  1.1  mrg 
     28  1.1  mrg /* Not set up to just include std::vector et al, here's a simple
     29  1.1  mrg    implementation.  */
     30  1.1  mrg 
     31  1.1  mrg /* Keep this structure local to this file, so clients don't find it
     32  1.1  mrg    easy to start making assumptions.  */
     33  1.1  mrg class mkdeps
     34  1.1  mrg {
     35  1.1  mrg public:
     36  1.1  mrg   /* T has trivial cctor & dtor.  */
     37  1.1  mrg   template <typename T>
     38  1.1  mrg   class vec
     39  1.1  mrg   {
     40  1.1  mrg   private:
     41  1.1  mrg     T *ary;
     42  1.1  mrg     unsigned num;
     43  1.1  mrg     unsigned alloc;
     44  1.1  mrg 
     45  1.1  mrg   public:
     46  1.1  mrg     vec ()
     47  1.1  mrg       : ary (NULL), num (0), alloc (0)
     48  1.1  mrg       {}
     49  1.1  mrg     ~vec ()
     50  1.1  mrg       {
     51  1.1  mrg 	XDELETEVEC (ary);
     52  1.1  mrg       }
     53  1.1  mrg 
     54  1.1  mrg   public:
     55  1.1  mrg     unsigned size () const
     56  1.1  mrg     {
     57  1.1  mrg       return num;
     58  1.1  mrg     }
     59  1.1  mrg     const T &operator[] (unsigned ix) const
     60  1.1  mrg     {
     61  1.1  mrg       return ary[ix];
     62  1.1  mrg     }
     63  1.1  mrg     T &operator[] (unsigned ix)
     64  1.1  mrg     {
     65  1.1  mrg       return ary[ix];
     66  1.1  mrg     }
     67  1.1  mrg     void push (const T &elt)
     68  1.1  mrg     {
     69  1.1  mrg       if (num == alloc)
     70  1.1  mrg 	{
     71  1.1  mrg 	  alloc = alloc ? alloc * 2 : 16;
     72  1.1  mrg 	  ary = XRESIZEVEC (T, ary, alloc);
     73  1.1  mrg 	}
     74  1.1  mrg       ary[num++] = elt;
     75  1.1  mrg     }
     76  1.1  mrg   };
     77  1.1  mrg   struct velt
     78  1.1  mrg   {
     79  1.1  mrg     const char *str;
     80  1.1  mrg     size_t len;
     81  1.1  mrg   };
     82  1.1  mrg 
     83  1.1  mrg   mkdeps ()
     84  1.1  mrg     : module_name (NULL), cmi_name (NULL), is_header_unit (false), quote_lwm (0)
     85  1.1  mrg   {
     86  1.1  mrg   }
     87  1.1  mrg   ~mkdeps ()
     88  1.1  mrg   {
     89  1.1  mrg     unsigned int i;
     90  1.1  mrg 
     91  1.1  mrg     for (i = targets.size (); i--;)
     92  1.1  mrg       free (const_cast <char *> (targets[i]));
     93  1.1  mrg     for (i = deps.size (); i--;)
     94  1.1  mrg       free (const_cast <char *> (deps[i]));
     95  1.1  mrg     for (i = vpath.size (); i--;)
     96  1.1  mrg       XDELETEVEC (vpath[i].str);
     97  1.1  mrg     for (i = modules.size (); i--;)
     98  1.1  mrg       XDELETEVEC (modules[i]);
     99  1.1  mrg     XDELETEVEC (module_name);
    100  1.1  mrg     free (const_cast <char *> (cmi_name));
    101  1.1  mrg   }
    102  1.1  mrg 
    103  1.1  mrg public:
    104  1.1  mrg   vec<const char *> targets;
    105  1.1  mrg   vec<const char *> deps;
    106  1.1  mrg   vec<velt> vpath;
    107  1.1  mrg   vec<const char *> modules;
    108  1.1  mrg 
    109  1.1  mrg public:
    110  1.1  mrg   const char *module_name;
    111  1.1  mrg   const char *cmi_name;
    112  1.1  mrg   bool is_header_unit;
    113  1.1  mrg   unsigned short quote_lwm;
    114  1.1  mrg };
    115  1.1  mrg 
    116  1.1  mrg /* Apply Make quoting to STR, TRAIL.  Note that it's not possible to
    117  1.1  mrg    quote all such characters - e.g. \n, %, *, ?, [, \ (in some
    118  1.1  mrg    contexts), and ~ are not properly handled.  It isn't possible to
    119  1.1  mrg    get this right in any current version of Make.  (??? Still true?
    120  1.1  mrg    Old comment referred to 3.76.1.)  */
    121  1.1  mrg 
    122  1.1  mrg static const char *
    123  1.1  mrg munge (const char *str, const char *trail = nullptr)
    124  1.1  mrg {
    125  1.1  mrg   static unsigned alloc;
    126  1.1  mrg   static char *buf;
    127  1.1  mrg   unsigned dst = 0;
    128  1.1  mrg 
    129  1.1  mrg   for (; str; str = trail, trail = nullptr)
    130  1.1  mrg     {
    131  1.1  mrg       unsigned slashes = 0;
    132  1.1  mrg       char c;
    133  1.1  mrg       for (const char *probe = str; (c = *probe++);)
    134  1.1  mrg 	{
    135  1.1  mrg 	  if (alloc < dst + 4 + slashes)
    136  1.1  mrg 	    {
    137  1.1  mrg 	      alloc = alloc * 2 + 32;
    138  1.1  mrg 	      buf = XRESIZEVEC (char, buf, alloc);
    139  1.1  mrg 	    }
    140  1.1  mrg 
    141  1.1  mrg 	  switch (c)
    142  1.1  mrg 	    {
    143  1.1  mrg 	    case '\\':
    144  1.1  mrg 	      slashes++;
    145  1.1  mrg 	      break;
    146  1.1  mrg 
    147  1.1  mrg 	    case '$':
    148  1.1  mrg 	      buf[dst++] = '$';
    149  1.1  mrg 	      goto def;
    150  1.1  mrg 
    151  1.1  mrg 	    case ' ':
    152  1.1  mrg 	    case '\t':
    153  1.1  mrg 	      /* GNU make uses a weird quoting scheme for white space.
    154  1.1  mrg 		 A space or tab preceded by 2N+1 backslashes
    155  1.1  mrg 		 represents N backslashes followed by space; a space
    156  1.1  mrg 		 or tab preceded by 2N backslashes represents N
    157  1.1  mrg 		 backslashes at the end of a file name; and
    158  1.1  mrg 		 backslashes in other contexts should not be
    159  1.1  mrg 		 doubled.  */
    160  1.1  mrg 	      while (slashes--)
    161  1.1  mrg 		buf[dst++] = '\\';
    162  1.1  mrg 	      /* FALLTHROUGH  */
    163  1.1  mrg 
    164  1.1  mrg 	    case '#':
    165  1.1  mrg 	      buf[dst++] = '\\';
    166  1.1  mrg 	      /* FALLTHROUGH  */
    167  1.1  mrg 
    168  1.1  mrg 	    default:
    169  1.1  mrg 	    def:
    170  1.1  mrg 	      slashes = 0;
    171  1.1  mrg 	      break;
    172  1.1  mrg 	    }
    173  1.1  mrg 
    174  1.1  mrg 	  buf[dst++] = c;
    175  1.1  mrg 	}
    176  1.1  mrg     }
    177  1.1  mrg 
    178  1.1  mrg   buf[dst] = 0;
    179  1.1  mrg   return buf;
    180  1.1  mrg }
    181  1.1  mrg 
    182  1.1  mrg /* If T begins with any of the partial pathnames listed in d->vpathv,
    183  1.1  mrg    then advance T to point beyond that pathname.  */
    184  1.1  mrg static const char *
    185  1.1  mrg apply_vpath (class mkdeps *d, const char *t)
    186  1.1  mrg {
    187  1.1  mrg   if (unsigned len = d->vpath.size ())
    188  1.1  mrg     for (unsigned i = len; i--;)
    189  1.1  mrg       {
    190  1.1  mrg 	if (!filename_ncmp (d->vpath[i].str, t, d->vpath[i].len))
    191  1.1  mrg 	  {
    192  1.1  mrg 	    const char *p = t + d->vpath[i].len;
    193  1.1  mrg 	    if (!IS_DIR_SEPARATOR (*p))
    194  1.1  mrg 	      goto not_this_one;
    195  1.1  mrg 
    196  1.1  mrg 	    /* Do not simplify $(vpath)/../whatever.  ??? Might not
    197  1.1  mrg 	       be necessary. */
    198  1.1  mrg 	    if (p[1] == '.' && p[2] == '.' && IS_DIR_SEPARATOR (p[3]))
    199  1.1  mrg 	      goto not_this_one;
    200  1.1  mrg 
    201  1.1  mrg 	    /* found a match */
    202  1.1  mrg 	    t = t + d->vpath[i].len + 1;
    203  1.1  mrg 	    break;
    204  1.1  mrg 	  }
    205  1.1  mrg       not_this_one:;
    206  1.1  mrg       }
    207  1.1  mrg 
    208  1.1  mrg   /* Remove leading ./ in any case.  */
    209  1.1  mrg   while (t[0] == '.' && IS_DIR_SEPARATOR (t[1]))
    210  1.1  mrg     {
    211  1.1  mrg       t += 2;
    212  1.1  mrg       /* If we removed a leading ./, then also remove any /s after the
    213  1.1  mrg 	 first.  */
    214  1.1  mrg       while (IS_DIR_SEPARATOR (t[0]))
    215  1.1  mrg 	++t;
    216  1.1  mrg     }
    217  1.1  mrg 
    218  1.1  mrg   return t;
    219  1.1  mrg }
    220  1.1  mrg 
    221  1.1  mrg /* Public routines.  */
    222  1.1  mrg 
    223  1.1  mrg class mkdeps *
    224  1.1  mrg deps_init (void)
    225  1.1  mrg {
    226  1.1  mrg   return new mkdeps ();
    227  1.1  mrg }
    228  1.1  mrg 
    229  1.1  mrg void
    230  1.1  mrg deps_free (class mkdeps *d)
    231  1.1  mrg {
    232  1.1  mrg   delete d;
    233  1.1  mrg }
    234  1.1  mrg 
    235  1.1  mrg /* Adds a target T.  We make a copy, so it need not be a permanent
    236  1.1  mrg    string.  QUOTE is true if the string should be quoted.  */
    237  1.1  mrg void
    238  1.1  mrg deps_add_target (class mkdeps *d, const char *t, int quote)
    239  1.1  mrg {
    240  1.1  mrg   t = xstrdup (apply_vpath (d, t));
    241  1.1  mrg 
    242  1.1  mrg   if (!quote)
    243  1.1  mrg     {
    244  1.1  mrg       /* Sometimes unquoted items are added after quoted ones.
    245  1.1  mrg 	 Swap out the lowest quoted.  */
    246  1.1  mrg       if (d->quote_lwm != d->targets.size ())
    247  1.1  mrg 	{
    248  1.1  mrg 	  const char *lowest = d->targets[d->quote_lwm];
    249  1.1  mrg 	  d->targets[d->quote_lwm] = t;
    250  1.1  mrg 	  t = lowest;
    251  1.1  mrg 	}
    252  1.1  mrg       d->quote_lwm++;
    253  1.1  mrg     }
    254  1.1  mrg 
    255  1.1  mrg   d->targets.push (t);
    256  1.1  mrg }
    257  1.1  mrg 
    258  1.1  mrg /* Sets the default target if none has been given already.  An empty
    259  1.1  mrg    string as the default target in interpreted as stdin.  The string
    260  1.1  mrg    is quoted for MAKE.  */
    261  1.1  mrg void
    262  1.1  mrg deps_add_default_target (class mkdeps *d, const char *tgt)
    263  1.1  mrg {
    264  1.1  mrg   /* Only if we have no targets.  */
    265  1.1  mrg   if (d->targets.size ())
    266  1.1  mrg     return;
    267  1.1  mrg 
    268  1.1  mrg   if (tgt[0] == '\0')
    269  1.1  mrg     d->targets.push (xstrdup ("-"));
    270  1.1  mrg   else
    271  1.1  mrg     {
    272  1.1  mrg #ifndef TARGET_OBJECT_SUFFIX
    273  1.1  mrg # define TARGET_OBJECT_SUFFIX ".o"
    274  1.1  mrg #endif
    275  1.1  mrg       const char *start = lbasename (tgt);
    276  1.1  mrg       char *o = (char *) alloca (strlen (start)
    277  1.1  mrg                                  + strlen (TARGET_OBJECT_SUFFIX) + 1);
    278  1.1  mrg       char *suffix;
    279  1.1  mrg 
    280  1.1  mrg       strcpy (o, start);
    281  1.1  mrg 
    282  1.1  mrg       suffix = strrchr (o, '.');
    283  1.1  mrg       if (!suffix)
    284  1.1  mrg         suffix = o + strlen (o);
    285  1.1  mrg       strcpy (suffix, TARGET_OBJECT_SUFFIX);
    286  1.1  mrg 
    287  1.1  mrg       deps_add_target (d, o, 1);
    288  1.1  mrg     }
    289  1.1  mrg }
    290  1.1  mrg 
    291  1.1  mrg void
    292  1.1  mrg deps_add_dep (class mkdeps *d, const char *t)
    293  1.1  mrg {
    294  1.1  mrg   gcc_assert (*t);
    295  1.1  mrg 
    296  1.1  mrg   t = apply_vpath (d, t);
    297  1.1  mrg 
    298  1.1  mrg   d->deps.push (xstrdup (t));
    299  1.1  mrg }
    300  1.1  mrg 
    301  1.1  mrg void
    302  1.1  mrg deps_add_vpath (class mkdeps *d, const char *vpath)
    303  1.1  mrg {
    304  1.1  mrg   const char *elem, *p;
    305  1.1  mrg 
    306  1.1  mrg   for (elem = vpath; *elem; elem = p)
    307  1.1  mrg     {
    308  1.1  mrg       for (p = elem; *p && *p != ':'; p++)
    309  1.1  mrg 	continue;
    310  1.1  mrg       mkdeps::velt elt;
    311  1.1  mrg       elt.len = p - elem;
    312  1.1  mrg       char *str = XNEWVEC (char, elt.len + 1);
    313  1.1  mrg       elt.str = str;
    314  1.1  mrg       memcpy (str, elem, elt.len);
    315  1.1  mrg       str[elt.len] = '\0';
    316  1.1  mrg       if (*p == ':')
    317  1.1  mrg 	p++;
    318  1.1  mrg 
    319  1.1  mrg       d->vpath.push (elt);
    320  1.1  mrg     }
    321  1.1  mrg }
    322  1.1  mrg 
    323  1.1  mrg /* Add a new module target (there can only be one).  M is the module
    324  1.1  mrg    name.   */
    325  1.1  mrg 
    326  1.1  mrg void
    327  1.1  mrg deps_add_module_target (struct mkdeps *d, const char *m,
    328  1.1  mrg 			const char *cmi, bool is_header_unit)
    329  1.1  mrg {
    330  1.1  mrg   gcc_assert (!d->module_name);
    331  1.1  mrg 
    332  1.1  mrg   d->module_name = xstrdup (m);
    333  1.1  mrg   d->is_header_unit = is_header_unit;
    334  1.1  mrg   d->cmi_name = xstrdup (cmi);
    335  1.1  mrg }
    336  1.1  mrg 
    337  1.1  mrg /* Add a new module dependency.  M is the module name.  */
    338  1.1  mrg 
    339  1.1  mrg void
    340  1.1  mrg deps_add_module_dep (struct mkdeps *d, const char *m)
    341  1.1  mrg {
    342  1.1  mrg   d->modules.push (xstrdup (m));
    343  1.1  mrg }
    344  1.1  mrg 
    345  1.1  mrg /* Write NAME, with a leading space to FP, a Makefile.  Advance COL as
    346  1.1  mrg    appropriate, wrap at COLMAX, returning new column number.  Iff
    347  1.1  mrg    QUOTE apply quoting.  Append TRAIL.  */
    348  1.1  mrg 
    349  1.1  mrg static unsigned
    350  1.1  mrg make_write_name (const char *name, FILE *fp, unsigned col, unsigned colmax,
    351  1.1  mrg 		 bool quote = true, const char *trail = NULL)
    352  1.1  mrg {
    353  1.1  mrg   if (quote)
    354  1.1  mrg     name = munge (name, trail);
    355  1.1  mrg   unsigned size = strlen (name);
    356  1.1  mrg 
    357  1.1  mrg   if (col)
    358  1.1  mrg     {
    359  1.1  mrg       if (colmax && col + size> colmax)
    360  1.1  mrg 	{
    361  1.1  mrg 	  fputs (" \\\n", fp);
    362  1.1  mrg 	  col = 0;
    363  1.1  mrg 	}
    364  1.1  mrg       col++;
    365  1.1  mrg       fputs (" ", fp);
    366  1.1  mrg     }
    367  1.1  mrg 
    368  1.1  mrg   col += size;
    369  1.1  mrg   fputs (name, fp);
    370  1.1  mrg 
    371  1.1  mrg   return col;
    372  1.1  mrg }
    373  1.1  mrg 
    374  1.1  mrg /* Write all the names in VEC via make_write_name.  */
    375  1.1  mrg 
    376  1.1  mrg static unsigned
    377  1.1  mrg make_write_vec (const mkdeps::vec<const char *> &vec, FILE *fp,
    378  1.1  mrg 		unsigned col, unsigned colmax, unsigned quote_lwm = 0,
    379  1.1  mrg 		const char *trail = NULL)
    380  1.1  mrg {
    381  1.1  mrg   for (unsigned ix = 0; ix != vec.size (); ix++)
    382  1.1  mrg     col = make_write_name (vec[ix], fp, col, colmax, ix >= quote_lwm, trail);
    383  1.1  mrg   return col;
    384  1.1  mrg }
    385  1.1  mrg 
    386  1.1  mrg /* Write the dependencies to a Makefile.  If PHONY is true, add
    387  1.1  mrg    .PHONY targets for all the dependencies too.  */
    388  1.1  mrg 
    389  1.1  mrg static void
    390  1.1  mrg make_write (const cpp_reader *pfile, FILE *fp, unsigned int colmax)
    391  1.1  mrg {
    392  1.1  mrg   const mkdeps *d = pfile->deps;
    393  1.1  mrg 
    394  1.1  mrg   unsigned column = 0;
    395  1.1  mrg   if (colmax && colmax < 34)
    396  1.1  mrg     colmax = 34;
    397  1.1  mrg 
    398  1.1  mrg   if (d->deps.size ())
    399  1.1  mrg     {
    400  1.1  mrg       column = make_write_vec (d->targets, fp, 0, colmax, d->quote_lwm);
    401  1.1  mrg       if (CPP_OPTION (pfile, deps.modules) && d->cmi_name)
    402  1.1  mrg 	column = make_write_name (d->cmi_name, fp, column, colmax);
    403  1.1  mrg       fputs (":", fp);
    404  1.1  mrg       column++;
    405  1.1  mrg       make_write_vec (d->deps, fp, column, colmax);
    406  1.1  mrg       fputs ("\n", fp);
    407  1.1  mrg       if (CPP_OPTION (pfile, deps.phony_targets))
    408  1.1  mrg 	for (unsigned i = 1; i < d->deps.size (); i++)
    409  1.1  mrg 	  fprintf (fp, "%s:\n", munge (d->deps[i]));
    410  1.1  mrg     }
    411  1.1  mrg 
    412  1.1  mrg   if (!CPP_OPTION (pfile, deps.modules))
    413  1.1  mrg     return;
    414  1.1  mrg 
    415  1.1  mrg   if (d->modules.size ())
    416  1.1  mrg     {
    417  1.1  mrg       column = make_write_vec (d->targets, fp, 0, colmax, d->quote_lwm);
    418  1.1  mrg       if (d->cmi_name)
    419  1.1  mrg 	column = make_write_name (d->cmi_name, fp, column, colmax);
    420  1.1  mrg       fputs (":", fp);
    421  1.1  mrg       column++;
    422  1.1  mrg       column = make_write_vec (d->modules, fp, column, colmax, 0, ".c++m");
    423  1.1  mrg       fputs ("\n", fp);
    424  1.1  mrg     }
    425  1.1  mrg 
    426  1.1  mrg   if (d->module_name)
    427  1.1  mrg     {
    428  1.1  mrg       if (d->cmi_name)
    429  1.1  mrg 	{
    430  1.1  mrg 	  /* module-name : cmi-name */
    431  1.1  mrg 	  column = make_write_name (d->module_name, fp, 0, colmax,
    432  1.1  mrg 				    true, ".c++m");
    433  1.1  mrg 	  fputs (":", fp);
    434  1.1  mrg 	  column++;
    435  1.1  mrg 	  column = make_write_name (d->cmi_name, fp, column, colmax);
    436  1.1  mrg 	  fputs ("\n", fp);
    437  1.1  mrg 
    438  1.1  mrg 	  column = fprintf (fp, ".PHONY:");
    439  1.1  mrg 	  column = make_write_name (d->module_name, fp, column, colmax,
    440  1.1  mrg 				    true, ".c++m");
    441  1.1  mrg 	  fputs ("\n", fp);
    442  1.1  mrg 	}
    443  1.1  mrg 
    444  1.1  mrg       if (d->cmi_name && !d->is_header_unit)
    445  1.1  mrg 	{
    446  1.1  mrg 	  /* An order-only dependency.
    447  1.1  mrg 	      cmi-name :| first-target
    448  1.1  mrg 	     We can probably drop this this in favour of Make-4.3's grouped
    449  1.1  mrg 	      targets '&:'  */
    450  1.1  mrg 	  column = make_write_name (d->cmi_name, fp, 0, colmax);
    451  1.1  mrg 	  fputs (":|", fp);
    452  1.1  mrg 	  column++;
    453  1.1  mrg 	  column = make_write_name (d->targets[0], fp, column, colmax);
    454  1.1  mrg 	  fputs ("\n", fp);
    455  1.1  mrg 	}
    456  1.1  mrg     }
    457  1.1  mrg 
    458  1.1  mrg   if (d->modules.size ())
    459  1.1  mrg     {
    460  1.1  mrg       column = fprintf (fp, "CXX_IMPORTS +=");
    461  1.1  mrg       make_write_vec (d->modules, fp, column, colmax, 0, ".c++m");
    462  1.1  mrg       fputs ("\n", fp);
    463  1.1  mrg     }
    464  1.1  mrg }
    465  1.1  mrg 
    466  1.1  mrg /* Write out dependencies according to the selected format (which is
    467  1.1  mrg    only Make at the moment).  */
    468  1.1  mrg /* Really we should be opening fp here.  */
    469  1.1  mrg 
    470  1.1  mrg void
    471  1.1  mrg deps_write (const cpp_reader *pfile, FILE *fp, unsigned int colmax)
    472  1.1  mrg {
    473  1.1  mrg   make_write (pfile, fp, colmax);
    474  1.1  mrg }
    475  1.1  mrg 
    476  1.1  mrg /* Write out a deps buffer to a file, in a form that can be read back
    477  1.1  mrg    with deps_restore.  Returns nonzero on error, in which case the
    478  1.1  mrg    error number will be in errno.  */
    479  1.1  mrg 
    480  1.1  mrg int
    481  1.1  mrg deps_save (class mkdeps *deps, FILE *f)
    482  1.1  mrg {
    483  1.1  mrg   unsigned int i;
    484  1.1  mrg   size_t size;
    485  1.1  mrg 
    486  1.1  mrg   /* The cppreader structure contains makefile dependences.  Write out this
    487  1.1  mrg      structure.  */
    488  1.1  mrg 
    489  1.1  mrg   /* The number of dependences.  */
    490  1.1  mrg   size = deps->deps.size ();
    491  1.1  mrg   if (fwrite (&size, sizeof (size), 1, f) != 1)
    492  1.1  mrg     return -1;
    493  1.1  mrg 
    494  1.1  mrg   /* The length of each dependence followed by the string.  */
    495  1.1  mrg   for (i = 0; i < deps->deps.size (); i++)
    496  1.1  mrg     {
    497  1.1  mrg       size = strlen (deps->deps[i]);
    498  1.1  mrg       if (fwrite (&size, sizeof (size), 1, f) != 1)
    499  1.1  mrg 	return -1;
    500  1.1  mrg       if (fwrite (deps->deps[i], size, 1, f) != 1)
    501  1.1  mrg 	return -1;
    502  1.1  mrg     }
    503  1.1  mrg 
    504  1.1  mrg   return 0;
    505  1.1  mrg }
    506  1.1  mrg 
    507  1.1  mrg /* Read back dependency information written with deps_save into
    508  1.1  mrg    the deps sizefer.  The third argument may be NULL, in which case
    509  1.1  mrg    the dependency information is just skipped, or it may be a filename,
    510  1.1  mrg    in which case that filename is skipped.  */
    511  1.1  mrg 
    512  1.1  mrg int
    513  1.1  mrg deps_restore (class mkdeps *deps, FILE *fd, const char *self)
    514  1.1  mrg {
    515  1.1  mrg   size_t size;
    516  1.1  mrg   char *buf = NULL;
    517  1.1  mrg   size_t buf_size = 0;
    518  1.1  mrg 
    519  1.1  mrg   /* Number of dependences.  */
    520  1.1  mrg   if (fread (&size, sizeof (size), 1, fd) != 1)
    521  1.1  mrg     return -1;
    522  1.1  mrg 
    523  1.1  mrg   /* The length of each dependence string, followed by the string.  */
    524  1.1  mrg   for (unsigned i = size; i--;)
    525  1.1  mrg     {
    526  1.1  mrg       /* Read in # bytes in string.  */
    527  1.1  mrg       if (fread (&size, sizeof (size), 1, fd) != 1)
    528  1.1  mrg 	return -1;
    529  1.1  mrg 
    530  1.1  mrg       if (size >= buf_size)
    531  1.1  mrg 	{
    532  1.1  mrg 	  buf_size = size + 512;
    533  1.1  mrg 	  buf = XRESIZEVEC (char, buf, buf_size);
    534  1.1  mrg 	}
    535  1.1  mrg       if (fread (buf, 1, size, fd) != size)
    536  1.1  mrg 	{
    537  1.1  mrg 	  XDELETEVEC (buf);
    538  1.1  mrg 	  return -1;
    539  1.1  mrg 	}
    540  1.1  mrg       buf[size] = 0;
    541  1.1  mrg 
    542  1.1  mrg       /* Generate makefile dependencies from .pch if -nopch-deps.  */
    543  1.1  mrg       if (self != NULL && filename_cmp (buf, self) != 0)
    544  1.1  mrg         deps_add_dep (deps, buf);
    545  1.1  mrg     }
    546  1.1  mrg 
    547  1.1  mrg   XDELETEVEC (buf);
    548  1.1  mrg   return 0;
    549  1.1  mrg }
    550