#include <alloca.h>
#include <fcntl.h>
#include <mk/defs.h>
#include <mksh/i18n.h>
#include <mksh/macro.h>
#include <mksh/misc.h>
#include <poll.h>
#include <libintl.h>
#include <signal.h>
#include <stropts.h>
#include <sys/errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <unistd.h>
# define LOCALHOST "localhost"
#define MAXRULES 100
const int STAT_RETRY_SLEEP_TIME = 100000;
static char hostName[MAXNAMELEN] = "";
static char userName[MAXNAMELEN] = "";
static int second_pass = 0;
extern Doname doname_check(Name target, Boolean do_get, Boolean implicit, Boolean automatic);
extern Doname doname(Name target, Boolean do_get, Boolean implicit, Boolean automatic);
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);
void dynamic_dependencies(Name target);
static Doname run_command(Property line, Boolean print_machine);
extern Doname execute_serial(Property line);
extern Name vpath_translation(Name cmd);
extern void check_state(Name temp_file_name);
static void read_dependency_file(Name filename);
static void check_read_state_file(void);
static void do_assign(Name line, Name target);
static void build_command_strings(Name target, Property line);
static Doname touch_command(Property line, Name target, Doname result);
extern void update_target(Property line, Doname result);
static Doname sccs_get(Name target, Property *command);
extern void read_directory_of_file(Name file);
static void add_pattern_conditionals(Name target);
extern void set_locals(Name target, Property old_locals);
extern void reset_locals(Name target, Property old_locals, Property conditional, int index);
extern Boolean check_auto_dependencies(Name target, int auto_count, Name *automatics);
static void delete_query_chain(Chain ch);
extern Name normalize_name(wchar_t *name_string, int length);
Doname
doname_check(Name target, Boolean do_get, Boolean implicit, Boolean automatic)
{
int first_time = 1;
Doname rv = build_failed;
(void) fflush(stdout);
try_again:
switch (doname(target, do_get, implicit, automatic)) {
case build_ok:
second_pass = 0;
rv = build_ok;
break;
case build_running:
second_pass = 0;
rv = build_running;
break;
case build_failed:
if (!continue_after_error) {
fatal(
gettext("Target `%s' not remade because of errors"),
target->string_mb);
}
build_failed_seen = true;
second_pass = 0;
rv = build_failed;
break;
case build_dont_know:
if (automatic || (report_dependencies_level > 0)) {
second_pass = 0;
rv = build_dont_know;
break;
}
if(first_time) {
first_time = 0;
second_pass = 1;
goto try_again;
}
second_pass = 0;
if (continue_after_error && !svr4) {
warning(gettext("Don't know how to make target `%s'"),
target->string_mb);
build_failed_seen = true;
rv = build_failed;
break;
}
fatal(gettext("Don't know how to make target `%s'"),
target->string_mb);
break;
}
return (rv);
}
void
enter_explicit_rule_from_dynamic_rule(Name target, Name source)
{
Property line, source_line;
Dependency dependency;
source_line = get_prop(source->prop, line_prop);
line = maybe_append_prop(target, line_prop);
line->body.line.sccs_command = false;
line->body.line.target = target;
if (line->body.line.command_template == NULL) {
line->body.line.command_template = source_line->body.line.command_template;
for (dependency = source_line->body.line.dependencies;
dependency != NULL;
dependency = dependency->next) {
enter_dependency(line, dependency->name, false);
}
line->body.line.less = target;
}
line->body.line.percent = NULL;
}
Name
find_dyntarget(Name target)
{
Dyntarget p;
int i;
String_rec string;
wchar_t buffer[STRING_BUFFER_LENGTH];
wchar_t *pp, * bufend;
wchar_t tbuffer[MAXPATHLEN];
Wstring wcb(target);
for (p = dyntarget_list; p != NULL; p = p->next) {
INIT_STRING_FROM_STACK(string, buffer);
expand_value(p->name, &string, false);
i = 0;
pp = string.buffer.start;
bufend = pp + STRING_BUFFER_LENGTH;
while((*pp != nul_char) && (pp < bufend)) {
if(iswspace(*pp)) {
tbuffer[i] = nul_char;
if(i > 0) {
if (wcb.equal(tbuffer)) {
enter_explicit_rule_from_dynamic_rule(target, p->name);
return(target);
}
}
pp++;
i = 0;
continue;
}
tbuffer[i] = *pp;
i++;
pp++;
if(*pp == nul_char) {
tbuffer[i] = nul_char;
if(i > 0) {
if (wcb.equal(tbuffer)) {
enter_explicit_rule_from_dynamic_rule(target, p->name);
return(target);
}
}
break;
}
}
}
return(NULL);
}
Doname
doname(Name target, Boolean do_get, Boolean implicit, Boolean automatic)
{
Doname result = build_dont_know;
Chain out_of_date_list = NULL;
Chain target_group;
Property old_locals = NULL;
Property line;
Property command = NULL;
Dependency dependency;
Name less = NULL;
Name true_target = target;
Name *automatics = NULL;
int auto_count;
Boolean rechecking_target = false;
Boolean saved_commands_done;
Boolean restart = false;
Boolean save_parallel = parallel;
Boolean doing_subtree = false;
Boolean recheck_conditionals = false;
if (target->state == build_running) {
return build_running;
}
line = get_prop(target->prop, line_prop);
if (line != NULL) {
for (target_group = line->body.line.target_group;
target_group != NULL;
target_group = target_group->next) {
if (is_running(target_group->name)) {
target->state = build_running;
add_pending(target,
recursion_level,
do_get,
implicit,
false);
return build_running;
}
}
}
if (target->has_target_prop) {
true_target = get_prop(target->prop,
target_prop)->body.target.target;
if (true_target->colon_splits > 0) {
Property time;
time = get_prop(true_target->prop, time_prop);
if (time != NULL) {
true_target->stat.time = time->body.time.time;
}
}
}
(void) exists(true_target);
if (target->state == build_ok) {
if((!keep_state || (!target->depends_on_conditional && !assign_done))) {
return build_ok;
} else {
recheck_conditionals = true;
}
}
if (target->state == build_subtree) {
target->state = build_dont_know;
doing_subtree = true;
if (!target->checking_subtree) {
restart = true;
}
} else if (target->state == build_pending) {
target->state = build_dont_know;
restart = true;
}
if (line != NULL) {
line->body.line.percent = NULL;
}
recheck_target:
result = build_dont_know;
out_of_date_list = NULL;
command = NULL;
less = NULL;
auto_count = 0;
if (!restart && line != NULL) {
for (dependency = line->body.line.dependencies;
dependency != NULL;
dependency = dependency->next) {
dependency->built = false;
}
}
if (keep_state &&
(line != NULL) &&
(line->body.line.dependencies != NULL)) {
Name *p;
for (dependency = line->body.line.dependencies;
dependency != NULL;
dependency = dependency->next) {
if (dependency->automatic && !dependency->stale) {
auto_count++;
}
}
automatics =
(Name *) alloca((int) (auto_count * sizeof (Name)));
for (p = automatics, dependency = line->body.line.dependencies;
dependency != NULL;
dependency = dependency->next) {
if (dependency->automatic && !dependency->stale) {
*p++ = dependency->name;
}
}
}
if (debug_level > 1) {
(void) printf("%*sdoname(%s)\n",
recursion_level,
"",
target->string_mb);
}
recursion_level++;
if (target->state == build_in_progress) {
warning(gettext("Infinite loop: Target `%s' depends on itself"),
target->string_mb);
return build_ok;
}
target->state = build_in_progress;
if (!target->added_pattern_conditionals) {
add_pattern_conditionals(target);
target->added_pattern_conditionals = true;
}
if (target->conditional_cnt > 0) {
old_locals = (Property) alloca(target->conditional_cnt *
sizeof (Property_rec));
set_locals(target, old_locals);
}
if (!target->has_depe_list_expanded)
{
dynamic_dependencies(target);
}
if ((line = get_prop(target->prop, line_prop)) != NULL) {
if (check_dependencies(&result,
line,
do_get,
target,
true_target,
doing_subtree,
&out_of_date_list,
old_locals,
implicit,
&command,
less,
rechecking_target,
recheck_conditionals)) {
return build_running;
}
if (line->body.line.query != NULL) {
delete_query_chain(line->body.line.query);
}
line->body.line.query = out_of_date_list;
}
if (target->colon_splits == 0 && !rechecking_target) {
if ((result == build_dont_know) &&
(command == NULL)) {
switch (find_percent_rule(
target,
&command,
recheck_conditionals)) {
case build_failed:
result = build_failed;
break;
case build_running:
target->state = build_running;
add_pending(target,
--recursion_level,
do_get,
implicit,
false);
if (target->conditional_cnt > 0) {
reset_locals(target,
old_locals,
get_prop(target->prop,
conditional_prop),
0);
}
return build_running;
case build_ok:
result = build_ok;
break;
}
}
if (result == build_dont_know) {
Property member;
if (target->is_member &&
((member = get_prop(target->prop, member_prop)) !=
NULL)) {
switch (find_ar_suffix_rule(target,
member->body.
member.member,
&command,
recheck_conditionals)) {
case build_failed:
result = build_failed;
break;
case build_running:
target->state = build_running;
add_pending(target,
--recursion_level,
do_get,
implicit,
false);
if (target->conditional_cnt > 0) {
reset_locals(target,
old_locals,
get_prop(target->prop,
conditional_prop),
0);
}
return build_running;
default:
if (line == NULL) {
line =
maybe_append_prop(target,
line_prop);
}
line->body.line.percent =
member->body.member.member;
break;
}
} else {
switch (find_double_suffix_rule(target,
&command,
recheck_conditionals)) {
case build_failed:
result = build_failed;
break;
case build_running:
target->state = build_running;
add_pending(target,
--recursion_level,
do_get,
implicit,
false);
if (target->conditional_cnt > 0) {
reset_locals(target,
old_locals,
get_prop(target->
prop,
conditional_prop),
0);
}
return build_running;
}
}
}
if ((result == build_dont_know) && !automatic && (!implicit || second_pass) &&
((line == NULL) ||
((line->body.line.target != NULL) &&
!line->body.line.target->has_regular_dependency))) {
switch (find_suffix_rule(target,
target,
empty_name,
&command,
recheck_conditionals)) {
case build_failed:
result = build_failed;
break;
case build_running:
target->state = build_running;
add_pending(target,
--recursion_level,
do_get,
implicit,
false);
if (target->conditional_cnt > 0) {
reset_locals(target,
old_locals,
get_prop(target->prop,
conditional_prop),
0);
}
return build_running;
}
}
if ((command == NULL) &&
(result == build_dont_know) &&
do_get) {
result = sccs_get(target, &command);
}
if ((command == NULL) &&
(result == build_dont_know) &&
(true_target->colons == no_colon) &&
default_rule &&
!implicit) {
line = maybe_append_prop(target, line_prop);
command = line;
Boolean out_of_date;
if (true_target->is_member) {
out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
line->body.line.dependency_time);
} else {
out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
line->body.line.dependency_time);
}
if (build_unconditional || out_of_date) {
line->body.line.is_out_of_date = true;
if (debug_level > 0) {
(void) printf(gettext("%*sBuilding %s using .DEFAULT because it is out of date\n"),
recursion_level,
"",
true_target->string_mb);
}
}
line->body.line.sccs_command = false;
line->body.line.command_template = default_rule;
line->body.line.target = true_target;
line->body.line.star = NULL;
line->body.line.less = true_target;
line->body.line.percent = NULL;
}
}
if (!target->is_double_colon_parent) {
commands_done = false;
}
silent = silent_all;
ignore_errors = ignore_errors_all;
if (posix)
{
if (!silent)
{
silent = (Boolean) target->silent_mode;
}
if (!ignore_errors)
{
ignore_errors = (Boolean) target->ignore_error_mode;
}
}
int doname_dyntarget = 0;
r_command:
if ((command != NULL) &&
(command->body.line.command_template != NULL)) {
if (result != build_failed) {
result = run_command(command,
(Boolean) ((parallel || save_parallel) && !silent));
}
switch (result) {
case build_running:
add_running(target,
true_target,
command,
--recursion_level,
auto_count,
automatics,
do_get,
implicit);
target->state = build_running;
if ((line = get_prop(target->prop,
line_prop)) != NULL) {
if (line->body.line.query != NULL) {
delete_query_chain(line->body.line.query);
}
line->body.line.query = NULL;
}
if (target->conditional_cnt > 0) {
reset_locals(target,
old_locals,
get_prop(target->prop,
conditional_prop),
0);
}
return build_running;
case build_serial:
add_serial(target,
--recursion_level,
do_get,
implicit);
target->state = build_running;
line = get_prop(target->prop, line_prop);
if (line != NULL) {
if (line->body.line.query != NULL) {
delete_query_chain(line->body.line.query);
}
line->body.line.query = NULL;
}
if (target->conditional_cnt > 0) {
reset_locals(target,
old_locals,
get_prop(target->prop,
conditional_prop),
0);
}
return build_running;
case build_ok:
if (true_target->stat.time == file_doesnt_exist) {
true_target->stat.time = file_max_time;
}
break;
}
} else {
if (target->colons != no_colon) {
if (true_target->stat.time == file_doesnt_exist){
true_target->stat.time = file_max_time;
}
result = build_ok;
}
if(!doname_dyntarget) {
doname_dyntarget = 1;
Name dtarg = find_dyntarget(target);
if(dtarg!=NULL) {
if (!target->has_depe_list_expanded) {
dynamic_dependencies(target);
}
if ((line = get_prop(target->prop, line_prop)) != NULL) {
if (check_dependencies(&result,
line,
do_get,
target,
true_target,
doing_subtree,
&out_of_date_list,
old_locals,
implicit,
&command,
less,
rechecking_target,
recheck_conditionals))
{
return build_running;
}
if (line->body.line.query != NULL) {
delete_query_chain(line->body.line.query);
}
line->body.line.query = out_of_date_list;
}
goto r_command;
}
}
(void) exists(target);
if ((target->stat.time != file_doesnt_exist) &&
(result == build_dont_know)) {
result = build_ok;
}
}
if ((line = get_prop(target->prop, line_prop)) != NULL) {
if (line->body.line.query != NULL) {
delete_query_chain(line->body.line.query);
}
line->body.line.query = NULL;
}
target->state = result;
parallel = save_parallel;
if (target->conditional_cnt > 0) {
reset_locals(target,
old_locals,
get_prop(target->prop, conditional_prop),
0);
}
recursion_level--;
if (target->is_member) {
Property member;
if ((target->stat.time != file_max_time) &&
((member = get_prop(target->prop, member_prop)) != NULL) &&
(exists(member->body.member.member) > file_doesnt_exist)) {
target->stat.time =
member->body.member.member->stat.time;
}
}
if ((result == build_ok) && check_auto_dependencies(target,
auto_count,
automatics)) {
if (debug_level > 0) {
(void) printf(gettext("%*sTarget `%s' acquired new dependencies from build, rechecking all dependencies\n"),
recursion_level,
"",
true_target->string_mb);
}
rechecking_target = true;
saved_commands_done = commands_done;
goto recheck_target;
}
if (rechecking_target && !commands_done) {
commands_done = saved_commands_done;
}
return result;
}
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)
{
Boolean dependencies_running;
Dependency dependency;
Doname dep_result;
Boolean dependency_changed = false;
line->body.line.dependency_time = file_doesnt_exist;
if (line->body.line.query != NULL) {
delete_query_chain(line->body.line.query);
}
line->body.line.query = NULL;
line->body.line.is_out_of_date = false;
dependencies_running = false;
for (dependency = line->body.line.dependencies;
dependency != NULL;
dependency = dependency->next) {
Boolean this_dependency_changed = false;
if (!dependency->automatic &&
(rechecking_target || target->rechecking_target)) {
continue;
}
if (dependency->name == wait_name) {
if (dependencies_running) {
break;
}
} else if ((!parallel_ok(dependency->name, false)) &&
(dependencies_running)) {
break;
} else {
timestruc_t depe_time = file_doesnt_exist;
if (true_target->is_member) {
depe_time = exists(dependency->name);
}
if (dependency->built ||
(dependency->name->state == build_failed)) {
dep_result = (Doname) dependency->name->state;
} else {
dep_result = doname_check(dependency->name,
do_get,
false,
(Boolean) dependency->automatic);
}
if (true_target->is_member || dependency->name->is_member) {
if (depe_time.tv_sec != dependency->name->stat.time.tv_sec) {
this_dependency_changed =
dependency_changed =
true;
}
} else {
if (depe_time != dependency->name->stat.time) {
this_dependency_changed =
dependency_changed =
true;
}
}
dependency->built = true;
switch (dep_result) {
case build_running:
dependencies_running = true;
continue;
case build_failed:
*result = build_failed;
break;
case build_dont_know:
if(!recheck_conditionals) {
line->body.line.is_out_of_date = true;
}
dependency->stale = true;
rewrite_statefile =
command_changed =
true;
if (debug_level > 0) {
(void) printf(gettext("Target %s rebuilt because dependency %s does not exist\n"),
true_target->string_mb,
dependency->name->string_mb);
}
break;
}
if (dependency->name->depends_on_conditional) {
target->depends_on_conditional = true;
}
if (dependency->name == force) {
target->stat.time =
dependency->name->stat.time;
}
(void) exists(dependency->name);
line->body.line.dependency_time =
MAX(dependency->name->stat.time,
line->body.line.dependency_time);
if(true_target->is_member || dependency->name->is_member) {
line->body.line.dependency_time.tv_nsec = 0;
}
if (debug_level > 1) {
(void) printf(gettext("%*sDate(%s)=%s \n"),
recursion_level,
"",
dependency->name->string_mb,
time_to_string(dependency->name->
stat.time));
if (dependency->name->stat.time > line->body.line.dependency_time) {
(void) printf(gettext("%*sDate-dependencies(%s) set to %s\n"),
recursion_level,
"",
true_target->string_mb,
time_to_string(line->body.line.
dependency_time));
}
}
if (true_target->is_member) {
if (this_dependency_changed == true) {
true_target->stat.time = dependency->name->stat.time;
true_target->stat.time.tv_sec--;
} else {
(void) exists(true_target);
}
} else {
(void) exists(true_target);
}
Boolean out_of_date;
if (true_target->is_member || dependency->name->is_member) {
out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
dependency->name->stat.time);
} else {
out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
dependency->name->stat.time);
}
if ((build_unconditional || out_of_date) &&
(dependency->name != force) &&
(dependency->stale == false)) {
*out_of_date_tail = ALLOC(Chain);
if (dependency->name->is_member &&
(get_prop(dependency->name->prop,
member_prop) != NULL)) {
(*out_of_date_tail)->name =
get_prop(dependency->name->prop,
member_prop)->
body.member.member;
} else {
(*out_of_date_tail)->name =
dependency->name;
}
(*out_of_date_tail)->next = NULL;
out_of_date_tail = &(*out_of_date_tail)->next;
if (debug_level > 0) {
if (dependency->name->stat.time == file_max_time) {
(void) printf(gettext("%*sBuilding %s because %s does not exist\n"),
recursion_level,
"",
true_target->string_mb,
dependency->name->string_mb);
} else {
(void) printf(gettext("%*sBuilding %s because it is out of date relative to %s\n"),
recursion_level,
"",
true_target->string_mb,
dependency->name->string_mb);
}
}
}
if (dependency->name == force) {
force->stat.time =
file_max_time;
force->state = build_dont_know;
}
}
}
if (dependencies_running) {
if (doing_subtree) {
if (target->conditional_cnt > 0) {
reset_locals(target,
old_locals,
get_prop(target->prop,
conditional_prop),
0);
}
return true;
} else {
target->state = build_running;
add_pending(target,
--recursion_level,
do_get,
implicit,
false);
if (target->conditional_cnt > 0) {
reset_locals(target,
old_locals,
get_prop(target->prop,
conditional_prop),
0);
}
return true;
}
}
if (target->is_double_colon_parent) {
for (dependency = line->body.line.dependencies;
dependency != NULL;
dependency = dependency->next) {
Property tmp_line;
if ((tmp_line = get_prop(dependency->name->prop, line_prop)) != NULL) {
if(tmp_line->body.line.dependency_time != file_max_time) {
target->stat.time =
MAX(tmp_line->body.line.dependency_time,
target->stat.time);
}
}
}
}
if ((true_target->is_member) && (dependency_changed == true)) {
true_target->stat.time = file_no_time;
}
if (line->body.line.command_template != NULL) {
if (line->body.line.command_template_redefined) {
warning(gettext("Too many rules defined for target %s"),
target->string_mb);
}
*command = line;
Boolean out_of_date;
if (true_target->is_member) {
out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
line->body.line.dependency_time);
} else {
out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
line->body.line.dependency_time);
}
if (build_unconditional || out_of_date){
if(!recheck_conditionals) {
line->body.line.is_out_of_date = true;
}
}
line->body.line.sccs_command = false;
line->body.line.target = true_target;
if(gnu_style) {
if(line->body.line.dependencies != NULL) {
less = line->body.line.dependencies->name;
}
Name target_body;
Name tt = true_target;
Property member;
wchar_t *target_end;
Dependency suffix;
int suffix_length;
Wstring targ_string;
Wstring suf_string;
if (true_target->is_member &&
((member = get_prop(target->prop, member_prop)) !=
NULL)) {
tt = member->body.member.member;
}
targ_string.init(tt);
target_end = targ_string.get_string() + tt->hash.length;
for (suffix = suffixes; suffix != NULL; suffix = suffix->next) {
suffix_length = suffix->name->hash.length;
suf_string.init(suffix->name);
if (tt->hash.length < suffix_length) {
continue;
} else if (!IS_WEQUALN(suf_string.get_string(),
(target_end - suffix_length),
suffix_length)) {
continue;
}
target_body = GETNAME(
targ_string.get_string(),
(int)(tt->hash.length - suffix_length)
);
line->body.line.star = target_body;
}
if(*result == build_dont_know) {
*result = build_ok;
}
}
if (less != NULL) {
line->body.line.less = less;
}
}
return false;
}
void
dynamic_dependencies(Name target)
{
wchar_t pattern[MAXPATHLEN];
wchar_t *p;
Property line;
Dependency dependency;
Dependency *remove;
String_rec string;
wchar_t buffer[MAXPATHLEN];
Boolean set_at = false;
wchar_t *start;
Dependency new_depe;
Boolean reuse_cell;
Dependency first_member;
Name directory;
Name lib;
Name member;
Property prop;
Name true_target = target;
wchar_t *library;
if ((line = get_prop(target->prop, line_prop)) == NULL) {
return;
}
if (target->has_target_prop) {
true_target = get_prop(target->prop,
target_prop)->body.target.target;
}
for (dependency = line->body.line.dependencies;
dependency != NULL;
dependency = dependency->next) {
if (!dependency->name->dollar) {
continue;
}
target->has_depe_list_expanded = true;
if (!set_at) {
(void) SETVAR(c_at, true_target, false);
set_at = true;
}
INIT_STRING_FROM_STACK(string, buffer);
expand_value(dependency->name, &string, false);
start = string.buffer.start;
while (iswspace(*start)) {
start++;
}
if (start[0] == (int) nul_char) {
dependency->name = NULL;
}
if ((start[0] == (int) period_char) &&
(start[1] == (int) slash_char)) {
start += 2;
}
first_member = NULL;
reuse_cell = true;
for (p = start; *p != (int) nul_char; p++) {
if ((*p == (int) parenleft_char)) {
lib = GETNAME(start, p - start);
lib->is_member = true;
first_member = dependency;
start = p + 1;
while (iswspace(*start)) {
start++;
}
break;
}
}
do {
for (p = start; *p != (int) nul_char; p++) {
if ((*p == (int) nul_char) ||
iswspace(*p) ||
(*p == (int) parenright_char)) {
break;
}
}
if (p != start) {
if (!reuse_cell) {
new_depe = ALLOC(Dependency);
new_depe->next = dependency->next;
new_depe->automatic = false;
new_depe->stale = false;
new_depe->built = false;
dependency->next = new_depe;
dependency = new_depe;
}
reuse_cell = false;
dependency->name = normalize_name(start, p - start);
if ((debug_level > 0) &&
(first_member == NULL)) {
(void) printf(gettext("%*sDynamic dependency `%s' for target `%s'\n"),
recursion_level,
"",
dependency->name->string_mb,
true_target->string_mb);
}
for (start = p; iswspace(*start); start++);
p = start;
}
} while ((*p != (int) nul_char) &&
(*p != (int) parenright_char));
if (first_member != NULL) {
for (; 1; first_member = first_member->next) {
INIT_STRING_FROM_STACK(string, buffer);
APPEND_NAME(lib,
&string,
(int) lib->hash.length);
append_char((int) parenleft_char, &string);
APPEND_NAME(first_member->name,
&string,
FIND_LENGTH);
append_char((int) parenright_char, &string);
member = first_member->name;
first_member->name =
GETNAME(string.buffer.start, FIND_LENGTH);
if (string.free_after_use) {
retmem(string.buffer.start);
}
if (debug_level > 0) {
(void) printf(gettext("%*sDynamic dependency `%s' for target `%s'\n"),
recursion_level,
"",
first_member->name->
string_mb,
true_target->string_mb);
}
first_member->name->is_member = lib->is_member;
prop = maybe_append_prop(first_member->name,
member_prop);
prop->body.member.library = lib;
prop->body.member.entry = NULL;
prop->body.member.member = member;
if (first_member == dependency) {
break;
}
}
}
}
Wstring wcb;
for (remove = &line->body.line.dependencies, dependency = *remove;
dependency != NULL;
dependency = *remove) {
if (dependency->name == NULL) {
dependency = *remove = (*remove)->next;
continue;
}
if (dependency->name->wildcard) {
wcb.init(dependency->name);
if ((start = (wchar_t *) wcschr(wcb.get_string(),
(int) parenleft_char)) != NULL) {
library = buffer;
(void) wcsncpy(buffer,
wcb.get_string(),
start - wcb.get_string());
buffer[start-wcb.get_string()] =
(int) nul_char;
(void) wcsncpy(pattern,
start + 1,
(int) (dependency->name->hash.length-(start-wcb.get_string())-2));
pattern[dependency->name->hash.length -
(start-wcb.get_string()) - 2] =
(int) nul_char;
} else {
library = NULL;
(void) wcsncpy(pattern,
wcb.get_string(),
(int) dependency->name->hash.length);
pattern[dependency->name->hash.length] =
(int) nul_char;
}
start = (wchar_t *) wcsrchr(pattern, (int) slash_char);
if (start == NULL) {
directory = dot;
p = pattern;
} else {
directory = GETNAME(pattern, start-pattern);
p = start+1;
}
if (read_dir(directory, p, line, library)) {
*remove = (*remove)->next;
} else {
remove = &dependency->next;
}
} else {
remove = &dependency->next;
}
}
(void) SETVAR(c_at, (Name) NULL, false);
}
static Doname
run_command(Property line, Boolean)
{
Doname result = build_ok;
Boolean remember_only = false;
Name target = line->body.line.target;
wchar_t *string;
char tmp_file_path[MAXPATHLEN];
if (!line->body.line.is_out_of_date && target->rechecking_target) {
target->rechecking_target = false;
return build_ok;
}
if (line->body.line.is_out_of_date || keep_state) {
if (!line->body.line.dont_rebuild_command_used) {
build_command_strings(target, line);
}
}
if (!line->body.line.is_out_of_date) {
return build_ok;
}
if (quest) {
if (posix) {
result = execute_parallel(line, true);
}
exit_status = 1;
exit(1);
}
rewrite_statefile = commands_done = true;
if (!touch &&
line->body.line.sccs_command &&
(target->stat.time != file_doesnt_exist) &&
((target->stat.mode & 0222) != 0)) {
fatal(gettext("%s is writable so it cannot be sccs gotten"),
target->string_mb);
target->has_complained = remember_only = true;
}
if (!touch &&
keep_state &&
!remember_only) {
(void) exists(make_state);
if((strlen(temp_file_directory) == 1) &&
(temp_file_directory[0] == '/')) {
tmp_file_path[0] = '\0';
} else {
strcpy(tmp_file_path, temp_file_directory);
}
sprintf(mbs_buffer,
"%s/.make.dependency.%08x.%d.%d",
tmp_file_path,
hostid,
getpid(),
file_number++);
MBSTOWCS(wcs_buffer, mbs_buffer);
Boolean fnd;
temp_file_name = getname_fn(wcs_buffer, FIND_LENGTH, false, &fnd);
temp_file_name->stat.is_file = true;
int len = 2*MAXPATHLEN + strlen(target->string_mb) + 2;
wchar_t *to = string = ALLOC_WC(len);
for (wchar_t *from = wcs_buffer; *from != (int) nul_char; ) {
if (*from == (int) space_char) {
*to++ = (int) backslash_char;
}
*to++ = *from++;
}
*to++ = (int) space_char;
MBSTOWCS(to, target->string_mb);
Name sprodep_name = getname_fn(string, FIND_LENGTH, false, &fnd);
(void) SETVAR(sunpro_dependencies,
sprodep_name,
false);
retmem(string);
} else {
temp_file_name = NULL;
}
current_target = target;
current_line = line;
if (remember_only) {
} else if (touch) {
result = touch_command(line, target, result);
if (posix) {
result = execute_parallel(line, true);
}
} else {
if (parallel) {
if (!parallel_ok(target, true)) {
if (parallel_process_cnt == 0) {
result = execute_parallel(line, true, target->localhost);
} else {
current_target = NULL;
current_line = NULL;
line->body.line.dont_rebuild_command_used = true;
return build_serial;
}
} else {
result = execute_parallel(line, false);
switch (result) {
case build_running:
return build_running;
case build_serial:
if (parallel_process_cnt == 0) {
result = execute_parallel(line, true, target->localhost);
} else {
current_target = NULL;
current_line = NULL;
target->parallel = false;
line->body.line.command_used =
NULL;
return build_serial;
}
}
}
} else {
result = execute_parallel(line, true, target->localhost);
}
}
temp_file_name = NULL;
if (report_dependencies_level == 0){
update_target(line, result);
}
current_target = NULL;
current_line = NULL;
return result;
}
Doname
execute_serial(Property line)
{
int child_pid = 0;
Boolean printed_serial;
Doname result = build_ok;
Cmd_line rule, cmd_tail, command = NULL;
char mbstring[MAXPATHLEN];
int filed;
Name target = line->body.line.target;
target->has_recursive_dependency = false;
for (rule = line->body.line.command_used;
rule != NULL;
rule = rule->next) {
if (command == NULL) {
command = cmd_tail = ALLOC(Cmd_line);
} else {
cmd_tail->next = ALLOC(Cmd_line);
cmd_tail = cmd_tail->next;
}
*cmd_tail = *rule;
}
if (command) {
cmd_tail->next = NULL;
}
for (rule = command; rule != NULL; rule = rule->next) {
if (posix && (touch || quest) && !rule->always_exec) {
continue;
}
if (vpath_defined) {
rule->command_line =
vpath_translation(rule->command_line);
}
if ((rule->command_line->hash.length > 0) &&
!silent &&
(!rule->silent || do_not_exec_rule) &&
(report_dependencies_level == 0)) {
(void) printf("%s\n", rule->command_line->string_mb);
}
if (rule->command_line->hash.length > 0) {
if (rule->assign) {
result = build_ok;
do_assign(rule->command_line, target);
} else if (report_dependencies_level == 0) {
setvar_envvar();
result = dosys(rule->command_line,
(Boolean) rule->ignore_error,
(Boolean) rule->make_refd,
false,
(Boolean) rule->always_exec,
target);
check_state(temp_file_name);
}
} else {
result = build_ok;
}
if (result == build_failed) {
if (silent || rule->silent) {
(void) printf(gettext("The following command caused the error:\n%s\n"),
rule->command_line->string_mb);
}
if (!rule->ignore_error && !ignore_errors) {
if (!continue_after_error) {
fatal(gettext("Command failed for target `%s'"),
target->string_mb);
}
line->body.line.command_used = NULL;
break;
} else {
result = build_ok;
}
}
}
for (rule = command; rule != NULL; rule = cmd_tail) {
cmd_tail = rule->next;
free(rule);
}
command = NULL;
if (temp_file_name != NULL) {
free_name(temp_file_name);
}
temp_file_name = NULL;
Property spro = get_prop(sunpro_dependencies->prop, macro_prop);
if(spro != NULL) {
Name val = spro->body.macro.value;
if(val != NULL) {
free_name(val);
spro->body.macro.value = NULL;
}
}
spro = get_prop(sunpro_dependencies->prop, env_mem_prop);
if(spro) {
char *val = spro->body.env_mem.value;
if(val != NULL) {
spro->body.env_mem.value = NULL;
}
}
return result;
}
Name
vpath_translation(Name cmd)
{
wchar_t buffer[STRING_BUFFER_LENGTH];
String_rec new_cmd;
wchar_t *p;
wchar_t *start;
if (!vpath_defined || (cmd == NULL) || (cmd->hash.length == 0)) {
return cmd;
}
INIT_STRING_FROM_STACK(new_cmd, buffer);
Wstring wcb(cmd);
p = wcb.get_string();
while (*p != (int) nul_char) {
while (iswspace(*p) && (*p != (int) nul_char)) {
append_char(*p++, &new_cmd);
}
start = p;
while (!iswspace(*p) && (*p != (int) nul_char)) {
p++;
}
cmd = GETNAME(start, p - start);
if (cmd->has_vpath_alias_prop) {
cmd = get_prop(cmd->prop, vpath_alias_prop)->
body.vpath_alias.alias;
APPEND_NAME(cmd,
&new_cmd,
(int) cmd->hash.length);
} else {
append_string(start, &new_cmd, p - start);
}
}
cmd = GETNAME(new_cmd.buffer.start, FIND_LENGTH);
if (new_cmd.free_after_use) {
retmem(new_cmd.buffer.start);
}
return cmd;
}
void
check_state(Name temp_file_name)
{
if (!keep_state) {
return;
}
read_dependency_file(temp_file_name);
check_read_state_file();
if (temp_file_name != NULL) {
(void) unlink(temp_file_name->string_mb);
}
}
static void
read_dependency_file(Name filename)
{
Makefile_type save_makefile_type;
if (filename == NULL) {
return;
}
filename->stat.time = file_no_time;
if (exists(filename) > file_doesnt_exist) {
save_makefile_type = makefile_type;
makefile_type = reading_cpp_file;
if (read_trace_level > 1) {
trace_reader = true;
}
temp_file_number++;
(void) read_simple_file(filename,
false,
false,
false,
false,
false,
false);
trace_reader = false;
makefile_type = save_makefile_type;
}
}
static void
check_read_state_file(void)
{
timestruc_t previous = make_state->stat.time;
Makefile_type save_makefile_type;
Property makefile;
make_state->stat.time = file_no_time;
if ((exists(make_state) == file_doesnt_exist) ||
(make_state->stat.time == previous)) {
return;
}
save_makefile_type = makefile_type;
makefile_type = rereading_statefile;
makefile = maybe_append_prop(make_state, makefile_prop);
if (makefile->body.makefile.contents != NULL) {
retmem(makefile->body.makefile.contents);
makefile->body.makefile.contents = NULL;
}
if (read_trace_level > 1) {
trace_reader = true;
}
temp_file_number++;
(void) read_simple_file(make_state,
false,
false,
false,
false,
false,
true);
trace_reader = false;
makefile_type = save_makefile_type;
}
static void
do_assign(Name line, Name target)
{
Wstring wcb(line);
wchar_t *string = wcb.get_string();
wchar_t *equal;
Name name;
Boolean append = false;
assign_done = true;
while (iswspace(*string)) {
string++;
}
equal = string;
while (!iswspace(*equal) &&
(*equal != (int) plus_char) &&
(*equal != (int) equal_char)) {
equal++;
}
name = GETNAME(string, equal - string);
while (!((*equal == (int) nul_char) ||
(*equal == (int) equal_char) ||
(*equal == (int) plus_char))) {
equal++;
}
switch (*equal) {
case nul_char:
fatal(gettext("= expected in rule `%s' for target `%s'"),
line->string_mb,
target->string_mb);
case plus_char:
append = true;
equal++;
break;
}
equal++;
while (iswspace(*equal)) {
equal++;
}
enter_equal(name,
GETNAME(equal, wcb.get_string() + line->hash.length - equal),
append);
}
static void
build_command_strings(Name target, Property line)
{
String_rec command_line;
Cmd_line command_template = line->body.line.command_template;
Cmd_line *insert = &line->body.line.command_used;
Cmd_line used = *insert;
wchar_t buffer[STRING_BUFFER_LENGTH];
wchar_t *start;
Name new_command_line;
Boolean new_command_longer = false;
Boolean ignore_all_command_dependency = true;
Property member;
static Name less_name;
static Name percent_name;
static Name star;
Name tmp_name;
if (less_name == NULL) {
MBSTOWCS(wcs_buffer, "<");
less_name = GETNAME(wcs_buffer, FIND_LENGTH);
MBSTOWCS(wcs_buffer, "%");
percent_name = GETNAME(wcs_buffer, FIND_LENGTH);
MBSTOWCS(wcs_buffer, "*");
star = GETNAME(wcs_buffer, FIND_LENGTH);
}
conditional_macro_used = false;
if (target->is_member &&
((member = get_prop(target->prop, member_prop)) != NULL)) {
target = member->body.member.library;
}
if (target->has_target_prop) {
target = get_prop(target->prop, target_prop)->
body.target.target;
}
tmp_name = target;
if(tmp_name != NULL) {
if (tmp_name->has_vpath_alias_prop) {
tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)->
body.vpath_alias.alias;
}
}
(void) SETVAR(c_at, tmp_name, false);
tmp_name = line->body.line.star;
if(tmp_name != NULL) {
if (tmp_name->has_vpath_alias_prop) {
tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)->
body.vpath_alias.alias;
}
}
(void) SETVAR(star, tmp_name, false);
tmp_name = line->body.line.less;
if(tmp_name != NULL) {
if (tmp_name->has_vpath_alias_prop) {
tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)->
body.vpath_alias.alias;
}
}
(void) SETVAR(less_name, tmp_name, false);
tmp_name = line->body.line.percent;
if(tmp_name != NULL) {
if (tmp_name->has_vpath_alias_prop) {
tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)->
body.vpath_alias.alias;
}
}
(void) SETVAR(percent_name, tmp_name, false);
Chain query_list = NULL;
Chain *query_list_tail = &query_list;
for (Chain ch = line->body.line.query; ch != NULL; ch = ch->next) {
*query_list_tail = ALLOC(Chain);
(*query_list_tail)->name = ch->name;
if ((*query_list_tail)->name->has_vpath_alias_prop) {
(*query_list_tail)->name =
get_prop((*query_list_tail)->name->prop,
vpath_alias_prop)->body.vpath_alias.alias;
}
(*query_list_tail)->next = NULL;
query_list_tail = &(*query_list_tail)->next;
}
(void) setvar_daemon(query,
(Name) query_list,
false,
chain_daemon,
false,
debug_level);
Chain hat_list = NULL;
Chain *hat_list_tail = &hat_list;
for (Dependency dependency = line->body.line.dependencies;
dependency != NULL;
dependency = dependency->next) {
if (!dependency->automatic) {
if ((dependency->name != force) &&
(dependency->stale == false)) {
*hat_list_tail = ALLOC(Chain);
if (dependency->name->is_member &&
(get_prop(dependency->name->prop, member_prop) != NULL)) {
(*hat_list_tail)->name =
get_prop(dependency->name->prop,
member_prop)->body.member.member;
} else {
(*hat_list_tail)->name = dependency->name;
}
if((*hat_list_tail)->name != NULL) {
if ((*hat_list_tail)->name->has_vpath_alias_prop) {
(*hat_list_tail)->name =
get_prop((*hat_list_tail)->name->prop,
vpath_alias_prop)->body.vpath_alias.alias;
}
}
(*hat_list_tail)->next = NULL;
hat_list_tail = &(*hat_list_tail)->next;
}
}
}
(void) setvar_daemon(hat,
(Name) hat_list,
false,
chain_daemon,
false,
debug_level);
if (used == NULL) {
new_command_longer = true;
*insert = used = ALLOC(Cmd_line);
used->next = NULL;
used->command_line = NULL;
insert = &used->next;
}
for (;
command_template != NULL;
command_template = command_template->next, insert = &used->next, used = *insert) {
if (used == NULL) {
new_command_longer = true;
*insert = used = ALLOC(Cmd_line);
used->next = NULL;
used->command_line = empty_name;
}
used->assign = false;
used->ignore_error = ignore_errors;
used->silent = silent;
used->always_exec = false;
INIT_STRING_FROM_STACK(command_line, buffer);
make_word_mentioned =
query_mentioned =
false;
expand_value(command_template->command_line, &command_line, true);
used->make_refd = make_word_mentioned;
used->ignore_command_dependency = query_mentioned;
start = command_line.buffer.start;
for (;
iswspace(*start) ||
(get_char_semantics_value(*start) & (int) command_prefix_sem);
start++) {
switch (*start) {
case question_char:
used->ignore_command_dependency = true;
break;
case exclam_char:
used->ignore_command_dependency = false;
break;
case equal_char:
used->assign = true;
break;
case hyphen_char:
used->ignore_error = true;
break;
case at_char:
if (!do_not_exec_rule) {
used->silent = true;
}
break;
case plus_char:
if(posix) {
used->always_exec = true;
}
break;
}
}
if (!used->ignore_command_dependency) {
ignore_all_command_dependency = false;
}
new_command_line = GETNAME(start, FIND_LENGTH);
if ((used->command_line == NULL) &&
(line->body.line.sccs_command)) {
used->command_line = new_command_line;
new_command_longer = false;
}
if (used->command_line != new_command_line) {
Name vpath_translated = vpath_translation(new_command_line);
if (keep_state &&
!used->ignore_command_dependency && (vpath_translated != used->command_line)) {
if (debug_level > 0) {
if (used->command_line != NULL
&& *used->command_line->string_mb !=
'\0') {
(void) printf(gettext("%*sBuilding %s because new command \n\t%s\n%*sdifferent from old\n\t%s\n"),
recursion_level,
"",
target->string_mb,
vpath_translated->string_mb,
recursion_level,
"",
used->
command_line->
string_mb);
} else {
(void) printf(gettext("%*sBuilding %s because new command \n\t%s\n%*sdifferent from empty old command\n"),
recursion_level,
"",
target->string_mb,
vpath_translated->string_mb,
recursion_level,
"");
}
}
command_changed = true;
line->body.line.is_out_of_date = true;
}
used->command_line = new_command_line;
}
if (command_line.free_after_use) {
retmem(command_line.buffer.start);
}
}
if (used != NULL) {
*insert = NULL;
if (keep_state &&
!ignore_all_command_dependency) {
if (debug_level > 0) {
(void) printf(gettext("%*sBuilding %s because new command shorter than old\n"),
recursion_level,
"",
target->string_mb);
}
command_changed = true;
line->body.line.is_out_of_date = true;
}
}
if (new_command_longer &&
!ignore_all_command_dependency &&
keep_state) {
if (debug_level > 0) {
(void) printf(gettext("%*sBuilding %s because new command longer than old\n"),
recursion_level,
"",
target->string_mb);
}
command_changed = true;
line->body.line.is_out_of_date = true;
}
(void) SETVAR(c_at, (Name) NULL, false);
(void) SETVAR(star, (Name) NULL, false);
(void) SETVAR(less_name, (Name) NULL, false);
(void) SETVAR(percent_name, (Name) NULL, false);
(void) SETVAR(query, (Name) NULL, false);
if (query_list != NULL) {
delete_query_chain(query_list);
}
(void) SETVAR(hat, (Name) NULL, false);
if (hat_list != NULL) {
delete_query_chain(hat_list);
}
if (conditional_macro_used) {
target->conditional_macro_list = cond_macro_list;
cond_macro_list = NULL;
target->depends_on_conditional = true;
}
}
static Doname
touch_command(Property line, Name target, Doname result)
{
Name name;
Chain target_group;
String_rec touch_string;
wchar_t buffer[MAXPATHLEN];
Name touch_cmd;
Cmd_line rule;
for (name = target, target_group = NULL; name != NULL;) {
if (!name->is_member) {
INIT_STRING_FROM_STACK(touch_string, buffer);
MBSTOWCS(wcs_buffer, "touch ");
append_string(wcs_buffer, &touch_string, FIND_LENGTH);
touch_cmd = name;
if (name->has_vpath_alias_prop) {
touch_cmd = get_prop(name->prop,
vpath_alias_prop)->
body.vpath_alias.alias;
}
APPEND_NAME(touch_cmd,
&touch_string,
FIND_LENGTH);
touch_cmd = GETNAME(touch_string.buffer.start,
FIND_LENGTH);
if (touch_string.free_after_use) {
retmem(touch_string.buffer.start);
}
if (!silent ||
do_not_exec_rule &&
(target_group == NULL)) {
(void) printf("%s\n", touch_cmd->string_mb);
}
if (!do_not_exec_rule) {
result = dosys(touch_cmd,
false,
false,
false,
false,
name);
} else {
result = build_ok;
}
} else {
result = build_ok;
}
if (target_group == NULL) {
target_group = line->body.line.target_group;
} else {
target_group = target_group->next;
}
if (target_group != NULL) {
name = target_group->name;
} else {
name = NULL;
}
}
return result;
}
void
update_target(Property line, Doname result)
{
Name target;
Chain target_group;
Property line2;
timestruc_t old_stat_time;
Property member;
if(line == NULL) {
return;
}
target = line->body.line.target;
if ((result == build_ok) && (line->body.line.command_used != NULL)) {
if (do_not_exec_rule ||
touch ||
(target->is_member &&
(line->body.line.command_template != NULL) &&
(line->body.line.command_template->command_line->string_mb[0] == 0) &&
(line->body.line.command_template->next == NULL))) {
target->stat.time = file_max_time;
} else {
old_stat_time = target->stat.time;
target->stat.time = file_no_time;
(void) exists(target);
if ((target->is_member) &&
(target->stat.time == old_stat_time)) {
member = get_prop(target->prop, member_prop);
if (member != NULL) {
target->stat.time = member->body.member.library->stat.time;
target->stat.time.tv_sec++;
}
}
}
for (target_group = line->body.line.target_group;
target_group != NULL;
target_group = target_group->next) {
target_group->name->stat.time = target->stat.time;
line2 = maybe_append_prop(target_group->name,
line_prop);
line2->body.line.command_used =
line->body.line.command_used;
line2->body.line.target = target_group->name;
}
}
target->has_built = true;
}
static Doname
sccs_get(Name target, Property *command)
{
int result;
char link[MAXPATHLEN];
String_rec string;
wchar_t name[MAXPATHLEN];
wchar_t *p;
timestruc_t sccs_time;
Property line;
int sym_link_depth = 0;
while (target->stat.is_sym_link) {
if (sym_link_depth++ > 90) {
fatal(gettext("Can't read symbolic link `%s': Number of symbolic links encountered during path name traversal exceeds 90."),
target->string_mb);
}
result = readlink_vroot(target->string_mb,
link,
sizeof(link),
NULL,
VROOT_DEFAULT);
if (result == -1) {
fatal(gettext("Can't read symbolic link `%s': %s"),
target->string_mb, errmsg(errno));
}
link[result] = 0;
INIT_STRING_FROM_STACK(string, name);
Wstring wcb(target);
if ((link[0] != slash_char) &&
((p = (wchar_t *) wcsrchr(wcb.get_string(), slash_char)) != NULL)) {
append_string(wcb.get_string(), &string, p - wcb.get_string() + 1);
}
append_string(link, &string, result);
target = normalize_name(string.buffer.start, string.text.p - string.buffer.start);
(void) exists(target);
if (string.free_after_use) {
retmem(string.buffer.start);
}
}
if (target->stat.has_sccs == DONT_KNOW_SCCS) {
read_directory_of_file(target);
}
switch (target->stat.has_sccs) {
case DONT_KNOW_SCCS:
target->stat.has_sccs = NO_SCCS;
case NO_SCCS:
if (target->stat.time > file_doesnt_exist) {
return build_ok;
}
return build_dont_know;
case HAS_SCCS:
sccs_time = exists(get_prop(target->prop,
sccs_prop)->body.sccs.file);
break;
}
if ((!target->has_complained &&
(sccs_time != file_doesnt_exist) &&
(sccs_get_rule != NULL))) {
if (command == NULL) {
return build_ok;
}
line = maybe_append_prop(target, line_prop);
*command = line;
if (sccs_time > target->stat.time) {
line->body.line.is_out_of_date = true;
if (debug_level > 0) {
(void) printf(gettext("%*sSccs getting %s because s. file is younger than source file\n"),
recursion_level,
"",
target->string_mb);
}
}
line->body.line.sccs_command = true;
line->body.line.command_template = sccs_get_rule;
if(!svr4 && (!allrules_read || posix)) {
if((target->prop) &&
(target->prop->body.sccs.file) &&
(target->prop->body.sccs.file->string_mb)) {
if((strlen(target->prop->body.sccs.file->string_mb) ==
strlen(target->string_mb) + 2) &&
(target->prop->body.sccs.file->string_mb[0] == 's') &&
(target->prop->body.sccs.file->string_mb[1] == '.')) {
line->body.line.command_template = get_posix_rule;
}
}
}
line->body.line.target = target;
line->body.line.star = NULL;
line->body.line.less = NULL;
line->body.line.percent = NULL;
return build_ok;
}
return build_dont_know;
}
void
read_directory_of_file(Name file)
{
Wstring file_string(file);
wchar_t * wcb = file_string.get_string();
wchar_t usr_include_buf[MAXPATHLEN];
wchar_t usr_include_sys_buf[MAXPATHLEN];
Name directory = dot;
wchar_t *p = (wchar_t *) wcsrchr(wcb,
(int) slash_char);
int length = p - wcb;
static Name usr_include;
static Name usr_include_sys;
if (usr_include == NULL) {
MBSTOWCS(usr_include_buf, "/usr/include");
usr_include = GETNAME(usr_include_buf, FIND_LENGTH);
MBSTOWCS(usr_include_sys_buf, "/usr/include/sys");
usr_include_sys = GETNAME(usr_include_sys_buf, FIND_LENGTH);
}
if (p != NULL) {
if ((usr_include->hash.length == length) &&
IS_WEQUALN(usr_include_buf,
wcb,
length)) {
directory = usr_include;
} else if ((usr_include_sys->hash.length == length) &&
IS_WEQUALN(usr_include_sys_buf,
wcb,
length)) {
directory = usr_include_sys;
} else {
directory = GETNAME(wcb, length);
}
}
(void) read_dir(directory,
(wchar_t *) NULL,
(Property) NULL,
(wchar_t *) NULL);
}
static void
add_pattern_conditionals(Name target)
{
Property conditional;
Property new_prop;
Property *previous;
Name_rec dummy;
wchar_t *pattern;
wchar_t *percent;
int length;
Wstring wcb(target);
Wstring wcb1;
for (conditional = get_prop(conditionals->prop, conditional_prop);
conditional != NULL;
conditional = get_prop(conditional->next, conditional_prop)) {
wcb1.init(conditional->body.conditional.target);
pattern = wcb1.get_string();
if (pattern[1] != 0) {
percent = (wchar_t *) wcschr(pattern, (int) percent_char);
if ((length = wcb.length()-wcslen(percent+1)) <= 0) {
continue;
}
if (!wcb.equaln(pattern, percent-pattern) ||
!IS_WEQUAL(wcb.get_string(length), percent+1)) {
continue;
}
}
for (previous = &target->prop;
*previous != NULL;
previous = &(*previous)->next) {
if (((*previous)->type == conditional_prop) &&
((*previous)->body.conditional.sequence >
conditional->body.conditional.sequence)) {
break;
}
}
if (*previous == NULL) {
new_prop = append_prop(target, conditional_prop);
} else {
dummy.prop = NULL;
new_prop = append_prop(&dummy, conditional_prop);
new_prop->next = *previous;
*previous = new_prop;
}
target->conditional_cnt++;
new_prop->body.conditional = conditional->body.conditional;
}
}
void
set_locals(Name target, Property old_locals)
{
Property conditional;
int i;
Boolean saved_conditional_macro_used;
Chain cond_name;
Chain cond_chain;
if (target->dont_activate_cond_values) {
return;
}
saved_conditional_macro_used = conditional_macro_used;
for (conditional = get_prop(target->prop, conditional_prop), i = 0;
conditional != NULL;
conditional = get_prop(conditional->next, conditional_prop),
i++) {
old_locals[i].body.macro =
maybe_append_prop(conditional->body.conditional.name,
macro_prop)->body.macro;
if (debug_level > 1) {
(void) printf(gettext("%*sActivating conditional value: "),
recursion_level,
"");
}
if ((conditional->body.conditional.name != virtual_root) ||
(conditional->body.conditional.value != virtual_root)) {
(void) SETVAR(conditional->body.conditional.name,
conditional->body.conditional.value,
(Boolean) conditional->body.conditional.append);
}
cond_name = ALLOC(Chain);
cond_name->name = conditional->body.conditional.name;
}
cond_chain = ALLOC(Chain);
cond_chain->name = target;
cond_chain->next = conditional_targets;
conditional_targets = cond_chain;
conditional_macro_used = saved_conditional_macro_used;
}
void
reset_locals(Name target, Property old_locals, Property conditional, int index)
{
Property this_conditional;
Chain cond_chain;
if (target->dont_activate_cond_values) {
return;
}
this_conditional = get_prop(conditional->next, conditional_prop);
if (this_conditional != NULL) {
reset_locals(target, old_locals, this_conditional, index+1);
} else {
if (conditional_targets == NULL ||
conditional_targets->name != target) {
warning(gettext("Internal error: reset target not at head of condtional_targets chain"));
} else {
cond_chain = conditional_targets->next;
retmem_mb((caddr_t) conditional_targets);
conditional_targets = cond_chain;
}
}
get_prop(conditional->body.conditional.name->prop,
macro_prop)->body.macro = old_locals[index].body.macro;
if (conditional->body.conditional.name == virtual_root) {
(void) SETVAR(virtual_root, getvar(virtual_root), false);
}
if (debug_level > 1) {
if (old_locals[index].body.macro.value != NULL) {
(void) printf(gettext("%*sdeactivating conditional value: %s= %s\n"),
recursion_level,
"",
conditional->body.conditional.name->
string_mb,
old_locals[index].body.macro.value->
string_mb);
} else {
(void) printf(gettext("%*sdeactivating conditional value: %s =\n"),
recursion_level,
"",
conditional->body.conditional.name->
string_mb);
}
}
}
Boolean
check_auto_dependencies(Name target, int auto_count, Name *automatics)
{
Name *p;
int n;
Property line;
Dependency dependency;
if (keep_state) {
if ((line = get_prop(target->prop, line_prop)) == NULL) {
return false;
}
for (dependency = line->body.line.dependencies;
dependency != NULL;
dependency = dependency->next) {
if (dependency->automatic && !dependency->stale) {
for (n = auto_count, p = automatics;
n > 0;
n--) {
if (*p++ == dependency->name) {
goto not_new;
}
}
return true;
}
not_new:;
}
return false;
} else {
return false;
}
}
static void
delete_query_chain(Chain ch)
{
if (ch == NULL) {
return;
} else {
delete_query_chain(ch->next);
retmem_mb((char *) ch);
}
}
Doname
target_can_be_built(Name target) {
Doname result = build_dont_know;
Name true_target = target;
Property line;
if (target == wait_name) {
return(build_ok);
}
if (target->has_target_prop) {
true_target = get_prop(target->prop,
target_prop)->body.target.target;
}
(void) exists(true_target);
if (true_target->state == build_running) {
return(build_running);
}
if (true_target->stat.time != file_doesnt_exist) {
result = build_ok;
}
line = get_prop(true_target->prop, line_prop);
if (line != NULL && line->body.line.command_template != NULL) {
result = build_ok;
}
if (result == build_dont_know) {
result = find_percent_rule(target, NULL, false);
}
if (result == build_dont_know) {
if (target->is_member) {
Property member = get_prop(target->prop, member_prop);
if (member != NULL && member->body.member.member != NULL) {
result = find_ar_suffix_rule(target, member->body.member.member, NULL, false);
} else {
result = find_double_suffix_rule(target, NULL, false);
}
} else {
result = find_double_suffix_rule(target, NULL, false);
}
}
if ((result == build_dont_know) && second_pass) {
result = find_suffix_rule(target, target, empty_name, NULL, false);
}
if (result == build_dont_know) {
result = sccs_get(target, NULL);
}
if (result == build_dont_know) {
Name dtarg = find_dyntarget(target);
if (dtarg != NULL) {
result = target_can_be_built(dtarg);
}
}
if (result == build_dont_know) {
if (target->colons != no_colon) {
result = build_ok;
}
}
return result;
}