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