Fix typo in last change.
[make.git] / remake.c
blobc7b183c4679a43ec6b6dec8711a4f25247d20bc4
1 /* Basic dependency engine for GNU Make.
2 Copyright (C) 1988, 89, 90, 91, 92, 93, 94 Free Software Foundation, Inc.
3 This file is part of GNU Make.
5 GNU Make is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
10 GNU Make 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.
15 You should have received a copy of the GNU General Public License
16 along with GNU Make; see the file COPYING. If not, write to
17 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19 #include "make.h"
20 #include "commands.h"
21 #include "job.h"
22 #include "dep.h"
23 #include "file.h"
25 #ifdef HAVE_FCNTL_H
26 #include <fcntl.h>
27 #else
28 #include <sys/file.h>
29 #endif
31 extern int try_implicit_rule ();
34 /* Incremented when a command is started (under -n, when one would be). */
35 unsigned int commands_started = 0;
37 static int update_file (), update_file_1 (), check_dep (), touch_file ();
38 static void remake_file ();
39 static time_t name_mtime ();
40 static int library_search ();
41 extern time_t f_mtime ();
43 /* Remake all the goals in the `struct dep' chain GOALS. Return -1 if nothing
44 was done, 0 if all goals were updated successfully, or 1 if a goal failed.
45 If MAKEFILES is nonzero, these goals are makefiles, so -t, -q, and -n should
46 be disabled for them unless they were also command-line targets, and we
47 should only make one goal at a time and return as soon as one goal whose
48 `changed' member is nonzero is successfully made. */
50 int
51 update_goal_chain (goals, makefiles)
52 register struct dep *goals;
53 int makefiles;
55 int t = touch_flag, q = question_flag, n = just_print_flag;
56 unsigned int j = job_slots;
57 int status = -1;
59 #define MTIME(file) (makefiles ? file_mtime_no_search (file) \
60 : file_mtime (file))
62 /* Duplicate the chain so we can remove things from it. */
64 goals = copy_dep_chain (goals);
67 /* Clear the `changed' flag of each goal in the chain.
68 We will use the flag below to notice when any commands
69 have actually been run for a target. When no commands
70 have been run, we give an "up to date" diagnostic. */
72 struct dep *g;
73 for (g = goals; g != 0; g = g->next)
74 g->changed = 0;
77 if (makefiles)
78 /* Only run one job at a time. */
79 job_slots = 1;
81 /* Update all the goals until they are all finished. */
83 while (goals != 0)
85 register struct dep *g, *lastgoal;
87 /* Start jobs that are waiting for the load to go down. */
89 start_waiting_jobs ();
91 /* Wait for a child to die. */
93 reap_children (1, 0);
95 lastgoal = 0;
96 g = goals;
97 while (g != 0)
99 /* Iterate over all double-colon entries for this file. */
100 struct file *file = g->file;
101 int stop, any_not_updated = 0;
102 for (file = g->file->double_colon ? g->file->double_colon : g->file;
103 file != NULL;
104 file = file->prev)
106 unsigned int ocommands_started;
107 int x;
108 time_t mtime = MTIME (file);
109 check_renamed (file);
111 if (makefiles)
113 if (file->cmd_target)
115 touch_flag = t;
116 question_flag = q;
117 just_print_flag = n;
119 else
120 touch_flag = question_flag = just_print_flag = 0;
123 /* Save the old value of `commands_started' so we can compare
124 later. It will be incremented when any commands are
125 actually run. */
126 ocommands_started = commands_started;
128 x = update_file (file, makefiles ? 1 : 0);
129 check_renamed (file);
131 /* Set the goal's `changed' flag if any commands were started
132 by calling update_file above. We check this flag below to
133 decide when to give an "up to date" diagnostic. */
134 g->changed += commands_started - ocommands_started;
136 stop = 0;
137 if (x != 0 || file->updated)
139 /* If STATUS was not already 1, set it to 1 if
140 updating failed, or to 0 if updating succeeded.
141 Leave STATUS as it is if no updating was done. */
143 if (status < 1)
145 if (file->update_status != 0)
147 /* Updating failed, or -q triggered.
148 The STATUS value tells our caller which. */
149 status = file->update_status;
150 /* If -q just triggered, stop immediately.
151 It doesn't matter how much more we run,
152 since we already know the answer to return. */
153 stop = (!keep_going_flag && !question_flag
154 && !makefiles);
156 else if (MTIME (file) != mtime)
158 /* Updating was done. If this is a makefile and
159 just_print_flag or question_flag is set
160 (meaning -n or -q was given and this file was
161 specified as a command-line target), don't
162 change STATUS. If STATUS is changed, we will
163 get re-exec'd, and fall into an infinite loop. */
164 if (!makefiles
165 || (!just_print_flag && !question_flag))
166 status = 0;
167 if (makefiles && file->dontcare)
168 /* This is a default makefile. Stop remaking. */
169 stop = 1;
174 /* Keep track if any double-colon entry is not finished.
175 When they are all finished, the goal is finished. */
176 any_not_updated |= !file->updated;
178 if (stop)
179 break;
182 /* Reset FILE since it is null at the end of the loop. */
183 file = g->file;
185 if (stop || !any_not_updated)
187 /* If we have found nothing whatever to do for the goal,
188 print a message saying nothing needs doing. */
190 if (!makefiles
191 /* If the update_status is zero, we updated successfully
192 or not at all. G->changed will have been set above if
193 any commands were actually started for this goal. */
194 && file->update_status == 0 && !g->changed
195 /* Never give a message under -s or -q. */
196 && !silent_flag && !question_flag)
198 if (file->phony || file->cmds == 0)
199 message ("Nothing to be done for `%s'.",
200 file->name);
201 else
202 message ("`%s' is up to date.", file->name);
203 fflush (stdout);
206 /* This goal is finished. Remove it from the chain. */
207 if (lastgoal == 0)
208 goals = g->next;
209 else
210 lastgoal->next = g->next;
212 /* Free the storage. */
213 free ((char *) g);
215 g = lastgoal == 0 ? goals : lastgoal->next;
217 if (stop)
218 break;
220 else
222 lastgoal = g;
223 g = g->next;
228 if (makefiles)
230 touch_flag = t;
231 question_flag = q;
232 just_print_flag = n;
233 job_slots = j;
236 return status;
239 /* If FILE is not up to date, execute the commands for it.
240 Return 0 if successful, 1 if unsuccessful;
241 but with some flag settings, just call `exit' if unsuccessful.
243 DEPTH is the depth in recursions of this function.
244 We increment it during the consideration of our dependencies,
245 then decrement it again after finding out whether this file
246 is out of date.
248 If there are multiple double-colon entries for FILE,
249 each is considered in turn. */
251 static int
252 update_file (file, depth)
253 struct file *file;
254 unsigned int depth;
256 register int status = 0;
257 register struct file *f;
259 for (f = file->double_colon ? file->double_colon : file; f != 0; f = f->prev)
261 status |= update_file_1 (f, depth);
262 check_renamed (f);
264 if (status != 0 && !keep_going_flag)
265 return status;
267 switch (f->command_state)
269 case cs_finished:
270 /* The file is done being remade. */
271 break;
273 case cs_running:
274 case cs_deps_running:
275 /* Don't run the other :: rules for this
276 file until this rule is finished. */
277 return 0;
279 default:
280 error ("internal error: `%s' command_state == %d in update_file",
281 f->name, (int) f->command_state);
282 abort ();
283 break;
287 return status;
290 /* Consider a single `struct file' and update it as appropriate. */
292 static int
293 update_file_1 (file, depth)
294 struct file *file;
295 unsigned int depth;
297 register time_t this_mtime;
298 int noexist, must_make, deps_changed;
299 int dep_status = 0;
300 register struct dep *d, *lastd;
301 int running = 0;
303 DEBUGPR ("Considering target file `%s'.\n");
305 if (file->updated)
307 if (file->update_status > 0)
309 DEBUGPR ("Recently tried and failed to update file `%s'.\n");
310 return file->update_status;
313 DEBUGPR ("File `%s' was considered already.\n");
314 return 0;
317 switch (file->command_state)
319 case cs_not_started:
320 case cs_deps_running:
321 break;
322 case cs_running:
323 DEBUGPR ("Still updating file `%s'.\n");
324 return 0;
325 case cs_finished:
326 DEBUGPR ("Finished updating file `%s'.\n");
327 return file->update_status;
328 default:
329 abort ();
332 ++depth;
334 /* Notice recursive update of the same file. */
335 file->updating = 1;
337 /* Looking at the file's modtime beforehand allows the possibility
338 that its name may be changed by a VPATH search, and thus it may
339 not need an implicit rule. If this were not done, the file
340 might get implicit commands that apply to its initial name, only
341 to have that name replaced with another found by VPATH search. */
343 this_mtime = file_mtime (file);
344 check_renamed (file);
345 noexist = this_mtime == (time_t) -1;
346 if (noexist)
347 DEBUGPR ("File `%s' does not exist.\n");
349 must_make = noexist;
351 /* If file was specified as a target with no commands,
352 come up with some default commands. */
354 if (!file->phony && file->cmds == 0 && !file->tried_implicit)
356 if (try_implicit_rule (file, depth))
357 DEBUGPR ("Found an implicit rule for `%s'.\n");
358 else
359 DEBUGPR ("No implicit rule found for `%s'.\n");
360 file->tried_implicit = 1;
362 if (file->cmds == 0 && !file->is_target
363 && default_file != 0 && default_file->cmds != 0)
365 DEBUGPR ("Using default commands for `%s'.\n");
366 file->cmds = default_file->cmds;
369 /* Update all non-intermediate files we depend on, if necessary,
370 and see whether any of them is more recent than this file. */
372 lastd = 0;
373 d = file->deps;
374 while (d != 0)
376 time_t mtime;
378 check_renamed (d->file);
380 mtime = file_mtime (d->file);
381 check_renamed (d->file);
383 if (d->file->updating)
385 error ("Circular %s <- %s dependency dropped.",
386 file->name, d->file->name);
387 if (lastd == 0)
389 file->deps = d->next;
390 free ((char *) d);
391 d = file->deps;
393 else
395 lastd->next = d->next;
396 free ((char *) d);
397 d = lastd->next;
399 continue;
402 d->file->parent = file;
403 dep_status |= check_dep (d->file, depth, this_mtime, &must_make);
404 check_renamed (d->file);
407 register struct file *f = d->file;
408 if (f->double_colon)
409 f = f->double_colon;
412 running |= (f->command_state == cs_running
413 || f->command_state == cs_deps_running);
414 f = f->prev;
416 while (f != 0);
419 if (dep_status != 0 && !keep_going_flag)
420 break;
422 if (!running)
423 d->changed = file_mtime (d->file) != mtime;
425 lastd = d;
426 d = d->next;
429 /* Now we know whether this target needs updating.
430 If it does, update all the intermediate files we depend on. */
432 if (must_make)
434 for (d = file->deps; d != 0; d = d->next)
435 if (d->file->intermediate)
437 time_t mtime = file_mtime (d->file);
438 check_renamed (d->file);
439 d->file->parent = file;
440 dep_status |= update_file (d->file, depth);
441 check_renamed (d->file);
444 register struct file *f = d->file;
445 if (f->double_colon)
446 f = f->double_colon;
449 running |= (f->command_state == cs_running
450 || f->command_state == cs_deps_running);
451 f = f->prev;
453 while (f != 0);
456 if (dep_status != 0 && !keep_going_flag)
457 break;
459 if (!running)
460 d->changed = ((file->phony && file->cmds != 0)
461 || file_mtime (d->file) != mtime);
465 file->updating = 0;
467 DEBUGPR ("Finished dependencies of target file `%s'.\n");
469 if (running)
471 file->command_state = cs_deps_running;
472 --depth;
473 DEBUGPR ("The dependencies of `%s' are being made.\n");
474 return 0;
477 /* If any dependency failed, give up now. */
479 if (dep_status != 0)
481 file->command_state = cs_finished;
482 file->update_status = dep_status;
483 file->updated = 1;
485 depth--;
487 DEBUGPR ("Giving up on target file `%s'.\n");
489 if (depth == 0 && keep_going_flag
490 && !just_print_flag && !question_flag)
491 error ("Target `%s' not remade because of errors.", file->name);
493 return dep_status;
496 file->command_state = cs_not_started;
498 /* Now record which dependencies are more
499 recent than this file, so we can define $?. */
501 deps_changed = 0;
502 for (d = file->deps; d != 0; d = d->next)
504 time_t d_mtime = file_mtime (d->file);
505 check_renamed (d->file);
507 #if 1 /* %%% In version 4, remove this code completely to
508 implement not remaking deps if their deps are newer
509 than their parents. */
510 if (d_mtime == (time_t) -1 && !d->file->intermediate)
511 /* We must remake if this dep does not
512 exist and is not intermediate. */
513 must_make = 1;
514 #endif
516 /* Set DEPS_CHANGED if this dep actually changed. */
517 deps_changed |= d->changed;
519 /* Set D->changed if either this dep actually changed,
520 or its dependent, FILE, is older or does not exist. */
521 d->changed |= noexist || d_mtime > this_mtime;
523 if (debug_flag && !noexist)
525 print_spaces (depth);
526 if (d_mtime == (time_t) -1)
527 printf ("Dependency `%s' does not exist.\n", dep_name (d));
528 else
529 printf ("Dependency `%s' is %s than dependent `%s'.\n",
530 dep_name (d), d->changed ? "newer" : "older", file->name);
531 fflush (stdout);
535 /* Here depth returns to the value it had when we were called. */
536 depth--;
538 if (file->double_colon && file->deps == 0)
540 must_make = 1;
541 DEBUGPR ("Target `%s' is double-colon and has no dependencies.\n");
543 else if (!noexist && file->is_target && !deps_changed && file->cmds == 0)
545 must_make = 0;
546 DEBUGPR ("No commands for `%s' and no dependencies actually changed.\n");
549 if (!must_make)
551 DEBUGPR ("No need to remake target `%s'.\n");
552 file->command_state = cs_finished;
553 file->update_status = 0;
554 file->updated = 1;
555 return 0;
558 DEBUGPR ("Must remake target `%s'.\n");
560 /* Now, take appropriate actions to remake the file. */
561 remake_file (file);
563 if (file->command_state != cs_finished)
565 DEBUGPR ("Commands of `%s' are being run.\n");
566 return 0;
569 switch (file->update_status)
571 case 1:
572 DEBUGPR ("Failed to remake target file `%s'.\n");
573 break;
574 case 0:
575 DEBUGPR ("Successfully remade target file `%s'.\n");
576 break;
577 case -1:
578 error ("internal error: `%s' update_status is -1 at cs_finished!",
579 file->name);
580 abort ();
581 default:
582 error ("internal error: `%s' update_status invalid!", file->name);
583 abort ();
586 file->updated = 1;
587 return file->update_status;
590 /* Set FILE's `updated' flag and re-check its mtime and the mtime's of all
591 files listed in its `also_make' member. Under -t, this function also
592 touches FILE. */
594 void
595 notice_finished_file (file)
596 register struct file *file;
598 struct dep *d;
600 file->command_state = cs_finished;
601 file->updated = 1;
603 if (touch_flag
604 /* The update status will be:
605 -1 if no commands were run;
606 0 if some commands (+ or ${MAKE}) were run and won;
607 1 if some commands were run and lost.
608 The only time we don't want to touch the target is if
609 it had some recursive commands, and they lost. */
610 && file->update_status != 1)
612 if (file->cmds != 0 && file->cmds->any_recurse)
614 /* If all the command lines were recursive,
615 we don't want to do the touching. */
616 unsigned int i;
617 for (i = 0; i < file->cmds->ncommand_lines; ++i)
618 if (!(file->cmds->lines_flags[i] & COMMANDS_RECURSE))
619 goto have_nonrecursing;
621 else
623 have_nonrecursing:
624 if (file->phony)
625 file->update_status = 0;
626 else
627 /* Should set file's modification date and do nothing else. */
628 file->update_status = touch_file (file);
632 if (!file->phony)
634 struct file *f;
636 if (just_print_flag || question_flag
637 || (file->is_target && file->cmds == 0))
638 file->last_mtime = NEW_MTIME;
639 else
640 file->last_mtime = 0;
642 /* Propagate the change of modification time to all the double-colon
643 entries for this file. */
644 for (f = file->double_colon; f != 0; f = f->next)
645 f->last_mtime = file->last_mtime;
648 if (file->update_status != -1)
649 /* We actually tried to update FILE, which has
650 updated its also_make's as well (if it worked).
651 If it didn't work, it wouldn't work again for them.
652 So mark them as updated with the same status. */
653 for (d = file->also_make; d != 0; d = d->next)
655 d->file->command_state = cs_finished;
656 d->file->updated = 1;
657 d->file->update_status = file->update_status;
659 if (!d->file->phony)
660 /* Fetch the new modification time.
661 We do this instead of just invalidating the cached time
662 so that a vpath_search can happen. Otherwise, it would
663 never be done because the target is already updated. */
664 (void) f_mtime (d->file, 0);
668 /* Check whether another file (whose mtime is THIS_MTIME)
669 needs updating on account of a dependency which is file FILE.
670 If it does, store 1 in *MUST_MAKE_PTR.
671 In the process, update any non-intermediate files
672 that FILE depends on (including FILE itself).
673 Return nonzero if any updating failed. */
675 static int
676 check_dep (file, depth, this_mtime, must_make_ptr)
677 struct file *file;
678 unsigned int depth;
679 time_t this_mtime;
680 int *must_make_ptr;
682 register struct dep *d;
683 int dep_status = 0;
685 ++depth;
686 file->updating = 1;
688 if (!file->intermediate)
689 /* If this is a non-intermediate file, update it and record
690 whether it is newer than THIS_MTIME. */
692 time_t mtime;
693 dep_status = update_file (file, depth);
694 check_renamed (file);
695 mtime = file_mtime (file);
696 check_renamed (file);
697 if (mtime == (time_t) -1 || mtime > this_mtime)
698 *must_make_ptr = 1;
700 else
702 /* FILE is an intermediate file.
703 Update all non-intermediate files we depend on, if necessary,
704 and see whether any of them is more recent than the file
705 on whose behalf we are checking. */
706 register struct dep *lastd;
707 lastd = 0;
708 d = file->deps;
709 while (d != 0)
711 if (d->file->updating)
713 error ("Circular %s <- %s dependency dropped.",
714 file->name, d->file->name);
715 if (lastd == 0)
717 file->deps = d->next;
718 free ((char *) d);
719 d = file->deps;
721 else
723 lastd->next = d->next;
724 free ((char *) d);
725 d = lastd->next;
727 continue;
730 d->file->parent = file;
731 dep_status |= check_dep (d->file, depth, this_mtime, must_make_ptr);
732 check_renamed (d->file);
733 if (dep_status != 0 && !keep_going_flag)
734 break;
736 if (d->file->command_state == cs_running
737 || d->file->command_state == cs_deps_running)
738 /* Record that some of FILE's dependencies are still being made.
739 This tells the upper levels to wait on processing it until
740 the commands are finished. */
741 file->command_state = cs_deps_running;
743 lastd = d;
744 d = d->next;
748 file->updating = 0;
749 return dep_status;
752 /* Touch FILE. Return zero if successful, one if not. */
754 #define TOUCH_ERROR(call) return (perror_with_name (call, file->name), 1)
756 static int
757 touch_file (file)
758 register struct file *file;
760 if (!silent_flag)
762 printf ("touch %s\n", file->name);
763 fflush (stdout);
766 #ifndef NO_ARCHIVES
767 if (ar_name (file->name))
768 return ar_touch (file->name);
769 else
770 #endif
772 int fd = open (file->name, O_RDWR | O_CREAT, 0666);
774 if (fd < 0)
775 TOUCH_ERROR ("touch: open: ");
776 else
778 struct stat statbuf;
779 char buf;
781 if (fstat (fd, &statbuf) < 0)
782 TOUCH_ERROR ("touch: fstat: ");
783 /* Rewrite character 0 same as it already is. */
784 if (read (fd, &buf, 1) < 0)
785 TOUCH_ERROR ("touch: read: ");
786 if (lseek (fd, 0L, 0) < 0L)
787 TOUCH_ERROR ("touch: lseek: ");
788 if (write (fd, &buf, 1) < 0)
789 TOUCH_ERROR ("touch: write: ");
790 /* If file length was 0, we just
791 changed it, so change it back. */
792 if (statbuf.st_size == 0)
794 (void) close (fd);
795 fd = open (file->name, O_RDWR | O_TRUNC, 0666);
796 if (fd < 0)
797 TOUCH_ERROR ("touch: open: ");
799 (void) close (fd);
803 return 0;
806 /* Having checked and updated the dependencies of FILE,
807 do whatever is appropriate to remake FILE itself.
808 Return the status from executing FILE's commands. */
810 static void
811 remake_file (file)
812 struct file *file;
814 if (file->cmds == 0)
816 if (file->phony)
817 /* Phony target. Pretend it succeeded. */
818 file->update_status = 0;
819 else if (file->is_target)
820 /* This is a nonexistent target file we cannot make.
821 Pretend it was successfully remade. */
822 file->update_status = 0;
823 else
825 /* This is a dependency file we cannot remake. Fail. */
826 static char noway[] = "No rule to make target";
827 if (keep_going_flag || file->dontcare)
829 if (!file->dontcare)
830 error ("*** %s `%s'.", noway, file->name);
831 file->update_status = 1;
833 else
834 fatal ("%s `%s'", noway, file->name);
837 else
839 chop_commands (file->cmds);
841 if (!touch_flag || file->cmds->any_recurse)
843 execute_file_commands (file);
844 return;
848 /* This does the touching under -t. */
849 notice_finished_file (file);
852 /* Return the mtime of a file, given a `struct file'.
853 Caches the time in the struct file to avoid excess stat calls.
855 If the file is not found, and SEARCH is nonzero, VPATH searching and
856 replacement is done. If that fails, a library (-lLIBNAME) is tried and
857 the library's actual name (/lib/libLIBNAME.a, etc.) is substituted into
858 FILE. */
860 time_t
861 f_mtime (file, search)
862 register struct file *file;
863 int search;
865 time_t mtime;
867 /* File's mtime is not known; must get it from the system. */
869 #ifndef NO_ARCHIVES
870 if (ar_name (file->name))
872 /* This file is an archive-member reference. */
874 char *arname, *memname;
875 struct file *arfile;
876 int arname_used = 0;
878 /* Find the archive's name. */
879 ar_parse_name (file->name, &arname, &memname);
881 /* Find the modification time of the archive itself.
882 Also allow for its name to be changed via VPATH search. */
883 arfile = lookup_file (arname);
884 if (arfile == 0)
886 arfile = enter_file (arname);
887 arname_used = 1;
889 mtime = f_mtime (arfile, search);
890 check_renamed (arfile);
891 if (search && strcmp (arfile->name, arname))
893 /* The archive's name has changed.
894 Change the archive-member reference accordingly. */
896 unsigned int arlen, memlen;
898 if (!arname_used)
900 free (arname);
901 arname_used = 1;
904 arname = arfile->name;
905 arlen = strlen (arname);
906 memlen = strlen (memname);
908 free (file->name);
910 file->name = (char *) xmalloc (arlen + 1 + memlen + 2);
911 bcopy (arname, file->name, arlen);
912 file->name[arlen] = '(';
913 bcopy (memname, file->name + arlen + 1, memlen);
914 file->name[arlen + 1 + memlen] = ')';
915 file->name[arlen + 1 + memlen + 1] = '\0';
918 if (!arname_used)
919 free (arname);
920 free (memname);
922 if (mtime == (time_t) -1)
923 /* The archive doesn't exist, so it's members don't exist either. */
924 return (time_t) -1;
926 mtime = ar_member_date (file->name);
928 else
929 #endif
931 mtime = name_mtime (file->name);
933 if (mtime == (time_t) -1 && search)
935 /* If name_mtime failed, search VPATH. */
936 char *name = file->name;
937 if (vpath_search (&name, &mtime)
938 /* Last resort, is it a library (-lxxx)? */
939 || (name[0] == '-' && name[1] == 'l'
940 && library_search (&name, &mtime)))
942 if (mtime != 0)
943 /* vpath_search and library_search store zero in MTIME
944 if they didn't need to do a stat call for their work. */
945 file->last_mtime = mtime;
946 rename_file (file, name);
947 check_renamed (file);
948 return file_mtime (file);
953 /* Store the mtime into all the entries for this file. */
954 if (file->double_colon)
955 file = file->double_colon;
958 file->last_mtime = mtime;
959 file = file->prev;
960 } while (file != 0);
962 return mtime;
966 /* Return the mtime of the file or archive-member reference NAME. */
968 static time_t
969 name_mtime (name)
970 register char *name;
972 struct stat st;
974 if (stat (name, &st) < 0)
975 return (time_t) -1;
977 return (time_t) st.st_mtime;
981 /* Search for a library file specified as -lLIBNAME, searching for a
982 suitable library file in the system library directories and the VPATH
983 directories. */
985 static int
986 library_search (lib, mtime_ptr)
987 char **lib;
988 time_t *mtime_ptr;
990 static char *dirs[] =
992 "/lib",
993 "/usr/lib",
994 LIBDIR, /* Defined by configuration. */
998 char *libname = &(*lib)[2]; /* Name without the `-l'. */
999 time_t mtime;
1001 /* Buffer to construct possible names in. */
1002 char *buf = xmalloc (sizeof (LIBDIR) + 8 + strlen (libname) + 4 + 2 + 1);
1003 char *file, **dp;
1005 /* Look first for `libNAME.a' in the current directory. */
1007 sprintf (buf, "lib%s.a", libname);
1008 mtime = name_mtime (buf);
1009 if (mtime != (time_t) -1)
1011 *lib = buf;
1012 if (mtime_ptr != 0)
1013 *mtime_ptr = mtime;
1014 return 1;
1017 /* Now try VPATH search on that. */
1019 file = buf;
1020 if (vpath_search (&file, mtime_ptr))
1022 free (buf);
1023 *lib = file;
1024 return 1;
1027 /* Now try the standard set of directories. */
1029 for (dp = dirs; *dp != 0; ++dp)
1031 sprintf (buf, "%s/lib%s.a", *dp, libname);
1032 mtime = name_mtime (buf);
1033 if (mtime != (time_t) -1)
1035 *lib = buf;
1036 if (mtime_ptr != 0)
1037 *mtime_ptr = mtime;
1038 return 1;
1042 free (buf);
1043 return 0;