4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 * Copyright 2016 RackTop Systems.
26 * Copyright (c) 2016 by Delphix. All rights reserved.
32 * Figure out which targets are out of date and rebuild them
38 #include <alloca.h> /* alloca() */
41 #include <mksh/i18n.h> /* get_char_semantics_value() */
42 #include <mksh/macro.h> /* getvar(), expand_value() */
43 #include <mksh/misc.h> /* getmem() */
48 #include <sys/errno.h>
50 #include <sys/types.h>
51 #include <sys/utsname.h> /* uname() */
53 #include <unistd.h> /* close() */
58 # define LOCALHOST "localhost"
62 // Sleep for .1 seconds between stat()'s
63 const int STAT_RETRY_SLEEP_TIME
= 100000;
72 static char hostName
[MAXNAMELEN
] = "";
73 static char userName
[MAXNAMELEN
] = "";
76 static int second_pass
= 0;
79 * File table of contents
81 extern Doname
doname_check(register Name target
, register Boolean do_get
, register Boolean implicit
, register Boolean automatic
);
82 extern Doname
doname(register Name target
, register Boolean do_get
, register Boolean implicit
, register Boolean automatic
);
83 static Boolean
check_dependencies(Doname
*result
, Property line
, Boolean do_get
, Name target
, Name true_target
, Boolean doing_subtree
, Chain
*out_of_date_tail
, Property old_locals
, Boolean implicit
, Property
*command
, Name less
, Boolean rechecking_target
, Boolean recheck_conditionals
);
84 void dynamic_dependencies(Name target
);
85 static Doname
run_command(register Property line
, Boolean print_machine
);
86 extern Doname
execute_serial(Property line
);
87 extern Name
vpath_translation(register Name cmd
);
88 extern void check_state(Name temp_file_name
);
89 static void read_dependency_file(register Name filename
);
90 static void check_read_state_file(void);
91 static void do_assign(register Name line
, register Name target
);
92 static void build_command_strings(Name target
, register Property line
);
93 static Doname
touch_command(register Property line
, register Name target
, Doname result
);
94 extern void update_target(Property line
, Doname result
);
95 static Doname
sccs_get(register Name target
, register Property
*command
);
96 extern void read_directory_of_file(register Name file
);
97 static void add_pattern_conditionals(register Name target
);
98 extern void set_locals(register Name target
, register Property old_locals
);
99 extern void reset_locals(register Name target
, register Property old_locals
, register Property conditional
, register int index
);
100 extern Boolean
check_auto_dependencies(Name target
, int auto_count
, Name
*automatics
);
101 static void delete_query_chain(Chain ch
);
104 extern Name
normalize_name(register wchar_t *name_string
, register int length
);
111 * doname_check(target, do_get, implicit, automatic)
113 * Will call doname() and then inspect the return value
116 * Indication if the build failed or not
119 * target The target to build
120 * do_get Passed thru to doname()
121 * implicit Passed thru to doname()
122 * automatic Are we building a hidden dependency?
124 * Global variables used:
125 * build_failed_seen Set if -k is on and error occurs
126 * continue_after_error Indicates that -k is on
127 * report_dependencies No error msg if -P is on
130 doname_check(register Name target
, register Boolean do_get
, register Boolean implicit
, register Boolean automatic
)
133 (void) fflush(stdout
);
135 switch (doname(target
, do_get
, implicit
, automatic
)) {
141 return build_running
;
143 if (!continue_after_error
) {
144 fatal(gettext("Target `%s' not remade because of errors"),
147 build_failed_seen
= true;
150 case build_dont_know
:
152 * If we can't figure out how to build an automatic
153 * (hidden) dependency, we just ignore it.
154 * We later declare the target to be out of date just in
155 * case something changed.
156 * Also, don't complain if just reporting the dependencies
157 * and not building anything.
159 if (automatic
|| (report_dependencies_level
> 0)) {
161 return build_dont_know
;
169 if (continue_after_error
&& !svr4
) {
170 warning(gettext("Don't know how to make target `%s'"),
172 build_failed_seen
= true;
175 fatal(gettext("Don't know how to make target `%s'"), target
->string_mb
);
185 enter_explicit_rule_from_dynamic_rule(Name target
, Name source
)
187 Property line
, source_line
;
188 Dependency dependency
;
190 source_line
= get_prop(source
->prop
, line_prop
);
191 line
= maybe_append_prop(target
, line_prop
);
192 line
->body
.line
.sccs_command
= false;
193 line
->body
.line
.target
= target
;
194 if (line
->body
.line
.command_template
== NULL
) {
195 line
->body
.line
.command_template
= source_line
->body
.line
.command_template
;
196 for (dependency
= source_line
->body
.line
.dependencies
;
198 dependency
= dependency
->next
) {
199 enter_dependency(line
, dependency
->name
, false);
201 line
->body
.line
.less
= target
;
203 line
->body
.line
.percent
= NULL
;
209 find_dyntarget(Name target
)
214 wchar_t buffer
[STRING_BUFFER_LENGTH
];
215 wchar_t *pp
, * bufend
;
216 wchar_t tbuffer
[MAXPATHLEN
];
219 for (p
= dyntarget_list
; p
!= NULL
; p
= p
->next
) {
220 INIT_STRING_FROM_STACK(string
, buffer
);
221 expand_value(p
->name
, &string
, false);
223 pp
= string
.buffer
.start
;
224 bufend
= pp
+ STRING_BUFFER_LENGTH
;
225 while((*pp
!= nul_char
) && (pp
< bufend
)) {
227 tbuffer
[i
] = nul_char
;
229 if (wcb
.equal(tbuffer
)) {
230 enter_explicit_rule_from_dynamic_rule(target
, p
->name
);
241 if(*pp
== nul_char
) {
242 tbuffer
[i
] = nul_char
;
244 if (wcb
.equal(tbuffer
)) {
245 enter_explicit_rule_from_dynamic_rule(target
, p
->name
);
259 * doname(target, do_get, implicit)
261 * Chases all files the target depends on and builds any that
262 * are out of date. If the target is out of date it is then rebuilt.
265 * Indiates if build failed or nt
268 * target Target to build
269 * do_get Run sccs get is nessecary
270 * implicit doname is trying to find an implicit rule
272 * Global variables used:
273 * assign_done True if command line assgnment has happened
274 * commands_done Preserved for the case that we need local value
275 * debug_level Should we trace make's actions?
276 * default_rule The rule for ".DEFAULT", used as last resort
277 * empty_name The Name "", used when looking for single sfx
278 * keep_state Indicates that .KEEP_STATE is on
279 * parallel True if building in parallel
280 * recursion_level Used for tracing
281 * report_dependencies make -P is on
284 doname(register Name target
, register Boolean do_get
, register Boolean implicit
, register Boolean automatic
)
286 Doname result
= build_dont_know
;
287 Chain out_of_date_list
= NULL
;
289 Property old_locals
= NULL
;
290 register Property line
;
291 Property command
= NULL
;
292 register Dependency dependency
;
294 Name true_target
= target
;
295 Name
*automatics
= NULL
;
296 register int auto_count
;
297 Boolean rechecking_target
= false;
298 Boolean saved_commands_done
;
299 Boolean restart
= false;
300 Boolean save_parallel
= parallel
;
301 Boolean doing_subtree
= false;
303 Boolean recheck_conditionals
= false;
305 if (target
->state
== build_running
) {
306 return build_running
;
308 line
= get_prop(target
->prop
, line_prop
);
311 * If this target is a member of target group and one of the
312 * other members of the group is running, mark this target
315 for (target_group
= line
->body
.line
.target_group
;
316 target_group
!= NULL
;
317 target_group
= target_group
->next
) {
318 if (is_running(target_group
->name
)) {
319 target
->state
= build_running
;
325 return build_running
;
330 * If the target is a constructed one for a "::" target,
331 * we need to consider that.
333 if (target
->has_target_prop
) {
334 true_target
= get_prop(target
->prop
,
335 target_prop
)->body
.target
.target
;
336 if (true_target
->colon_splits
> 0) {
337 /* Make sure we have a valid time for :: targets */
340 time
= get_prop(true_target
->prop
, time_prop
);
342 true_target
->stat
.time
= time
->body
.time
.time
;
346 (void) exists(true_target
);
348 * If the target has been processed, we don't need to do it again,
349 * unless it depends on conditional macros or a delayed assignment,
350 * or it has been done when KEEP_STATE is on.
352 if (target
->state
== build_ok
) {
353 if((!keep_state
|| (!target
->depends_on_conditional
&& !assign_done
))) {
356 recheck_conditionals
= true;
359 if (target
->state
== build_subtree
) {
360 /* A dynamic macro subtree is being built */
361 target
->state
= build_dont_know
;
362 doing_subtree
= true;
363 if (!target
->checking_subtree
) {
365 * This target has been started before and therefore
366 * not all dependencies have to be built.
370 } else if (target
->state
== build_pending
) {
371 target
->state
= build_dont_know
;
374 } else if (parallel &&
376 (target->conditional_cnt > 0)) {
377 if (!parallel_ok(target, false)) {
378 add_subtree(target, recursion_level, do_get, implicit);
379 target->state = build_running;
380 return build_running;
385 * If KEEP_STATE is on, we have to rebuild the target if the
386 * building of it caused new automatic dependencies to be reported.
387 * This is where we restart the build.
390 line
->body
.line
.percent
= NULL
;
393 /* Init all local variables */
394 result
= build_dont_know
;
395 out_of_date_list
= NULL
;
399 if (!restart
&& line
!= NULL
) {
401 * If this target has never been built before, mark all
402 * of the dependencies as never built.
404 for (dependency
= line
->body
.line
.dependencies
;
406 dependency
= dependency
->next
) {
407 dependency
->built
= false;
410 /* Save the set of automatic depes defined for this target */
413 (line
->body
.line
.dependencies
!= NULL
)) {
417 * First run thru the dependency list to see how many
420 for (dependency
= line
->body
.line
.dependencies
;
422 dependency
= dependency
->next
) {
423 if (dependency
->automatic
&& !dependency
->stale
) {
427 /* Create vector to hold the current autos */
429 (Name
*) alloca((int) (auto_count
* sizeof (Name
)));
431 for (p
= automatics
, dependency
= line
->body
.line
.dependencies
;
433 dependency
= dependency
->next
) {
434 if (dependency
->automatic
&& !dependency
->stale
) {
435 *p
++ = dependency
->name
;
439 if (debug_level
> 1) {
440 (void) printf("%*sdoname(%s)\n",
446 /* Avoid infinite loops */
447 if (target
->state
== build_in_progress
) {
448 warning(gettext("Infinite loop: Target `%s' depends on itself"),
452 target
->state
= build_in_progress
;
454 /* Activate conditional macros for the target */
455 if (!target
->added_pattern_conditionals
) {
456 add_pattern_conditionals(target
);
457 target
->added_pattern_conditionals
= true;
459 if (target
->conditional_cnt
> 0) {
460 old_locals
= (Property
) alloca(target
->conditional_cnt
*
461 sizeof (Property_rec
));
462 set_locals(target
, old_locals
);
466 * after making the call to dynamic_dependecies unconditional we can handle
467 * target names that are same as file name. In this case $$@ in the
468 * dependencies did not mean anything. WIth this change it expands it
471 if (!target
->has_depe_list_expanded
)
473 dynamic_dependencies(target
);
477 * FIRST SECTION -- GO THROUGH DEPENDENCIES AND COLLECT EXPLICIT
480 if ((line
= get_prop(target
->prop
, line_prop
)) != NULL
) {
481 if (check_dependencies(&result
,
493 recheck_conditionals
)) {
494 return build_running
;
496 if (line
->body
.line
.query
!= NULL
) {
497 delete_query_chain(line
->body
.line
.query
);
499 line
->body
.line
.query
= out_of_date_list
;
504 * If the target is a :: type, do not try to find the rule for the target,
505 * all actions will be taken by separate branches.
506 * Else, we try to find an implicit rule using various methods,
507 * we quit as soon as one is found.
509 * [tolik, 12 Sep 2002] Do not try to find implicit rule for the target
510 * being rechecked - the target is being rechecked means that it already
511 * has explicit dependencies derived from an implicit rule found
514 if (target
->colon_splits
== 0 && !rechecking_target
) {
515 /* Look for percent matched rule */
516 if ((result
== build_dont_know
) &&
518 switch (find_percent_rule(
521 recheck_conditionals
)) {
523 result
= build_failed
;
526 target
->state
= build_running
;
532 if (target
->conditional_cnt
> 0) {
535 get_prop(target
->prop
,
539 return build_running
;
545 /* Look for double suffix rule */
546 if (result
== build_dont_know
) {
549 if (target
->is_member
&&
550 ((member
= get_prop(target
->prop
, member_prop
)) !=
552 switch (find_ar_suffix_rule(target
,
556 recheck_conditionals
)) {
558 result
= build_failed
;
561 target
->state
= build_running
;
567 if (target
->conditional_cnt
> 0) {
570 get_prop(target
->prop
,
574 return build_running
;
576 /* ALWAYS bind $% for old style */
580 maybe_append_prop(target
,
583 line
->body
.line
.percent
=
584 member
->body
.member
.member
;
588 switch (find_double_suffix_rule(target
,
590 recheck_conditionals
)) {
592 result
= build_failed
;
595 target
->state
= build_running
;
601 if (target
->conditional_cnt
> 0) {
609 return build_running
;
613 /* Look for single suffix rule */
616 * I commented !implicit to fix bug 1247448: Suffix Rules failed when combine with Pattern Matching Rules.
617 * This caused problem with SVR4 tilde rules (infinite recursion). So I made some changes in "implicit.cc"
620 * Regression! See BugId 1255360
621 * If more than one percent rules are defined for the same target then
622 * the behaviour of 'make' with my previous fix may be different from one
624 * The global variable second_pass (maybe it should be an argument to doname())
625 * is intended to avoid this regression. It is set in doname_check().
626 * First, 'make' will work as it worked before. Only when it is
627 * going to say "don't know how to make target" it sets second_pass to true and
628 * run 'doname' again but now trying to use Single Suffix Rules.
630 if ((result
== build_dont_know
) && !automatic
&& (!implicit
|| second_pass
) &&
632 ((line
->body
.line
.target
!= NULL
) &&
633 !line
->body
.line
.target
->has_regular_dependency
))) {
634 switch (find_suffix_rule(target
,
638 recheck_conditionals
)) {
640 result
= build_failed
;
643 target
->state
= build_running
;
649 if (target
->conditional_cnt
> 0) {
652 get_prop(target
->prop
,
656 return build_running
;
659 /* Try to sccs get */
660 if ((command
== NULL
) &&
661 (result
== build_dont_know
) &&
663 result
= sccs_get(target
, &command
);
666 /* Use .DEFAULT rule if it is defined. */
667 if ((command
== NULL
) &&
668 (result
== build_dont_know
) &&
669 (true_target
->colons
== no_colon
) &&
672 /* Make sure we have a line prop */
673 line
= maybe_append_prop(target
, line_prop
);
676 if (true_target
->is_member
) {
677 out_of_date
= (Boolean
) OUT_OF_DATE_SEC(true_target
->stat
.time
,
678 line
->body
.line
.dependency_time
);
680 out_of_date
= (Boolean
) OUT_OF_DATE(true_target
->stat
.time
,
681 line
->body
.line
.dependency_time
);
683 if (build_unconditional
|| out_of_date
) {
684 line
->body
.line
.is_out_of_date
= true;
685 if (debug_level
> 0) {
686 (void) printf(gettext("%*sBuilding %s using .DEFAULT because it is out of date\n"),
689 true_target
->string_mb
);
692 line
->body
.line
.sccs_command
= false;
693 line
->body
.line
.command_template
= default_rule
;
694 line
->body
.line
.target
= true_target
;
695 line
->body
.line
.star
= NULL
;
696 line
->body
.line
.less
= true_target
;
697 line
->body
.line
.percent
= NULL
;
701 /* We say "target up to date" if no cmd were executed for the target */
702 if (!target
->is_double_colon_parent
) {
703 commands_done
= false;
707 ignore_errors
= ignore_errors_all
;
712 silent
= (Boolean
) target
->silent_mode
;
716 ignore_errors
= (Boolean
) target
->ignore_error_mode
;
720 int doname_dyntarget
= 0;
722 /* Run commands if any. */
723 if ((command
!= NULL
) &&
724 (command
->body
.line
.command_template
!= NULL
)) {
725 if (result
!= build_failed
) {
726 result
= run_command(command
,
727 (Boolean
) ((parallel
|| save_parallel
) && !silent
));
739 target
->state
= build_running
;
740 if ((line
= get_prop(target
->prop
,
741 line_prop
)) != NULL
) {
742 if (line
->body
.line
.query
!= NULL
) {
743 delete_query_chain(line
->body
.line
.query
);
745 line
->body
.line
.query
= NULL
;
747 if (target
->conditional_cnt
> 0) {
750 get_prop(target
->prop
,
754 return build_running
;
760 target
->state
= build_running
;
761 line
= get_prop(target
->prop
, line_prop
);
763 if (line
->body
.line
.query
!= NULL
) {
764 delete_query_chain(line
->body
.line
.query
);
766 line
->body
.line
.query
= NULL
;
768 if (target
->conditional_cnt
> 0) {
771 get_prop(target
->prop
,
775 return build_running
;
777 /* If all went OK set a nice timestamp */
778 if (true_target
->stat
.time
== file_doesnt_exist
) {
779 true_target
->stat
.time
= file_max_time
;
785 * If no command was found for the target, and it doesn't
786 * exist, and it is mentioned as a target in the makefile,
787 * we say it is extremely new and that it is OK.
789 if (target
->colons
!= no_colon
) {
790 if (true_target
->stat
.time
== file_doesnt_exist
){
791 true_target
->stat
.time
= file_max_time
;
796 * Trying dynamic targets.
798 if(!doname_dyntarget
) {
799 doname_dyntarget
= 1;
800 Name dtarg
= find_dyntarget(target
);
802 if (!target
->has_depe_list_expanded
) {
803 dynamic_dependencies(target
);
805 if ((line
= get_prop(target
->prop
, line_prop
)) != NULL
) {
806 if (check_dependencies(&result
,
818 recheck_conditionals
))
820 return build_running
;
822 if (line
->body
.line
.query
!= NULL
) {
823 delete_query_chain(line
->body
.line
.query
);
825 line
->body
.line
.query
= out_of_date_list
;
831 * If the file exists, it is OK that we couldnt figure
832 * out how to build it.
834 (void) exists(target
);
835 if ((target
->stat
.time
!= file_doesnt_exist
) &&
836 (result
== build_dont_know
)) {
842 * Some of the following is duplicated in the function finish_doname.
843 * If anything is changed here, check to see if it needs to be
846 if ((line
= get_prop(target
->prop
, line_prop
)) != NULL
) {
847 if (line
->body
.line
.query
!= NULL
) {
848 delete_query_chain(line
->body
.line
.query
);
850 line
->body
.line
.query
= NULL
;
852 target
->state
= result
;
853 parallel
= save_parallel
;
854 if (target
->conditional_cnt
> 0) {
857 get_prop(target
->prop
, conditional_prop
),
861 if (target
->is_member
) {
864 /* Propagate the timestamp from the member file to the member*/
865 if ((target
->stat
.time
!= file_max_time
) &&
866 ((member
= get_prop(target
->prop
, member_prop
)) != NULL
) &&
867 (exists(member
->body
.member
.member
) > file_doesnt_exist
)) {
869 member
->body
.member
.member
->stat
.time
;
873 * Check if we found any new auto dependencies when we
876 if ((result
== build_ok
) && check_auto_dependencies(target
,
879 if (debug_level
> 0) {
880 (void) printf(gettext("%*sTarget `%s' acquired new dependencies from build, rechecking all dependencies\n"),
883 true_target
->string_mb
);
885 rechecking_target
= true;
886 saved_commands_done
= commands_done
;
890 if (rechecking_target
&& !commands_done
) {
891 commands_done
= saved_commands_done
;
900 * check_dependencies(result, line, do_get,
901 * target, true_target, doing_subtree, out_of_date_tail,
902 * old_locals, implicit, command, less, rechecking_target)
905 * True returned if some dependencies left running
908 * result Pointer to cell we update if build failed
909 * line We get the dependencies from here
910 * do_get Allow use of sccs get in recursive doname()
911 * target The target to chase dependencies for
912 * true_target The real one for :: and lib(member)
913 * doing_subtree True if building a conditional macro subtree
914 * out_of_date_tail Used to set the $? list
915 * old_locals Used for resetting the local macros
916 * implicit Called when scanning for implicit rules?
917 * command Place to stuff command
918 * less Set to $< value
920 * Global variables used:
921 * command_changed Set if we suspect .make.state needs rewrite
922 * debug_level Should we trace actions?
923 * force The Name " FORCE", compared against
924 * recursion_level Used for tracing
925 * rewrite_statefile Set if .make.state needs rewriting
926 * wait_name The Name ".WAIT", compared against
929 check_dependencies(Doname
*result
, Property line
, Boolean do_get
, Name target
, Name true_target
, Boolean doing_subtree
, Chain
*out_of_date_tail
, Property old_locals
, Boolean implicit
, Property
*command
, Name less
, Boolean rechecking_target
, Boolean recheck_conditionals
)
931 Boolean dependencies_running
;
932 register Dependency dependency
;
934 Boolean dependency_changed
= false;
936 line
->body
.line
.dependency_time
= file_doesnt_exist
;
937 if (line
->body
.line
.query
!= NULL
) {
938 delete_query_chain(line
->body
.line
.query
);
940 line
->body
.line
.query
= NULL
;
941 line
->body
.line
.is_out_of_date
= false;
942 dependencies_running
= false;
944 * Run thru all the dependencies and call doname() recursively
947 for (dependency
= line
->body
.line
.dependencies
;
949 dependency
= dependency
->next
) {
950 Boolean this_dependency_changed
= false;
952 if (!dependency
->automatic
&&
953 (rechecking_target
|| target
->rechecking_target
)) {
955 * We only bother with the autos when rechecking
960 if (dependency
->name
== wait_name
) {
962 * The special target .WAIT means finish all of
963 * the prior dependencies before continuing.
965 if (dependencies_running
) {
968 } else if ((!parallel_ok(dependency
->name
, false)) &&
969 (dependencies_running
)) {
971 * If we can't execute the current dependency in
972 * parallel, hold off the dependency processing
973 * to preserve the order of the dependencies.
977 timestruc_t depe_time
= file_doesnt_exist
;
980 if (true_target
->is_member
) {
981 depe_time
= exists(dependency
->name
);
983 if (dependency
->built
||
984 (dependency
->name
->state
== build_failed
)) {
985 dep_result
= (Doname
) dependency
->name
->state
;
987 dep_result
= doname_check(dependency
->name
,
990 (Boolean
) dependency
->automatic
);
992 if (true_target
->is_member
|| dependency
->name
->is_member
) {
993 /* should compare only secs, cause lib members does not have nsec time resolution */
994 if (depe_time
.tv_sec
!= dependency
->name
->stat
.time
.tv_sec
) {
995 this_dependency_changed
=
1000 if (depe_time
!= dependency
->name
->stat
.time
) {
1001 this_dependency_changed
=
1002 dependency_changed
=
1006 dependency
->built
= true;
1007 switch (dep_result
) {
1009 dependencies_running
= true;
1012 *result
= build_failed
;
1014 case build_dont_know
:
1016 * If make can't figure out how to make a dependency, maybe the dependency
1017 * is out of date. In this case, we just declare the target out of date
1018 * and go on. If we really need the dependency, the make'ing of the target
1019 * will fail. This will only happen for automatic (hidden) dependencies.
1021 if(!recheck_conditionals
) {
1022 line
->body
.line
.is_out_of_date
= true;
1025 * Make sure the dependency is not saved
1026 * in the state file.
1028 dependency
->stale
= true;
1032 if (debug_level
> 0) {
1033 (void) printf(gettext("Target %s rebuilt because dependency %s does not exist\n"),
1034 true_target
->string_mb
,
1035 dependency
->name
->string_mb
);
1039 if (dependency
->name
->depends_on_conditional
) {
1040 target
->depends_on_conditional
= true;
1042 if (dependency
->name
== force
) {
1044 dependency
->name
->stat
.time
;
1047 * Propagate new timestamp from "member" to
1050 (void) exists(dependency
->name
);
1052 /* Collect the timestamp of the youngest dependency */
1053 line
->body
.line
.dependency_time
=
1054 MAX(dependency
->name
->stat
.time
,
1055 line
->body
.line
.dependency_time
);
1057 /* Correction: do not consider nanosecs for members */
1058 if(true_target
->is_member
|| dependency
->name
->is_member
) {
1059 line
->body
.line
.dependency_time
.tv_nsec
= 0;
1062 if (debug_level
> 1) {
1063 (void) printf(gettext("%*sDate(%s)=%s \n"),
1066 dependency
->name
->string_mb
,
1067 time_to_string(dependency
->name
->
1069 if (dependency
->name
->stat
.time
> line
->body
.line
.dependency_time
) {
1070 (void) printf(gettext("%*sDate-dependencies(%s) set to %s\n"),
1073 true_target
->string_mb
,
1074 time_to_string(line
->body
.line
.
1079 /* Build the $? list */
1080 if (true_target
->is_member
) {
1081 if (this_dependency_changed
== true) {
1082 true_target
->stat
.time
= dependency
->name
->stat
.time
;
1083 true_target
->stat
.time
.tv_sec
--;
1086 * The next statement is commented
1087 * out as a fix for bug #1051032.
1088 * if dependency hasn't changed
1089 * then there's no need to invalidate
1090 * true_target. This statemnt causes
1091 * make to take much longer to process
1092 * an already-built archive. Soren
1093 * said it was a quick fix for some
1094 * problem he doesn't remember.
1095 true_target->stat.time = file_no_time;
1097 (void) exists(true_target
);
1100 (void) exists(true_target
);
1102 Boolean out_of_date
;
1103 if (true_target
->is_member
|| dependency
->name
->is_member
) {
1104 out_of_date
= (Boolean
) OUT_OF_DATE_SEC(true_target
->stat
.time
,
1105 dependency
->name
->stat
.time
);
1107 out_of_date
= (Boolean
) OUT_OF_DATE(true_target
->stat
.time
,
1108 dependency
->name
->stat
.time
);
1110 if ((build_unconditional
|| out_of_date
) &&
1111 (dependency
->name
!= force
) &&
1112 (dependency
->stale
== false)) {
1113 *out_of_date_tail
= ALLOC(Chain
);
1114 if (dependency
->name
->is_member
&&
1115 (get_prop(dependency
->name
->prop
,
1116 member_prop
) != NULL
)) {
1117 (*out_of_date_tail
)->name
=
1118 get_prop(dependency
->name
->prop
,
1122 (*out_of_date_tail
)->name
=
1125 (*out_of_date_tail
)->next
= NULL
;
1126 out_of_date_tail
= &(*out_of_date_tail
)->next
;
1127 if (debug_level
> 0) {
1128 if (dependency
->name
->stat
.time
== file_max_time
) {
1129 (void) printf(gettext("%*sBuilding %s because %s does not exist\n"),
1132 true_target
->string_mb
,
1133 dependency
->name
->string_mb
);
1135 (void) printf(gettext("%*sBuilding %s because it is out of date relative to %s\n"),
1138 true_target
->string_mb
,
1139 dependency
->name
->string_mb
);
1143 if (dependency
->name
== force
) {
1146 force
->state
= build_dont_know
;
1150 if (dependencies_running
) {
1151 if (doing_subtree
) {
1152 if (target
->conditional_cnt
> 0) {
1153 reset_locals(target
,
1155 get_prop(target
->prop
,
1161 target
->state
= build_running
;
1167 if (target
->conditional_cnt
> 0) {
1168 reset_locals(target
,
1170 get_prop(target
->prop
,
1178 * Collect the timestamp of the youngest double colon target
1181 if (target
->is_double_colon_parent
) {
1182 for (dependency
= line
->body
.line
.dependencies
;
1184 dependency
= dependency
->next
) {
1187 if ((tmp_line
= get_prop(dependency
->name
->prop
, line_prop
)) != NULL
) {
1188 if(tmp_line
->body
.line
.dependency_time
!= file_max_time
) {
1190 MAX(tmp_line
->body
.line
.dependency_time
,
1196 if ((true_target
->is_member
) && (dependency_changed
== true)) {
1197 true_target
->stat
.time
= file_no_time
;
1200 * After scanning all the dependencies, we check the rule
1203 if (line
->body
.line
.command_template
!= NULL
) {
1204 if (line
->body
.line
.command_template_redefined
) {
1205 warning(gettext("Too many rules defined for target %s"),
1209 /* Check if the target is out of date */
1210 Boolean out_of_date
;
1211 if (true_target
->is_member
) {
1212 out_of_date
= (Boolean
) OUT_OF_DATE_SEC(true_target
->stat
.time
,
1213 line
->body
.line
.dependency_time
);
1215 out_of_date
= (Boolean
) OUT_OF_DATE(true_target
->stat
.time
,
1216 line
->body
.line
.dependency_time
);
1218 if (build_unconditional
|| out_of_date
){
1219 if(!recheck_conditionals
) {
1220 line
->body
.line
.is_out_of_date
= true;
1223 line
->body
.line
.sccs_command
= false;
1224 line
->body
.line
.target
= true_target
;
1227 // set $< for explicit rule
1228 if(line
->body
.line
.dependencies
!= NULL
) {
1229 less
= line
->body
.line
.dependencies
->name
;
1232 // set $* for explicit rule
1234 Name tt
= true_target
;
1236 register wchar_t *target_end
;
1237 register Dependency suffix
;
1238 register int suffix_length
;
1239 Wstring targ_string
;
1242 if (true_target
->is_member
&&
1243 ((member
= get_prop(target
->prop
, member_prop
)) !=
1245 tt
= member
->body
.member
.member
;
1247 targ_string
.init(tt
);
1248 target_end
= targ_string
.get_string() + tt
->hash
.length
;
1249 for (suffix
= suffixes
; suffix
!= NULL
; suffix
= suffix
->next
) {
1250 suffix_length
= suffix
->name
->hash
.length
;
1251 suf_string
.init(suffix
->name
);
1252 if (tt
->hash
.length
< suffix_length
) {
1254 } else if (!IS_WEQUALN(suf_string
.get_string(),
1255 (target_end
- suffix_length
),
1259 target_body
= GETNAME(
1260 targ_string
.get_string(),
1261 (int)(tt
->hash
.length
- suffix_length
)
1263 line
->body
.line
.star
= target_body
;
1266 // set result = build_ok so that implicit rules are not used.
1267 if(*result
== build_dont_know
) {
1272 line
->body
.line
.less
= less
;
1280 * dynamic_dependencies(target)
1282 * Checks if any dependency contains a macro ref
1283 * If so, it replaces the dependency with the expanded version.
1284 * Here, "$@" gets translated to target->string. That is
1285 * the current name on the left of the colon in the
1291 * Also, "$(@F)" translates to the same thing without a preceeding
1292 * directory path (if one exists).
1293 * Note, to enter "$@" on a dependency line in a makefile
1294 * "$$@" must be typed. This is because make expands
1295 * macros in dependency lists upon reading them.
1296 * dynamic_dependencies() also expands file wildcards.
1297 * If there are any Shell meta characters in the name,
1298 * search the directory, and replace the dependency
1299 * with the set of files the pattern matches
1302 * target Target to sanitize dependencies for
1304 * Global variables used:
1305 * c_at The Name "@", used to set macro value
1306 * debug_level Should we trace actions?
1307 * dot The Name ".", used to read directory
1308 * recursion_level Used for tracing
1311 dynamic_dependencies(Name target
)
1313 wchar_t pattern
[MAXPATHLEN
];
1314 register wchar_t *p
;
1316 register Dependency dependency
;
1317 register Dependency
*remove
;
1319 wchar_t buffer
[MAXPATHLEN
];
1320 register Boolean set_at
= false;
1321 register wchar_t *start
;
1322 Dependency new_depe
;
1323 register Boolean reuse_cell
;
1324 Dependency first_member
;
1329 Name true_target
= target
;
1332 if ((line
= get_prop(target
->prop
, line_prop
)) == NULL
) {
1335 /* If the target is constructed from a "::" target we consider that */
1336 if (target
->has_target_prop
) {
1337 true_target
= get_prop(target
->prop
,
1338 target_prop
)->body
.target
.target
;
1340 /* Scan all dependencies and process the ones that contain "$" chars */
1341 for (dependency
= line
->body
.line
.dependencies
;
1343 dependency
= dependency
->next
) {
1344 if (!dependency
->name
->dollar
) {
1347 target
->has_depe_list_expanded
= true;
1349 /* The make macro $@ is bound to the target name once per */
1350 /* invocation of dynamic_dependencies() */
1352 (void) SETVAR(c_at
, true_target
, false);
1355 /* Expand this dependency string */
1356 INIT_STRING_FROM_STACK(string
, buffer
);
1357 expand_value(dependency
->name
, &string
, false);
1358 /* Scan the expanded string. It could contain whitespace */
1359 /* which mean it expands to several dependencies */
1360 start
= string
.buffer
.start
;
1361 while (iswspace(*start
)) {
1364 /* Remove the cell (later) if the macro was empty */
1365 if (start
[0] == (int) nul_char
) {
1366 dependency
->name
= NULL
;
1369 /* azv 10/26/95 to fix bug BID_1170218 */
1370 if ((start
[0] == (int) period_char
) &&
1371 (start
[1] == (int) slash_char
)) {
1376 first_member
= NULL
;
1377 /* We use the original dependency cell for the first */
1378 /* dependency from the expansion */
1380 /* We also have to deal with dependencies that expand to */
1381 /* lib.a(members) notation */
1382 for (p
= start
; *p
!= (int) nul_char
; p
++) {
1383 if ((*p
== (int) parenleft_char
)) {
1384 lib
= GETNAME(start
, p
- start
);
1385 lib
->is_member
= true;
1386 first_member
= dependency
;
1388 while (iswspace(*start
)) {
1395 /* First skip whitespace */
1396 for (p
= start
; *p
!= (int) nul_char
; p
++) {
1397 if ((*p
== (int) nul_char
) ||
1399 (*p
== (int) parenright_char
)) {
1403 /* Enter dependency from expansion */
1405 /* Create new dependency cell if */
1406 /* this is not the first dependency */
1407 /* picked from the expansion */
1409 new_depe
= ALLOC(Dependency
);
1410 new_depe
->next
= dependency
->next
;
1411 new_depe
->automatic
= false;
1412 new_depe
->stale
= false;
1413 new_depe
->built
= false;
1414 dependency
->next
= new_depe
;
1415 dependency
= new_depe
;
1418 /* Internalize the dependency name */
1419 // tolik. Fix for bug 4110429: inconsistent expansion for macros that
1420 // include "//" and "/./"
1421 //dependency->name = GETNAME(start, p - start);
1422 dependency
->name
= normalize_name(start
, p
- start
);
1423 if ((debug_level
> 0) &&
1424 (first_member
== NULL
)) {
1425 (void) printf(gettext("%*sDynamic dependency `%s' for target `%s'\n"),
1428 dependency
->name
->string_mb
,
1429 true_target
->string_mb
);
1431 for (start
= p
; iswspace(*start
); start
++);
1434 } while ((*p
!= (int) nul_char
) &&
1435 (*p
!= (int) parenright_char
));
1436 /* If the expansion was of lib.a(members) format we now */
1437 /* enter the proper member cells */
1438 if (first_member
!= NULL
) {
1439 /* Scan the new dependencies and transform them from */
1440 /* "foo" to "lib.a(foo)" */
1441 for (; 1; first_member
= first_member
->next
) {
1442 /* Build "lib.a(foo)" name */
1443 INIT_STRING_FROM_STACK(string
, buffer
);
1446 (int) lib
->hash
.length
);
1447 append_char((int) parenleft_char
, &string
);
1448 APPEND_NAME(first_member
->name
,
1451 append_char((int) parenright_char
, &string
);
1452 member
= first_member
->name
;
1453 /* Replace "foo" with "lib.a(foo)" */
1454 first_member
->name
=
1455 GETNAME(string
.buffer
.start
, FIND_LENGTH
);
1456 if (string
.free_after_use
) {
1457 retmem(string
.buffer
.start
);
1459 if (debug_level
> 0) {
1460 (void) printf(gettext("%*sDynamic dependency `%s' for target `%s'\n"),
1463 first_member
->name
->
1465 true_target
->string_mb
);
1467 first_member
->name
->is_member
= lib
->is_member
;
1468 /* Add member property to member */
1469 prop
= maybe_append_prop(first_member
->name
,
1471 prop
->body
.member
.library
= lib
;
1472 prop
->body
.member
.entry
= NULL
;
1473 prop
->body
.member
.member
= member
;
1474 if (first_member
== dependency
) {
1481 /* Then scan all the dependencies again. This time we want to expand */
1482 /* shell file wildcards */
1483 for (remove
= &line
->body
.line
.dependencies
, dependency
= *remove
;
1485 dependency
= *remove
) {
1486 if (dependency
->name
== NULL
) {
1487 dependency
= *remove
= (*remove
)->next
;
1490 /* If dependency name string contains shell wildcards */
1491 /* replace the name with the expansion */
1492 if (dependency
->name
->wildcard
) {
1493 wcb
.init(dependency
->name
);
1494 if ((start
= (wchar_t *) wcschr(wcb
.get_string(),
1495 (int) parenleft_char
)) != NULL
) {
1496 /* lib(*) type pattern */
1498 (void) wcsncpy(buffer
,
1500 start
- wcb
.get_string());
1501 buffer
[start
-wcb
.get_string()] =
1503 (void) wcsncpy(pattern
,
1505 (int) (dependency
->name
->hash
.length
-(start
-wcb
.get_string())-2));
1506 pattern
[dependency
->name
->hash
.length
-
1507 (start
-wcb
.get_string()) - 2] =
1511 (void) wcsncpy(pattern
,
1513 (int) dependency
->name
->hash
.length
);
1514 pattern
[dependency
->name
->hash
.length
] =
1517 start
= (wchar_t *) wcsrchr(pattern
, (int) slash_char
);
1518 if (start
== NULL
) {
1522 directory
= GETNAME(pattern
, start
-pattern
);
1525 /* The expansion is handled by the read_dir() routine*/
1526 if (read_dir(directory
, p
, line
, library
)) {
1527 *remove
= (*remove
)->next
;
1529 remove
= &dependency
->next
;
1532 remove
= &dependency
->next
;
1536 /* Then unbind $@ */
1537 (void) SETVAR(c_at
, (Name
) NULL
, false);
1545 * Takes one Cmd_line and runs the commands from it.
1548 * Indicates if the command failed or not
1551 * line The command line to run
1553 * Global variables used:
1554 * commands_done Set if we do run command
1555 * current_line Set to the line we run a command from
1556 * current_target Set to the target we run a command for
1557 * file_number Used to form temp file name
1558 * keep_state Indicates that .KEEP_STATE is on
1559 * make_state The Name ".make.state", used to check timestamp
1560 * parallel True if currently building in parallel
1561 * parallel_process_cnt Count of parallel processes running
1562 * quest Indicates that make -q is on
1563 * rewrite_statefile Set if we do run a command
1564 * sunpro_dependencies The Name "SUNPRO_DEPENDENCIES", set value
1565 * temp_file_directory Used to form temp fie name
1566 * temp_file_name Set to the name of the temp file
1567 * touch Indicates that make -t is on
1570 run_command(register Property line
, Boolean
)
1572 register Doname result
= build_ok
;
1573 register Boolean remember_only
= false;
1574 register Name target
= line
->body
.line
.target
;
1576 char tmp_file_path
[MAXPATHLEN
];
1578 if (!line
->body
.line
.is_out_of_date
&& target
->rechecking_target
) {
1579 target
->rechecking_target
= false;
1584 * Build the command if we know the target is out of date,
1585 * or if we want to check cmd consistency.
1587 if (line
->body
.line
.is_out_of_date
|| keep_state
) {
1588 /* Hack for handling conditional macros in DMake. */
1589 if (!line
->body
.line
.dont_rebuild_command_used
) {
1590 build_command_strings(target
, line
);
1594 if (!line
->body
.line
.is_out_of_date
) {
1597 /* If quest, then exit(1) because the target is out of date */
1600 result
= execute_parallel(line
, true);
1605 /* We actually had to do something this time */
1606 rewrite_statefile
= commands_done
= true;
1608 * If this is an sccs command, we have to do some extra checking
1609 * and possibly complain. If the file can't be gotten because it's
1610 * checked out, we complain and behave as if the command was
1611 * executed eventhough we ignored the command.
1614 line
->body
.line
.sccs_command
&&
1615 (target
->stat
.time
!= file_doesnt_exist
) &&
1616 ((target
->stat
.mode
& 0222) != 0)) {
1617 fatal(gettext("%s is writable so it cannot be sccs gotten"),
1619 target
->has_complained
= remember_only
= true;
1622 * If KEEP_STATE is on, we make sure we have the timestamp for
1623 * .make.state. If .make.state changes during the command run,
1624 * we reread .make.state after the command. We also setup the
1625 * environment variable that asks utilities to report dependencies.
1630 (void) exists(make_state
);
1631 if((strlen(temp_file_directory
) == 1) &&
1632 (temp_file_directory
[0] == '/')) {
1633 tmp_file_path
[0] = '\0';
1635 strcpy(tmp_file_path
, temp_file_directory
);
1638 "%s/.make.dependency.%08x.%d.%d",
1643 MBSTOWCS(wcs_buffer
, mbs_buffer
);
1645 temp_file_name
= getname_fn(wcs_buffer
, FIND_LENGTH
, false, &fnd
);
1646 temp_file_name
->stat
.is_file
= true;
1647 int len
= 2*MAXPATHLEN
+ strlen(target
->string_mb
) + 2;
1648 wchar_t *to
= string
= ALLOC_WC(len
);
1649 for (wchar_t *from
= wcs_buffer
; *from
!= (int) nul_char
; ) {
1650 if (*from
== (int) space_char
) {
1651 *to
++ = (int) backslash_char
;
1655 *to
++ = (int) space_char
;
1656 MBSTOWCS(to
, target
->string_mb
);
1657 Name sprodep_name
= getname_fn(string
, FIND_LENGTH
, false, &fnd
);
1658 (void) SETVAR(sunpro_dependencies
,
1663 temp_file_name
= NULL
;
1667 * In case we are interrupted, we need to know what was going on.
1669 current_target
= target
;
1671 * We also need to be able to save an empty command instead of the
1672 * interrupted one in .make.state.
1674 current_line
= line
;
1675 if (remember_only
) {
1676 /* Empty block!!! */
1678 result
= touch_command(line
, target
, result
);
1680 result
= execute_parallel(line
, true);
1684 * If this is not a touch run, we need to execute the
1685 * proper command(s) for the target.
1688 if (!parallel_ok(target
, true)) {
1690 * We are building in parallel, but
1691 * this target must be built in serial.
1694 * If nothing else is building,
1695 * do this one, else wait.
1697 if (parallel_process_cnt
== 0) {
1698 result
= execute_parallel(line
, true, target
->localhost
);
1700 current_target
= NULL
;
1701 current_line
= NULL
;
1703 line->body.line.command_used = NULL;
1705 line
->body
.line
.dont_rebuild_command_used
= true;
1706 return build_serial
;
1709 result
= execute_parallel(line
, false);
1712 return build_running
;
1714 if (parallel_process_cnt
== 0) {
1715 result
= execute_parallel(line
, true, target
->localhost
);
1717 current_target
= NULL
;
1718 current_line
= NULL
;
1719 target
->parallel
= false;
1720 line
->body
.line
.command_used
=
1722 return build_serial
;
1727 result
= execute_parallel(line
, true, target
->localhost
);
1730 temp_file_name
= NULL
;
1731 if (report_dependencies_level
== 0){
1732 update_target(line
, result
);
1734 current_target
= NULL
;
1735 current_line
= NULL
;
1740 * execute_serial(line)
1742 * Runs thru the command line for the target and
1743 * executes the rules one by one.
1746 * The result of the command build
1749 * line The command to execute
1751 * Static variables used:
1753 * Global variables used:
1754 * continue_after_error -k flag
1755 * do_not_exec_rule -n flag
1756 * report_dependencies -P flag
1757 * silent Don't echo commands before executing
1758 * temp_file_name Temp file for auto dependencies
1759 * vpath_defined If true, translate path for command
1762 execute_serial(Property line
)
1765 Boolean printed_serial
;
1766 Doname result
= build_ok
;
1767 Cmd_line rule
, cmd_tail
, command
= NULL
;
1768 char mbstring
[MAXPATHLEN
];
1770 Name target
= line
->body
.line
.target
;
1772 target
->has_recursive_dependency
= false;
1773 // We have to create a copy of the rules chain for processing because
1774 // the original one can be destroyed during .make.state file rereading.
1775 for (rule
= line
->body
.line
.command_used
;
1777 rule
= rule
->next
) {
1778 if (command
== NULL
) {
1779 command
= cmd_tail
= ALLOC(Cmd_line
);
1781 cmd_tail
->next
= ALLOC(Cmd_line
);
1782 cmd_tail
= cmd_tail
->next
;
1787 cmd_tail
->next
= NULL
;
1789 for (rule
= command
; rule
!= NULL
; rule
= rule
->next
) {
1790 if (posix
&& (touch
|| quest
) && !rule
->always_exec
) {
1793 if (vpath_defined
) {
1794 rule
->command_line
=
1795 vpath_translation(rule
->command_line
);
1797 /* Echo command line, maybe. */
1798 if ((rule
->command_line
->hash
.length
> 0) &&
1800 (!rule
->silent
|| do_not_exec_rule
) &&
1801 (report_dependencies_level
== 0)) {
1802 (void) printf("%s\n", rule
->command_line
->string_mb
);
1804 if (rule
->command_line
->hash
.length
> 0) {
1805 /* Do assignment if command line prefixed with "=" */
1808 do_assign(rule
->command_line
, target
);
1809 } else if (report_dependencies_level
== 0) {
1810 /* Execute command line. */
1812 result
= dosys(rule
->command_line
,
1813 (Boolean
) rule
->ignore_error
,
1814 (Boolean
) rule
->make_refd
,
1815 /* ds 98.04.23 bug #4085164. make should always show error messages */
1817 /* BOOLEAN(rule->silent &&
1818 rule->ignore_error), */
1819 (Boolean
) rule
->always_exec
,
1821 check_state(temp_file_name
);
1826 if (result
== build_failed
) {
1827 if (silent
|| rule
->silent
) {
1828 (void) printf(gettext("The following command caused the error:\n%s\n"),
1829 rule
->command_line
->string_mb
);
1831 if (!rule
->ignore_error
&& !ignore_errors
) {
1832 if (!continue_after_error
) {
1833 fatal(gettext("Command failed for target `%s'"),
1837 * Make sure a failing command is not
1838 * saved in .make.state.
1840 line
->body
.line
.command_used
= NULL
;
1847 for (rule
= command
; rule
!= NULL
; rule
= cmd_tail
) {
1848 cmd_tail
= rule
->next
;
1852 if (temp_file_name
!= NULL
) {
1853 free_name(temp_file_name
);
1855 temp_file_name
= NULL
;
1857 Property spro
= get_prop(sunpro_dependencies
->prop
, macro_prop
);
1859 Name val
= spro
->body
.macro
.value
;
1862 spro
->body
.macro
.value
= NULL
;
1865 spro
= get_prop(sunpro_dependencies
->prop
, env_mem_prop
);
1867 char *val
= spro
->body
.env_mem
.value
;
1870 * Do not return memory allocated for SUNPRO_DEPENDENCIES
1871 * It will be returned in setvar_daemon() in macro.cc
1874 spro
->body
.env_mem
.value
= NULL
;
1884 * vpath_translation(cmd)
1886 * Translates one command line by
1887 * checking each word. If the word has an alias it is translated.
1890 * The translated command
1893 * cmd Command to translate
1895 * Global variables used:
1898 vpath_translation(register Name cmd
)
1900 wchar_t buffer
[STRING_BUFFER_LENGTH
];
1905 if (!vpath_defined
|| (cmd
== NULL
) || (cmd
->hash
.length
== 0)) {
1908 INIT_STRING_FROM_STACK(new_cmd
, buffer
);
1911 p
= wcb
.get_string();
1913 while (*p
!= (int) nul_char
) {
1914 while (iswspace(*p
) && (*p
!= (int) nul_char
)) {
1915 append_char(*p
++, &new_cmd
);
1918 while (!iswspace(*p
) && (*p
!= (int) nul_char
)) {
1921 cmd
= GETNAME(start
, p
- start
);
1922 if (cmd
->has_vpath_alias_prop
) {
1923 cmd
= get_prop(cmd
->prop
, vpath_alias_prop
)->
1924 body
.vpath_alias
.alias
;
1927 (int) cmd
->hash
.length
);
1929 append_string(start
, &new_cmd
, p
- start
);
1932 cmd
= GETNAME(new_cmd
.buffer
.start
, FIND_LENGTH
);
1933 if (new_cmd
.free_after_use
) {
1934 retmem(new_cmd
.buffer
.start
);
1940 * check_state(temp_file_name)
1942 * Reads and checks the state changed by the previously executed command.
1945 * temp_file_name The auto dependency temp file
1947 * Global variables used:
1950 check_state(Name temp_file_name
)
1957 * Then read the temp file that now might
1958 * contain dependency reports from utilities
1960 read_dependency_file(temp_file_name
);
1963 * And reread .make.state if it
1964 * changed (the command ran recursive makes)
1966 check_read_state_file();
1967 if (temp_file_name
!= NULL
) {
1968 (void) unlink(temp_file_name
->string_mb
);
1973 * read_dependency_file(filename)
1975 * Read the temp file used for reporting dependencies to make
1978 * filename The name of the file with the state info
1980 * Global variables used:
1981 * makefile_type The type of makefile being read
1982 * read_trace_level Debug flag
1983 * temp_file_number The always increasing number for unique files
1984 * trace_reader Debug flag
1987 read_dependency_file(register Name filename
)
1989 register Makefile_type save_makefile_type
;
1991 if (filename
== NULL
) {
1994 filename
->stat
.time
= file_no_time
;
1995 if (exists(filename
) > file_doesnt_exist
) {
1996 save_makefile_type
= makefile_type
;
1997 makefile_type
= reading_cpp_file
;
1998 if (read_trace_level
> 1) {
1999 trace_reader
= true;
2002 (void) read_simple_file(filename
,
2009 trace_reader
= false;
2010 makefile_type
= save_makefile_type
;
2015 * check_read_state_file()
2017 * Check if .make.state has changed
2018 * If it has we reread it
2022 * Global variables used:
2023 * make_state Make state file name
2024 * makefile_type Type of makefile being read
2025 * read_trace_level Debug flag
2026 * trace_reader Debug flag
2029 check_read_state_file(void)
2031 timestruc_t previous
= make_state
->stat
.time
;
2032 register Makefile_type save_makefile_type
;
2033 register Property makefile
;
2035 make_state
->stat
.time
= file_no_time
;
2036 if ((exists(make_state
) == file_doesnt_exist
) ||
2037 (make_state
->stat
.time
== previous
)) {
2040 save_makefile_type
= makefile_type
;
2041 makefile_type
= rereading_statefile
;
2042 /* Make sure we clear the old cached contents of .make.state */
2043 makefile
= maybe_append_prop(make_state
, makefile_prop
);
2044 if (makefile
->body
.makefile
.contents
!= NULL
) {
2045 retmem(makefile
->body
.makefile
.contents
);
2046 makefile
->body
.makefile
.contents
= NULL
;
2048 if (read_trace_level
> 1) {
2049 trace_reader
= true;
2052 (void) read_simple_file(make_state
,
2059 trace_reader
= false;
2060 makefile_type
= save_makefile_type
;
2064 * do_assign(line, target)
2066 * Handles runtime assignments for command lines prefixed with "=".
2069 * line The command that contains an assignment
2070 * target The Name of the target, used for error reports
2072 * Global variables used:
2073 * assign_done Set to indicate doname needs to reprocess
2076 do_assign(register Name line
, register Name target
)
2079 register wchar_t *string
= wcb
.get_string();
2080 register wchar_t *equal
;
2082 register Boolean append
= false;
2085 * If any runtime assignments are done, doname() must reprocess all
2086 * targets in the future since the macro values used to build the
2087 * command lines for the targets might have changed.
2090 /* Skip white space. */
2091 while (iswspace(*string
)) {
2095 /* Find "+=" or "=". */
2096 while (!iswspace(*equal
) &&
2097 (*equal
!= (int) plus_char
) &&
2098 (*equal
!= (int) equal_char
)) {
2101 /* Internalize macro name. */
2102 name
= GETNAME(string
, equal
- string
);
2103 /* Skip over "+=" "=". */
2104 while (!((*equal
== (int) nul_char
) ||
2105 (*equal
== (int) equal_char
) ||
2106 (*equal
== (int) plus_char
))) {
2111 fatal(gettext("= expected in rule `%s' for target `%s'"),
2120 /* Skip over whitespace in front of value. */
2121 while (iswspace(*equal
)) {
2124 /* Enter new macro value. */
2126 GETNAME(equal
, wcb
.get_string() + line
->hash
.length
- equal
),
2131 * build_command_strings(target, line)
2133 * Builds the command string to used when
2134 * building a target. If the string is different from the previous one
2135 * is_out_of_date is set.
2138 * target Target to build commands for
2139 * line Where to stuff result
2141 * Global variables used:
2142 * c_at The Name "@", used to set macro value
2143 * command_changed Set if command is different from old
2144 * debug_level Should we trace activities?
2145 * do_not_exec_rule Always echo when running -n
2146 * empty_name The Name "", used for empty rule
2147 * funny Semantics of characters
2148 * ignore_errors Used to init field for line
2149 * is_conditional Set to false befor evaling macro, checked
2150 * after expanding macros
2151 * keep_state Indicates that .KEEP_STATE is on
2152 * make_word_mentioned Set by macro eval, inits field for cmd
2153 * query The Name "?", used to set macro value
2154 * query_mentioned Set by macro eval, inits field for cmd
2155 * recursion_level Used for tracing
2156 * silent Used to init field for line
2159 build_command_strings(Name target
, register Property line
)
2161 String_rec command_line
;
2162 register Cmd_line command_template
= line
->body
.line
.command_template
;
2163 register Cmd_line
*insert
= &line
->body
.line
.command_used
;
2164 register Cmd_line used
= *insert
;
2165 wchar_t buffer
[STRING_BUFFER_LENGTH
];
2167 Name new_command_line
;
2168 register Boolean new_command_longer
= false;
2169 register Boolean ignore_all_command_dependency
= true;
2171 static Name less_name
;
2172 static Name percent_name
;
2176 if (less_name
== NULL
) {
2177 MBSTOWCS(wcs_buffer
, "<");
2178 less_name
= GETNAME(wcs_buffer
, FIND_LENGTH
);
2179 MBSTOWCS(wcs_buffer
, "%");
2180 percent_name
= GETNAME(wcs_buffer
, FIND_LENGTH
);
2181 MBSTOWCS(wcs_buffer
, "*");
2182 star
= GETNAME(wcs_buffer
, FIND_LENGTH
);
2185 /* We have to check if a target depends on conditional macros */
2186 /* Targets that do must be reprocessed by doname() each time around */
2187 /* since the macro values used when building the target might have */
2189 conditional_macro_used
= false;
2190 /* If we are building a lib.a(member) target $@ should be bound */
2192 if (target
->is_member
&&
2193 ((member
= get_prop(target
->prop
, member_prop
)) != NULL
)) {
2194 target
= member
->body
.member
.library
;
2196 /* If we are building a "::" help target $@ should be bound to */
2197 /* the real target name */
2198 /* A lib.a(member) target is never :: */
2199 if (target
->has_target_prop
) {
2200 target
= get_prop(target
->prop
, target_prop
)->
2203 /* Bind the magic macros that make supplies */
2205 if(tmp_name
!= NULL
) {
2206 if (tmp_name
->has_vpath_alias_prop
) {
2207 tmp_name
= get_prop(tmp_name
->prop
, vpath_alias_prop
)->
2208 body
.vpath_alias
.alias
;
2211 (void) SETVAR(c_at
, tmp_name
, false);
2213 tmp_name
= line
->body
.line
.star
;
2214 if(tmp_name
!= NULL
) {
2215 if (tmp_name
->has_vpath_alias_prop
) {
2216 tmp_name
= get_prop(tmp_name
->prop
, vpath_alias_prop
)->
2217 body
.vpath_alias
.alias
;
2220 (void) SETVAR(star
, tmp_name
, false);
2222 tmp_name
= line
->body
.line
.less
;
2223 if(tmp_name
!= NULL
) {
2224 if (tmp_name
->has_vpath_alias_prop
) {
2225 tmp_name
= get_prop(tmp_name
->prop
, vpath_alias_prop
)->
2226 body
.vpath_alias
.alias
;
2229 (void) SETVAR(less_name
, tmp_name
, false);
2231 tmp_name
= line
->body
.line
.percent
;
2232 if(tmp_name
!= NULL
) {
2233 if (tmp_name
->has_vpath_alias_prop
) {
2234 tmp_name
= get_prop(tmp_name
->prop
, vpath_alias_prop
)->
2235 body
.vpath_alias
.alias
;
2238 (void) SETVAR(percent_name
, tmp_name
, false);
2240 /* $? is seldom used and it is expensive to build */
2241 /* so we store the list form and build the string on demand */
2242 Chain query_list
= NULL
;
2243 Chain
*query_list_tail
= &query_list
;
2245 for (Chain ch
= line
->body
.line
.query
; ch
!= NULL
; ch
= ch
->next
) {
2246 *query_list_tail
= ALLOC(Chain
);
2247 (*query_list_tail
)->name
= ch
->name
;
2248 if ((*query_list_tail
)->name
->has_vpath_alias_prop
) {
2249 (*query_list_tail
)->name
=
2250 get_prop((*query_list_tail
)->name
->prop
,
2251 vpath_alias_prop
)->body
.vpath_alias
.alias
;
2253 (*query_list_tail
)->next
= NULL
;
2254 query_list_tail
= &(*query_list_tail
)->next
;
2256 (void) setvar_daemon(query
,
2264 Chain hat_list
= NULL
;
2265 Chain
*hat_list_tail
= &hat_list
;
2267 for (Dependency dependency
= line
->body
.line
.dependencies
;
2269 dependency
= dependency
->next
) {
2270 /* skip automatic dependencies */
2271 if (!dependency
->automatic
) {
2272 if ((dependency
->name
!= force
) &&
2273 (dependency
->stale
== false)) {
2274 *hat_list_tail
= ALLOC(Chain
);
2276 if (dependency
->name
->is_member
&&
2277 (get_prop(dependency
->name
->prop
, member_prop
) != NULL
)) {
2278 (*hat_list_tail
)->name
=
2279 get_prop(dependency
->name
->prop
,
2280 member_prop
)->body
.member
.member
;
2282 (*hat_list_tail
)->name
= dependency
->name
;
2285 if((*hat_list_tail
)->name
!= NULL
) {
2286 if ((*hat_list_tail
)->name
->has_vpath_alias_prop
) {
2287 (*hat_list_tail
)->name
=
2288 get_prop((*hat_list_tail
)->name
->prop
,
2289 vpath_alias_prop
)->body
.vpath_alias
.alias
;
2293 (*hat_list_tail
)->next
= NULL
;
2294 hat_list_tail
= &(*hat_list_tail
)->next
;
2298 (void) setvar_daemon(hat
,
2305 /* We have two command sequences we need to handle */
2306 /* The old one that we probably read from .make.state */
2307 /* and the new one we are building that will replace the old one */
2308 /* Even when KEEP_STATE is not on we build a new command sequence and store */
2309 /* it in the line prop. This command sequence is then executed by */
2310 /* run_command(). If KEEP_STATE is on it is also later written to */
2311 /* .make.state. The routine replaces the old command line by line with the */
2312 /* new one trying to reuse Cmd_lines */
2314 /* If there is no old command_used we have to start creating */
2315 /* Cmd_lines to keep the new cmd in */
2317 new_command_longer
= true;
2318 *insert
= used
= ALLOC(Cmd_line
);
2320 used
->command_line
= NULL
;
2321 insert
= &used
->next
;
2323 /* Run thru the template for the new command and build the expanded */
2324 /* new command lines */
2326 command_template
!= NULL
;
2327 command_template
= command_template
->next
, insert
= &used
->next
, used
= *insert
) {
2328 /* If there is no old command_used Cmd_line we need to */
2329 /* create one and say that cmd consistency failed */
2331 new_command_longer
= true;
2332 *insert
= used
= ALLOC(Cmd_line
);
2334 used
->command_line
= empty_name
;
2336 /* Prepare the Cmd_line for the processing */
2337 /* The command line prefixes "@-=?" are stripped and that */
2338 /* information is saved in the Cmd_line */
2339 used
->assign
= false;
2340 used
->ignore_error
= ignore_errors
;
2341 used
->silent
= silent
;
2342 used
->always_exec
= false;
2343 /* Expand the macros in the command line */
2344 INIT_STRING_FROM_STACK(command_line
, buffer
);
2345 make_word_mentioned
=
2348 expand_value(command_template
->command_line
, &command_line
, true);
2349 /* If the macro $(MAKE) is mentioned in the command */
2350 /* "make -n" runs actually execute the command */
2351 used
->make_refd
= make_word_mentioned
;
2352 used
->ignore_command_dependency
= query_mentioned
;
2353 /* Strip the prefixes */
2354 start
= command_line
.buffer
.start
;
2357 (get_char_semantics_value(*start
) & (int) command_prefix_sem
);
2361 used
->ignore_command_dependency
= true;
2364 used
->ignore_command_dependency
= false;
2367 used
->assign
= true;
2370 used
->ignore_error
= true;
2373 if (!do_not_exec_rule
) {
2374 used
->silent
= true;
2379 used
->always_exec
= true;
2384 /* If all command lines of the template are prefixed with "?"*/
2385 /* the VIRTUAL_ROOT is not used for cmd consistency checks */
2386 if (!used
->ignore_command_dependency
) {
2387 ignore_all_command_dependency
= false;
2389 /* Internalize the expanded and stripped command line */
2390 new_command_line
= GETNAME(start
, FIND_LENGTH
);
2391 if ((used
->command_line
== NULL
) &&
2392 (line
->body
.line
.sccs_command
)) {
2393 used
->command_line
= new_command_line
;
2394 new_command_longer
= false;
2396 /* Compare it with the old one for command consistency */
2397 if (used
->command_line
!= new_command_line
) {
2398 Name vpath_translated
= vpath_translation(new_command_line
);
2400 !used
->ignore_command_dependency
&& (vpath_translated
!= used
->command_line
)) {
2401 if (debug_level
> 0) {
2402 if (used
->command_line
!= NULL
2403 && *used
->command_line
->string_mb
!=
2405 (void) printf(gettext("%*sBuilding %s because new command \n\t%s\n%*sdifferent from old\n\t%s\n"),
2409 vpath_translated
->string_mb
,
2416 (void) printf(gettext("%*sBuilding %s because new command \n\t%s\n%*sdifferent from empty old command\n"),
2420 vpath_translated
->string_mb
,
2425 command_changed
= true;
2426 line
->body
.line
.is_out_of_date
= true;
2428 used
->command_line
= new_command_line
;
2430 if (command_line
.free_after_use
) {
2431 retmem(command_line
.buffer
.start
);
2434 /* Check if the old command is longer than the new for */
2435 /* command consistency */
2439 !ignore_all_command_dependency
) {
2440 if (debug_level
> 0) {
2441 (void) printf(gettext("%*sBuilding %s because new command shorter than old\n"),
2446 command_changed
= true;
2447 line
->body
.line
.is_out_of_date
= true;
2450 /* Check if the new command is longer than the old command for */
2451 /* command consistency */
2452 if (new_command_longer
&&
2453 !ignore_all_command_dependency
&&
2455 if (debug_level
> 0) {
2456 (void) printf(gettext("%*sBuilding %s because new command longer than old\n"),
2461 command_changed
= true;
2462 line
->body
.line
.is_out_of_date
= true;
2464 /* Unbind the magic macros */
2465 (void) SETVAR(c_at
, (Name
) NULL
, false);
2466 (void) SETVAR(star
, (Name
) NULL
, false);
2467 (void) SETVAR(less_name
, (Name
) NULL
, false);
2468 (void) SETVAR(percent_name
, (Name
) NULL
, false);
2469 (void) SETVAR(query
, (Name
) NULL
, false);
2470 if (query_list
!= NULL
) {
2471 delete_query_chain(query_list
);
2473 (void) SETVAR(hat
, (Name
) NULL
, false);
2474 if (hat_list
!= NULL
) {
2475 delete_query_chain(hat_list
);
2478 if (conditional_macro_used
) {
2479 target
->conditional_macro_list
= cond_macro_list
;
2480 cond_macro_list
= NULL
;
2481 target
->depends_on_conditional
= true;
2486 * touch_command(line, target, result)
2488 * If this is an "make -t" run we do this.
2489 * We touch all targets in the target group ("foo + fie:") if any.
2492 * Indicates if the command failed or not
2495 * line The command line to update
2496 * target The target we are touching
2497 * result Initial value for the result we return
2499 * Global variables used:
2500 * do_not_exec_rule Indicates that -n is on
2501 * silent Do not echo commands
2504 touch_command(register Property line
, register Name target
, Doname result
)
2507 register Chain target_group
;
2508 String_rec touch_string
;
2509 wchar_t buffer
[MAXPATHLEN
];
2513 for (name
= target
, target_group
= NULL
; name
!= NULL
;) {
2514 if (!name
->is_member
) {
2516 * Build a touch command that can be passed
2517 * to dosys(). If KEEP_STATE is on, "make -t"
2518 * will save the proper command, not the
2519 * "touch" in .make.state.
2521 INIT_STRING_FROM_STACK(touch_string
, buffer
);
2522 MBSTOWCS(wcs_buffer
, "touch ");
2523 append_string(wcs_buffer
, &touch_string
, FIND_LENGTH
);
2525 if (name
->has_vpath_alias_prop
) {
2526 touch_cmd
= get_prop(name
->prop
,
2528 body
.vpath_alias
.alias
;
2530 APPEND_NAME(touch_cmd
,
2533 touch_cmd
= GETNAME(touch_string
.buffer
.start
,
2535 if (touch_string
.free_after_use
) {
2536 retmem(touch_string
.buffer
.start
);
2540 (target_group
== NULL
)) {
2541 (void) printf("%s\n", touch_cmd
->string_mb
);
2543 /* Run the touch command, or simulate it */
2544 if (!do_not_exec_rule
) {
2545 result
= dosys(touch_cmd
,
2557 if (target_group
== NULL
) {
2558 target_group
= line
->body
.line
.target_group
;
2560 target_group
= target_group
->next
;
2562 if (target_group
!= NULL
) {
2563 name
= target_group
->name
;
2572 * update_target(line, result)
2574 * updates the status of a target after executing its commands.
2577 * line The command line block to update
2578 * result Indicates that build is OK so can update
2580 * Global variables used:
2581 * do_not_exec_rule Indicates that -n is on
2582 * touch Fake the new timestamp if we are just touching
2585 update_target(Property line
, Doname result
)
2590 timestruc_t old_stat_time
;
2594 * [tolik] Additional fix for bug 1063790. It was fixed
2595 * for serial make long ago, but DMake dumps core when
2596 * target is a symlink and sccs file is newer then target.
2597 * In this case, finish_children() calls update_target()
2601 /* XXX. Should we do anything here? */
2605 target
= line
->body
.line
.target
;
2607 if ((result
== build_ok
) && (line
->body
.line
.command_used
!= NULL
)) {
2608 if (do_not_exec_rule
||
2610 (target
->is_member
&&
2611 (line
->body
.line
.command_template
!= NULL
) &&
2612 (line
->body
.line
.command_template
->command_line
->string_mb
[0] == 0) &&
2613 (line
->body
.line
.command_template
->next
== NULL
))) {
2614 /* If we are simulating execution we need to fake a */
2615 /* new timestamp for the target we didnt build */
2616 target
->stat
.time
= file_max_time
;
2619 * If we really built the target we read the new
2621 * Fix for bug #1110906: if .c file is newer than
2622 * the corresponding .o file which is in an archive
2623 * file, make will compile the .c file but it won't
2624 * update the object in the .a file.
2626 old_stat_time
= target
->stat
.time
;
2627 target
->stat
.time
= file_no_time
;
2628 (void) exists(target
);
2629 if ((target
->is_member
) &&
2630 (target
->stat
.time
== old_stat_time
)) {
2631 member
= get_prop(target
->prop
, member_prop
);
2632 if (member
!= NULL
) {
2633 target
->stat
.time
= member
->body
.member
.library
->stat
.time
;
2634 target
->stat
.time
.tv_sec
++;
2638 /* If the target is part of a group we need to propagate the */
2639 /* result of the run to all members */
2640 for (target_group
= line
->body
.line
.target_group
;
2641 target_group
!= NULL
;
2642 target_group
= target_group
->next
) {
2643 target_group
->name
->stat
.time
= target
->stat
.time
;
2644 line2
= maybe_append_prop(target_group
->name
,
2646 line2
->body
.line
.command_used
=
2647 line
->body
.line
.command_used
;
2648 line2
->body
.line
.target
= target_group
->name
;
2651 target
->has_built
= true;
2655 * sccs_get(target, command)
2657 * Figures out if it possible to sccs get a file
2658 * and builds the command to do it if it is.
2661 * Indicates if sccs get failed or not
2664 * target Target to get
2665 * command Where to deposit command to use
2667 * Global variables used:
2668 * debug_level Should we trace activities?
2669 * recursion_level Used for tracing
2670 * sccs_get_rule The rule to used for sccs getting
2673 sccs_get(register Name target
, register Property
*command
)
2675 register int result
;
2676 char link
[MAXPATHLEN
];
2678 wchar_t name
[MAXPATHLEN
];
2679 register wchar_t *p
;
2680 timestruc_t sccs_time
;
2681 register Property line
;
2682 int sym_link_depth
= 0;
2684 /* For sccs, we need to chase symlinks. */
2685 while (target
->stat
.is_sym_link
) {
2686 if (sym_link_depth
++ > 90) {
2687 fatal(gettext("Can't read symbolic link `%s': Number of symbolic links encountered during path name traversal exceeds 90."),
2690 /* Read the value of the link. */
2691 result
= readlink_vroot(target
->string_mb
,
2697 fatal(gettext("Can't read symbolic link `%s': %s"),
2698 target
->string_mb
, errmsg(errno
));
2701 /* Use the value to build the proper filename. */
2702 INIT_STRING_FROM_STACK(string
, name
);
2704 Wstring
wcb(target
);
2705 if ((link
[0] != slash_char
) &&
2706 ((p
= (wchar_t *) wcsrchr(wcb
.get_string(), slash_char
)) != NULL
)) {
2707 append_string(wcb
.get_string(), &string
, p
- wcb
.get_string() + 1);
2709 append_string(link
, &string
, result
);
2710 /* Replace the old name with the translated name. */
2711 target
= normalize_name(string
.buffer
.start
, string
.text
.p
- string
.buffer
.start
);
2712 (void) exists(target
);
2713 if (string
.free_after_use
) {
2714 retmem(string
.buffer
.start
);
2719 * read_dir() also reads the ?/SCCS dir and saves information
2720 * about which files have SCSC/s. files.
2722 if (target
->stat
.has_sccs
== DONT_KNOW_SCCS
) {
2723 read_directory_of_file(target
);
2725 switch (target
->stat
.has_sccs
) {
2726 case DONT_KNOW_SCCS
:
2727 /* We dont know by now there is no SCCS/s.* */
2728 target
->stat
.has_sccs
= NO_SCCS
;
2731 * If there is no SCCS/s.* but the plain file exists,
2732 * we say things are OK.
2734 if (target
->stat
.time
> file_doesnt_exist
) {
2737 /* If we cant find the plain file, we give up. */
2738 return build_dont_know
;
2741 * Pay dirt. We now need to figure out if the plain file
2742 * is out of date relative to the SCCS/s.* file.
2744 sccs_time
= exists(get_prop(target
->prop
,
2745 sccs_prop
)->body
.sccs
.file
);
2749 if ((!target
->has_complained
&&
2750 (sccs_time
!= file_doesnt_exist
) &&
2751 (sccs_get_rule
!= NULL
))) {
2753 if (command
== NULL
) {
2757 * We provide a command line for the target. The line is a
2758 * "sccs get" command from default.mk.
2760 line
= maybe_append_prop(target
, line_prop
);
2762 if (sccs_time
> target
->stat
.time
) {
2764 * And only if the plain file is out of date do we
2765 * request execution of the command.
2767 line
->body
.line
.is_out_of_date
= true;
2768 if (debug_level
> 0) {
2769 (void) printf(gettext("%*sSccs getting %s because s. file is younger than source file\n"),
2775 line
->body
.line
.sccs_command
= true;
2776 line
->body
.line
.command_template
= sccs_get_rule
;
2777 if(!svr4
&& (!allrules_read
|| posix
)) {
2778 if((target
->prop
) &&
2779 (target
->prop
->body
.sccs
.file
) &&
2780 (target
->prop
->body
.sccs
.file
->string_mb
)) {
2781 if((strlen(target
->prop
->body
.sccs
.file
->string_mb
) ==
2782 strlen(target
->string_mb
) + 2) &&
2783 (target
->prop
->body
.sccs
.file
->string_mb
[0] == 's') &&
2784 (target
->prop
->body
.sccs
.file
->string_mb
[1] == '.')) {
2786 line
->body
.line
.command_template
= get_posix_rule
;
2790 line
->body
.line
.target
= target
;
2792 * Also make sure the rule is build with $* and $<
2795 line
->body
.line
.star
= NULL
;
2796 line
->body
.line
.less
= NULL
;
2797 line
->body
.line
.percent
= NULL
;
2800 return build_dont_know
;
2804 * read_directory_of_file(file)
2806 * Reads the directory the specified file lives in.
2809 * file The file we need to read dir for
2811 * Global variables used:
2812 * dot The Name ".", used as the default dir
2815 read_directory_of_file(register Name file
)
2818 Wstring
file_string(file
);
2819 wchar_t * wcb
= file_string
.get_string();
2820 wchar_t usr_include_buf
[MAXPATHLEN
];
2821 wchar_t usr_include_sys_buf
[MAXPATHLEN
];
2823 register Name directory
= dot
;
2824 register wchar_t *p
= (wchar_t *) wcsrchr(wcb
,
2826 register int length
= p
- wcb
;
2827 static Name usr_include
;
2828 static Name usr_include_sys
;
2830 if (usr_include
== NULL
) {
2831 MBSTOWCS(usr_include_buf
, "/usr/include");
2832 usr_include
= GETNAME(usr_include_buf
, FIND_LENGTH
);
2833 MBSTOWCS(usr_include_sys_buf
, "/usr/include/sys");
2834 usr_include_sys
= GETNAME(usr_include_sys_buf
, FIND_LENGTH
);
2838 * If the filename contains a "/" we have to extract the path
2839 * Else the path defaults to ".".
2843 * Check some popular directories first to possibly
2844 * save time. Compare string length first to gain speed.
2846 if ((usr_include
->hash
.length
== length
) &&
2847 IS_WEQUALN(usr_include_buf
,
2850 directory
= usr_include
;
2851 } else if ((usr_include_sys
->hash
.length
== length
) &&
2852 IS_WEQUALN(usr_include_sys_buf
,
2855 directory
= usr_include_sys
;
2857 directory
= GETNAME(wcb
, length
);
2860 (void) read_dir(directory
,
2867 * add_pattern_conditionals(target)
2869 * Scan the list of conditionals defined for pattern targets and add any
2870 * that match this target to its list of conditionals.
2873 * target The target we should add conditionals for
2875 * Global variables used:
2876 * conditionals The list of pattern conditionals
2879 add_pattern_conditionals(register Name target
)
2881 register Property conditional
;
2889 Wstring
wcb(target
);
2892 for (conditional
= get_prop(conditionals
->prop
, conditional_prop
);
2893 conditional
!= NULL
;
2894 conditional
= get_prop(conditional
->next
, conditional_prop
)) {
2895 wcb1
.init(conditional
->body
.conditional
.target
);
2896 pattern
= wcb1
.get_string();
2897 if (pattern
[1] != 0) {
2898 percent
= (wchar_t *) wcschr(pattern
, (int) percent_char
);
2899 /* Check for possible buffer under-read */
2900 if ((length
= wcb
.length()-wcslen(percent
+1)) <= 0) {
2903 if (!wcb
.equaln(pattern
, percent
-pattern
) ||
2904 !IS_WEQUAL(wcb
.get_string(length
), percent
+1)) {
2908 for (previous
= &target
->prop
;
2910 previous
= &(*previous
)->next
) {
2911 if (((*previous
)->type
== conditional_prop
) &&
2912 ((*previous
)->body
.conditional
.sequence
>
2913 conditional
->body
.conditional
.sequence
)) {
2917 if (*previous
== NULL
) {
2918 new_prop
= append_prop(target
, conditional_prop
);
2921 new_prop
= append_prop(&dummy
, conditional_prop
);
2922 new_prop
->next
= *previous
;
2923 *previous
= new_prop
;
2925 target
->conditional_cnt
++;
2926 new_prop
->body
.conditional
= conditional
->body
.conditional
;
2931 * set_locals(target, old_locals)
2933 * Sets any conditional macros for the target.
2934 * Each target carries a possibly empty set of conditional properties.
2937 * target The target to set conditional macros for
2938 * old_locals Space to store old values in
2940 * Global variables used:
2941 * debug_level Should we trace activity?
2942 * is_conditional We need to preserve this value
2943 * recursion_level Used for tracing
2946 set_locals(register Name target
, register Property old_locals
)
2948 register Property conditional
;
2950 register Boolean saved_conditional_macro_used
;
2954 if (target
->dont_activate_cond_values
) {
2958 saved_conditional_macro_used
= conditional_macro_used
;
2960 /* Scan the list of conditional properties and apply each one */
2961 for (conditional
= get_prop(target
->prop
, conditional_prop
), i
= 0;
2962 conditional
!= NULL
;
2963 conditional
= get_prop(conditional
->next
, conditional_prop
),
2965 /* Save the old value */
2966 old_locals
[i
].body
.macro
=
2967 maybe_append_prop(conditional
->body
.conditional
.name
,
2968 macro_prop
)->body
.macro
;
2969 if (debug_level
> 1) {
2970 (void) printf(gettext("%*sActivating conditional value: "),
2974 /* Set the conditional value. Macros are expanded when the */
2975 /* macro is refd as usual */
2976 if ((conditional
->body
.conditional
.name
!= virtual_root
) ||
2977 (conditional
->body
.conditional
.value
!= virtual_root
)) {
2978 (void) SETVAR(conditional
->body
.conditional
.name
,
2979 conditional
->body
.conditional
.value
,
2980 (Boolean
) conditional
->body
.conditional
.append
);
2982 cond_name
= ALLOC(Chain
);
2983 cond_name
->name
= conditional
->body
.conditional
.name
;
2985 /* Put this target on the front of the chain of conditional targets */
2986 cond_chain
= ALLOC(Chain
);
2987 cond_chain
->name
= target
;
2988 cond_chain
->next
= conditional_targets
;
2989 conditional_targets
= cond_chain
;
2990 conditional_macro_used
= saved_conditional_macro_used
;
2994 * reset_locals(target, old_locals, conditional, index)
2996 * Removes any conditional macros for the target.
2999 * target The target we are retoring values for
3000 * old_locals The values to restore
3001 * conditional The first conditional block for the target
3002 * index into the old_locals vector
3003 * Global variables used:
3004 * debug_level Should we trace activities?
3005 * recursion_level Used for tracing
3008 reset_locals(register Name target
, register Property old_locals
, register Property conditional
, register int index
)
3010 register Property this_conditional
;
3013 if (target
->dont_activate_cond_values
) {
3017 /* Scan the list of conditional properties and restore the old value */
3018 /* to each one Reverse the order relative to when we assigned macros */
3019 this_conditional
= get_prop(conditional
->next
, conditional_prop
);
3020 if (this_conditional
!= NULL
) {
3021 reset_locals(target
, old_locals
, this_conditional
, index
+1);
3023 /* Remove conditional target from chain */
3024 if (conditional_targets
== NULL
||
3025 conditional_targets
->name
!= target
) {
3026 warning(gettext("Internal error: reset target not at head of condtional_targets chain"));
3028 cond_chain
= conditional_targets
->next
;
3029 retmem_mb((caddr_t
) conditional_targets
);
3030 conditional_targets
= cond_chain
;
3033 get_prop(conditional
->body
.conditional
.name
->prop
,
3034 macro_prop
)->body
.macro
= old_locals
[index
].body
.macro
;
3035 if (conditional
->body
.conditional
.name
== virtual_root
) {
3036 (void) SETVAR(virtual_root
, getvar(virtual_root
), false);
3038 if (debug_level
> 1) {
3039 if (old_locals
[index
].body
.macro
.value
!= NULL
) {
3040 (void) printf(gettext("%*sdeactivating conditional value: %s= %s\n"),
3043 conditional
->body
.conditional
.name
->
3045 old_locals
[index
].body
.macro
.value
->
3048 (void) printf(gettext("%*sdeactivating conditional value: %s =\n"),
3051 conditional
->body
.conditional
.name
->
3058 * check_auto_dependencies(target, auto_count, automatics)
3060 * Returns true if the target now has a dependency
3061 * it didn't previously have (saved on automatics).
3064 * true if new dependency found
3067 * target Target we check
3068 * auto_count Number of old automatic vars
3069 * automatics Saved old automatics
3071 * Global variables used:
3072 * keep_state Indicates that .KEEP_STATE is on
3075 check_auto_dependencies(Name target
, int auto_count
, Name
*automatics
)
3080 Dependency dependency
;
3083 if ((line
= get_prop(target
->prop
, line_prop
)) == NULL
) {
3086 /* Go thru new list of automatic depes */
3087 for (dependency
= line
->body
.line
.dependencies
;
3089 dependency
= dependency
->next
) {
3090 /* And make sure that each one existed before we */
3091 /* built the target */
3092 if (dependency
->automatic
&& !dependency
->stale
) {
3093 for (n
= auto_count
, p
= automatics
;
3096 if (*p
++ == dependency
->name
) {
3097 /* If we can find it on the */
3098 /* saved list of autos we */
3103 /* But if we scan over the old list */
3104 /* of auto. without finding it it is */
3105 /* new and we must check it */
3117 // Recursively delete each of the Chain struct on the chain.
3120 delete_query_chain(Chain ch
)
3125 delete_query_chain(ch
->next
);
3126 retmem_mb((char *) ch
);
3131 target_can_be_built(register Name target
) {
3132 Doname result
= build_dont_know
;
3133 Name true_target
= target
;
3136 if (target
== wait_name
) {
3140 * If the target is a constructed one for a "::" target,
3141 * we need to consider that.
3143 if (target
->has_target_prop
) {
3144 true_target
= get_prop(target
->prop
,
3145 target_prop
)->body
.target
.target
;
3148 (void) exists(true_target
);
3150 if (true_target
->state
== build_running
) {
3151 return(build_running
);
3153 if (true_target
->stat
.time
!= file_doesnt_exist
) {
3157 /* get line property for the target */
3158 line
= get_prop(true_target
->prop
, line_prop
);
3160 /* first check for explicit rule */
3161 if (line
!= NULL
&& line
->body
.line
.command_template
!= NULL
) {
3164 /* try to find pattern rule */
3165 if (result
== build_dont_know
) {
3166 result
= find_percent_rule(target
, NULL
, false);
3169 /* try to find double suffix rule */
3170 if (result
== build_dont_know
) {
3171 if (target
->is_member
) {
3172 Property member
= get_prop(target
->prop
, member_prop
);
3173 if (member
!= NULL
&& member
->body
.member
.member
!= NULL
) {
3174 result
= find_ar_suffix_rule(target
, member
->body
.member
.member
, NULL
, false);
3176 result
= find_double_suffix_rule(target
, NULL
, false);
3179 result
= find_double_suffix_rule(target
, NULL
, false);
3183 /* try to find suffix rule */
3184 if ((result
== build_dont_know
) && second_pass
) {
3185 result
= find_suffix_rule(target
, target
, empty_name
, NULL
, false);
3188 /* check for sccs */
3189 if (result
== build_dont_know
) {
3190 result
= sccs_get(target
, NULL
);
3193 /* try to find dyn target */
3194 if (result
== build_dont_know
) {
3195 Name dtarg
= find_dyntarget(target
);
3196 if (dtarg
!= NULL
) {
3197 result
= target_can_be_built(dtarg
);
3201 /* check whether target was mentioned in makefile */
3202 if (result
== build_dont_know
) {
3203 if (target
->colons
!= no_colon
) {