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