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