7812 Remove gender specific language
[unleashed.git] / usr / src / cmd / make / bin / doname.cc
blobc97e1593a64290edc3d5d874cdebf3920523ac5f
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 * Copyright 2016 RackTop Systems.
26 * Copyright (c) 2016 by Delphix. All rights reserved.
30 * doname.c
32 * Figure out which targets are out of date and rebuild them
36 * Included files
38 #include <alloca.h> /* alloca() */
39 #include <fcntl.h>
40 #include <mk/defs.h>
41 #include <mksh/i18n.h> /* get_char_semantics_value() */
42 #include <mksh/macro.h> /* getvar(), expand_value() */
43 #include <mksh/misc.h> /* getmem() */
44 #include <poll.h>
45 #include <libintl.h>
46 #include <signal.h>
47 #include <stropts.h>
48 #include <sys/errno.h>
49 #include <sys/stat.h>
50 #include <sys/types.h>
51 #include <sys/utsname.h> /* uname() */
52 #include <sys/wait.h>
53 #include <unistd.h> /* close() */
56 * Defined macros
58 # define LOCALHOST "localhost"
60 #define MAXRULES 100
62 // Sleep for .1 seconds between stat()'s
63 const int STAT_RETRY_SLEEP_TIME = 100000;
66 * typedefs & structs
70 * Static variables
72 static char hostName[MAXNAMELEN] = "";
73 static char userName[MAXNAMELEN] = "";
76 static int second_pass = 0;
79 * File table of contents
81 extern Doname doname_check(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic);
82 extern Doname doname(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic);
83 static Boolean check_dependencies(Doname *result, Property line, Boolean do_get, Name target, Name true_target, Boolean doing_subtree, Chain *out_of_date_tail, Property old_locals, Boolean implicit, Property *command, Name less, Boolean rechecking_target, Boolean recheck_conditionals);
84 void dynamic_dependencies(Name target);
85 static Doname run_command(register Property line, Boolean print_machine);
86 extern Doname execute_serial(Property line);
87 extern Name vpath_translation(register Name cmd);
88 extern void check_state(Name temp_file_name);
89 static void read_dependency_file(register Name filename);
90 static void check_read_state_file(void);
91 static void do_assign(register Name line, register Name target);
92 static void build_command_strings(Name target, register Property line);
93 static Doname touch_command(register Property line, register Name target, Doname result);
94 extern void update_target(Property line, Doname result);
95 static Doname sccs_get(register Name target, register Property *command);
96 extern void read_directory_of_file(register Name file);
97 static void add_pattern_conditionals(register Name target);
98 extern void set_locals(register Name target, register Property old_locals);
99 extern void reset_locals(register Name target, register Property old_locals, register Property conditional, register int index);
100 extern Boolean check_auto_dependencies(Name target, int auto_count, Name *automatics);
101 static void delete_query_chain(Chain ch);
103 // From read2.cc
104 extern Name normalize_name(register wchar_t *name_string, register int length);
109 * DONE.
111 * doname_check(target, do_get, implicit, automatic)
113 * Will call doname() and then inspect the return value
115 * Return value:
116 * Indication if the build failed or not
118 * Parameters:
119 * target The target to build
120 * do_get Passed thru to doname()
121 * implicit Passed thru to doname()
122 * automatic Are we building a hidden dependency?
124 * Global variables used:
125 * build_failed_seen Set if -k is on and error occurs
126 * continue_after_error Indicates that -k is on
127 * report_dependencies No error msg if -P is on
129 Doname
130 doname_check(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic)
132 int first_time = 1;
133 (void) fflush(stdout);
134 try_again:
135 switch (doname(target, do_get, implicit, automatic)) {
136 case build_ok:
137 second_pass = 0;
138 return build_ok;
139 case build_running:
140 second_pass = 0;
141 return build_running;
142 case build_failed:
143 if (!continue_after_error) {
144 fatal(gettext("Target `%s' not remade because of errors"),
145 target->string_mb);
147 build_failed_seen = true;
148 second_pass = 0;
149 return build_failed;
150 case build_dont_know:
152 * If we can't figure out how to build an automatic
153 * (hidden) dependency, we just ignore it.
154 * We later declare the target to be out of date just in
155 * case something changed.
156 * Also, don't complain if just reporting the dependencies
157 * and not building anything.
159 if (automatic || (report_dependencies_level > 0)) {
160 second_pass = 0;
161 return build_dont_know;
163 if(first_time) {
164 first_time = 0;
165 second_pass = 1;
166 goto try_again;
168 second_pass = 0;
169 if (continue_after_error && !svr4) {
170 warning(gettext("Don't know how to make target `%s'"),
171 target->string_mb);
172 build_failed_seen = true;
173 return build_failed;
175 fatal(gettext("Don't know how to make target `%s'"), target->string_mb);
176 break;
178 #ifdef lint
179 return build_failed;
180 #endif
184 void
185 enter_explicit_rule_from_dynamic_rule(Name target, Name source)
187 Property line, source_line;
188 Dependency dependency;
190 source_line = get_prop(source->prop, line_prop);
191 line = maybe_append_prop(target, line_prop);
192 line->body.line.sccs_command = false;
193 line->body.line.target = target;
194 if (line->body.line.command_template == NULL) {
195 line->body.line.command_template = source_line->body.line.command_template;
196 for (dependency = source_line->body.line.dependencies;
197 dependency != NULL;
198 dependency = dependency->next) {
199 enter_dependency(line, dependency->name, false);
201 line->body.line.less = target;
203 line->body.line.percent = NULL;
208 Name
209 find_dyntarget(Name target)
211 Dyntarget p;
212 int i;
213 String_rec string;
214 wchar_t buffer[STRING_BUFFER_LENGTH];
215 wchar_t *pp, * bufend;
216 wchar_t tbuffer[MAXPATHLEN];
217 Wstring wcb(target);
219 for (p = dyntarget_list; p != NULL; p = p->next) {
220 INIT_STRING_FROM_STACK(string, buffer);
221 expand_value(p->name, &string, false);
222 i = 0;
223 pp = string.buffer.start;
224 bufend = pp + STRING_BUFFER_LENGTH;
225 while((*pp != nul_char) && (pp < bufend)) {
226 if(iswspace(*pp)) {
227 tbuffer[i] = nul_char;
228 if(i > 0) {
229 if (wcb.equal(tbuffer)) {
230 enter_explicit_rule_from_dynamic_rule(target, p->name);
231 return(target);
234 pp++;
235 i = 0;
236 continue;
238 tbuffer[i] = *pp;
239 i++;
240 pp++;
241 if(*pp == nul_char) {
242 tbuffer[i] = nul_char;
243 if(i > 0) {
244 if (wcb.equal(tbuffer)) {
245 enter_explicit_rule_from_dynamic_rule(target, p->name);
246 return(target);
249 break;
253 return(NULL);
257 * DONE.
259 * doname(target, do_get, implicit)
261 * Chases all files the target depends on and builds any that
262 * are out of date. If the target is out of date it is then rebuilt.
264 * Return value:
265 * Indiates if build failed or nt
267 * Parameters:
268 * target Target to build
269 * do_get Run sccs get is nessecary
270 * implicit doname is trying to find an implicit rule
272 * Global variables used:
273 * assign_done True if command line assgnment has happened
274 * commands_done Preserved for the case that we need local value
275 * debug_level Should we trace make's actions?
276 * default_rule The rule for ".DEFAULT", used as last resort
277 * empty_name The Name "", used when looking for single sfx
278 * keep_state Indicates that .KEEP_STATE is on
279 * parallel True if building in parallel
280 * recursion_level Used for tracing
281 * report_dependencies make -P is on
283 Doname
284 doname(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic)
286 Doname result = build_dont_know;
287 Chain out_of_date_list = NULL;
288 Chain target_group;
289 Property old_locals = NULL;
290 register Property line;
291 Property command = NULL;
292 register Dependency dependency;
293 Name less = NULL;
294 Name true_target = target;
295 Name *automatics = NULL;
296 register int auto_count;
297 Boolean rechecking_target = false;
298 Boolean saved_commands_done;
299 Boolean restart = false;
300 Boolean save_parallel = parallel;
301 Boolean doing_subtree = false;
303 Boolean recheck_conditionals = false;
305 if (target->state == build_running) {
306 return build_running;
308 line = get_prop(target->prop, line_prop);
309 if (line != NULL) {
311 * If this target is a member of target group and one of the
312 * other members of the group is running, mark this target
313 * as running.
315 for (target_group = line->body.line.target_group;
316 target_group != NULL;
317 target_group = target_group->next) {
318 if (is_running(target_group->name)) {
319 target->state = build_running;
320 add_pending(target,
321 recursion_level,
322 do_get,
323 implicit,
324 false);
325 return build_running;
330 * If the target is a constructed one for a "::" target,
331 * we need to consider that.
333 if (target->has_target_prop) {
334 true_target = get_prop(target->prop,
335 target_prop)->body.target.target;
336 if (true_target->colon_splits > 0) {
337 /* Make sure we have a valid time for :: targets */
338 Property time;
340 time = get_prop(true_target->prop, time_prop);
341 if (time != NULL) {
342 true_target->stat.time = time->body.time.time;
346 (void) exists(true_target);
348 * If the target has been processed, we don't need to do it again,
349 * unless it depends on conditional macros or a delayed assignment,
350 * or it has been done when KEEP_STATE is on.
352 if (target->state == build_ok) {
353 if((!keep_state || (!target->depends_on_conditional && !assign_done))) {
354 return build_ok;
355 } else {
356 recheck_conditionals = true;
359 if (target->state == build_subtree) {
360 /* A dynamic macro subtree is being built */
361 target->state = build_dont_know;
362 doing_subtree = true;
363 if (!target->checking_subtree) {
365 * This target has been started before and therefore
366 * not all dependencies have to be built.
368 restart = true;
370 } else if (target->state == build_pending) {
371 target->state = build_dont_know;
372 restart = true;
374 } else if (parallel &&
375 keep_state &&
376 (target->conditional_cnt > 0)) {
377 if (!parallel_ok(target, false)) {
378 add_subtree(target, recursion_level, do_get, implicit);
379 target->state = build_running;
380 return build_running;
385 * If KEEP_STATE is on, we have to rebuild the target if the
386 * building of it caused new automatic dependencies to be reported.
387 * This is where we restart the build.
389 if (line != NULL) {
390 line->body.line.percent = NULL;
392 recheck_target:
393 /* Init all local variables */
394 result = build_dont_know;
395 out_of_date_list = NULL;
396 command = NULL;
397 less = NULL;
398 auto_count = 0;
399 if (!restart && line != NULL) {
401 * If this target has never been built before, mark all
402 * of the dependencies as never built.
404 for (dependency = line->body.line.dependencies;
405 dependency != NULL;
406 dependency = dependency->next) {
407 dependency->built = false;
410 /* Save the set of automatic depes defined for this target */
411 if (keep_state &&
412 (line != NULL) &&
413 (line->body.line.dependencies != NULL)) {
414 Name *p;
417 * First run thru the dependency list to see how many
418 * autos there are.
420 for (dependency = line->body.line.dependencies;
421 dependency != NULL;
422 dependency = dependency->next) {
423 if (dependency->automatic && !dependency->stale) {
424 auto_count++;
427 /* Create vector to hold the current autos */
428 automatics =
429 (Name *) alloca((int) (auto_count * sizeof (Name)));
430 /* Copy them */
431 for (p = automatics, dependency = line->body.line.dependencies;
432 dependency != NULL;
433 dependency = dependency->next) {
434 if (dependency->automatic && !dependency->stale) {
435 *p++ = dependency->name;
439 if (debug_level > 1) {
440 (void) printf("%*sdoname(%s)\n",
441 recursion_level,
443 target->string_mb);
445 recursion_level++;
446 /* Avoid infinite loops */
447 if (target->state == build_in_progress) {
448 warning(gettext("Infinite loop: Target `%s' depends on itself"),
449 target->string_mb);
450 return build_ok;
452 target->state = build_in_progress;
454 /* Activate conditional macros for the target */
455 if (!target->added_pattern_conditionals) {
456 add_pattern_conditionals(target);
457 target->added_pattern_conditionals = true;
459 if (target->conditional_cnt > 0) {
460 old_locals = (Property) alloca(target->conditional_cnt *
461 sizeof (Property_rec));
462 set_locals(target, old_locals);
466 * after making the call to dynamic_dependecies unconditional we can handle
467 * target names that are same as file name. In this case $$@ in the
468 * dependencies did not mean anything. WIth this change it expands it
469 * as expected.
471 if (!target->has_depe_list_expanded)
473 dynamic_dependencies(target);
477 * FIRST SECTION -- GO THROUGH DEPENDENCIES AND COLLECT EXPLICIT
478 * COMMANDS TO RUN
480 if ((line = get_prop(target->prop, line_prop)) != NULL) {
481 if (check_dependencies(&result,
482 line,
483 do_get,
484 target,
485 true_target,
486 doing_subtree,
487 &out_of_date_list,
488 old_locals,
489 implicit,
490 &command,
491 less,
492 rechecking_target,
493 recheck_conditionals)) {
494 return build_running;
496 if (line->body.line.query != NULL) {
497 delete_query_chain(line->body.line.query);
499 line->body.line.query = out_of_date_list;
504 * If the target is a :: type, do not try to find the rule for the target,
505 * all actions will be taken by separate branches.
506 * Else, we try to find an implicit rule using various methods,
507 * we quit as soon as one is found.
509 * [tolik, 12 Sep 2002] Do not try to find implicit rule for the target
510 * being rechecked - the target is being rechecked means that it already
511 * has explicit dependencies derived from an implicit rule found
512 * in previous step.
514 if (target->colon_splits == 0 && !rechecking_target) {
515 /* Look for percent matched rule */
516 if ((result == build_dont_know) &&
517 (command == NULL)) {
518 switch (find_percent_rule(
519 target,
520 &command,
521 recheck_conditionals)) {
522 case build_failed:
523 result = build_failed;
524 break;
525 case build_running:
526 target->state = build_running;
527 add_pending(target,
528 --recursion_level,
529 do_get,
530 implicit,
531 false);
532 if (target->conditional_cnt > 0) {
533 reset_locals(target,
534 old_locals,
535 get_prop(target->prop,
536 conditional_prop),
539 return build_running;
540 case build_ok:
541 result = build_ok;
542 break;
545 /* Look for double suffix rule */
546 if (result == build_dont_know) {
547 Property member;
549 if (target->is_member &&
550 ((member = get_prop(target->prop, member_prop)) !=
551 NULL)) {
552 switch (find_ar_suffix_rule(target,
553 member->body.
554 member.member,
555 &command,
556 recheck_conditionals)) {
557 case build_failed:
558 result = build_failed;
559 break;
560 case build_running:
561 target->state = build_running;
562 add_pending(target,
563 --recursion_level,
564 do_get,
565 implicit,
566 false);
567 if (target->conditional_cnt > 0) {
568 reset_locals(target,
569 old_locals,
570 get_prop(target->prop,
571 conditional_prop),
574 return build_running;
575 default:
576 /* ALWAYS bind $% for old style */
577 /* ar rules */
578 if (line == NULL) {
579 line =
580 maybe_append_prop(target,
581 line_prop);
583 line->body.line.percent =
584 member->body.member.member;
585 break;
587 } else {
588 switch (find_double_suffix_rule(target,
589 &command,
590 recheck_conditionals)) {
591 case build_failed:
592 result = build_failed;
593 break;
594 case build_running:
595 target->state = build_running;
596 add_pending(target,
597 --recursion_level,
598 do_get,
599 implicit,
600 false);
601 if (target->conditional_cnt > 0) {
602 reset_locals(target,
603 old_locals,
604 get_prop(target->
605 prop,
606 conditional_prop),
609 return build_running;
613 /* Look for single suffix rule */
615 /* /tolik/
616 * I commented !implicit to fix bug 1247448: Suffix Rules failed when combine with Pattern Matching Rules.
617 * This caused problem with SVR4 tilde rules (infinite recursion). So I made some changes in "implicit.cc"
619 /* /tolik, 06.21.96/
620 * Regression! See BugId 1255360
621 * If more than one percent rules are defined for the same target then
622 * the behaviour of 'make' with my previous fix may be different from one
623 * of the 'old make'.
624 * The global variable second_pass (maybe it should be an argument to doname())
625 * is intended to avoid this regression. It is set in doname_check().
626 * First, 'make' will work as it worked before. Only when it is
627 * going to say "don't know how to make target" it sets second_pass to true and
628 * run 'doname' again but now trying to use Single Suffix Rules.
630 if ((result == build_dont_know) && !automatic && (!implicit || second_pass) &&
631 ((line == NULL) ||
632 ((line->body.line.target != NULL) &&
633 !line->body.line.target->has_regular_dependency))) {
634 switch (find_suffix_rule(target,
635 target,
636 empty_name,
637 &command,
638 recheck_conditionals)) {
639 case build_failed:
640 result = build_failed;
641 break;
642 case build_running:
643 target->state = build_running;
644 add_pending(target,
645 --recursion_level,
646 do_get,
647 implicit,
648 false);
649 if (target->conditional_cnt > 0) {
650 reset_locals(target,
651 old_locals,
652 get_prop(target->prop,
653 conditional_prop),
656 return build_running;
659 /* Try to sccs get */
660 if ((command == NULL) &&
661 (result == build_dont_know) &&
662 do_get) {
663 result = sccs_get(target, &command);
666 /* Use .DEFAULT rule if it is defined. */
667 if ((command == NULL) &&
668 (result == build_dont_know) &&
669 (true_target->colons == no_colon) &&
670 default_rule &&
671 !implicit) {
672 /* Make sure we have a line prop */
673 line = maybe_append_prop(target, line_prop);
674 command = line;
675 Boolean out_of_date;
676 if (true_target->is_member) {
677 out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
678 line->body.line.dependency_time);
679 } else {
680 out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
681 line->body.line.dependency_time);
683 if (build_unconditional || out_of_date) {
684 line->body.line.is_out_of_date = true;
685 if (debug_level > 0) {
686 (void) printf(gettext("%*sBuilding %s using .DEFAULT because it is out of date\n"),
687 recursion_level,
689 true_target->string_mb);
692 line->body.line.sccs_command = false;
693 line->body.line.command_template = default_rule;
694 line->body.line.target = true_target;
695 line->body.line.star = NULL;
696 line->body.line.less = true_target;
697 line->body.line.percent = NULL;
701 /* We say "target up to date" if no cmd were executed for the target */
702 if (!target->is_double_colon_parent) {
703 commands_done = false;
706 silent = silent_all;
707 ignore_errors = ignore_errors_all;
708 if (posix)
710 if (!silent)
712 silent = (Boolean) target->silent_mode;
714 if (!ignore_errors)
716 ignore_errors = (Boolean) target->ignore_error_mode;
720 int doname_dyntarget = 0;
721 r_command:
722 /* Run commands if any. */
723 if ((command != NULL) &&
724 (command->body.line.command_template != NULL)) {
725 if (result != build_failed) {
726 result = run_command(command,
727 (Boolean) ((parallel || save_parallel) && !silent));
729 switch (result) {
730 case build_running:
731 add_running(target,
732 true_target,
733 command,
734 --recursion_level,
735 auto_count,
736 automatics,
737 do_get,
738 implicit);
739 target->state = build_running;
740 if ((line = get_prop(target->prop,
741 line_prop)) != NULL) {
742 if (line->body.line.query != NULL) {
743 delete_query_chain(line->body.line.query);
745 line->body.line.query = NULL;
747 if (target->conditional_cnt > 0) {
748 reset_locals(target,
749 old_locals,
750 get_prop(target->prop,
751 conditional_prop),
754 return build_running;
755 case build_serial:
756 add_serial(target,
757 --recursion_level,
758 do_get,
759 implicit);
760 target->state = build_running;
761 line = get_prop(target->prop, line_prop);
762 if (line != NULL) {
763 if (line->body.line.query != NULL) {
764 delete_query_chain(line->body.line.query);
766 line->body.line.query = NULL;
768 if (target->conditional_cnt > 0) {
769 reset_locals(target,
770 old_locals,
771 get_prop(target->prop,
772 conditional_prop),
775 return build_running;
776 case build_ok:
777 /* If all went OK set a nice timestamp */
778 if (true_target->stat.time == file_doesnt_exist) {
779 true_target->stat.time = file_max_time;
781 break;
783 } else {
785 * If no command was found for the target, and it doesn't
786 * exist, and it is mentioned as a target in the makefile,
787 * we say it is extremely new and that it is OK.
789 if (target->colons != no_colon) {
790 if (true_target->stat.time == file_doesnt_exist){
791 true_target->stat.time = file_max_time;
793 result = build_ok;
796 * Trying dynamic targets.
798 if(!doname_dyntarget) {
799 doname_dyntarget = 1;
800 Name dtarg = find_dyntarget(target);
801 if(dtarg!=NULL) {
802 if (!target->has_depe_list_expanded) {
803 dynamic_dependencies(target);
805 if ((line = get_prop(target->prop, line_prop)) != NULL) {
806 if (check_dependencies(&result,
807 line,
808 do_get,
809 target,
810 true_target,
811 doing_subtree,
812 &out_of_date_list,
813 old_locals,
814 implicit,
815 &command,
816 less,
817 rechecking_target,
818 recheck_conditionals))
820 return build_running;
822 if (line->body.line.query != NULL) {
823 delete_query_chain(line->body.line.query);
825 line->body.line.query = out_of_date_list;
827 goto r_command;
831 * If the file exists, it is OK that we couldnt figure
832 * out how to build it.
834 (void) exists(target);
835 if ((target->stat.time != file_doesnt_exist) &&
836 (result == build_dont_know)) {
837 result = build_ok;
842 * Some of the following is duplicated in the function finish_doname.
843 * If anything is changed here, check to see if it needs to be
844 * changed there.
846 if ((line = get_prop(target->prop, line_prop)) != NULL) {
847 if (line->body.line.query != NULL) {
848 delete_query_chain(line->body.line.query);
850 line->body.line.query = NULL;
852 target->state = result;
853 parallel = save_parallel;
854 if (target->conditional_cnt > 0) {
855 reset_locals(target,
856 old_locals,
857 get_prop(target->prop, conditional_prop),
860 recursion_level--;
861 if (target->is_member) {
862 Property member;
864 /* Propagate the timestamp from the member file to the member*/
865 if ((target->stat.time != file_max_time) &&
866 ((member = get_prop(target->prop, member_prop)) != NULL) &&
867 (exists(member->body.member.member) > file_doesnt_exist)) {
868 target->stat.time =
869 member->body.member.member->stat.time;
873 * Check if we found any new auto dependencies when we
874 * built the target.
876 if ((result == build_ok) && check_auto_dependencies(target,
877 auto_count,
878 automatics)) {
879 if (debug_level > 0) {
880 (void) printf(gettext("%*sTarget `%s' acquired new dependencies from build, rechecking all dependencies\n"),
881 recursion_level,
883 true_target->string_mb);
885 rechecking_target = true;
886 saved_commands_done = commands_done;
887 goto recheck_target;
890 if (rechecking_target && !commands_done) {
891 commands_done = saved_commands_done;
894 return result;
898 * DONE.
900 * check_dependencies(result, line, do_get,
901 * target, true_target, doing_subtree, out_of_date_tail,
902 * old_locals, implicit, command, less, rechecking_target)
904 * Return value:
905 * True returned if some dependencies left running
907 * Parameters:
908 * result Pointer to cell we update if build failed
909 * line We get the dependencies from here
910 * do_get Allow use of sccs get in recursive doname()
911 * target The target to chase dependencies for
912 * true_target The real one for :: and lib(member)
913 * doing_subtree True if building a conditional macro subtree
914 * out_of_date_tail Used to set the $? list
915 * old_locals Used for resetting the local macros
916 * implicit Called when scanning for implicit rules?
917 * command Place to stuff command
918 * less Set to $< value
920 * Global variables used:
921 * command_changed Set if we suspect .make.state needs rewrite
922 * debug_level Should we trace actions?
923 * force The Name " FORCE", compared against
924 * recursion_level Used for tracing
925 * rewrite_statefile Set if .make.state needs rewriting
926 * wait_name The Name ".WAIT", compared against
928 static Boolean
929 check_dependencies(Doname *result, Property line, Boolean do_get, Name target, Name true_target, Boolean doing_subtree, Chain *out_of_date_tail, Property old_locals, Boolean implicit, Property *command, Name less, Boolean rechecking_target, Boolean recheck_conditionals)
931 Boolean dependencies_running;
932 register Dependency dependency;
933 Doname dep_result;
934 Boolean dependency_changed = false;
936 line->body.line.dependency_time = file_doesnt_exist;
937 if (line->body.line.query != NULL) {
938 delete_query_chain(line->body.line.query);
940 line->body.line.query = NULL;
941 line->body.line.is_out_of_date = false;
942 dependencies_running = false;
944 * Run thru all the dependencies and call doname() recursively
945 * on each of them.
947 for (dependency = line->body.line.dependencies;
948 dependency != NULL;
949 dependency = dependency->next) {
950 Boolean this_dependency_changed = false;
952 if (!dependency->automatic &&
953 (rechecking_target || target->rechecking_target)) {
955 * We only bother with the autos when rechecking
957 continue;
960 if (dependency->name == wait_name) {
962 * The special target .WAIT means finish all of
963 * the prior dependencies before continuing.
965 if (dependencies_running) {
966 break;
968 } else if ((!parallel_ok(dependency->name, false)) &&
969 (dependencies_running)) {
971 * If we can't execute the current dependency in
972 * parallel, hold off the dependency processing
973 * to preserve the order of the dependencies.
975 break;
976 } else {
977 timestruc_t depe_time = file_doesnt_exist;
980 if (true_target->is_member) {
981 depe_time = exists(dependency->name);
983 if (dependency->built ||
984 (dependency->name->state == build_failed)) {
985 dep_result = (Doname) dependency->name->state;
986 } else {
987 dep_result = doname_check(dependency->name,
988 do_get,
989 false,
990 (Boolean) dependency->automatic);
992 if (true_target->is_member || dependency->name->is_member) {
993 /* should compare only secs, cause lib members does not have nsec time resolution */
994 if (depe_time.tv_sec != dependency->name->stat.time.tv_sec) {
995 this_dependency_changed =
996 dependency_changed =
997 true;
999 } else {
1000 if (depe_time != dependency->name->stat.time) {
1001 this_dependency_changed =
1002 dependency_changed =
1003 true;
1006 dependency->built = true;
1007 switch (dep_result) {
1008 case build_running:
1009 dependencies_running = true;
1010 continue;
1011 case build_failed:
1012 *result = build_failed;
1013 break;
1014 case build_dont_know:
1016 * If make can't figure out how to make a dependency, maybe the dependency
1017 * is out of date. In this case, we just declare the target out of date
1018 * and go on. If we really need the dependency, the make'ing of the target
1019 * will fail. This will only happen for automatic (hidden) dependencies.
1021 if(!recheck_conditionals) {
1022 line->body.line.is_out_of_date = true;
1025 * Make sure the dependency is not saved
1026 * in the state file.
1028 dependency->stale = true;
1029 rewrite_statefile =
1030 command_changed =
1031 true;
1032 if (debug_level > 0) {
1033 (void) printf(gettext("Target %s rebuilt because dependency %s does not exist\n"),
1034 true_target->string_mb,
1035 dependency->name->string_mb);
1037 break;
1039 if (dependency->name->depends_on_conditional) {
1040 target->depends_on_conditional = true;
1042 if (dependency->name == force) {
1043 target->stat.time =
1044 dependency->name->stat.time;
1047 * Propagate new timestamp from "member" to
1048 * "lib.a(member)".
1050 (void) exists(dependency->name);
1052 /* Collect the timestamp of the youngest dependency */
1053 line->body.line.dependency_time =
1054 MAX(dependency->name->stat.time,
1055 line->body.line.dependency_time);
1057 /* Correction: do not consider nanosecs for members */
1058 if(true_target->is_member || dependency->name->is_member) {
1059 line->body.line.dependency_time.tv_nsec = 0;
1062 if (debug_level > 1) {
1063 (void) printf(gettext("%*sDate(%s)=%s \n"),
1064 recursion_level,
1066 dependency->name->string_mb,
1067 time_to_string(dependency->name->
1068 stat.time));
1069 if (dependency->name->stat.time > line->body.line.dependency_time) {
1070 (void) printf(gettext("%*sDate-dependencies(%s) set to %s\n"),
1071 recursion_level,
1073 true_target->string_mb,
1074 time_to_string(line->body.line.
1075 dependency_time));
1079 /* Build the $? list */
1080 if (true_target->is_member) {
1081 if (this_dependency_changed == true) {
1082 true_target->stat.time = dependency->name->stat.time;
1083 true_target->stat.time.tv_sec--;
1084 } else {
1085 /* Dina:
1086 * The next statement is commented
1087 * out as a fix for bug #1051032.
1088 * if dependency hasn't changed
1089 * then there's no need to invalidate
1090 * true_target. This statemnt causes
1091 * make to take much longer to process
1092 * an already-built archive. Soren
1093 * said it was a quick fix for some
1094 * problem he doesn't remember.
1095 true_target->stat.time = file_no_time;
1097 (void) exists(true_target);
1099 } else {
1100 (void) exists(true_target);
1102 Boolean out_of_date;
1103 if (true_target->is_member || dependency->name->is_member) {
1104 out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
1105 dependency->name->stat.time);
1106 } else {
1107 out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
1108 dependency->name->stat.time);
1110 if ((build_unconditional || out_of_date) &&
1111 (dependency->name != force) &&
1112 (dependency->stale == false)) {
1113 *out_of_date_tail = ALLOC(Chain);
1114 if (dependency->name->is_member &&
1115 (get_prop(dependency->name->prop,
1116 member_prop) != NULL)) {
1117 (*out_of_date_tail)->name =
1118 get_prop(dependency->name->prop,
1119 member_prop)->
1120 body.member.member;
1121 } else {
1122 (*out_of_date_tail)->name =
1123 dependency->name;
1125 (*out_of_date_tail)->next = NULL;
1126 out_of_date_tail = &(*out_of_date_tail)->next;
1127 if (debug_level > 0) {
1128 if (dependency->name->stat.time == file_max_time) {
1129 (void) printf(gettext("%*sBuilding %s because %s does not exist\n"),
1130 recursion_level,
1132 true_target->string_mb,
1133 dependency->name->string_mb);
1134 } else {
1135 (void) printf(gettext("%*sBuilding %s because it is out of date relative to %s\n"),
1136 recursion_level,
1138 true_target->string_mb,
1139 dependency->name->string_mb);
1143 if (dependency->name == force) {
1144 force->stat.time =
1145 file_max_time;
1146 force->state = build_dont_know;
1150 if (dependencies_running) {
1151 if (doing_subtree) {
1152 if (target->conditional_cnt > 0) {
1153 reset_locals(target,
1154 old_locals,
1155 get_prop(target->prop,
1156 conditional_prop),
1159 return true;
1160 } else {
1161 target->state = build_running;
1162 add_pending(target,
1163 --recursion_level,
1164 do_get,
1165 implicit,
1166 false);
1167 if (target->conditional_cnt > 0) {
1168 reset_locals(target,
1169 old_locals,
1170 get_prop(target->prop,
1171 conditional_prop),
1174 return true;
1178 * Collect the timestamp of the youngest double colon target
1179 * dependency.
1181 if (target->is_double_colon_parent) {
1182 for (dependency = line->body.line.dependencies;
1183 dependency != NULL;
1184 dependency = dependency->next) {
1185 Property tmp_line;
1187 if ((tmp_line = get_prop(dependency->name->prop, line_prop)) != NULL) {
1188 if(tmp_line->body.line.dependency_time != file_max_time) {
1189 target->stat.time =
1190 MAX(tmp_line->body.line.dependency_time,
1191 target->stat.time);
1196 if ((true_target->is_member) && (dependency_changed == true)) {
1197 true_target->stat.time = file_no_time;
1200 * After scanning all the dependencies, we check the rule
1201 * if we found one.
1203 if (line->body.line.command_template != NULL) {
1204 if (line->body.line.command_template_redefined) {
1205 warning(gettext("Too many rules defined for target %s"),
1206 target->string_mb);
1208 *command = line;
1209 /* Check if the target is out of date */
1210 Boolean out_of_date;
1211 if (true_target->is_member) {
1212 out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
1213 line->body.line.dependency_time);
1214 } else {
1215 out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
1216 line->body.line.dependency_time);
1218 if (build_unconditional || out_of_date){
1219 if(!recheck_conditionals) {
1220 line->body.line.is_out_of_date = true;
1223 line->body.line.sccs_command = false;
1224 line->body.line.target = true_target;
1225 if(gnu_style) {
1227 // set $< for explicit rule
1228 if(line->body.line.dependencies != NULL) {
1229 less = line->body.line.dependencies->name;
1232 // set $* for explicit rule
1233 Name target_body;
1234 Name tt = true_target;
1235 Property member;
1236 register wchar_t *target_end;
1237 register Dependency suffix;
1238 register int suffix_length;
1239 Wstring targ_string;
1240 Wstring suf_string;
1242 if (true_target->is_member &&
1243 ((member = get_prop(target->prop, member_prop)) !=
1244 NULL)) {
1245 tt = member->body.member.member;
1247 targ_string.init(tt);
1248 target_end = targ_string.get_string() + tt->hash.length;
1249 for (suffix = suffixes; suffix != NULL; suffix = suffix->next) {
1250 suffix_length = suffix->name->hash.length;
1251 suf_string.init(suffix->name);
1252 if (tt->hash.length < suffix_length) {
1253 continue;
1254 } else if (!IS_WEQUALN(suf_string.get_string(),
1255 (target_end - suffix_length),
1256 suffix_length)) {
1257 continue;
1259 target_body = GETNAME(
1260 targ_string.get_string(),
1261 (int)(tt->hash.length - suffix_length)
1263 line->body.line.star = target_body;
1266 // set result = build_ok so that implicit rules are not used.
1267 if(*result == build_dont_know) {
1268 *result = build_ok;
1271 if (less != NULL) {
1272 line->body.line.less = less;
1276 return false;
1280 * dynamic_dependencies(target)
1282 * Checks if any dependency contains a macro ref
1283 * If so, it replaces the dependency with the expanded version.
1284 * Here, "$@" gets translated to target->string. That is
1285 * the current name on the left of the colon in the
1286 * makefile. Thus,
1287 * xyz: s.$@.c
1288 * translates into
1289 * xyz: s.xyz.c
1291 * Also, "$(@F)" translates to the same thing without a preceeding
1292 * directory path (if one exists).
1293 * Note, to enter "$@" on a dependency line in a makefile
1294 * "$$@" must be typed. This is because make expands
1295 * macros in dependency lists upon reading them.
1296 * dynamic_dependencies() also expands file wildcards.
1297 * If there are any Shell meta characters in the name,
1298 * search the directory, and replace the dependency
1299 * with the set of files the pattern matches
1301 * Parameters:
1302 * target Target to sanitize dependencies for
1304 * Global variables used:
1305 * c_at The Name "@", used to set macro value
1306 * debug_level Should we trace actions?
1307 * dot The Name ".", used to read directory
1308 * recursion_level Used for tracing
1310 void
1311 dynamic_dependencies(Name target)
1313 wchar_t pattern[MAXPATHLEN];
1314 register wchar_t *p;
1315 Property line;
1316 register Dependency dependency;
1317 register Dependency *remove;
1318 String_rec string;
1319 wchar_t buffer[MAXPATHLEN];
1320 register Boolean set_at = false;
1321 register wchar_t *start;
1322 Dependency new_depe;
1323 register Boolean reuse_cell;
1324 Dependency first_member;
1325 Name directory;
1326 Name lib;
1327 Name member;
1328 Property prop;
1329 Name true_target = target;
1330 wchar_t *library;
1332 if ((line = get_prop(target->prop, line_prop)) == NULL) {
1333 return;
1335 /* If the target is constructed from a "::" target we consider that */
1336 if (target->has_target_prop) {
1337 true_target = get_prop(target->prop,
1338 target_prop)->body.target.target;
1340 /* Scan all dependencies and process the ones that contain "$" chars */
1341 for (dependency = line->body.line.dependencies;
1342 dependency != NULL;
1343 dependency = dependency->next) {
1344 if (!dependency->name->dollar) {
1345 continue;
1347 target->has_depe_list_expanded = true;
1349 /* The make macro $@ is bound to the target name once per */
1350 /* invocation of dynamic_dependencies() */
1351 if (!set_at) {
1352 (void) SETVAR(c_at, true_target, false);
1353 set_at = true;
1355 /* Expand this dependency string */
1356 INIT_STRING_FROM_STACK(string, buffer);
1357 expand_value(dependency->name, &string, false);
1358 /* Scan the expanded string. It could contain whitespace */
1359 /* which mean it expands to several dependencies */
1360 start = string.buffer.start;
1361 while (iswspace(*start)) {
1362 start++;
1364 /* Remove the cell (later) if the macro was empty */
1365 if (start[0] == (int) nul_char) {
1366 dependency->name = NULL;
1369 /* azv 10/26/95 to fix bug BID_1170218 */
1370 if ((start[0] == (int) period_char) &&
1371 (start[1] == (int) slash_char)) {
1372 start += 2;
1374 /* azv */
1376 first_member = NULL;
1377 /* We use the original dependency cell for the first */
1378 /* dependency from the expansion */
1379 reuse_cell = true;
1380 /* We also have to deal with dependencies that expand to */
1381 /* lib.a(members) notation */
1382 for (p = start; *p != (int) nul_char; p++) {
1383 if ((*p == (int) parenleft_char)) {
1384 lib = GETNAME(start, p - start);
1385 lib->is_member = true;
1386 first_member = dependency;
1387 start = p + 1;
1388 while (iswspace(*start)) {
1389 start++;
1391 break;
1394 do {
1395 /* First skip whitespace */
1396 for (p = start; *p != (int) nul_char; p++) {
1397 if ((*p == (int) nul_char) ||
1398 iswspace(*p) ||
1399 (*p == (int) parenright_char)) {
1400 break;
1403 /* Enter dependency from expansion */
1404 if (p != start) {
1405 /* Create new dependency cell if */
1406 /* this is not the first dependency */
1407 /* picked from the expansion */
1408 if (!reuse_cell) {
1409 new_depe = ALLOC(Dependency);
1410 new_depe->next = dependency->next;
1411 new_depe->automatic = false;
1412 new_depe->stale = false;
1413 new_depe->built = false;
1414 dependency->next = new_depe;
1415 dependency = new_depe;
1417 reuse_cell = false;
1418 /* Internalize the dependency name */
1419 // tolik. Fix for bug 4110429: inconsistent expansion for macros that
1420 // include "//" and "/./"
1421 //dependency->name = GETNAME(start, p - start);
1422 dependency->name = normalize_name(start, p - start);
1423 if ((debug_level > 0) &&
1424 (first_member == NULL)) {
1425 (void) printf(gettext("%*sDynamic dependency `%s' for target `%s'\n"),
1426 recursion_level,
1428 dependency->name->string_mb,
1429 true_target->string_mb);
1431 for (start = p; iswspace(*start); start++);
1432 p = start;
1434 } while ((*p != (int) nul_char) &&
1435 (*p != (int) parenright_char));
1436 /* If the expansion was of lib.a(members) format we now */
1437 /* enter the proper member cells */
1438 if (first_member != NULL) {
1439 /* Scan the new dependencies and transform them from */
1440 /* "foo" to "lib.a(foo)" */
1441 for (; 1; first_member = first_member->next) {
1442 /* Build "lib.a(foo)" name */
1443 INIT_STRING_FROM_STACK(string, buffer);
1444 APPEND_NAME(lib,
1445 &string,
1446 (int) lib->hash.length);
1447 append_char((int) parenleft_char, &string);
1448 APPEND_NAME(first_member->name,
1449 &string,
1450 FIND_LENGTH);
1451 append_char((int) parenright_char, &string);
1452 member = first_member->name;
1453 /* Replace "foo" with "lib.a(foo)" */
1454 first_member->name =
1455 GETNAME(string.buffer.start, FIND_LENGTH);
1456 if (string.free_after_use) {
1457 retmem(string.buffer.start);
1459 if (debug_level > 0) {
1460 (void) printf(gettext("%*sDynamic dependency `%s' for target `%s'\n"),
1461 recursion_level,
1463 first_member->name->
1464 string_mb,
1465 true_target->string_mb);
1467 first_member->name->is_member = lib->is_member;
1468 /* Add member property to member */
1469 prop = maybe_append_prop(first_member->name,
1470 member_prop);
1471 prop->body.member.library = lib;
1472 prop->body.member.entry = NULL;
1473 prop->body.member.member = member;
1474 if (first_member == dependency) {
1475 break;
1480 Wstring wcb;
1481 /* Then scan all the dependencies again. This time we want to expand */
1482 /* shell file wildcards */
1483 for (remove = &line->body.line.dependencies, dependency = *remove;
1484 dependency != NULL;
1485 dependency = *remove) {
1486 if (dependency->name == NULL) {
1487 dependency = *remove = (*remove)->next;
1488 continue;
1490 /* If dependency name string contains shell wildcards */
1491 /* replace the name with the expansion */
1492 if (dependency->name->wildcard) {
1493 wcb.init(dependency->name);
1494 if ((start = (wchar_t *) wcschr(wcb.get_string(),
1495 (int) parenleft_char)) != NULL) {
1496 /* lib(*) type pattern */
1497 library = buffer;
1498 (void) wcsncpy(buffer,
1499 wcb.get_string(),
1500 start - wcb.get_string());
1501 buffer[start-wcb.get_string()] =
1502 (int) nul_char;
1503 (void) wcsncpy(pattern,
1504 start + 1,
1505 (int) (dependency->name->hash.length-(start-wcb.get_string())-2));
1506 pattern[dependency->name->hash.length -
1507 (start-wcb.get_string()) - 2] =
1508 (int) nul_char;
1509 } else {
1510 library = NULL;
1511 (void) wcsncpy(pattern,
1512 wcb.get_string(),
1513 (int) dependency->name->hash.length);
1514 pattern[dependency->name->hash.length] =
1515 (int) nul_char;
1517 start = (wchar_t *) wcsrchr(pattern, (int) slash_char);
1518 if (start == NULL) {
1519 directory = dot;
1520 p = pattern;
1521 } else {
1522 directory = GETNAME(pattern, start-pattern);
1523 p = start+1;
1525 /* The expansion is handled by the read_dir() routine*/
1526 if (read_dir(directory, p, line, library)) {
1527 *remove = (*remove)->next;
1528 } else {
1529 remove = &dependency->next;
1531 } else {
1532 remove = &dependency->next;
1536 /* Then unbind $@ */
1537 (void) SETVAR(c_at, (Name) NULL, false);
1541 * DONE.
1543 * run_command(line)
1545 * Takes one Cmd_line and runs the commands from it.
1547 * Return value:
1548 * Indicates if the command failed or not
1550 * Parameters:
1551 * line The command line to run
1553 * Global variables used:
1554 * commands_done Set if we do run command
1555 * current_line Set to the line we run a command from
1556 * current_target Set to the target we run a command for
1557 * file_number Used to form temp file name
1558 * keep_state Indicates that .KEEP_STATE is on
1559 * make_state The Name ".make.state", used to check timestamp
1560 * parallel True if currently building in parallel
1561 * parallel_process_cnt Count of parallel processes running
1562 * quest Indicates that make -q is on
1563 * rewrite_statefile Set if we do run a command
1564 * sunpro_dependencies The Name "SUNPRO_DEPENDENCIES", set value
1565 * temp_file_directory Used to form temp fie name
1566 * temp_file_name Set to the name of the temp file
1567 * touch Indicates that make -t is on
1569 static Doname
1570 run_command(register Property line, Boolean)
1572 register Doname result = build_ok;
1573 register Boolean remember_only = false;
1574 register Name target = line->body.line.target;
1575 wchar_t *string;
1576 char tmp_file_path[MAXPATHLEN];
1578 if (!line->body.line.is_out_of_date && target->rechecking_target) {
1579 target->rechecking_target = false;
1580 return build_ok;
1584 * Build the command if we know the target is out of date,
1585 * or if we want to check cmd consistency.
1587 if (line->body.line.is_out_of_date || keep_state) {
1588 /* Hack for handling conditional macros in DMake. */
1589 if (!line->body.line.dont_rebuild_command_used) {
1590 build_command_strings(target, line);
1593 /* Never mind */
1594 if (!line->body.line.is_out_of_date) {
1595 return build_ok;
1597 /* If quest, then exit(1) because the target is out of date */
1598 if (quest) {
1599 if (posix) {
1600 result = execute_parallel(line, true);
1602 exit_status = 1;
1603 exit(1);
1605 /* We actually had to do something this time */
1606 rewrite_statefile = commands_done = true;
1608 * If this is an sccs command, we have to do some extra checking
1609 * and possibly complain. If the file can't be gotten because it's
1610 * checked out, we complain and behave as if the command was
1611 * executed eventhough we ignored the command.
1613 if (!touch &&
1614 line->body.line.sccs_command &&
1615 (target->stat.time != file_doesnt_exist) &&
1616 ((target->stat.mode & 0222) != 0)) {
1617 fatal(gettext("%s is writable so it cannot be sccs gotten"),
1618 target->string_mb);
1619 target->has_complained = remember_only = true;
1622 * If KEEP_STATE is on, we make sure we have the timestamp for
1623 * .make.state. If .make.state changes during the command run,
1624 * we reread .make.state after the command. We also setup the
1625 * environment variable that asks utilities to report dependencies.
1627 if (!touch &&
1628 keep_state &&
1629 !remember_only) {
1630 (void) exists(make_state);
1631 if((strlen(temp_file_directory) == 1) &&
1632 (temp_file_directory[0] == '/')) {
1633 tmp_file_path[0] = '\0';
1634 } else {
1635 strcpy(tmp_file_path, temp_file_directory);
1637 sprintf(mbs_buffer,
1638 "%s/.make.dependency.%08x.%d.%d",
1639 tmp_file_path,
1640 hostid,
1641 getpid(),
1642 file_number++);
1643 MBSTOWCS(wcs_buffer, mbs_buffer);
1644 Boolean fnd;
1645 temp_file_name = getname_fn(wcs_buffer, FIND_LENGTH, false, &fnd);
1646 temp_file_name->stat.is_file = true;
1647 int len = 2*MAXPATHLEN + strlen(target->string_mb) + 2;
1648 wchar_t *to = string = ALLOC_WC(len);
1649 for (wchar_t *from = wcs_buffer; *from != (int) nul_char; ) {
1650 if (*from == (int) space_char) {
1651 *to++ = (int) backslash_char;
1653 *to++ = *from++;
1655 *to++ = (int) space_char;
1656 MBSTOWCS(to, target->string_mb);
1657 Name sprodep_name = getname_fn(string, FIND_LENGTH, false, &fnd);
1658 (void) SETVAR(sunpro_dependencies,
1659 sprodep_name,
1660 false);
1661 retmem(string);
1662 } else {
1663 temp_file_name = NULL;
1667 * In case we are interrupted, we need to know what was going on.
1669 current_target = target;
1671 * We also need to be able to save an empty command instead of the
1672 * interrupted one in .make.state.
1674 current_line = line;
1675 if (remember_only) {
1676 /* Empty block!!! */
1677 } else if (touch) {
1678 result = touch_command(line, target, result);
1679 if (posix) {
1680 result = execute_parallel(line, true);
1682 } else {
1684 * If this is not a touch run, we need to execute the
1685 * proper command(s) for the target.
1687 if (parallel) {
1688 if (!parallel_ok(target, true)) {
1690 * We are building in parallel, but
1691 * this target must be built in serial.
1694 * If nothing else is building,
1695 * do this one, else wait.
1697 if (parallel_process_cnt == 0) {
1698 result = execute_parallel(line, true, target->localhost);
1699 } else {
1700 current_target = NULL;
1701 current_line = NULL;
1703 line->body.line.command_used = NULL;
1705 line->body.line.dont_rebuild_command_used = true;
1706 return build_serial;
1708 } else {
1709 result = execute_parallel(line, false);
1710 switch (result) {
1711 case build_running:
1712 return build_running;
1713 case build_serial:
1714 if (parallel_process_cnt == 0) {
1715 result = execute_parallel(line, true, target->localhost);
1716 } else {
1717 current_target = NULL;
1718 current_line = NULL;
1719 target->parallel = false;
1720 line->body.line.command_used =
1721 NULL;
1722 return build_serial;
1726 } else {
1727 result = execute_parallel(line, true, target->localhost);
1730 temp_file_name = NULL;
1731 if (report_dependencies_level == 0){
1732 update_target(line, result);
1734 current_target = NULL;
1735 current_line = NULL;
1736 return result;
1740 * execute_serial(line)
1742 * Runs thru the command line for the target and
1743 * executes the rules one by one.
1745 * Return value:
1746 * The result of the command build
1748 * Parameters:
1749 * line The command to execute
1751 * Static variables used:
1753 * Global variables used:
1754 * continue_after_error -k flag
1755 * do_not_exec_rule -n flag
1756 * report_dependencies -P flag
1757 * silent Don't echo commands before executing
1758 * temp_file_name Temp file for auto dependencies
1759 * vpath_defined If true, translate path for command
1761 Doname
1762 execute_serial(Property line)
1764 int child_pid = 0;
1765 Boolean printed_serial;
1766 Doname result = build_ok;
1767 Cmd_line rule, cmd_tail, command = NULL;
1768 char mbstring[MAXPATHLEN];
1769 int filed;
1770 Name target = line->body.line.target;
1772 target->has_recursive_dependency = false;
1773 // We have to create a copy of the rules chain for processing because
1774 // the original one can be destroyed during .make.state file rereading.
1775 for (rule = line->body.line.command_used;
1776 rule != NULL;
1777 rule = rule->next) {
1778 if (command == NULL) {
1779 command = cmd_tail = ALLOC(Cmd_line);
1780 } else {
1781 cmd_tail->next = ALLOC(Cmd_line);
1782 cmd_tail = cmd_tail->next;
1784 *cmd_tail = *rule;
1786 if (command) {
1787 cmd_tail->next = NULL;
1789 for (rule = command; rule != NULL; rule = rule->next) {
1790 if (posix && (touch || quest) && !rule->always_exec) {
1791 continue;
1793 if (vpath_defined) {
1794 rule->command_line =
1795 vpath_translation(rule->command_line);
1797 /* Echo command line, maybe. */
1798 if ((rule->command_line->hash.length > 0) &&
1799 !silent &&
1800 (!rule->silent || do_not_exec_rule) &&
1801 (report_dependencies_level == 0)) {
1802 (void) printf("%s\n", rule->command_line->string_mb);
1804 if (rule->command_line->hash.length > 0) {
1805 /* Do assignment if command line prefixed with "=" */
1806 if (rule->assign) {
1807 result = build_ok;
1808 do_assign(rule->command_line, target);
1809 } else if (report_dependencies_level == 0) {
1810 /* Execute command line. */
1811 setvar_envvar();
1812 result = dosys(rule->command_line,
1813 (Boolean) rule->ignore_error,
1814 (Boolean) rule->make_refd,
1815 /* ds 98.04.23 bug #4085164. make should always show error messages */
1816 false,
1817 /* BOOLEAN(rule->silent &&
1818 rule->ignore_error), */
1819 (Boolean) rule->always_exec,
1820 target);
1821 check_state(temp_file_name);
1823 } else {
1824 result = build_ok;
1826 if (result == build_failed) {
1827 if (silent || rule->silent) {
1828 (void) printf(gettext("The following command caused the error:\n%s\n"),
1829 rule->command_line->string_mb);
1831 if (!rule->ignore_error && !ignore_errors) {
1832 if (!continue_after_error) {
1833 fatal(gettext("Command failed for target `%s'"),
1834 target->string_mb);
1837 * Make sure a failing command is not
1838 * saved in .make.state.
1840 line->body.line.command_used = NULL;
1841 break;
1842 } else {
1843 result = build_ok;
1847 for (rule = command; rule != NULL; rule = cmd_tail) {
1848 cmd_tail = rule->next;
1849 free(rule);
1851 command = NULL;
1852 if (temp_file_name != NULL) {
1853 free_name(temp_file_name);
1855 temp_file_name = NULL;
1857 Property spro = get_prop(sunpro_dependencies->prop, macro_prop);
1858 if(spro != NULL) {
1859 Name val = spro->body.macro.value;
1860 if(val != NULL) {
1861 free_name(val);
1862 spro->body.macro.value = NULL;
1865 spro = get_prop(sunpro_dependencies->prop, env_mem_prop);
1866 if(spro) {
1867 char *val = spro->body.env_mem.value;
1868 if(val != NULL) {
1870 * Do not return memory allocated for SUNPRO_DEPENDENCIES
1871 * It will be returned in setvar_daemon() in macro.cc
1873 // retmem_mb(val);
1874 spro->body.env_mem.value = NULL;
1878 return result;
1884 * vpath_translation(cmd)
1886 * Translates one command line by
1887 * checking each word. If the word has an alias it is translated.
1889 * Return value:
1890 * The translated command
1892 * Parameters:
1893 * cmd Command to translate
1895 * Global variables used:
1897 Name
1898 vpath_translation(register Name cmd)
1900 wchar_t buffer[STRING_BUFFER_LENGTH];
1901 String_rec new_cmd;
1902 wchar_t *p;
1903 wchar_t *start;
1905 if (!vpath_defined || (cmd == NULL) || (cmd->hash.length == 0)) {
1906 return cmd;
1908 INIT_STRING_FROM_STACK(new_cmd, buffer);
1910 Wstring wcb(cmd);
1911 p = wcb.get_string();
1913 while (*p != (int) nul_char) {
1914 while (iswspace(*p) && (*p != (int) nul_char)) {
1915 append_char(*p++, &new_cmd);
1917 start = p;
1918 while (!iswspace(*p) && (*p != (int) nul_char)) {
1919 p++;
1921 cmd = GETNAME(start, p - start);
1922 if (cmd->has_vpath_alias_prop) {
1923 cmd = get_prop(cmd->prop, vpath_alias_prop)->
1924 body.vpath_alias.alias;
1925 APPEND_NAME(cmd,
1926 &new_cmd,
1927 (int) cmd->hash.length);
1928 } else {
1929 append_string(start, &new_cmd, p - start);
1932 cmd = GETNAME(new_cmd.buffer.start, FIND_LENGTH);
1933 if (new_cmd.free_after_use) {
1934 retmem(new_cmd.buffer.start);
1936 return cmd;
1940 * check_state(temp_file_name)
1942 * Reads and checks the state changed by the previously executed command.
1944 * Parameters:
1945 * temp_file_name The auto dependency temp file
1947 * Global variables used:
1949 void
1950 check_state(Name temp_file_name)
1952 if (!keep_state) {
1953 return;
1957 * Then read the temp file that now might
1958 * contain dependency reports from utilities
1960 read_dependency_file(temp_file_name);
1963 * And reread .make.state if it
1964 * changed (the command ran recursive makes)
1966 check_read_state_file();
1967 if (temp_file_name != NULL) {
1968 (void) unlink(temp_file_name->string_mb);
1973 * read_dependency_file(filename)
1975 * Read the temp file used for reporting dependencies to make
1977 * Parameters:
1978 * filename The name of the file with the state info
1980 * Global variables used:
1981 * makefile_type The type of makefile being read
1982 * read_trace_level Debug flag
1983 * temp_file_number The always increasing number for unique files
1984 * trace_reader Debug flag
1986 static void
1987 read_dependency_file(register Name filename)
1989 register Makefile_type save_makefile_type;
1991 if (filename == NULL) {
1992 return;
1994 filename->stat.time = file_no_time;
1995 if (exists(filename) > file_doesnt_exist) {
1996 save_makefile_type = makefile_type;
1997 makefile_type = reading_cpp_file;
1998 if (read_trace_level > 1) {
1999 trace_reader = true;
2001 temp_file_number++;
2002 (void) read_simple_file(filename,
2003 false,
2004 false,
2005 false,
2006 false,
2007 false,
2008 false);
2009 trace_reader = false;
2010 makefile_type = save_makefile_type;
2015 * check_read_state_file()
2017 * Check if .make.state has changed
2018 * If it has we reread it
2020 * Parameters:
2022 * Global variables used:
2023 * make_state Make state file name
2024 * makefile_type Type of makefile being read
2025 * read_trace_level Debug flag
2026 * trace_reader Debug flag
2028 static void
2029 check_read_state_file(void)
2031 timestruc_t previous = make_state->stat.time;
2032 register Makefile_type save_makefile_type;
2033 register Property makefile;
2035 make_state->stat.time = file_no_time;
2036 if ((exists(make_state) == file_doesnt_exist) ||
2037 (make_state->stat.time == previous)) {
2038 return;
2040 save_makefile_type = makefile_type;
2041 makefile_type = rereading_statefile;
2042 /* Make sure we clear the old cached contents of .make.state */
2043 makefile = maybe_append_prop(make_state, makefile_prop);
2044 if (makefile->body.makefile.contents != NULL) {
2045 retmem(makefile->body.makefile.contents);
2046 makefile->body.makefile.contents = NULL;
2048 if (read_trace_level > 1) {
2049 trace_reader = true;
2051 temp_file_number++;
2052 (void) read_simple_file(make_state,
2053 false,
2054 false,
2055 false,
2056 false,
2057 false,
2058 true);
2059 trace_reader = false;
2060 makefile_type = save_makefile_type;
2064 * do_assign(line, target)
2066 * Handles runtime assignments for command lines prefixed with "=".
2068 * Parameters:
2069 * line The command that contains an assignment
2070 * target The Name of the target, used for error reports
2072 * Global variables used:
2073 * assign_done Set to indicate doname needs to reprocess
2075 static void
2076 do_assign(register Name line, register Name target)
2078 Wstring wcb(line);
2079 register wchar_t *string = wcb.get_string();
2080 register wchar_t *equal;
2081 register Name name;
2082 register Boolean append = false;
2085 * If any runtime assignments are done, doname() must reprocess all
2086 * targets in the future since the macro values used to build the
2087 * command lines for the targets might have changed.
2089 assign_done = true;
2090 /* Skip white space. */
2091 while (iswspace(*string)) {
2092 string++;
2094 equal = string;
2095 /* Find "+=" or "=". */
2096 while (!iswspace(*equal) &&
2097 (*equal != (int) plus_char) &&
2098 (*equal != (int) equal_char)) {
2099 equal++;
2101 /* Internalize macro name. */
2102 name = GETNAME(string, equal - string);
2103 /* Skip over "+=" "=". */
2104 while (!((*equal == (int) nul_char) ||
2105 (*equal == (int) equal_char) ||
2106 (*equal == (int) plus_char))) {
2107 equal++;
2109 switch (*equal) {
2110 case nul_char:
2111 fatal(gettext("= expected in rule `%s' for target `%s'"),
2112 line->string_mb,
2113 target->string_mb);
2114 case plus_char:
2115 append = true;
2116 equal++;
2117 break;
2119 equal++;
2120 /* Skip over whitespace in front of value. */
2121 while (iswspace(*equal)) {
2122 equal++;
2124 /* Enter new macro value. */
2125 enter_equal(name,
2126 GETNAME(equal, wcb.get_string() + line->hash.length - equal),
2127 append);
2131 * build_command_strings(target, line)
2133 * Builds the command string to used when
2134 * building a target. If the string is different from the previous one
2135 * is_out_of_date is set.
2137 * Parameters:
2138 * target Target to build commands for
2139 * line Where to stuff result
2141 * Global variables used:
2142 * c_at The Name "@", used to set macro value
2143 * command_changed Set if command is different from old
2144 * debug_level Should we trace activities?
2145 * do_not_exec_rule Always echo when running -n
2146 * empty_name The Name "", used for empty rule
2147 * funny Semantics of characters
2148 * ignore_errors Used to init field for line
2149 * is_conditional Set to false befor evaling macro, checked
2150 * after expanding macros
2151 * keep_state Indicates that .KEEP_STATE is on
2152 * make_word_mentioned Set by macro eval, inits field for cmd
2153 * query The Name "?", used to set macro value
2154 * query_mentioned Set by macro eval, inits field for cmd
2155 * recursion_level Used for tracing
2156 * silent Used to init field for line
2158 static void
2159 build_command_strings(Name target, register Property line)
2161 String_rec command_line;
2162 register Cmd_line command_template = line->body.line.command_template;
2163 register Cmd_line *insert = &line->body.line.command_used;
2164 register Cmd_line used = *insert;
2165 wchar_t buffer[STRING_BUFFER_LENGTH];
2166 wchar_t *start;
2167 Name new_command_line;
2168 register Boolean new_command_longer = false;
2169 register Boolean ignore_all_command_dependency = true;
2170 Property member;
2171 static Name less_name;
2172 static Name percent_name;
2173 static Name star;
2174 Name tmp_name;
2176 if (less_name == NULL) {
2177 MBSTOWCS(wcs_buffer, "<");
2178 less_name = GETNAME(wcs_buffer, FIND_LENGTH);
2179 MBSTOWCS(wcs_buffer, "%");
2180 percent_name = GETNAME(wcs_buffer, FIND_LENGTH);
2181 MBSTOWCS(wcs_buffer, "*");
2182 star = GETNAME(wcs_buffer, FIND_LENGTH);
2185 /* We have to check if a target depends on conditional macros */
2186 /* Targets that do must be reprocessed by doname() each time around */
2187 /* since the macro values used when building the target might have */
2188 /* changed */
2189 conditional_macro_used = false;
2190 /* If we are building a lib.a(member) target $@ should be bound */
2191 /* to lib.a */
2192 if (target->is_member &&
2193 ((member = get_prop(target->prop, member_prop)) != NULL)) {
2194 target = member->body.member.library;
2196 /* If we are building a "::" help target $@ should be bound to */
2197 /* the real target name */
2198 /* A lib.a(member) target is never :: */
2199 if (target->has_target_prop) {
2200 target = get_prop(target->prop, target_prop)->
2201 body.target.target;
2203 /* Bind the magic macros that make supplies */
2204 tmp_name = target;
2205 if(tmp_name != NULL) {
2206 if (tmp_name->has_vpath_alias_prop) {
2207 tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)->
2208 body.vpath_alias.alias;
2211 (void) SETVAR(c_at, tmp_name, false);
2213 tmp_name = line->body.line.star;
2214 if(tmp_name != NULL) {
2215 if (tmp_name->has_vpath_alias_prop) {
2216 tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)->
2217 body.vpath_alias.alias;
2220 (void) SETVAR(star, tmp_name, false);
2222 tmp_name = line->body.line.less;
2223 if(tmp_name != NULL) {
2224 if (tmp_name->has_vpath_alias_prop) {
2225 tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)->
2226 body.vpath_alias.alias;
2229 (void) SETVAR(less_name, tmp_name, false);
2231 tmp_name = line->body.line.percent;
2232 if(tmp_name != NULL) {
2233 if (tmp_name->has_vpath_alias_prop) {
2234 tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)->
2235 body.vpath_alias.alias;
2238 (void) SETVAR(percent_name, tmp_name, false);
2240 /* $? is seldom used and it is expensive to build */
2241 /* so we store the list form and build the string on demand */
2242 Chain query_list = NULL;
2243 Chain *query_list_tail = &query_list;
2245 for (Chain ch = line->body.line.query; ch != NULL; ch = ch->next) {
2246 *query_list_tail = ALLOC(Chain);
2247 (*query_list_tail)->name = ch->name;
2248 if ((*query_list_tail)->name->has_vpath_alias_prop) {
2249 (*query_list_tail)->name =
2250 get_prop((*query_list_tail)->name->prop,
2251 vpath_alias_prop)->body.vpath_alias.alias;
2253 (*query_list_tail)->next = NULL;
2254 query_list_tail = &(*query_list_tail)->next;
2256 (void) setvar_daemon(query,
2257 (Name) query_list,
2258 false,
2259 chain_daemon,
2260 false,
2261 debug_level);
2263 /* build $^ */
2264 Chain hat_list = NULL;
2265 Chain *hat_list_tail = &hat_list;
2267 for (Dependency dependency = line->body.line.dependencies;
2268 dependency != NULL;
2269 dependency = dependency->next) {
2270 /* skip automatic dependencies */
2271 if (!dependency->automatic) {
2272 if ((dependency->name != force) &&
2273 (dependency->stale == false)) {
2274 *hat_list_tail = ALLOC(Chain);
2276 if (dependency->name->is_member &&
2277 (get_prop(dependency->name->prop, member_prop) != NULL)) {
2278 (*hat_list_tail)->name =
2279 get_prop(dependency->name->prop,
2280 member_prop)->body.member.member;
2281 } else {
2282 (*hat_list_tail)->name = dependency->name;
2285 if((*hat_list_tail)->name != NULL) {
2286 if ((*hat_list_tail)->name->has_vpath_alias_prop) {
2287 (*hat_list_tail)->name =
2288 get_prop((*hat_list_tail)->name->prop,
2289 vpath_alias_prop)->body.vpath_alias.alias;
2293 (*hat_list_tail)->next = NULL;
2294 hat_list_tail = &(*hat_list_tail)->next;
2298 (void) setvar_daemon(hat,
2299 (Name) hat_list,
2300 false,
2301 chain_daemon,
2302 false,
2303 debug_level);
2305 /* We have two command sequences we need to handle */
2306 /* The old one that we probably read from .make.state */
2307 /* and the new one we are building that will replace the old one */
2308 /* Even when KEEP_STATE is not on we build a new command sequence and store */
2309 /* it in the line prop. This command sequence is then executed by */
2310 /* run_command(). If KEEP_STATE is on it is also later written to */
2311 /* .make.state. The routine replaces the old command line by line with the */
2312 /* new one trying to reuse Cmd_lines */
2314 /* If there is no old command_used we have to start creating */
2315 /* Cmd_lines to keep the new cmd in */
2316 if (used == NULL) {
2317 new_command_longer = true;
2318 *insert = used = ALLOC(Cmd_line);
2319 used->next = NULL;
2320 used->command_line = NULL;
2321 insert = &used->next;
2323 /* Run thru the template for the new command and build the expanded */
2324 /* new command lines */
2325 for (;
2326 command_template != NULL;
2327 command_template = command_template->next, insert = &used->next, used = *insert) {
2328 /* If there is no old command_used Cmd_line we need to */
2329 /* create one and say that cmd consistency failed */
2330 if (used == NULL) {
2331 new_command_longer = true;
2332 *insert = used = ALLOC(Cmd_line);
2333 used->next = NULL;
2334 used->command_line = empty_name;
2336 /* Prepare the Cmd_line for the processing */
2337 /* The command line prefixes "@-=?" are stripped and that */
2338 /* information is saved in the Cmd_line */
2339 used->assign = false;
2340 used->ignore_error = ignore_errors;
2341 used->silent = silent;
2342 used->always_exec = false;
2343 /* Expand the macros in the command line */
2344 INIT_STRING_FROM_STACK(command_line, buffer);
2345 make_word_mentioned =
2346 query_mentioned =
2347 false;
2348 expand_value(command_template->command_line, &command_line, true);
2349 /* If the macro $(MAKE) is mentioned in the command */
2350 /* "make -n" runs actually execute the command */
2351 used->make_refd = make_word_mentioned;
2352 used->ignore_command_dependency = query_mentioned;
2353 /* Strip the prefixes */
2354 start = command_line.buffer.start;
2355 for (;
2356 iswspace(*start) ||
2357 (get_char_semantics_value(*start) & (int) command_prefix_sem);
2358 start++) {
2359 switch (*start) {
2360 case question_char:
2361 used->ignore_command_dependency = true;
2362 break;
2363 case exclam_char:
2364 used->ignore_command_dependency = false;
2365 break;
2366 case equal_char:
2367 used->assign = true;
2368 break;
2369 case hyphen_char:
2370 used->ignore_error = true;
2371 break;
2372 case at_char:
2373 if (!do_not_exec_rule) {
2374 used->silent = true;
2376 break;
2377 case plus_char:
2378 if(posix) {
2379 used->always_exec = true;
2381 break;
2384 /* If all command lines of the template are prefixed with "?"*/
2385 /* the VIRTUAL_ROOT is not used for cmd consistency checks */
2386 if (!used->ignore_command_dependency) {
2387 ignore_all_command_dependency = false;
2389 /* Internalize the expanded and stripped command line */
2390 new_command_line = GETNAME(start, FIND_LENGTH);
2391 if ((used->command_line == NULL) &&
2392 (line->body.line.sccs_command)) {
2393 used->command_line = new_command_line;
2394 new_command_longer = false;
2396 /* Compare it with the old one for command consistency */
2397 if (used->command_line != new_command_line) {
2398 Name vpath_translated = vpath_translation(new_command_line);
2399 if (keep_state &&
2400 !used->ignore_command_dependency && (vpath_translated != used->command_line)) {
2401 if (debug_level > 0) {
2402 if (used->command_line != NULL
2403 && *used->command_line->string_mb !=
2404 '\0') {
2405 (void) printf(gettext("%*sBuilding %s because new command \n\t%s\n%*sdifferent from old\n\t%s\n"),
2406 recursion_level,
2408 target->string_mb,
2409 vpath_translated->string_mb,
2410 recursion_level,
2412 used->
2413 command_line->
2414 string_mb);
2415 } else {
2416 (void) printf(gettext("%*sBuilding %s because new command \n\t%s\n%*sdifferent from empty old command\n"),
2417 recursion_level,
2419 target->string_mb,
2420 vpath_translated->string_mb,
2421 recursion_level,
2422 "");
2425 command_changed = true;
2426 line->body.line.is_out_of_date = true;
2428 used->command_line = new_command_line;
2430 if (command_line.free_after_use) {
2431 retmem(command_line.buffer.start);
2434 /* Check if the old command is longer than the new for */
2435 /* command consistency */
2436 if (used != NULL) {
2437 *insert = NULL;
2438 if (keep_state &&
2439 !ignore_all_command_dependency) {
2440 if (debug_level > 0) {
2441 (void) printf(gettext("%*sBuilding %s because new command shorter than old\n"),
2442 recursion_level,
2444 target->string_mb);
2446 command_changed = true;
2447 line->body.line.is_out_of_date = true;
2450 /* Check if the new command is longer than the old command for */
2451 /* command consistency */
2452 if (new_command_longer &&
2453 !ignore_all_command_dependency &&
2454 keep_state) {
2455 if (debug_level > 0) {
2456 (void) printf(gettext("%*sBuilding %s because new command longer than old\n"),
2457 recursion_level,
2459 target->string_mb);
2461 command_changed = true;
2462 line->body.line.is_out_of_date = true;
2464 /* Unbind the magic macros */
2465 (void) SETVAR(c_at, (Name) NULL, false);
2466 (void) SETVAR(star, (Name) NULL, false);
2467 (void) SETVAR(less_name, (Name) NULL, false);
2468 (void) SETVAR(percent_name, (Name) NULL, false);
2469 (void) SETVAR(query, (Name) NULL, false);
2470 if (query_list != NULL) {
2471 delete_query_chain(query_list);
2473 (void) SETVAR(hat, (Name) NULL, false);
2474 if (hat_list != NULL) {
2475 delete_query_chain(hat_list);
2478 if (conditional_macro_used) {
2479 target->conditional_macro_list = cond_macro_list;
2480 cond_macro_list = NULL;
2481 target->depends_on_conditional = true;
2486 * touch_command(line, target, result)
2488 * If this is an "make -t" run we do this.
2489 * We touch all targets in the target group ("foo + fie:") if any.
2491 * Return value:
2492 * Indicates if the command failed or not
2494 * Parameters:
2495 * line The command line to update
2496 * target The target we are touching
2497 * result Initial value for the result we return
2499 * Global variables used:
2500 * do_not_exec_rule Indicates that -n is on
2501 * silent Do not echo commands
2503 static Doname
2504 touch_command(register Property line, register Name target, Doname result)
2506 Name name;
2507 register Chain target_group;
2508 String_rec touch_string;
2509 wchar_t buffer[MAXPATHLEN];
2510 Name touch_cmd;
2511 Cmd_line rule;
2513 for (name = target, target_group = NULL; name != NULL;) {
2514 if (!name->is_member) {
2516 * Build a touch command that can be passed
2517 * to dosys(). If KEEP_STATE is on, "make -t"
2518 * will save the proper command, not the
2519 * "touch" in .make.state.
2521 INIT_STRING_FROM_STACK(touch_string, buffer);
2522 MBSTOWCS(wcs_buffer, "touch ");
2523 append_string(wcs_buffer, &touch_string, FIND_LENGTH);
2524 touch_cmd = name;
2525 if (name->has_vpath_alias_prop) {
2526 touch_cmd = get_prop(name->prop,
2527 vpath_alias_prop)->
2528 body.vpath_alias.alias;
2530 APPEND_NAME(touch_cmd,
2531 &touch_string,
2532 FIND_LENGTH);
2533 touch_cmd = GETNAME(touch_string.buffer.start,
2534 FIND_LENGTH);
2535 if (touch_string.free_after_use) {
2536 retmem(touch_string.buffer.start);
2538 if (!silent ||
2539 do_not_exec_rule &&
2540 (target_group == NULL)) {
2541 (void) printf("%s\n", touch_cmd->string_mb);
2543 /* Run the touch command, or simulate it */
2544 if (!do_not_exec_rule) {
2545 result = dosys(touch_cmd,
2546 false,
2547 false,
2548 false,
2549 false,
2550 name);
2551 } else {
2552 result = build_ok;
2554 } else {
2555 result = build_ok;
2557 if (target_group == NULL) {
2558 target_group = line->body.line.target_group;
2559 } else {
2560 target_group = target_group->next;
2562 if (target_group != NULL) {
2563 name = target_group->name;
2564 } else {
2565 name = NULL;
2568 return result;
2572 * update_target(line, result)
2574 * updates the status of a target after executing its commands.
2576 * Parameters:
2577 * line The command line block to update
2578 * result Indicates that build is OK so can update
2580 * Global variables used:
2581 * do_not_exec_rule Indicates that -n is on
2582 * touch Fake the new timestamp if we are just touching
2584 void
2585 update_target(Property line, Doname result)
2587 Name target;
2588 Chain target_group;
2589 Property line2;
2590 timestruc_t old_stat_time;
2591 Property member;
2594 * [tolik] Additional fix for bug 1063790. It was fixed
2595 * for serial make long ago, but DMake dumps core when
2596 * target is a symlink and sccs file is newer then target.
2597 * In this case, finish_children() calls update_target()
2598 * with line==NULL.
2600 if(line == NULL) {
2601 /* XXX. Should we do anything here? */
2602 return;
2605 target = line->body.line.target;
2607 if ((result == build_ok) && (line->body.line.command_used != NULL)) {
2608 if (do_not_exec_rule ||
2609 touch ||
2610 (target->is_member &&
2611 (line->body.line.command_template != NULL) &&
2612 (line->body.line.command_template->command_line->string_mb[0] == 0) &&
2613 (line->body.line.command_template->next == NULL))) {
2614 /* If we are simulating execution we need to fake a */
2615 /* new timestamp for the target we didnt build */
2616 target->stat.time = file_max_time;
2617 } else {
2619 * If we really built the target we read the new
2620 * timestamp.
2621 * Fix for bug #1110906: if .c file is newer than
2622 * the corresponding .o file which is in an archive
2623 * file, make will compile the .c file but it won't
2624 * update the object in the .a file.
2626 old_stat_time = target->stat.time;
2627 target->stat.time = file_no_time;
2628 (void) exists(target);
2629 if ((target->is_member) &&
2630 (target->stat.time == old_stat_time)) {
2631 member = get_prop(target->prop, member_prop);
2632 if (member != NULL) {
2633 target->stat.time = member->body.member.library->stat.time;
2634 target->stat.time.tv_sec++;
2638 /* If the target is part of a group we need to propagate the */
2639 /* result of the run to all members */
2640 for (target_group = line->body.line.target_group;
2641 target_group != NULL;
2642 target_group = target_group->next) {
2643 target_group->name->stat.time = target->stat.time;
2644 line2 = maybe_append_prop(target_group->name,
2645 line_prop);
2646 line2->body.line.command_used =
2647 line->body.line.command_used;
2648 line2->body.line.target = target_group->name;
2651 target->has_built = true;
2655 * sccs_get(target, command)
2657 * Figures out if it possible to sccs get a file
2658 * and builds the command to do it if it is.
2660 * Return value:
2661 * Indicates if sccs get failed or not
2663 * Parameters:
2664 * target Target to get
2665 * command Where to deposit command to use
2667 * Global variables used:
2668 * debug_level Should we trace activities?
2669 * recursion_level Used for tracing
2670 * sccs_get_rule The rule to used for sccs getting
2672 static Doname
2673 sccs_get(register Name target, register Property *command)
2675 register int result;
2676 char link[MAXPATHLEN];
2677 String_rec string;
2678 wchar_t name[MAXPATHLEN];
2679 register wchar_t *p;
2680 timestruc_t sccs_time;
2681 register Property line;
2682 int sym_link_depth = 0;
2684 /* For sccs, we need to chase symlinks. */
2685 while (target->stat.is_sym_link) {
2686 if (sym_link_depth++ > 90) {
2687 fatal(gettext("Can't read symbolic link `%s': Number of symbolic links encountered during path name traversal exceeds 90."),
2688 target->string_mb);
2690 /* Read the value of the link. */
2691 result = readlink_vroot(target->string_mb,
2692 link,
2693 sizeof(link),
2694 NULL,
2695 VROOT_DEFAULT);
2696 if (result == -1) {
2697 fatal(gettext("Can't read symbolic link `%s': %s"),
2698 target->string_mb, errmsg(errno));
2700 link[result] = 0;
2701 /* Use the value to build the proper filename. */
2702 INIT_STRING_FROM_STACK(string, name);
2704 Wstring wcb(target);
2705 if ((link[0] != slash_char) &&
2706 ((p = (wchar_t *) wcsrchr(wcb.get_string(), slash_char)) != NULL)) {
2707 append_string(wcb.get_string(), &string, p - wcb.get_string() + 1);
2709 append_string(link, &string, result);
2710 /* Replace the old name with the translated name. */
2711 target = normalize_name(string.buffer.start, string.text.p - string.buffer.start);
2712 (void) exists(target);
2713 if (string.free_after_use) {
2714 retmem(string.buffer.start);
2719 * read_dir() also reads the ?/SCCS dir and saves information
2720 * about which files have SCSC/s. files.
2722 if (target->stat.has_sccs == DONT_KNOW_SCCS) {
2723 read_directory_of_file(target);
2725 switch (target->stat.has_sccs) {
2726 case DONT_KNOW_SCCS:
2727 /* We dont know by now there is no SCCS/s.* */
2728 target->stat.has_sccs = NO_SCCS;
2729 case NO_SCCS:
2731 * If there is no SCCS/s.* but the plain file exists,
2732 * we say things are OK.
2734 if (target->stat.time > file_doesnt_exist) {
2735 return build_ok;
2737 /* If we cant find the plain file, we give up. */
2738 return build_dont_know;
2739 case HAS_SCCS:
2741 * Pay dirt. We now need to figure out if the plain file
2742 * is out of date relative to the SCCS/s.* file.
2744 sccs_time = exists(get_prop(target->prop,
2745 sccs_prop)->body.sccs.file);
2746 break;
2749 if ((!target->has_complained &&
2750 (sccs_time != file_doesnt_exist) &&
2751 (sccs_get_rule != NULL))) {
2752 /* only checking */
2753 if (command == NULL) {
2754 return build_ok;
2757 * We provide a command line for the target. The line is a
2758 * "sccs get" command from default.mk.
2760 line = maybe_append_prop(target, line_prop);
2761 *command = line;
2762 if (sccs_time > target->stat.time) {
2764 * And only if the plain file is out of date do we
2765 * request execution of the command.
2767 line->body.line.is_out_of_date = true;
2768 if (debug_level > 0) {
2769 (void) printf(gettext("%*sSccs getting %s because s. file is younger than source file\n"),
2770 recursion_level,
2772 target->string_mb);
2775 line->body.line.sccs_command = true;
2776 line->body.line.command_template = sccs_get_rule;
2777 if(!svr4 && (!allrules_read || posix)) {
2778 if((target->prop) &&
2779 (target->prop->body.sccs.file) &&
2780 (target->prop->body.sccs.file->string_mb)) {
2781 if((strlen(target->prop->body.sccs.file->string_mb) ==
2782 strlen(target->string_mb) + 2) &&
2783 (target->prop->body.sccs.file->string_mb[0] == 's') &&
2784 (target->prop->body.sccs.file->string_mb[1] == '.')) {
2786 line->body.line.command_template = get_posix_rule;
2790 line->body.line.target = target;
2792 * Also make sure the rule is build with $* and $<
2793 * bound properly.
2795 line->body.line.star = NULL;
2796 line->body.line.less = NULL;
2797 line->body.line.percent = NULL;
2798 return build_ok;
2800 return build_dont_know;
2804 * read_directory_of_file(file)
2806 * Reads the directory the specified file lives in.
2808 * Parameters:
2809 * file The file we need to read dir for
2811 * Global variables used:
2812 * dot The Name ".", used as the default dir
2814 void
2815 read_directory_of_file(register Name file)
2818 Wstring file_string(file);
2819 wchar_t * wcb = file_string.get_string();
2820 wchar_t usr_include_buf[MAXPATHLEN];
2821 wchar_t usr_include_sys_buf[MAXPATHLEN];
2823 register Name directory = dot;
2824 register wchar_t *p = (wchar_t *) wcsrchr(wcb,
2825 (int) slash_char);
2826 register int length = p - wcb;
2827 static Name usr_include;
2828 static Name usr_include_sys;
2830 if (usr_include == NULL) {
2831 MBSTOWCS(usr_include_buf, "/usr/include");
2832 usr_include = GETNAME(usr_include_buf, FIND_LENGTH);
2833 MBSTOWCS(usr_include_sys_buf, "/usr/include/sys");
2834 usr_include_sys = GETNAME(usr_include_sys_buf, FIND_LENGTH);
2838 * If the filename contains a "/" we have to extract the path
2839 * Else the path defaults to ".".
2841 if (p != NULL) {
2843 * Check some popular directories first to possibly
2844 * save time. Compare string length first to gain speed.
2846 if ((usr_include->hash.length == length) &&
2847 IS_WEQUALN(usr_include_buf,
2848 wcb,
2849 length)) {
2850 directory = usr_include;
2851 } else if ((usr_include_sys->hash.length == length) &&
2852 IS_WEQUALN(usr_include_sys_buf,
2853 wcb,
2854 length)) {
2855 directory = usr_include_sys;
2856 } else {
2857 directory = GETNAME(wcb, length);
2860 (void) read_dir(directory,
2861 (wchar_t *) NULL,
2862 (Property) NULL,
2863 (wchar_t *) NULL);
2867 * add_pattern_conditionals(target)
2869 * Scan the list of conditionals defined for pattern targets and add any
2870 * that match this target to its list of conditionals.
2872 * Parameters:
2873 * target The target we should add conditionals for
2875 * Global variables used:
2876 * conditionals The list of pattern conditionals
2878 static void
2879 add_pattern_conditionals(register Name target)
2881 register Property conditional;
2882 Property new_prop;
2883 Property *previous;
2884 Name_rec dummy;
2885 wchar_t *pattern;
2886 wchar_t *percent;
2887 int length;
2889 Wstring wcb(target);
2890 Wstring wcb1;
2892 for (conditional = get_prop(conditionals->prop, conditional_prop);
2893 conditional != NULL;
2894 conditional = get_prop(conditional->next, conditional_prop)) {
2895 wcb1.init(conditional->body.conditional.target);
2896 pattern = wcb1.get_string();
2897 if (pattern[1] != 0) {
2898 percent = (wchar_t *) wcschr(pattern, (int) percent_char);
2899 /* Check for possible buffer under-read */
2900 if ((length = wcb.length()-wcslen(percent+1)) <= 0) {
2901 continue;
2903 if (!wcb.equaln(pattern, percent-pattern) ||
2904 !IS_WEQUAL(wcb.get_string(length), percent+1)) {
2905 continue;
2908 for (previous = &target->prop;
2909 *previous != NULL;
2910 previous = &(*previous)->next) {
2911 if (((*previous)->type == conditional_prop) &&
2912 ((*previous)->body.conditional.sequence >
2913 conditional->body.conditional.sequence)) {
2914 break;
2917 if (*previous == NULL) {
2918 new_prop = append_prop(target, conditional_prop);
2919 } else {
2920 dummy.prop = NULL;
2921 new_prop = append_prop(&dummy, conditional_prop);
2922 new_prop->next = *previous;
2923 *previous = new_prop;
2925 target->conditional_cnt++;
2926 new_prop->body.conditional = conditional->body.conditional;
2931 * set_locals(target, old_locals)
2933 * Sets any conditional macros for the target.
2934 * Each target carries a possibly empty set of conditional properties.
2936 * Parameters:
2937 * target The target to set conditional macros for
2938 * old_locals Space to store old values in
2940 * Global variables used:
2941 * debug_level Should we trace activity?
2942 * is_conditional We need to preserve this value
2943 * recursion_level Used for tracing
2945 void
2946 set_locals(register Name target, register Property old_locals)
2948 register Property conditional;
2949 register int i;
2950 register Boolean saved_conditional_macro_used;
2951 Chain cond_name;
2952 Chain cond_chain;
2954 if (target->dont_activate_cond_values) {
2955 return;
2958 saved_conditional_macro_used = conditional_macro_used;
2960 /* Scan the list of conditional properties and apply each one */
2961 for (conditional = get_prop(target->prop, conditional_prop), i = 0;
2962 conditional != NULL;
2963 conditional = get_prop(conditional->next, conditional_prop),
2964 i++) {
2965 /* Save the old value */
2966 old_locals[i].body.macro =
2967 maybe_append_prop(conditional->body.conditional.name,
2968 macro_prop)->body.macro;
2969 if (debug_level > 1) {
2970 (void) printf(gettext("%*sActivating conditional value: "),
2971 recursion_level,
2972 "");
2974 /* Set the conditional value. Macros are expanded when the */
2975 /* macro is refd as usual */
2976 if ((conditional->body.conditional.name != virtual_root) ||
2977 (conditional->body.conditional.value != virtual_root)) {
2978 (void) SETVAR(conditional->body.conditional.name,
2979 conditional->body.conditional.value,
2980 (Boolean) conditional->body.conditional.append);
2982 cond_name = ALLOC(Chain);
2983 cond_name->name = conditional->body.conditional.name;
2985 /* Put this target on the front of the chain of conditional targets */
2986 cond_chain = ALLOC(Chain);
2987 cond_chain->name = target;
2988 cond_chain->next = conditional_targets;
2989 conditional_targets = cond_chain;
2990 conditional_macro_used = saved_conditional_macro_used;
2994 * reset_locals(target, old_locals, conditional, index)
2996 * Removes any conditional macros for the target.
2998 * Parameters:
2999 * target The target we are retoring values for
3000 * old_locals The values to restore
3001 * conditional The first conditional block for the target
3002 * index into the old_locals vector
3003 * Global variables used:
3004 * debug_level Should we trace activities?
3005 * recursion_level Used for tracing
3007 void
3008 reset_locals(register Name target, register Property old_locals, register Property conditional, register int index)
3010 register Property this_conditional;
3011 Chain cond_chain;
3013 if (target->dont_activate_cond_values) {
3014 return;
3017 /* Scan the list of conditional properties and restore the old value */
3018 /* to each one Reverse the order relative to when we assigned macros */
3019 this_conditional = get_prop(conditional->next, conditional_prop);
3020 if (this_conditional != NULL) {
3021 reset_locals(target, old_locals, this_conditional, index+1);
3022 } else {
3023 /* Remove conditional target from chain */
3024 if (conditional_targets == NULL ||
3025 conditional_targets->name != target) {
3026 warning(gettext("Internal error: reset target not at head of condtional_targets chain"));
3027 } else {
3028 cond_chain = conditional_targets->next;
3029 retmem_mb((caddr_t) conditional_targets);
3030 conditional_targets = cond_chain;
3033 get_prop(conditional->body.conditional.name->prop,
3034 macro_prop)->body.macro = old_locals[index].body.macro;
3035 if (conditional->body.conditional.name == virtual_root) {
3036 (void) SETVAR(virtual_root, getvar(virtual_root), false);
3038 if (debug_level > 1) {
3039 if (old_locals[index].body.macro.value != NULL) {
3040 (void) printf(gettext("%*sdeactivating conditional value: %s= %s\n"),
3041 recursion_level,
3043 conditional->body.conditional.name->
3044 string_mb,
3045 old_locals[index].body.macro.value->
3046 string_mb);
3047 } else {
3048 (void) printf(gettext("%*sdeactivating conditional value: %s =\n"),
3049 recursion_level,
3051 conditional->body.conditional.name->
3052 string_mb);
3058 * check_auto_dependencies(target, auto_count, automatics)
3060 * Returns true if the target now has a dependency
3061 * it didn't previously have (saved on automatics).
3063 * Return value:
3064 * true if new dependency found
3066 * Parameters:
3067 * target Target we check
3068 * auto_count Number of old automatic vars
3069 * automatics Saved old automatics
3071 * Global variables used:
3072 * keep_state Indicates that .KEEP_STATE is on
3074 Boolean
3075 check_auto_dependencies(Name target, int auto_count, Name *automatics)
3077 Name *p;
3078 int n;
3079 Property line;
3080 Dependency dependency;
3082 if (keep_state) {
3083 if ((line = get_prop(target->prop, line_prop)) == NULL) {
3084 return false;
3086 /* Go thru new list of automatic depes */
3087 for (dependency = line->body.line.dependencies;
3088 dependency != NULL;
3089 dependency = dependency->next) {
3090 /* And make sure that each one existed before we */
3091 /* built the target */
3092 if (dependency->automatic && !dependency->stale) {
3093 for (n = auto_count, p = automatics;
3094 n > 0;
3095 n--) {
3096 if (*p++ == dependency->name) {
3097 /* If we can find it on the */
3098 /* saved list of autos we */
3099 /* are OK */
3100 goto not_new;
3103 /* But if we scan over the old list */
3104 /* of auto. without finding it it is */
3105 /* new and we must check it */
3106 return true;
3108 not_new:;
3110 return false;
3111 } else {
3112 return false;
3117 // Recursively delete each of the Chain struct on the chain.
3119 static void
3120 delete_query_chain(Chain ch)
3122 if (ch == NULL) {
3123 return;
3124 } else {
3125 delete_query_chain(ch->next);
3126 retmem_mb((char *) ch);
3130 Doname
3131 target_can_be_built(register Name target) {
3132 Doname result = build_dont_know;
3133 Name true_target = target;
3134 Property line;
3136 if (target == wait_name) {
3137 return(build_ok);
3140 * If the target is a constructed one for a "::" target,
3141 * we need to consider that.
3143 if (target->has_target_prop) {
3144 true_target = get_prop(target->prop,
3145 target_prop)->body.target.target;
3148 (void) exists(true_target);
3150 if (true_target->state == build_running) {
3151 return(build_running);
3153 if (true_target->stat.time != file_doesnt_exist) {
3154 result = build_ok;
3157 /* get line property for the target */
3158 line = get_prop(true_target->prop, line_prop);
3160 /* first check for explicit rule */
3161 if (line != NULL && line->body.line.command_template != NULL) {
3162 result = build_ok;
3164 /* try to find pattern rule */
3165 if (result == build_dont_know) {
3166 result = find_percent_rule(target, NULL, false);
3169 /* try to find double suffix rule */
3170 if (result == build_dont_know) {
3171 if (target->is_member) {
3172 Property member = get_prop(target->prop, member_prop);
3173 if (member != NULL && member->body.member.member != NULL) {
3174 result = find_ar_suffix_rule(target, member->body.member.member, NULL, false);
3175 } else {
3176 result = find_double_suffix_rule(target, NULL, false);
3178 } else {
3179 result = find_double_suffix_rule(target, NULL, false);
3183 /* try to find suffix rule */
3184 if ((result == build_dont_know) && second_pass) {
3185 result = find_suffix_rule(target, target, empty_name, NULL, false);
3188 /* check for sccs */
3189 if (result == build_dont_know) {
3190 result = sccs_get(target, NULL);
3193 /* try to find dyn target */
3194 if (result == build_dont_know) {
3195 Name dtarg = find_dyntarget(target);
3196 if (dtarg != NULL) {
3197 result = target_can_be_built(dtarg);
3201 /* check whether target was mentioned in makefile */
3202 if (result == build_dont_know) {
3203 if (target->colons != no_colon) {
3204 result = build_ok;
3208 /* result */
3209 return result;