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, ×pec) == 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