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