1/* Target file hash table management for GNU Make.
2Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
32002 Free Software Foundation, Inc.
4This file is part of GNU Make.
5
6GNU Make is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Make is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Make; see the file COPYING.  If not, write to
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA.  */
20
21#include "make.h"
22
23#include <assert.h>
24
25#include "dep.h"
26#include "filedef.h"
27#include "job.h"
28#include "commands.h"
29#include "variable.h"
30#include "debug.h"
31#include "hash.h"
32
33
34/* Hash table of files the makefile knows how to make.  */
35
36static unsigned long
37file_hash_1 (key)
38    const void *key;
39{
40  return_ISTRING_HASH_1 (((struct file const *) key)->hname);
41}
42
43static unsigned long
44file_hash_2 (key)
45    const void *key;
46{
47  return_ISTRING_HASH_2 (((struct file const *) key)->hname);
48}
49
50static int
51file_hash_cmp (x, y)
52    const void *x;
53    const void *y;
54{
55  return_ISTRING_COMPARE (((struct file const *) x)->hname,
56			  ((struct file const *) y)->hname);
57}
58
59#ifndef	FILE_BUCKETS
60#define FILE_BUCKETS	1007
61#endif
62static struct hash_table files;
63
64/* Whether or not .SECONDARY with no prerequisites was given.  */
65static int all_secondary = 0;
66
67/* Access the hash table of all file records.
68   lookup_file  given a name, return the struct file * for that name,
69           or nil if there is none.
70   enter_file   similar, but create one if there is none.  */
71
72struct file *
73lookup_file (name)
74     char *name;
75{
76  register struct file *f;
77  struct file file_key;
78#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
79  register char *lname, *ln;
80#endif
81
82  assert (*name != '\0');
83
84  /* This is also done in parse_file_seq, so this is redundant
85     for names read from makefiles.  It is here for names passed
86     on the command line.  */
87#ifdef VMS
88# ifndef WANT_CASE_SENSITIVE_TARGETS
89  {
90    register char *n;
91    lname = (char *) malloc (strlen (name) + 1);
92    for (n = name, ln = lname; *n != '\0'; ++n, ++ln)
93      *ln = isupper ((unsigned char)*n) ? tolower ((unsigned char)*n) : *n;
94    *ln = '\0';
95    name = lname;
96  }
97# endif
98
99  while (name[0] == '[' && name[1] == ']' && name[2] != '\0')
100      name += 2;
101#endif
102  while (name[0] == '.' && name[1] == '/' && name[2] != '\0')
103    {
104      name += 2;
105      while (*name == '/')
106	/* Skip following slashes: ".//foo" is "foo", not "/foo".  */
107	++name;
108    }
109
110  if (*name == '\0')
111    /* It was all slashes after a dot.  */
112#ifdef VMS
113    name = "[]";
114#else
115#ifdef _AMIGA
116    name = "";
117#else
118    name = "./";
119#endif /* AMIGA */
120#endif /* VMS */
121
122  file_key.hname = name;
123  f = (struct file *) hash_find_item (&files, &file_key);
124#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
125  free (lname);
126#endif
127  return f;
128}
129
130struct file *
131enter_file (name)
132     char *name;
133{
134  register struct file *f;
135  register struct file *new;
136  register struct file **file_slot;
137  struct file file_key;
138#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
139  char *lname, *ln;
140#endif
141
142  assert (*name != '\0');
143
144#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
145  {
146    register char *n;
147    lname = (char *) malloc (strlen (name) + 1);
148    for (n = name, ln = lname; *n != '\0'; ++n, ++ln)
149      {
150        if (isupper ((unsigned char)*n))
151          *ln = tolower ((unsigned char)*n);
152        else
153          *ln = *n;
154      }
155
156    *ln = 0;
157    /* Creates a possible leak, old value of name is unreachable, but I
158       currently don't know how to fix it. */
159    name = lname;
160  }
161#endif
162
163  file_key.hname = name;
164  file_slot = (struct file **) hash_find_slot (&files, &file_key);
165  f = *file_slot;
166  if (! HASH_VACANT (f) && !f->double_colon)
167    {
168#if defined(VMS) && !defined(WANT_CASE_SENSITIVE_TARGETS)
169      free(lname);
170#endif
171      return f;
172    }
173
174  new = (struct file *) xmalloc (sizeof (struct file));
175  bzero ((char *) new, sizeof (struct file));
176  new->name = new->hname = name;
177  new->update_status = -1;
178
179  if (HASH_VACANT (f))
180    hash_insert_at (&files, new, file_slot);
181  else
182    {
183      /* There is already a double-colon entry for this file.  */
184      new->double_colon = f;
185      while (f->prev != 0)
186	f = f->prev;
187      f->prev = new;
188    }
189
190  return new;
191}
192
193/* Rename FILE to NAME.  This is not as simple as resetting
194   the `name' member, since it must be put in a new hash bucket,
195   and possibly merged with an existing file called NAME.  */
196
197void
198rename_file (from_file, to_hname)
199     register struct file *from_file;
200     char *to_hname;
201{
202  rehash_file (from_file, to_hname);
203  while (from_file)
204    {
205      from_file->name = from_file->hname;
206      from_file = from_file->prev;
207    }
208}
209
210/* Rehash FILE to NAME.  This is not as simple as resetting
211   the `hname' member, since it must be put in a new hash bucket,
212   and possibly merged with an existing file called NAME.  */
213
214void
215rehash_file (from_file, to_hname)
216     register struct file *from_file;
217     char *to_hname;
218{
219  struct file file_key;
220  struct file **file_slot;
221  struct file *to_file;
222  struct file *deleted_file;
223  struct file *f;
224
225  file_key.hname = to_hname;
226  if (0 == file_hash_cmp (from_file, &file_key))
227    return;
228
229  file_key.hname = from_file->hname;
230  while (from_file->renamed != 0)
231    from_file = from_file->renamed;
232  if (file_hash_cmp (from_file, &file_key))
233    /* hname changed unexpectedly */
234    abort ();
235
236  deleted_file = hash_delete (&files, from_file);
237  if (deleted_file != from_file)
238    /* from_file isn't the one stored in files */
239    abort ();
240
241  file_key.hname = to_hname;
242  file_slot = (struct file **) hash_find_slot (&files, &file_key);
243  to_file = *file_slot;
244
245  from_file->hname = to_hname;
246  for (f = from_file->double_colon; f != 0; f = f->prev)
247    f->hname = to_hname;
248
249  if (HASH_VACANT (to_file))
250    hash_insert_at (&files, from_file, file_slot);
251  else
252    {
253      /* TO_FILE already exists under TO_HNAME.
254	 We must retain TO_FILE and merge FROM_FILE into it.  */
255
256      if (from_file->cmds != 0)
257	{
258	  if (to_file->cmds == 0)
259	    to_file->cmds = from_file->cmds;
260	  else if (from_file->cmds != to_file->cmds)
261	    {
262	      /* We have two sets of commands.  We will go with the
263		 one given in the rule explicitly mentioning this name,
264		 but give a message to let the user know what's going on.  */
265	      if (to_file->cmds->fileinfo.filenm != 0)
266                error (&from_file->cmds->fileinfo,
267		       _("Commands were specified for file `%s' at %s:%lu,"),
268		       from_file->name, to_file->cmds->fileinfo.filenm,
269		       to_file->cmds->fileinfo.lineno);
270	      else
271		error (&from_file->cmds->fileinfo,
272		       _("Commands for file `%s' were found by implicit rule search,"),
273		       from_file->name);
274	      error (&from_file->cmds->fileinfo,
275		     _("but `%s' is now considered the same file as `%s'."),
276		     from_file->name, to_hname);
277	      error (&from_file->cmds->fileinfo,
278		     _("Commands for `%s' will be ignored in favor of those for `%s'."),
279		     to_hname, from_file->name);
280	    }
281	}
282
283      /* Merge the dependencies of the two files.  */
284
285      if (to_file->deps == 0)
286	to_file->deps = from_file->deps;
287      else
288	{
289	  register struct dep *deps = to_file->deps;
290	  while (deps->next != 0)
291	    deps = deps->next;
292	  deps->next = from_file->deps;
293	}
294
295      merge_variable_set_lists (&to_file->variables, from_file->variables);
296
297      if (to_file->double_colon && from_file->is_target && !from_file->double_colon)
298	fatal (NILF, _("can't rename single-colon `%s' to double-colon `%s'"),
299	       from_file->name, to_hname);
300      if (!to_file->double_colon  && from_file->double_colon)
301	{
302	  if (to_file->is_target)
303	    fatal (NILF, _("can't rename double-colon `%s' to single-colon `%s'"),
304		   from_file->name, to_hname);
305	  else
306	    to_file->double_colon = from_file->double_colon;
307	}
308
309      if (from_file->last_mtime > to_file->last_mtime)
310	/* %%% Kludge so -W wins on a file that gets vpathized.  */
311	to_file->last_mtime = from_file->last_mtime;
312
313      to_file->mtime_before_update = from_file->mtime_before_update;
314
315#define MERGE(field) to_file->field |= from_file->field
316      MERGE (precious);
317      MERGE (tried_implicit);
318      MERGE (updating);
319      MERGE (updated);
320      MERGE (is_target);
321      MERGE (cmd_target);
322      MERGE (phony);
323      MERGE (ignore_vpath);
324#undef MERGE
325
326      from_file->renamed = to_file;
327    }
328}
329
330/* Remove all nonprecious intermediate files.
331   If SIG is nonzero, this was caused by a fatal signal,
332   meaning that a different message will be printed, and
333   the message will go to stderr rather than stdout.  */
334
335void
336remove_intermediates (sig)
337     int sig;
338{
339  register struct file **file_slot;
340  register struct file **file_end;
341  int doneany = 0;
342
343  /* If there's no way we will ever remove anything anyway, punt early.  */
344  if (question_flag || touch_flag || all_secondary)
345    return;
346
347  if (sig && just_print_flag)
348    return;
349
350  file_slot = (struct file **) files.ht_vec;
351  file_end = file_slot + files.ht_size;
352  for ( ; file_slot < file_end; file_slot++)
353    if (! HASH_VACANT (*file_slot))
354      {
355	register struct file *f = *file_slot;
356	if (f->intermediate && (f->dontcare || !f->precious)
357	    && !f->secondary && !f->cmd_target)
358	  {
359	    int status;
360	    if (f->update_status == -1)
361	      /* If nothing would have created this file yet,
362		 don't print an "rm" command for it.  */
363	      continue;
364	    if (just_print_flag)
365	      status = 0;
366	    else
367	      {
368		status = unlink (f->name);
369		if (status < 0 && errno == ENOENT)
370		  continue;
371	      }
372	    if (!f->dontcare)
373	      {
374		if (sig)
375		  error (NILF, _("*** Deleting intermediate file `%s'"), f->name);
376		else
377		  {
378		    if (! doneany)
379		      DB (DB_BASIC, (_("Removing intermediate files...\n")));
380		    if (!silent_flag)
381		      {
382			if (! doneany)
383			  {
384			    fputs ("rm ", stdout);
385			    doneany = 1;
386			  }
387			else
388			  putchar (' ');
389			fputs (f->name, stdout);
390			fflush (stdout);
391		      }
392		  }
393		if (status < 0)
394		  perror_with_name ("unlink: ", f->name);
395	      }
396	  }
397      }
398
399  if (doneany && !sig)
400    {
401      putchar ('\n');
402      fflush (stdout);
403    }
404}
405
406/* For each dependency of each file, make the `struct dep' point
407   at the appropriate `struct file' (which may have to be created).
408
409   Also mark the files depended on by .PRECIOUS, .PHONY, .SILENT,
410   and various other special targets.  */
411
412void
413snap_deps ()
414{
415  register struct file *f;
416  register struct file *f2;
417  register struct dep *d;
418  register struct file **file_slot_0;
419  register struct file **file_slot;
420  register struct file **file_end;
421
422  /* Enter each dependency name as a file.  */
423  /* We must use hash_dump (), because within this loop
424     we might add new files to the table, possibly causing
425     an in-situ table expansion.  */
426  file_slot_0 = (struct file **) hash_dump (&files, 0, 0);
427  file_end = file_slot_0 + files.ht_fill;
428  for (file_slot = file_slot_0; file_slot < file_end; file_slot++)
429    for (f2 = *file_slot; f2 != 0; f2 = f2->prev)
430      for (d = f2->deps; d != 0; d = d->next)
431	if (d->name != 0)
432	  {
433	    d->file = lookup_file (d->name);
434	    if (d->file == 0)
435	      d->file = enter_file (d->name);
436	    else
437	      free (d->name);
438	    d->name = 0;
439	  }
440  free (file_slot_0);
441
442  for (f = lookup_file (".PRECIOUS"); f != 0; f = f->prev)
443    for (d = f->deps; d != 0; d = d->next)
444      for (f2 = d->file; f2 != 0; f2 = f2->prev)
445	f2->precious = 1;
446
447  for (f = lookup_file (".LOW_RESOLUTION_TIME"); f != 0; f = f->prev)
448    for (d = f->deps; d != 0; d = d->next)
449      for (f2 = d->file; f2 != 0; f2 = f2->prev)
450	f2->low_resolution_time = 1;
451
452  for (f = lookup_file (".PHONY"); f != 0; f = f->prev)
453    for (d = f->deps; d != 0; d = d->next)
454      for (f2 = d->file; f2 != 0; f2 = f2->prev)
455	{
456	  /* Mark this file as phony and nonexistent.  */
457	  f2->phony = 1;
458	  f2->last_mtime = NONEXISTENT_MTIME;
459	  f2->mtime_before_update = NONEXISTENT_MTIME;
460	}
461
462  for (f = lookup_file (".INTERMEDIATE"); f != 0; f = f->prev)
463    {
464      /* .INTERMEDIATE with deps listed
465	 marks those deps as intermediate files.  */
466      for (d = f->deps; d != 0; d = d->next)
467	for (f2 = d->file; f2 != 0; f2 = f2->prev)
468	  f2->intermediate = 1;
469      /* .INTERMEDIATE with no deps does nothing.
470	 Marking all files as intermediates is useless
471	 since the goal targets would be deleted after they are built.  */
472    }
473
474  for (f = lookup_file (".SECONDARY"); f != 0; f = f->prev)
475    {
476      /* .SECONDARY with deps listed
477	 marks those deps as intermediate files
478	 in that they don't get rebuilt if not actually needed;
479	 but unlike real intermediate files,
480	 these are not deleted after make finishes.  */
481      if (f->deps)
482        for (d = f->deps; d != 0; d = d->next)
483          for (f2 = d->file; f2 != 0; f2 = f2->prev)
484            f2->intermediate = f2->secondary = 1;
485      /* .SECONDARY with no deps listed marks *all* files that way.  */
486      else
487        all_secondary = 1;
488    }
489
490  f = lookup_file (".EXPORT_ALL_VARIABLES");
491  if (f != 0 && f->is_target)
492    export_all_variables = 1;
493
494  f = lookup_file (".IGNORE");
495  if (f != 0 && f->is_target)
496    {
497      if (f->deps == 0)
498	ignore_errors_flag = 1;
499      else
500	for (d = f->deps; d != 0; d = d->next)
501	  for (f2 = d->file; f2 != 0; f2 = f2->prev)
502	    f2->command_flags |= COMMANDS_NOERROR;
503    }
504
505  f = lookup_file (".SILENT");
506  if (f != 0 && f->is_target)
507    {
508      if (f->deps == 0)
509	silent_flag = 1;
510      else
511	for (d = f->deps; d != 0; d = d->next)
512	  for (f2 = d->file; f2 != 0; f2 = f2->prev)
513	    f2->command_flags |= COMMANDS_SILENT;
514    }
515
516  f = lookup_file (".POSIX");
517  if (f != 0 && f->is_target)
518    posix_pedantic = 1;
519
520  f = lookup_file (".NOTPARALLEL");
521  if (f != 0 && f->is_target)
522    not_parallel = 1;
523}
524
525/* Set the `command_state' member of FILE and all its `also_make's.  */
526
527void
528set_command_state (file, state)
529     struct file *file;
530     int state;
531{
532  struct dep *d;
533
534  file->command_state = state;
535
536  for (d = file->also_make; d != 0; d = d->next)
537    d->file->command_state = state;
538}
539
540/* Convert an external file timestamp to internal form.  */
541
542FILE_TIMESTAMP
543file_timestamp_cons (fname, s, ns)
544     char const *fname;
545     time_t s;
546     int ns;
547{
548  int offset = ORDINARY_MTIME_MIN + (FILE_TIMESTAMP_HI_RES ? ns : 0);
549  FILE_TIMESTAMP product = (FILE_TIMESTAMP) s << FILE_TIMESTAMP_LO_BITS;
550  FILE_TIMESTAMP ts = product + offset;
551
552  if (! (s <= FILE_TIMESTAMP_S (ORDINARY_MTIME_MAX)
553	 && product <= ts && ts <= ORDINARY_MTIME_MAX))
554    {
555      char buf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1];
556      ts = s <= OLD_MTIME ? ORDINARY_MTIME_MIN : ORDINARY_MTIME_MAX;
557      file_timestamp_sprintf (buf, ts);
558      error (NILF, _("%s: Timestamp out of range; substituting %s"),
559	     fname ? fname : _("Current time"), buf);
560    }
561
562  return ts;
563}
564
565/* Return the current time as a file timestamp, setting *RESOLUTION to
566   its resolution.  */
567FILE_TIMESTAMP
568file_timestamp_now (resolution)
569     int *resolution;
570{
571  int r;
572  time_t s;
573  int ns;
574
575  /* Don't bother with high-resolution clocks if file timestamps have
576     only one-second resolution.  The code below should work, but it's
577     not worth the hassle of debugging it on hosts where it fails.  */
578#if FILE_TIMESTAMP_HI_RES
579# if HAVE_CLOCK_GETTIME && defined CLOCK_REALTIME
580  {
581    struct timespec timespec;
582    if (clock_gettime (CLOCK_REALTIME, &timespec) == 0)
583      {
584	r = 1;
585	s = timespec.tv_sec;
586	ns = timespec.tv_nsec;
587	goto got_time;
588      }
589  }
590# endif
591# if HAVE_GETTIMEOFDAY
592  {
593    struct timeval timeval;
594    if (gettimeofday (&timeval, 0) == 0)
595      {
596	r = 1000;
597	s = timeval.tv_sec;
598	ns = timeval.tv_usec * 1000;
599	goto got_time;
600      }
601  }
602# endif
603#endif
604
605  r = 1000000000;
606  s = time ((time_t *) 0);
607  ns = 0;
608
609 got_time:
610  *resolution = r;
611  return file_timestamp_cons (0, s, ns);
612}
613
614/* Place into the buffer P a printable representation of the file
615   timestamp TS.  */
616void
617file_timestamp_sprintf (p, ts)
618     char *p;
619     FILE_TIMESTAMP ts;
620{
621  time_t t = FILE_TIMESTAMP_S (ts);
622  struct tm *tm = localtime (&t);
623
624  if (tm)
625    sprintf (p, "%04d-%02d-%02d %02d:%02d:%02d",
626	     tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
627	     tm->tm_hour, tm->tm_min, tm->tm_sec);
628  else if (t < 0)
629    sprintf (p, "%ld", (long) t);
630  else
631    sprintf (p, "%lu", (unsigned long) t);
632  p += strlen (p);
633
634  /* Append nanoseconds as a fraction, but remove trailing zeros.
635     We don't know the actual timestamp resolution, since clock_getres
636     applies only to local times, whereas this timestamp might come
637     from a remote filesystem.  So removing trailing zeros is the
638     best guess that we can do.  */
639  sprintf (p, ".%09d", FILE_TIMESTAMP_NS (ts));
640  p += strlen (p) - 1;
641  while (*p == '0')
642    p--;
643  p += *p != '.';
644
645  *p = '\0';
646}
647
648/* Print the data base of files.  */
649
650static void
651print_file (f)
652     struct file *f;
653{
654  struct dep *d;
655  struct dep *ood = 0;
656
657  putchar ('\n');
658  if (!f->is_target)
659    puts (_("# Not a target:"));
660  printf ("%s:%s", f->name, f->double_colon ? ":" : "");
661
662  /* Print all normal dependencies; note any order-only deps.  */
663  for (d = f->deps; d != 0; d = d->next)
664    if (! d->ignore_mtime)
665      printf (" %s", dep_name (d));
666    else if (! ood)
667      ood = d;
668
669  /* Print order-only deps, if we have any.  */
670  if (ood)
671    {
672      printf (" | %s", dep_name (ood));
673      for (d = ood->next; d != 0; d = d->next)
674        if (d->ignore_mtime)
675          printf (" %s", dep_name (d));
676    }
677
678  putchar ('\n');
679
680  if (f->precious)
681    puts (_("#  Precious file (prerequisite of .PRECIOUS)."));
682  if (f->phony)
683    puts (_("#  Phony target (prerequisite of .PHONY)."));
684  if (f->cmd_target)
685    puts (_("#  Command-line target."));
686  if (f->dontcare)
687    puts (_("#  A default or MAKEFILES makefile."));
688  puts (f->tried_implicit
689        ? _("#  Implicit rule search has been done.")
690        : _("#  Implicit rule search has not been done."));
691  if (f->stem != 0)
692    printf (_("#  Implicit/static pattern stem: `%s'\n"), f->stem);
693  if (f->intermediate)
694    puts (_("#  File is an intermediate prerequisite."));
695  if (f->also_make != 0)
696    {
697      fputs (_("#  Also makes:"), stdout);
698      for (d = f->also_make; d != 0; d = d->next)
699	printf (" %s", dep_name (d));
700      putchar ('\n');
701    }
702  if (f->last_mtime == UNKNOWN_MTIME)
703    puts (_("#  Modification time never checked."));
704  else if (f->last_mtime == NONEXISTENT_MTIME)
705    puts (_("#  File does not exist."));
706  else if (f->last_mtime == OLD_MTIME)
707    puts (_("#  File is very old."));
708  else
709    {
710      char buf[FILE_TIMESTAMP_PRINT_LEN_BOUND + 1];
711      file_timestamp_sprintf (buf, f->last_mtime);
712      printf (_("#  Last modified %s\n"), buf);
713    }
714  puts (f->updated
715        ? _("#  File has been updated.") : _("#  File has not been updated."));
716  switch (f->command_state)
717    {
718    case cs_running:
719      puts (_("#  Commands currently running (THIS IS A BUG)."));
720      break;
721    case cs_deps_running:
722      puts (_("#  Dependencies commands running (THIS IS A BUG)."));
723      break;
724    case cs_not_started:
725    case cs_finished:
726      switch (f->update_status)
727	{
728	case -1:
729	  break;
730	case 0:
731	  puts (_("#  Successfully updated."));
732	  break;
733	case 1:
734	  assert (question_flag);
735	  puts (_("#  Needs to be updated (-q is set)."));
736	  break;
737	case 2:
738	  puts (_("#  Failed to be updated."));
739	  break;
740	default:
741	  puts (_("#  Invalid value in `update_status' member!"));
742	  fflush (stdout);
743	  fflush (stderr);
744	  abort ();
745	}
746      break;
747    default:
748      puts (_("#  Invalid value in `command_state' member!"));
749      fflush (stdout);
750      fflush (stderr);
751      abort ();
752    }
753
754  if (f->variables != 0)
755    print_file_variables (f);
756
757  if (f->cmds != 0)
758    print_commands (f->cmds);
759}
760
761void
762print_file_data_base ()
763{
764  puts (_("\n# Files"));
765
766  hash_map (&files, print_file);
767
768  fputs (_("\n# files hash-table stats:\n# "), stdout);
769  hash_print_stats (&files, stdout);
770}
771
772#define EXPANSION_INCREMENT(_l)  ((((_l) / 500) + 1) * 500)
773
774char *
775build_target_list (value)
776     char *value;
777{
778  static unsigned long last_targ_count = 0;
779
780  if (files.ht_fill != last_targ_count)
781    {
782      unsigned long max = EXPANSION_INCREMENT (strlen (value));
783      unsigned long len;
784      char *p;
785      struct file **fp = (struct file **) files.ht_vec;
786      struct file **end = &fp[files.ht_size];
787
788      /* Make sure we have at least MAX bytes in the allocated buffer.  */
789      value = xrealloc (value, max);
790
791      p = value;
792      len = 0;
793      for (; fp < end; ++fp)
794        if (!HASH_VACANT (*fp) && (*fp)->is_target)
795          {
796            struct file *f = *fp;
797            int l = strlen (f->name);
798
799            len += l + 1;
800            if (len > max)
801              {
802                unsigned long off = p - value;
803
804                max += EXPANSION_INCREMENT (l + 1);
805                value = xrealloc (value, max);
806                p = &value[off];
807              }
808
809            bcopy (f->name, p, l);
810            p += l;
811            *(p++) = ' ';
812          }
813      *(p-1) = '\0';
814
815      last_targ_count = files.ht_fill;
816    }
817
818  return value;
819}
820
821void
822init_hash_files ()
823{
824  hash_init (&files, 1000, file_hash_1, file_hash_2, file_hash_cmp);
825}
826
827/* EOF */
828