#include <bsd/bsd.h>
#include <locale.h>
#include <libgen.h>
#include <mk/defs.h>
#include <mksh/macro.h>
#include <mksh/misc.h>
#include <pwd.h>
#include <setjmp.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/errno.h>
#include <sys/stat.h>
#include <fcntl.h>
# include <sys/systeminfo.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <vroot/report.h>
extern Name normalize_name(wchar_t *name_string, int length);
extern void job_adjust_fini();
#define LD_SUPPORT_ENV_VAR "SGS_SUPPORT_32"
#define LD_SUPPORT_ENV_VAR_32 "SGS_SUPPORT_32"
#define LD_SUPPORT_ENV_VAR_64 "SGS_SUPPORT_64"
#define LD_SUPPORT_MAKE_LIB "libmakestate.so.1"
#ifdef __x86
#define LD_SUPPORT_MAKE_ARCH "i386"
#elif __sparc
#define LD_SUPPORT_MAKE_ARCH "sparc"
#else
#error "Unsupported architecture"
#endif
static char *argv_zero_string;
static Boolean build_failed_ever_seen;
static Boolean continue_after_error_ever_seen;
static Boolean dmake_group_specified;
static Boolean dmake_max_jobs_specified;
static Boolean dmake_mode_specified;
static Boolean dmake_add_mode_specified;
static Boolean dmake_output_mode_specified;
static Boolean dmake_compat_mode_specified;
static Boolean dmake_odir_specified;
static Boolean dmake_rcfile_specified;
static Boolean env_wins;
static Boolean ignore_default_mk;
static Boolean list_all_targets;
static int mf_argc;
static char **mf_argv;
static Dependency_rec not_auto_depen_struct;
static Dependency not_auto_depen = ¬_auto_depen_struct;
static Boolean pmake_cap_r_specified;
static Boolean pmake_machinesfile_specified;
static Boolean stop_after_error_ever_seen;
static Boolean trace_status;
#ifdef DMAKE_STATISTICS
static Boolean getname_stat = false;
#endif
static time_t start_time;
static int g_argc;
static char **g_argv;
extern "C" void cleanup_after_exit(void);
extern "C" {
extern void dmake_exit_callback(void);
extern void dmake_message_callback(char *);
}
extern Name normalize_name(wchar_t *name_string, int length);
extern int main(int, char * []);
static void append_makeflags_string(Name, String);
static void doalarm(int);
static void enter_argv_values(int , char **, ASCII_Dyn_Array *);
static void make_targets(int, char **, Boolean);
static int parse_command_option(char);
static void read_command_options(int, char **);
static void read_environment(Boolean);
static void read_files_and_state(int, char **);
static Boolean read_makefile(Name, Boolean, Boolean, Boolean);
static void report_recursion(Name);
static void set_sgs_support(void);
static void setup_for_projectdir(void);
static void setup_makeflags_argv(void);
static void report_dir_enter_leave(Boolean entering);
extern void expand_value(Name, String , Boolean);
static const char verstring[] = "illumos make";
jmp_buf jmpbuffer;
int
main(int argc, char *argv[])
{
char *cp;
char make_state_dir[MAXPATHLEN];
Boolean parallel_flag = false;
Boolean argv_zero_relative = false;
char *prognameptr;
char *slash_ptr;
mode_t um;
int i;
struct itimerval value;
char def_dmakerc_path[MAXPATHLEN];
Name dmake_name, dmake_name2;
Name dmake_value, dmake_value2;
Property prop, prop2;
struct stat statbuf;
int statval;
struct stat out_stat, err_stat;
hostid = gethostid();
bsd_signals();
(void) setlocale(LC_ALL, "");
#ifdef DMAKE_STATISTICS
if (getenv("DMAKE_STATISTICS")) {
getname_stat = true;
}
#endif
#ifndef TEXT_DOMAIN
#define TEXT_DOMAIN "SYS_TEST"
#endif
textdomain(TEXT_DOMAIN);
g_argc = argc;
g_argv = (char **) malloc((g_argc + 1) * sizeof(char *));
for (i = 0; i < argc; i++) {
g_argv[i] = argv[i];
}
g_argv[i] = NULL;
if (*argv[0] == (int) slash_char) {
argv_zero_string = strdup(argv[0]);
} else if (strchr(argv[0], (int) slash_char) == NULL) {
argv_zero_string = strdup(argv[0]);
} else {
char *tmp_current_path;
char *tmp_string;
tmp_current_path = get_current_path();
tmp_string = getmem(strlen(tmp_current_path) + 1 +
strlen(argv[0]) + 1);
(void) sprintf(tmp_string,
"%s/%s",
tmp_current_path,
argv[0]);
argv_zero_string = strdup(tmp_string);
retmem_mb(tmp_string);
argv_zero_relative = true;
}
make_state_lockfile = NULL;
make_state_locked = false;
svr4 = false;
posix = false;
if(!strcmp(argv_zero_string, "/usr/xpg4/bin/make")) {
svr4 = false;
posix = true;
} else {
prognameptr = strrchr(argv[0], '/');
if(prognameptr) {
prognameptr++;
} else {
prognameptr = argv[0];
}
if(!strcmp(prognameptr, "svr4.make")) {
svr4 = true;
posix = false;
}
}
if (getenv(USE_SVR4_MAKE) || getenv("USE_SVID")){
svr4 = true;
posix = false;
}
char * dmake_compat_mode_var = getenv("SUN_MAKE_COMPAT_MODE");
if (dmake_compat_mode_var != NULL) {
if (0 == strcasecmp(dmake_compat_mode_var, "GNU")) {
gnu_style = true;
}
}
char * tmpdir_var = getenv("TMPDIR");
if (tmpdir_var != NULL && *tmpdir_var == '/' && strlen(tmpdir_var) < MAXPATHLEN) {
strcpy(mbs_buffer, tmpdir_var);
for (tmpdir_var = mbs_buffer+strlen(mbs_buffer);
*(--tmpdir_var) == '/' && tmpdir_var > mbs_buffer;
*tmpdir_var = '\0');
if (strlen(mbs_buffer) + 32 < MAXPATHLEN) {
sprintf(mbs_buffer2, "%s/dmake.tst.%d.XXXXXX",
mbs_buffer, getpid());
int fd = mkstemp(mbs_buffer2);
if (fd >= 0) {
close(fd);
unlink(mbs_buffer2);
tmpdir = strdup(mbs_buffer);
}
}
}
if (fstat(1, &out_stat) < 0) {
fatal(gettext("fstat of standard out failed: %s"), errmsg(errno));
}
if (fstat(2, &err_stat) < 0) {
fatal(gettext("fstat of standard error failed: %s"), errmsg(errno));
}
if ((out_stat.st_dev == err_stat.st_dev) &&
(out_stat.st_ino == err_stat.st_ino)) {
stdout_stderr_same = true;
} else {
stdout_stderr_same = false;
}
set_path_style(0);
setup_char_semantics();
(void) atexit(cleanup_after_exit);
load_cached_names();
setup_makeflags_argv();
read_command_options(mf_argc, mf_argv);
read_command_options(argc, argv);
if (debug_level > 0) {
cp = getenv(makeflags->string_mb);
(void) printf(gettext("MAKEFLAGS value: %s\n"), cp == NULL ? "" : cp);
}
if (argv_zero_relative && rebuild_arg0) {
char *tmp_current_path;
char *tmp_string;
free(argv_zero_string);
tmp_current_path = get_current_path();
tmp_string = getmem(strlen(tmp_current_path) + 1 +
strlen(argv[0]) + 1);
(void) sprintf(tmp_string,
"%s/%s",
tmp_current_path,
argv[0]);
argv_zero_string = strdup(tmp_string);
retmem_mb(tmp_string);
}
setup_for_projectdir();
setup_interrupt(handle_interrupt);
read_files_and_state(argc, argv);
MBSTOWCS(wcs_buffer, "DMAKE_OUTPUT_MODE");
dmake_name2 = GETNAME(wcs_buffer, FIND_LENGTH);
prop2 = get_prop(dmake_name2->prop, macro_prop);
if (prop2 == NULL) {
output_mode = txt1_mode;
} else {
dmake_value2 = prop2->body.macro.value;
if ((dmake_value2 == NULL) ||
(IS_EQUAL(dmake_value2->string_mb, "TXT1"))) {
output_mode = txt1_mode;
} else if (IS_EQUAL(dmake_value2->string_mb, "TXT2")) {
output_mode = txt2_mode;
} else if (IS_EQUAL(dmake_value2->string_mb, "HTML1")) {
output_mode = html1_mode;
} else {
warning(gettext("Unsupported value `%s' for DMAKE_OUTPUT_MODE after -x flag (ignored)"),
dmake_value2->string_mb);
}
}
if ((!pmake_cap_r_specified) &&
(!pmake_machinesfile_specified)) {
char *s, *b;
if ((s = strdup(argv[0])) == NULL)
fatal(gettext("Out of memory"));
b = basename(s);
MBSTOWCS(wcs_buffer, "DMAKE_MODE");
dmake_name2 = GETNAME(wcs_buffer, FIND_LENGTH);
prop2 = get_prop(dmake_name2->prop, macro_prop);
if ((strcmp(b, "make") == 0) &&
!dmake_max_jobs_specified) {
dmake_mode_type = serial_mode;
no_parallel = true;
} else if (prop2 == NULL) {
if (strcmp(b, "dmake") == 0) {
dmake_mode_type = parallel_mode;
no_parallel = false;
}
} else {
dmake_value2 = prop2->body.macro.value;
if (IS_EQUAL(dmake_value2->string_mb, "parallel")) {
dmake_mode_type = parallel_mode;
no_parallel = false;
} else if (IS_EQUAL(dmake_value2->string_mb, "serial")) {
dmake_mode_type = serial_mode;
no_parallel = true;
} else {
fatal(gettext("Unknown dmake mode argument `%s' after -m flag"), dmake_value2->string_mb);
}
}
free(s);
}
parallel_flag = true;
putenv(strdup("DMAKE_CHILD=TRUE"));
if(touch) {
dmake_mode_type = serial_mode;
no_parallel = true;
}
out_err_same = true;
char * dmake_sep_var = getenv("__DMAKE_SEPARATE_STDERR");
if (dmake_sep_var == NULL || (0 != strcasecmp(dmake_sep_var, "NO"))) {
struct stat stdout_stat;
struct stat stderr_stat;
if( (fstat(1, &stdout_stat) == 0)
&& (fstat(2, &stderr_stat) == 0) )
{
if( (stdout_stat.st_dev != stderr_stat.st_dev)
|| (stdout_stat.st_ino != stderr_stat.st_ino) )
{
out_err_same = false;
}
}
}
(void) bsd_signal(SIGALRM, (SIG_PF)doalarm);
if (getenv(sunpro_dependencies->string_mb) != NULL) {
FILE *report_file;
report_dependency("");
report_file = get_report_file();
if ((report_file != NULL) && (report_file != (FILE*)-1)) {
(void) fprintf(report_file, "\n");
}
}
if (keep_state) {
maybe_append_prop(sunpro_dependencies, macro_prop)->
body.macro.exported = true;
} else {
maybe_append_prop(sunpro_dependencies, macro_prop)->
body.macro.exported = false;
}
working_on_targets = true;
if (trace_status) {
dump_make_state();
fclose(stdout);
fclose(stderr);
exit_status = 0;
exit(0);
}
if (list_all_targets) {
dump_target_list();
fclose(stdout);
fclose(stderr);
exit_status = 0;
exit(0);
}
trace_reader = false;
if ((slash_ptr = strrchr(make_state->string_mb, (int) slash_char)) == NULL) {
temp_file_directory = strdup(get_current_path());
} else {
*slash_ptr = (int) nul_char;
(void) strcpy(make_state_dir, make_state->string_mb);
*slash_ptr = (int) slash_char;
if(make_state_dir[0] == '\0') {
make_state_dir[0] = '/';
make_state_dir[1] = '\0';
}
if (make_state_dir[0] == (int) slash_char) {
temp_file_directory = strdup(make_state_dir);
} else {
char tmp_current_path2[MAXPATHLEN];
(void) sprintf(tmp_current_path2,
"%s/%s",
get_current_path(),
make_state_dir);
temp_file_directory = strdup(tmp_current_path2);
}
}
report_dir_enter_leave(true);
make_targets(argc, argv, parallel_flag);
report_dir_enter_leave(false);
if (build_failed_ever_seen) {
if (posix) {
exit_status = 1;
}
exit(1);
}
exit_status = 0;
exit(0);
}
extern "C" void
cleanup_after_exit(void)
{
Running rp;
extern long getname_bytes_count;
extern long getname_names_count;
extern long getname_struct_count;
extern long freename_bytes_count;
extern long freename_names_count;
extern long freename_struct_count;
extern long other_alloc;
extern long env_alloc_num;
extern long env_alloc_bytes;
#ifdef DMAKE_STATISTICS
if(getname_stat) {
printf(">>> Getname statistics:\n");
printf(" Allocated:\n");
printf(" Names: %ld\n", getname_names_count);
printf(" Strings: %ld Kb (%ld bytes)\n", getname_bytes_count/1000, getname_bytes_count);
printf(" Structs: %ld Kb (%ld bytes)\n", getname_struct_count/1000, getname_struct_count);
printf(" Total bytes: %ld Kb (%ld bytes)\n", getname_struct_count/1000 + getname_bytes_count/1000, getname_struct_count + getname_bytes_count);
printf("\n Unallocated: %ld\n", freename_names_count);
printf(" Names: %ld\n", freename_names_count);
printf(" Strings: %ld Kb (%ld bytes)\n", freename_bytes_count/1000, freename_bytes_count);
printf(" Structs: %ld Kb (%ld bytes)\n", freename_struct_count/1000, freename_struct_count);
printf(" Total bytes: %ld Kb (%ld bytes)\n", freename_struct_count/1000 + freename_bytes_count/1000, freename_struct_count + freename_bytes_count);
printf("\n Total used: %ld Kb (%ld bytes)\n", (getname_struct_count/1000 + getname_bytes_count/1000) - (freename_struct_count/1000 + freename_bytes_count/1000), (getname_struct_count + getname_bytes_count) - (freename_struct_count + freename_bytes_count));
printf("\n>>> Other:\n");
printf(
" Env (%ld): %ld Kb (%ld bytes)\n",
env_alloc_num,
env_alloc_bytes/1000,
env_alloc_bytes
);
}
#endif
parallel = false;
if (!getenv(USE_SVR4_MAKE)){
if (!quest && !list_all_targets) {
Name failed_name;
MBSTOWCS(wcs_buffer, ".FAILED");
failed_name = GETNAME(wcs_buffer, FIND_LENGTH);
if ((exit_status != 0) && (failed_name->prop != NULL)) {
dmake_mode_type = serial_mode;
no_parallel = true;
(void) doname(failed_name, false, true);
} else {
if (!trace_status) {
dmake_mode_type = serial_mode;
no_parallel = true;
(void) doname(done, false, true);
}
}
}
}
if (temp_file_name != NULL) {
(void) unlink(temp_file_name->string_mb);
}
if (current_line != NULL) {
command_changed = true;
current_line->body.line.command_used = NULL;
}
for (rp = running_list; rp != NULL; rp = rp->next) {
if (rp->temp_file != NULL) {
(void) unlink(rp->temp_file->string_mb);
}
if (rp->stdout_file != NULL) {
(void) unlink(rp->stdout_file);
retmem_mb(rp->stdout_file);
rp->stdout_file = NULL;
}
if (rp->stderr_file != NULL) {
(void) unlink(rp->stderr_file);
retmem_mb(rp->stderr_file);
rp->stderr_file = NULL;
}
command_changed = true;
}
if ((make_state_lockfile != NULL) && (make_state_locked)) {
(void) unlink(make_state_lockfile);
make_state_lockfile = NULL;
make_state_locked = false;
}
write_state_file(1, (Boolean) 1);
job_adjust_fini();
}
void
handle_interrupt(int)
{
Property member;
Running rp;
(void) fflush(stdout);
if (childPid > 0) {
kill(childPid, SIGTERM);
childPid = -1;
}
for (rp = running_list; rp != NULL; rp = rp->next) {
if (rp->state != build_running) {
continue;
}
if (rp->pid > 0) {
kill(rp->pid, SIGTERM);
rp->pid = -1;
}
}
if (getpid() == getpgrp()) {
bsd_signal(SIGTERM, SIG_IGN);
kill (-getpid(), SIGTERM);
}
finish_children(false);
while (wait((int *) NULL) != -1);
if ((current_target != NULL) &&
current_target->is_member &&
((member = get_prop(current_target->prop, member_prop)) != NULL)) {
current_target = member->body.member.library;
}
if (!do_not_exec_rule &&
!touch &&
!quest &&
(current_target != NULL) &&
!(current_target->stat.is_precious || all_precious)) {
current_target->stat.time = file_no_time;
if (exists(current_target) != file_doesnt_exist) {
(void) fprintf(stderr,
"\n*** %s ",
current_target->string_mb);
if (current_target->stat.is_dir) {
(void) fprintf(stderr,
gettext("not removed.\n"),
current_target->string_mb);
} else if (unlink(current_target->string_mb) == 0) {
(void) fprintf(stderr,
gettext("removed.\n"),
current_target->string_mb);
} else {
(void) fprintf(stderr,
gettext("could not be removed: %s.\n"),
current_target->string_mb,
errmsg(errno));
}
}
}
for (rp = running_list; rp != NULL; rp = rp->next) {
if (rp->state != build_running) {
continue;
}
if (rp->target->is_member &&
((member = get_prop(rp->target->prop, member_prop)) !=
NULL)) {
rp->target = member->body.member.library;
}
if (!do_not_exec_rule &&
!touch &&
!quest &&
!(rp->target->stat.is_precious || all_precious)) {
rp->target->stat.time = file_no_time;
if (exists(rp->target) != file_doesnt_exist) {
(void) fprintf(stderr,
"\n*** %s ",
rp->target->string_mb);
if (rp->target->stat.is_dir) {
(void) fprintf(stderr,
gettext("not removed.\n"),
rp->target->string_mb);
} else if (unlink(rp->target->string_mb) == 0) {
(void) fprintf(stderr,
gettext("removed.\n"),
rp->target->string_mb);
} else {
(void) fprintf(stderr,
gettext("could not be removed: %s.\n"),
rp->target->string_mb,
errmsg(errno));
}
}
}
}
if ((make_state_lockfile != NULL) && (make_state_locked)) {
unlink(make_state_lockfile);
make_state_lockfile = NULL;
make_state_locked = false;
}
check_state(NULL);
report_dir_enter_leave(false);
exit_status = 2;
exit(2);
}
static void
doalarm(int sig __attribute__((unused)))
{
return;
}
static void
read_command_options(int argc, char **argv)
{
int ch;
int current_optind = 1;
int last_optind_with_double_hyphen = 0;
int last_optind;
int last_current_optind;
int i;
int j;
int k;
int makefile_next = 0;
const char *tptr;
const char *CMD_OPTS;
extern char *optarg;
extern int optind, opterr, optopt;
#define SUNPRO_CMD_OPTS "-~Bbc:C:Ddef:g:ij:K:kM:m:NnO:o:PpqRrSsTtuVvwx:"
# define SVR4_CMD_OPTS "-c:C:ef:g:ij:km:nO:o:pqrsTtVv"
opterr = 0;
optind = 1;
while (1) {
last_optind=optind;
last_current_optind=current_optind;
if (svr4) {
CMD_OPTS=SVR4_CMD_OPTS;
ch = getopt(argc, argv, SVR4_CMD_OPTS);
} else {
CMD_OPTS=SUNPRO_CMD_OPTS;
ch = getopt(argc, argv, SUNPRO_CMD_OPTS);
}
if (ch == EOF) {
if(optind < argc) {
optind++;
current_optind++;
continue;
} else {
break;
}
}
if (ch == '?') {
if (optopt == '-') {
i = current_optind;
if (argv[i][0] == '-') {
if (argv[i][1] == '-') {
if (argv[i][2] != '\0') {
tptr = strchr(CMD_OPTS, argv[i][2]);
if (tptr) {
if (last_optind_with_double_hyphen != current_optind) {
last_optind_with_double_hyphen = current_optind;
for (j=0; argv[i][j] != '\0'; j++) {
argv[i][j] = argv[i][j+1];
}
optind=last_optind;
current_optind=last_current_optind;
continue;
}
}
}
}
}
}
}
if (ch == '?') {
if (svr4) {
fprintf(stderr,
gettext("Usage : dmake [ -f makefile ][ -c dmake_rcfile ][ -g dmake_group ][-C directory]\n"));
fprintf(stderr,
gettext(" [ -j dmake_max_jobs ][ -m dmake_mode ][ -o dmake_odir ]...\n"));
fprintf(stderr,
gettext(" [ -e ][ -i ][ -k ][ -n ][ -p ][ -q ][ -r ][ -s ][ -t ][ -v ]\n"));
tptr = strchr(SVR4_CMD_OPTS, optopt);
} else {
fprintf(stderr,
gettext("Usage : dmake [ -f makefile ][ -c dmake_rcfile ][ -g dmake_group ][-C directory]\n"));
fprintf(stderr,
gettext(" [ -j dmake_max_jobs ][ -K statefile ][ -m dmake_mode ][ -x MODE_NAME=VALUE ][ -o dmake_odir ]...\n"));
fprintf(stderr,
gettext(" [ -d ][ -dd ][ -D ][ -DD ][ -e ][ -i ][ -k ][ -n ][ -p ][ -P ][ -u ][ -w ]\n"));
fprintf(stderr,
gettext(" [ -q ][ -r ][ -s ][ -S ][ -t ][ -v ][ -V ][ target... ][ macro=value... ][ \"macro +=value\"... ]\n"));
tptr = strchr(SUNPRO_CMD_OPTS, optopt);
}
if (!tptr) {
fatal(gettext("Unknown option `-%c'"), optopt);
} else {
fatal(gettext("Missing argument after `-%c'"), optopt);
}
}
makefile_next |= parse_command_option(ch);
if (current_optind < optind) {
i = current_optind;
k = 0;
if ((optind - current_optind) > 1) {
k = i + 1;
}
switch (makefile_next) {
case 0:
argv[i] = NULL;
if (k) {
argv[k] = NULL;
}
break;
case 1:
argv[i] = (char *)"-f";
break;
case 2:
argv[i] = (char *)"-c";
break;
case 4:
argv[i] = (char *)"-g";
break;
case 8:
argv[i] = (char *)"-j";
break;
case 16:
argv[i] = (char *)"-M";
break;
case 32:
argv[i] = (char *)"-m";
break;
case 128:
argv[i] = (char *)"-O";
break;
case 256:
argv[i] = (char *)"-K";
break;
case 512:
argv[i] = (char *)"-o";
break;
case 1024:
argv[i] = (char *)"-x";
break;
case 2048:
argv[i] = (char *)"-C";
if (chdir(argv[k]) != 0) {
fatal(gettext("failed to change to directory %s: %s"),
argv[k], strerror(errno));
}
path_reset = true;
rebuild_arg0 = true;
(void) get_current_path();
break;
default:
fatal(gettext("Illegal command line. More than one option requiring\nan argument given in the same argument group"));
}
makefile_next = 0;
current_optind = optind;
}
}
}
static void
quote_str(char *str, char *qstr)
{
char *to;
char *from;
to = qstr;
for (from = str; *from; from++) {
switch (*from) {
case ';':
case '(':
case ')':
case '{':
case '}':
case '[':
case ']':
case '|':
case '^':
case '&':
case '<':
case '>':
case '*':
case '?':
case '$':
case '\'':
case '"':
case '`':
case '#':
case ' ':
case '\\':
*to++ = '\\';
break;
default:
break;
}
*to++ = *from;
}
*to = '\0';
}
static void
unquote_str(char *str, char *qstr)
{
char *to;
char *from;
to = qstr;
for (from = str; *from; from++) {
if (*from == '\\') {
from++;
}
*to++ = *from;
}
*to = '\0';
}
static void
setup_makeflags_argv()
{
char *cp;
char *cp1;
char *cp2;
char *cp3;
char *cp_orig;
Boolean add_hyphen;
int i;
char tmp_char;
mf_argc = 1;
cp = getenv(makeflags->string_mb);
cp_orig = cp;
if (cp) {
if ((strchr(cp, (int) hyphen_char) != NULL) ||
(strchr(cp, (int) equal_char) != NULL)) {
add_hyphen = false;
while (*cp) {
if (*cp != (int) hyphen_char) {
break;
}
cp++;
if (*cp == (int) hyphen_char) {
cp_orig = cp;
cp++;
}
if (!(*cp)) {
cp_orig = cp;
break;
}
}
} else {
add_hyphen = true;
}
}
while (cp && *cp) {
while (cp && *cp && isspace(*cp)) {
cp++;
}
if (cp && *cp) {
mf_argc++;
while (cp && *cp && !isspace(*cp)) {
if(*cp == (int) backslash_char) {
cp++;
}
cp++;
}
}
}
mf_argv = (char **) malloc((mf_argc + 1) * sizeof(char *));
mf_argv[0] = (char *)"MAKEFLAGS";
cp = cp_orig;
for (i = 1; i < mf_argc; i++) {
while (cp && *cp && isspace(*cp)) {
cp++;
}
if (cp && *cp) {
cp_orig = cp;
while (cp && *cp && !isspace(*cp)) {
if(*cp == (int) backslash_char) {
cp++;
}
cp++;
}
tmp_char = *cp;
*cp = (int) nul_char;
if (add_hyphen) {
mf_argv[i] = getmem(2 + strlen(cp_orig));
mf_argv[i][0] = '\0';
(void) strcat(mf_argv[i], "-");
unquote_str(cp_orig, mf_argv[i]+1);
} else {
mf_argv[i] = getmem(2 + strlen(cp_orig));
unquote_str(cp_orig, mf_argv[i]);
}
*cp = tmp_char;
}
}
mf_argv[i] = NULL;
}
static int
parse_command_option(char ch)
{
static int invert_next = 0;
int invert_this = invert_next;
invert_next = 0;
switch (ch) {
case '-':
return 0;
case '~':
invert_next = 1;
return 0;
case 'B':
return 0;
case 'b':
return 0;
case 'c':
if (invert_this) {
dmake_rcfile_specified = false;
} else {
dmake_rcfile_specified = true;
}
return 2;
case 'C':
return 2048;
case 'D':
if (invert_this) {
read_trace_level--;
} else {
read_trace_level++;
}
return 0;
case 'd':
if (invert_this) {
debug_level--;
} else {
debug_level++;
}
return 0;
case 'e':
if (invert_this) {
env_wins = false;
} else {
env_wins = true;
}
return 0;
case 'f':
return 1;
case 'g':
if (invert_this) {
dmake_group_specified = false;
} else {
dmake_group_specified = true;
}
return 4;
case 'i':
if (invert_this) {
ignore_errors_all = false;
} else {
ignore_errors_all = true;
}
return 0;
case 'j':
if (invert_this) {
dmake_max_jobs_specified = false;
} else {
dmake_mode_type = parallel_mode;
no_parallel = false;
dmake_max_jobs_specified = true;
}
return 8;
case 'K':
return 256;
case 'k':
if (invert_this) {
continue_after_error = false;
} else {
continue_after_error = true;
continue_after_error_ever_seen = true;
}
return 0;
case 'M':
if (invert_this) {
pmake_machinesfile_specified = false;
} else {
pmake_machinesfile_specified = true;
dmake_mode_type = parallel_mode;
no_parallel = false;
}
return 16;
case 'm':
if (invert_this) {
dmake_mode_specified = false;
} else {
dmake_mode_specified = true;
}
return 32;
case 'x':
if (invert_this) {
dmake_add_mode_specified = false;
} else {
dmake_add_mode_specified = true;
}
return 1024;
case 'N':
if (invert_this) {
do_not_exec_rule = true;
} else {
do_not_exec_rule = false;
}
return 0;
case 'n':
if (invert_this) {
do_not_exec_rule = false;
} else {
do_not_exec_rule = true;
}
return 0;
case 'O':
return 0;
case 'o':
if (invert_this) {
dmake_odir_specified = false;
} else {
dmake_odir_specified = true;
}
return 512;
case 'P':
if (invert_this) {
report_dependencies_level--;
} else {
report_dependencies_level++;
}
return 0;
case 'p':
if (invert_this) {
trace_status = false;
do_not_exec_rule = false;
} else {
trace_status = true;
do_not_exec_rule = true;
}
return 0;
case 'q':
if (invert_this) {
quest = false;
} else {
quest = true;
}
return 0;
case 'R':
if (invert_this) {
pmake_cap_r_specified = false;
no_parallel = false;
} else {
pmake_cap_r_specified = true;
dmake_mode_type = serial_mode;
no_parallel = true;
}
return 0;
case 'r':
if (invert_this) {
ignore_default_mk = false;
} else {
ignore_default_mk = true;
}
return 0;
case 'S':
if (invert_this) {
continue_after_error = true;
} else {
continue_after_error = false;
stop_after_error_ever_seen = true;
}
return 0;
case 's':
if (invert_this) {
silent_all = false;
} else {
silent_all = true;
}
return 0;
case 'T':
if (invert_this) {
list_all_targets = false;
do_not_exec_rule = false;
} else {
list_all_targets = true;
do_not_exec_rule = true;
}
return 0;
case 't':
if (invert_this) {
touch = false;
} else {
touch = true;
}
return 0;
case 'u':
if (invert_this) {
build_unconditional = false;
} else {
build_unconditional = true;
}
return 0;
case 'V':
svr4 = true;
return 0;
case 'v':
if (invert_this) {
} else {
fprintf(stdout, "%s: %s\n", getprogname(), verstring);
exit_status = 0;
exit(0);
}
return 0;
case 'w':
if (invert_this) {
report_cwd = false;
} else {
report_cwd = true;
}
return 0;
#if 0
case 'X':
if (invert_this) {
filter_stderr = false;
} else {
filter_stderr = true;
}
return 0;
#endif
default:
break;
}
return 0;
}
static void
setup_for_projectdir(void)
{
static char path[MAXPATHLEN];
char cwdpath[MAXPATHLEN];
uid_t uid;
int done=0;
sccs_dir_path = getenv("PROJECTDIR");
if ((sccs_dir_path != NULL) &&
(sccs_dir_path[0] != (int) slash_char)) {
struct passwd *pwent;
{
uid = getuid();
pwent = getpwuid(uid);
if (pwent == NULL) {
fatal(gettext("Bogus USERID "));
}
if ((pwent = getpwnam(sccs_dir_path)) == NULL) {
}
else {
(void) sprintf(path, "%s/src", pwent->pw_dir);
if (access(path, F_OK) == 0) {
sccs_dir_path = path;
done = 1;
} else {
(void) sprintf(path, "%s/source", pwent->pw_dir);
if (access(path, F_OK) == 0) {
sccs_dir_path = path;
done = 1;
}
}
}
if (!done) {
if (getcwd(cwdpath, MAXPATHLEN - 1 )) {
(void) sprintf(path, "%s/%s", cwdpath,sccs_dir_path);
if (access(path, F_OK) == 0) {
sccs_dir_path = path;
done = 1;
} else {
fatal(gettext("Bogus PROJECTDIR '%s'"), sccs_dir_path);
}
}
}
}
}
}
char *
make_install_prefix(void)
{
int ret;
char origin[PATH_MAX];
char *dir;
if ((ret = readlink("/proc/self/path/a.out", origin,
PATH_MAX - 1)) < 0)
fatal("failed to read origin from /proc\n");
origin[ret] = '\0';
return strdup(dirname(origin));
}
static char *
add_to_env(const char *var, const char *value, const char *fallback)
{
const char *oldpath;
char *newpath;
oldpath = getenv(var);
if (oldpath == NULL) {
if (value != NULL) {
asprintf(&newpath, "%s=%s",
var, value);
} else {
asprintf(&newpath, "%s=%s",
var, fallback);
}
} else {
if (value != NULL) {
asprintf(&newpath, "%s=%s:%s",
var, oldpath, value);
} else {
asprintf(&newpath, "%s=%s:%s",
var, oldpath, fallback);
}
}
return (newpath);
}
static void
set_sgs_support()
{
int len;
char *newpath, *newpath64;
char *lib32, *lib64;
static char *prev_path, *prev_path64;
char *origin = make_install_prefix();
struct stat st;
asprintf(&lib32, "%s/%s/%s", origin, "../lib",
LD_SUPPORT_MAKE_LIB);
if (stat(lib32, &st) != 0) {
free(lib32);
asprintf(&lib32, "%s/%s/%s/%s", origin, "../../lib/",
LD_SUPPORT_MAKE_ARCH, LD_SUPPORT_MAKE_LIB);
if (stat(lib32, &st) != 0) {
free(lib32);
lib32 = NULL;
}
}
asprintf(&lib64, "%s/%s/64/%s", origin, "../lib",
LD_SUPPORT_MAKE_LIB);
if (stat(lib64, &st) != 0) {
free(lib64);
asprintf(&lib64, "%s/%s/%s/64/%s", origin, "../../lib/",
LD_SUPPORT_MAKE_ARCH, LD_SUPPORT_MAKE_LIB);
if (stat(lib64, &st) != 0) {
free(lib64);
lib64 = NULL;
}
}
newpath = add_to_env(LD_SUPPORT_ENV_VAR_32, lib32, LD_SUPPORT_MAKE_LIB);
newpath64 = add_to_env(LD_SUPPORT_ENV_VAR_64, lib64, LD_SUPPORT_MAKE_LIB);
putenv(newpath);
if (prev_path) {
free(prev_path);
}
prev_path = newpath;
putenv(newpath64);
if (prev_path64) {
free(prev_path64);
}
prev_path64 = newpath64;
free(lib32);
free(lib64);
free(origin);
}
static void
read_files_and_state(int argc, char **argv)
{
wchar_t buffer[1000];
wchar_t buffer_posix[1000];
char ch;
char *cp;
Property def_make_macro = NULL;
Name def_make_name;
Name default_makefile;
String_rec dest;
wchar_t destbuffer[STRING_BUFFER_LENGTH];
int i;
int j;
Name keep_state_name;
int length;
Name Makefile;
Property macro;
struct stat make_state_stat;
Name makefile_name;
int makefile_next = 0;
Boolean makefile_read = false;
String_rec makeflags_string;
String_rec makeflags_string_posix;
String_rec * makeflags_string_current;
Name makeflags_value_saved;
Name name;
Name new_make_value;
Boolean save_do_not_exec_rule;
static wchar_t state_file_str;
static char state_file_str_mb[MAXPATHLEN];
static struct _Name state_filename;
Boolean temp;
char tmp_char;
wchar_t *tmp_wcs_buffer;
Name value;
ASCII_Dyn_Array makeflags_and_macro;
Boolean is_xpg4;
is_xpg4 = posix;
MBSTOWCS(wcs_buffer, "KEEP_STATE");
keep_state_name = GETNAME(wcs_buffer, FIND_LENGTH);
MBSTOWCS(wcs_buffer, "Makefile");
Makefile = GETNAME(wcs_buffer, FIND_LENGTH);
MBSTOWCS(wcs_buffer, "makefile");
makefile_name = GETNAME(wcs_buffer, FIND_LENGTH);
not_auto_depen->next = NULL;
not_auto_depen->name = not_auto;
not_auto_depen->automatic = not_auto_depen->stale = false;
if (read_trace_level > 1) {
trace_reader = true;
}
if (!ignore_default_mk) {
if (svr4) {
MBSTOWCS(wcs_buffer, "svr4.make.rules");
default_makefile = GETNAME(wcs_buffer, FIND_LENGTH);
} else {
MBSTOWCS(wcs_buffer, "make.rules");
default_makefile = GETNAME(wcs_buffer, FIND_LENGTH);
}
default_makefile->stat.is_file = true;
(void) read_makefile(default_makefile,
true,
false,
true);
}
MBSTOWCS(wcs_buffer, "MAKE");
def_make_name = GETNAME(wcs_buffer, wcslen(wcs_buffer));
def_make_macro = get_prop(def_make_name->prop, macro_prop);
if ((def_make_macro != NULL) &&
(IS_EQUAL(def_make_macro->body.macro.value->string_mb,
"make"))) {
MBSTOWCS(wcs_buffer, argv_zero_string);
new_make_value = GETNAME(wcs_buffer, wcslen(wcs_buffer));
(void) SETVAR(def_make_name,
new_make_value,
false);
}
default_target_to_build = NULL;
trace_reader = false;
read_environment(env_wins);
if (getvar(virtual_root)->hash.length == 0) {
maybe_append_prop(virtual_root, macro_prop)
->body.macro.exported = true;
MBSTOWCS(wcs_buffer, "/");
(void) SETVAR(virtual_root,
GETNAME(wcs_buffer, FIND_LENGTH),
false);
}
makeflags_and_macro.start = 0;
makeflags_and_macro.size = 0;
enter_argv_values(mf_argc, mf_argv, &makeflags_and_macro);
enter_argv_values(argc, argv, &makeflags_and_macro);
INIT_STRING_FROM_STACK(makeflags_string, buffer);
INIT_STRING_FROM_STACK(makeflags_string_posix, buffer_posix);
append_char((int) hyphen_char, &makeflags_string);
append_char((int) hyphen_char, &makeflags_string_posix);
switch (read_trace_level) {
case 2:
append_char('D', &makeflags_string);
append_char('D', &makeflags_string_posix);
case 1:
append_char('D', &makeflags_string);
append_char('D', &makeflags_string_posix);
}
switch (debug_level) {
case 2:
append_char('d', &makeflags_string);
append_char('d', &makeflags_string_posix);
case 1:
append_char('d', &makeflags_string);
append_char('d', &makeflags_string_posix);
}
if (env_wins) {
append_char('e', &makeflags_string);
append_char('e', &makeflags_string_posix);
}
if (ignore_errors_all) {
append_char('i', &makeflags_string);
append_char('i', &makeflags_string_posix);
}
if (continue_after_error) {
if (stop_after_error_ever_seen) {
append_char('S', &makeflags_string_posix);
append_char((int) space_char, &makeflags_string_posix);
append_char((int) hyphen_char, &makeflags_string_posix);
}
append_char('k', &makeflags_string);
append_char('k', &makeflags_string_posix);
} else {
if (stop_after_error_ever_seen
&& continue_after_error_ever_seen) {
append_char('k', &makeflags_string_posix);
append_char((int) space_char, &makeflags_string_posix);
append_char((int) hyphen_char, &makeflags_string_posix);
append_char('S', &makeflags_string_posix);
}
}
if (do_not_exec_rule) {
append_char('n', &makeflags_string);
append_char('n', &makeflags_string_posix);
}
switch (report_dependencies_level) {
case 4:
append_char('P', &makeflags_string);
append_char('P', &makeflags_string_posix);
case 3:
append_char('P', &makeflags_string);
append_char('P', &makeflags_string_posix);
case 2:
append_char('P', &makeflags_string);
append_char('P', &makeflags_string_posix);
case 1:
append_char('P', &makeflags_string);
append_char('P', &makeflags_string_posix);
}
if (trace_status) {
append_char('p', &makeflags_string);
append_char('p', &makeflags_string_posix);
}
if (quest) {
append_char('q', &makeflags_string);
append_char('q', &makeflags_string_posix);
}
if (silent_all) {
append_char('s', &makeflags_string);
append_char('s', &makeflags_string_posix);
}
if (touch) {
append_char('t', &makeflags_string);
append_char('t', &makeflags_string_posix);
}
if (build_unconditional) {
append_char('u', &makeflags_string);
append_char('u', &makeflags_string_posix);
}
if (report_cwd) {
append_char('w', &makeflags_string);
append_char('w', &makeflags_string_posix);
}
if (dmake_rcfile_specified) {
MBSTOWCS(wcs_buffer, "DMAKE_RCFILE");
dmake_rcfile = GETNAME(wcs_buffer, FIND_LENGTH);
append_makeflags_string(dmake_rcfile, &makeflags_string);
append_makeflags_string(dmake_rcfile, &makeflags_string_posix);
}
if (dmake_group_specified) {
MBSTOWCS(wcs_buffer, "DMAKE_GROUP");
dmake_group = GETNAME(wcs_buffer, FIND_LENGTH);
append_makeflags_string(dmake_group, &makeflags_string);
append_makeflags_string(dmake_group, &makeflags_string_posix);
}
if (dmake_max_jobs_specified) {
MBSTOWCS(wcs_buffer, "DMAKE_MAX_JOBS");
dmake_max_jobs = GETNAME(wcs_buffer, FIND_LENGTH);
append_makeflags_string(dmake_max_jobs, &makeflags_string);
append_makeflags_string(dmake_max_jobs, &makeflags_string_posix);
}
if (dmake_mode_specified) {
MBSTOWCS(wcs_buffer, "DMAKE_MODE");
dmake_mode = GETNAME(wcs_buffer, FIND_LENGTH);
append_makeflags_string(dmake_mode, &makeflags_string);
append_makeflags_string(dmake_mode, &makeflags_string_posix);
}
if (dmake_output_mode_specified) {
MBSTOWCS(wcs_buffer, "DMAKE_OUTPUT_MODE");
dmake_output_mode = GETNAME(wcs_buffer, FIND_LENGTH);
append_makeflags_string(dmake_output_mode, &makeflags_string);
append_makeflags_string(dmake_output_mode, &makeflags_string_posix);
}
if (dmake_odir_specified) {
MBSTOWCS(wcs_buffer, "DMAKE_ODIR");
dmake_odir = GETNAME(wcs_buffer, FIND_LENGTH);
append_makeflags_string(dmake_odir, &makeflags_string);
append_makeflags_string(dmake_odir, &makeflags_string_posix);
}
if (pmake_machinesfile_specified) {
MBSTOWCS(wcs_buffer, "PMAKE_MACHINESFILE");
pmake_machinesfile = GETNAME(wcs_buffer, FIND_LENGTH);
append_makeflags_string(pmake_machinesfile, &makeflags_string);
append_makeflags_string(pmake_machinesfile, &makeflags_string_posix);
}
if (pmake_cap_r_specified) {
append_char((int) space_char, &makeflags_string);
append_char((int) hyphen_char, &makeflags_string);
append_char('R', &makeflags_string);
append_char((int) space_char, &makeflags_string_posix);
append_char((int) hyphen_char, &makeflags_string_posix);
append_char('R', &makeflags_string_posix);
}
maybe_append_prop(makeflags, macro_prop)->
body.macro.exported = true;
if (makeflags_string.buffer.start[1] != (int) nul_char) {
if (makeflags_string.buffer.start[1] != (int) space_char) {
MBSTOWCS(wcs_buffer, "MFLAGS");
(void) SETVAR(GETNAME(wcs_buffer, FIND_LENGTH),
GETNAME(makeflags_string.buffer.start,
FIND_LENGTH),
false);
} else {
MBSTOWCS(wcs_buffer, "MFLAGS");
(void) SETVAR(GETNAME(wcs_buffer, FIND_LENGTH),
GETNAME(makeflags_string.buffer.start + 2,
FIND_LENGTH),
false);
}
}
if (makeflags_and_macro.start) {
tmp_char = (char) space_char;
cp = makeflags_and_macro.start;
do {
append_char(tmp_char, &makeflags_string_posix);
} while ( tmp_char = *cp++ );
retmem_mb(makeflags_and_macro.start);
}
macro = maybe_append_prop(makeflags, macro_prop);
temp = (Boolean) macro->body.macro.read_only;
macro->body.macro.read_only = false;
if(posix || gnu_style) {
makeflags_string_current = &makeflags_string_posix;
} else {
makeflags_string_current = &makeflags_string;
}
if (makeflags_string_current->buffer.start[1] == (int) nul_char) {
makeflags_value_saved =
GETNAME( makeflags_string_current->buffer.start + 1
, FIND_LENGTH
);
} else {
if (makeflags_string_current->buffer.start[1] != (int) space_char) {
makeflags_value_saved =
GETNAME( makeflags_string_current->buffer.start
, FIND_LENGTH
);
} else {
makeflags_value_saved =
GETNAME( makeflags_string_current->buffer.start + 2
, FIND_LENGTH
);
}
}
(void) SETVAR( makeflags
, makeflags_value_saved
, false
);
macro->body.macro.read_only = temp;
save_do_not_exec_rule = do_not_exec_rule;
do_not_exec_rule = false;
if (read_trace_level > 0) {
trace_reader = true;
}
for (i = 1; i < argc; i++) {
if (argv[i] &&
(argv[i][0] == (int) hyphen_char) &&
(argv[i][1] == 'f') &&
(argv[i][2] == (int) nul_char)) {
argv[i] = NULL;
if (i >= argc - 1) {
fatal(gettext("No filename argument after -f flag"));
}
MBSTOWCS(wcs_buffer, argv[++i]);
primary_makefile = GETNAME(wcs_buffer, FIND_LENGTH);
(void) read_makefile(primary_makefile, true, true, true);
argv[i] = NULL;
makefile_read = true;
} else if (argv[i] &&
(argv[i][0] == (int) hyphen_char) &&
(argv[i][1] == 'c' ||
argv[i][1] == 'g' ||
argv[i][1] == 'j' ||
argv[i][1] == 'K' ||
argv[i][1] == 'M' ||
argv[i][1] == 'm' ||
argv[i][1] == 'O' ||
argv[i][1] == 'o') &&
(argv[i][2] == (int) nul_char)) {
argv[i] = NULL;
argv[++i] = NULL;
}
}
if (!makefile_read) {
(void) read_dir(dot,
(wchar_t *) NULL,
(Property) NULL,
(wchar_t *) NULL);
if (!posix) {
if (makefile_name->stat.is_file) {
if (Makefile->stat.is_file) {
warning(gettext("Both `makefile' and `Makefile' exist"));
}
primary_makefile = makefile_name;
makefile_read = read_makefile(makefile_name,
false,
false,
true);
}
if (!makefile_read &&
Makefile->stat.is_file) {
primary_makefile = Makefile;
makefile_read = read_makefile(Makefile,
false,
false,
true);
}
} else {
enum sccs_stat save_m_has_sccs = NO_SCCS;
enum sccs_stat save_M_has_sccs = NO_SCCS;
if (makefile_name->stat.is_file) {
if (Makefile->stat.is_file) {
warning(gettext("Both `makefile' and `Makefile' exist"));
}
}
if (makefile_name->stat.is_file) {
if (makefile_name->stat.has_sccs == NO_SCCS) {
primary_makefile = makefile_name;
makefile_read = read_makefile(makefile_name,
false,
false,
true);
} else {
save_m_has_sccs = makefile_name->stat.has_sccs;
makefile_name->stat.has_sccs = NO_SCCS;
primary_makefile = makefile_name;
makefile_read = read_makefile(makefile_name,
false,
false,
true);
}
}
if (!makefile_read &&
Makefile->stat.is_file) {
if (Makefile->stat.has_sccs == NO_SCCS) {
primary_makefile = Makefile;
makefile_read = read_makefile(Makefile,
false,
false,
true);
} else {
save_M_has_sccs = Makefile->stat.has_sccs;
Makefile->stat.has_sccs = NO_SCCS;
primary_makefile = Makefile;
makefile_read = read_makefile(Makefile,
false,
false,
true);
}
}
if (!makefile_read &&
makefile_name->stat.is_file) {
makefile_name->stat.has_sccs = save_m_has_sccs;
primary_makefile = makefile_name;
makefile_read = read_makefile(makefile_name,
false,
false,
true);
}
if (!makefile_read &&
Makefile->stat.is_file) {
Makefile->stat.has_sccs = save_M_has_sccs;
primary_makefile = Makefile;
makefile_read = read_makefile(Makefile,
false,
false,
true);
}
}
}
do_not_exec_rule = save_do_not_exec_rule;
allrules_read = makefile_read;
trace_reader = false;
Name mf_val = getvar(makeflags);
if( (posix != is_xpg4)
&& (!strcmp(mf_val->string_mb, makeflags_value_saved->string_mb)))
{
if (makeflags_string_posix.buffer.start[1] == (int) nul_char) {
(void) SETVAR(makeflags,
GETNAME(makeflags_string_posix.buffer.start + 1,
FIND_LENGTH),
false);
} else {
if (makeflags_string_posix.buffer.start[1] != (int) space_char) {
(void) SETVAR(makeflags,
GETNAME(makeflags_string_posix.buffer.start,
FIND_LENGTH),
false);
} else {
(void) SETVAR(makeflags,
GETNAME(makeflags_string_posix.buffer.start + 2,
FIND_LENGTH),
false);
}
}
}
if (makeflags_string.free_after_use) {
retmem(makeflags_string.buffer.start);
}
if (makeflags_string_posix.free_after_use) {
retmem(makeflags_string_posix.buffer.start);
}
makeflags_string.buffer.start = NULL;
makeflags_string_posix.buffer.start = NULL;
if (posix) {
MBSTOWCS(wcs_buffer, "ARFLAGS");
name = GETNAME(wcs_buffer, wcslen(wcs_buffer));
macro = get_prop(name->prop, macro_prop);
if ((macro != NULL) &&
(IS_EQUAL(macro->body.macro.value->string_mb,
"rv"))) {
MBSTOWCS(wcs_buffer, "-rv");
value = GETNAME(wcs_buffer, wcslen(wcs_buffer));
(void) SETVAR(name,
value,
false);
}
}
if (!posix && !svr4) {
set_sgs_support();
}
macro = get_prop(keep_state_name->prop, macro_prop);
if ((macro != NULL) &&
macro->body.macro.exported) {
keep_state = true;
}
if (keep_state) {
if (macro == NULL) {
macro = maybe_append_prop(keep_state_name,
macro_prop);
}
macro->body.macro.exported = true;
(void) SETVAR(keep_state_name,
empty_name,
false);
INIT_STRING_FROM_STACK(dest, destbuffer);
expand_value(make_state, &dest, false);
make_state = GETNAME(dest.buffer.start, FIND_LENGTH);
if(!stat(make_state->string_mb, &make_state_stat)) {
if(!(make_state_stat.st_mode & S_IFREG) ) {
memcpy(&state_filename, make_state,sizeof(state_filename));
state_filename.string_mb = state_file_str_mb;
if((make_state->hash.length == 1)&&
(make_state->string_mb[0] == '/')) {
make_state->hash.length = 0;
make_state->string_mb[0] = '\0';
}
sprintf(state_file_str_mb,"%s%s",
make_state->string_mb,"/.make.state");
make_state = &state_filename;
make_state->hash.length += 12;
}
} else {
char tmp_path[MAXPATHLEN];
char *slashp;
if (slashp = strrchr(make_state->string_mb, '/')) {
strncpy(tmp_path, make_state->string_mb,
(slashp - make_state->string_mb));
tmp_path[slashp - make_state->string_mb]=0;
if(strlen(tmp_path)) {
if(stat(tmp_path, &make_state_stat)) {
warning(gettext("directory %s for .KEEP_STATE_FILE does not exist"),tmp_path);
}
if (access(tmp_path, F_OK) != 0) {
warning(gettext("can't access dir %s"),tmp_path);
}
}
}
}
if (report_dependencies_level != 1) {
Makefile_type makefile_type_temp = makefile_type;
makefile_type = reading_statefile;
if (read_trace_level > 1) {
trace_reader = true;
}
(void) read_simple_file(make_state,
false,
false,
false,
false,
false,
true);
trace_reader = false;
makefile_type = makefile_type_temp;
}
}
}
static void
enter_argv_values(int argc, char *argv[], ASCII_Dyn_Array *makeflags_and_macro)
{
char *cp;
int i;
int length;
Name name;
int opt_separator = argc;
char tmp_char;
wchar_t *tmp_wcs_buffer;
Name value;
Boolean append = false;
Property macro;
struct stat statbuf;
makefile_type = reading_nothing;
for (i = 1; i < argc; ++i) {
append = false;
if (argv[i] == NULL) {
continue;
} else if (((argv[i][0] == '-') && (argv[i][1] == '-')) ||
((argv[i][0] == (int) ' ') &&
(argv[i][1] == (int) '-') &&
(argv[i][2] == (int) ' ') &&
(argv[i][3] == (int) '-'))) {
argv[i] = NULL;
opt_separator = i;
continue;
} else if ((i < opt_separator) && (argv[i][0] == (int) hyphen_char)) {
switch (parse_command_option(argv[i][1])) {
case 1:
++i;
continue;
case 2:
if (argv[i+1] == NULL) {
fatal(gettext("No dmake rcfile argument after -c flag"));
}
MBSTOWCS(wcs_buffer, "DMAKE_RCFILE");
name = GETNAME(wcs_buffer, FIND_LENGTH);
break;
case 4:
if (argv[i+1] == NULL) {
fatal(gettext("No dmake group argument after -g flag"));
}
MBSTOWCS(wcs_buffer, "DMAKE_GROUP");
name = GETNAME(wcs_buffer, FIND_LENGTH);
break;
case 8:
if (argv[i+1] == NULL) {
fatal(gettext("No dmake max jobs argument after -j flag"));
}
MBSTOWCS(wcs_buffer, "DMAKE_MAX_JOBS");
name = GETNAME(wcs_buffer, FIND_LENGTH);
break;
case 16:
if (argv[i+1] == NULL) {
fatal(gettext("No pmake machinesfile argument after -M flag"));
}
MBSTOWCS(wcs_buffer, "PMAKE_MACHINESFILE");
name = GETNAME(wcs_buffer, FIND_LENGTH);
break;
case 32:
if (argv[i+1] == NULL) {
fatal(gettext("No dmake mode argument after -m flag"));
}
MBSTOWCS(wcs_buffer, "DMAKE_MODE");
name = GETNAME(wcs_buffer, FIND_LENGTH);
break;
case 256:
if (argv[i+1] == NULL) {
fatal(gettext("No makestate filename argument after -K flag"));
}
MBSTOWCS(wcs_buffer, argv[i+1]);
make_state = GETNAME(wcs_buffer, FIND_LENGTH);
keep_state = true;
argv[i] = NULL;
argv[i+1] = NULL;
continue;
case 512:
if (argv[i+1] == NULL) {
fatal(gettext("No dmake output dir argument after -o flag"));
}
MBSTOWCS(wcs_buffer, "DMAKE_ODIR");
name = GETNAME(wcs_buffer, FIND_LENGTH);
break;
case 1024:
if (argv[i+1] == NULL) {
fatal(gettext("No argument after -x flag"));
}
length = strlen( "SUN_MAKE_COMPAT_MODE=");
if (strncmp(argv[i+1], "SUN_MAKE_COMPAT_MODE=", length) == 0) {
argv[i+1] = &argv[i+1][length];
MBSTOWCS(wcs_buffer, "SUN_MAKE_COMPAT_MODE");
name = GETNAME(wcs_buffer, FIND_LENGTH);
dmake_compat_mode_specified = dmake_add_mode_specified;
break;
}
length = strlen( "DMAKE_OUTPUT_MODE=");
if (strncmp(argv[i+1], "DMAKE_OUTPUT_MODE=", length) == 0) {
argv[i+1] = &argv[i+1][length];
MBSTOWCS(wcs_buffer, "DMAKE_OUTPUT_MODE");
name = GETNAME(wcs_buffer, FIND_LENGTH);
dmake_output_mode_specified = dmake_add_mode_specified;
} else {
warning(gettext("Unknown argument `%s' after -x flag (ignored)"),
argv[i+1]);
argv[i] = argv[i + 1] = NULL;
continue;
}
break;
case 2048:
if (argv[i + 1] == NULL) {
fatal(gettext(
"No argument after -C flag"));
}
MBSTOWCS(wcs_buffer, "DMAKE_CDIR");
name = GETNAME(wcs_buffer, FIND_LENGTH);
break;
default:
argv[i] = NULL;
continue;
}
argv[i] = NULL;
if (i == (argc - 1)) {
break;
}
if ((length = strlen(argv[i+1])) >= MAXPATHLEN) {
tmp_wcs_buffer = ALLOC_WC(length + 1);
(void) mbstowcs(tmp_wcs_buffer, argv[i+1], length + 1);
value = GETNAME(tmp_wcs_buffer, FIND_LENGTH);
retmem(tmp_wcs_buffer);
} else {
MBSTOWCS(wcs_buffer, argv[i+1]);
value = GETNAME(wcs_buffer, FIND_LENGTH);
}
argv[i+1] = NULL;
} else if ((cp = strchr(argv[i], (int) equal_char)) != NULL) {
if(*(cp-1) == (int) plus_char)
{
if(isspace(*(cp-2))) {
append = true;
cp--;
}
}
if(!append)
append_or_replace_macro_in_dyn_array(makeflags_and_macro, argv[i]);
while (isspace(*(cp-1))) {
cp--;
}
tmp_char = *cp;
*cp = (int) nul_char;
MBSTOWCS(wcs_buffer, argv[i]);
*cp = tmp_char;
name = GETNAME(wcs_buffer, wcslen(wcs_buffer));
while (*cp != (int) equal_char) {
cp++;
}
cp++;
while (isspace(*cp) && (*cp != (int) nul_char)) {
cp++;
}
if ((length = strlen(cp)) >= MAXPATHLEN) {
tmp_wcs_buffer = ALLOC_WC(length + 1);
(void) mbstowcs(tmp_wcs_buffer, cp, length + 1);
value = GETNAME(tmp_wcs_buffer, FIND_LENGTH);
retmem(tmp_wcs_buffer);
} else {
MBSTOWCS(wcs_buffer, cp);
value = GETNAME(wcs_buffer, FIND_LENGTH);
}
argv[i] = NULL;
} else {
continue;
}
if(append) {
setvar_append(name, value);
append = false;
} else {
macro = maybe_append_prop(name, macro_prop);
macro->body.macro.exported = true;
SETVAR(name, value, false)->body.macro.read_only = true;
}
}
}
static void
append_makeflags_string(Name name, String makeflags_string)
{
const char *option;
if (strcmp(name->string_mb, "DMAKE_GROUP") == 0) {
option = " -g ";
} else if (strcmp(name->string_mb, "DMAKE_MAX_JOBS") == 0) {
option = " -j ";
} else if (strcmp(name->string_mb, "DMAKE_MODE") == 0) {
option = " -m ";
} else if (strcmp(name->string_mb, "DMAKE_ODIR") == 0) {
option = " -o ";
} else if (strcmp(name->string_mb, "DMAKE_RCFILE") == 0) {
option = " -c ";
} else if (strcmp(name->string_mb, "PMAKE_MACHINESFILE") == 0) {
option = " -M ";
} else if (strcmp(name->string_mb, "DMAKE_OUTPUT_MODE") == 0) {
option = " -x DMAKE_OUTPUT_MODE=";
} else if (strcmp(name->string_mb, "SUN_MAKE_COMPAT_MODE") == 0) {
option = " -x SUN_MAKE_COMPAT_MODE=";
} else {
fatal(gettext("Internal error: name not recognized in append_makeflags_string()"));
}
Property prop = maybe_append_prop(name, macro_prop);
if( prop == 0 || prop->body.macro.value == 0 ||
prop->body.macro.value->string_mb == 0 ) {
return;
}
char mbs_value[MAXPATHLEN + 100];
strcpy(mbs_value, option);
strcat(mbs_value, prop->body.macro.value->string_mb);
MBSTOWCS(wcs_buffer, mbs_value);
append_string(wcs_buffer, makeflags_string, FIND_LENGTH);
}
static void
read_environment(Boolean read_only)
{
char **environment;
int length;
wchar_t *tmp_wcs_buffer;
Boolean alloced_tmp_wcs_buffer = false;
wchar_t *name;
wchar_t *value;
Name macro;
Property val;
Boolean read_only_saved;
reading_environment = true;
environment = environ;
for (; *environment; environment++) {
read_only_saved = read_only;
if ((length = strlen(*environment)) >= MAXPATHLEN) {
tmp_wcs_buffer = ALLOC_WC(length + 1);
alloced_tmp_wcs_buffer = true;
(void) mbstowcs(tmp_wcs_buffer, *environment, length + 1);
name = tmp_wcs_buffer;
} else {
MBSTOWCS(wcs_buffer, *environment);
name = wcs_buffer;
}
value = (wchar_t *) wcschr(name, (int) equal_char);
if (!value) {
continue;
}
MBSTOWCS(wcs_buffer2, "SHELL=");
if (IS_WEQUALN(name, wcs_buffer2, wcslen(wcs_buffer2))) {
continue;
}
MBSTOWCS(wcs_buffer2, "MAKEFLAGS=");
if (IS_WEQUALN(name, wcs_buffer2, wcslen(wcs_buffer2))) {
report_pwd = true;
if(posix) {
read_only_saved = false;
}
}
MBSTOWCS(wcs_buffer2, "SUNPRO_DEPENDENCIES");
if (IS_WEQUALN(name, wcs_buffer2, wcslen(wcs_buffer2))) {
continue;
}
macro = GETNAME(name, value - name);
maybe_append_prop(macro, macro_prop)->body.macro.exported =
true;
if ((value == NULL) || ((value + 1)[0] == (int) nul_char)) {
val = setvar_daemon(macro,
(Name) NULL,
false, no_daemon, false, debug_level);
} else {
val = setvar_daemon(macro,
GETNAME(value + 1, FIND_LENGTH),
false, no_daemon, false, debug_level);
}
val->body.macro.read_only = read_only_saved;
if (alloced_tmp_wcs_buffer) {
retmem(tmp_wcs_buffer);
alloced_tmp_wcs_buffer = false;
}
}
reading_environment = false;
}
static Boolean
read_makefile(Name makefile, Boolean complain, Boolean must_exist, Boolean report_file)
{
Boolean b;
makefile_type = reading_makefile;
recursion_level = 0;
reading_dependencies = true;
b = read_simple_file(makefile, true, true, complain,
must_exist, report_file, false);
reading_dependencies = false;
return b;
}
static void
make_targets(int argc, char **argv, Boolean parallel_flag)
{
int i;
char *cp;
Doname result;
Boolean target_to_make_found = false;
(void) doname(init, true, true);
recursion_level = 1;
parallel = parallel_flag;
if (parallel) {
for (i = 1; i < argc; i++) {
if ((cp = argv[i]) != NULL) {
commands_done = false;
if ((cp[0] == (int) period_char) &&
(cp[1] == (int) slash_char)) {
cp += 2;
}
if((cp[0] == (int) ' ') &&
(cp[1] == (int) '-') &&
(cp[2] == (int) ' ') &&
(cp[3] == (int) '-')) {
argv[i] = NULL;
continue;
}
MBSTOWCS(wcs_buffer, cp);
default_target_to_build = normalize_name(wcs_buffer,
wcslen(wcs_buffer));
if (default_target_to_build == wait_name) {
if (parallel_process_cnt > 0) {
finish_running();
}
continue;
}
top_level_target = get_wstring(default_target_to_build->string_mb);
if (!parallel_ok(default_target_to_build, false)
&& parallel_process_cnt > 0) {
finish_running();
}
result = doname_check(default_target_to_build,
true,
false,
false);
gather_recursive_deps();
if (
(result == build_ok) &&
!quest &&
(report_dependencies_level == 0)
) {
if (posix) {
if (!commands_done) {
(void) printf(gettext("`%s' is updated.\n"),
default_target_to_build->string_mb);
} else {
if (no_action_was_taken) {
(void) printf(gettext("`%s': no action was taken.\n"),
default_target_to_build->string_mb);
}
}
} else {
default_target_to_build->stat.time = file_no_time;
if (!commands_done &&
(exists(default_target_to_build) > file_doesnt_exist)) {
(void) printf(gettext("`%s' is up to date.\n"),
default_target_to_build->string_mb);
}
}
}
}
}
finish_running();
}
for (i = 1; i < argc; i++) {
if ((cp = argv[i]) != NULL) {
target_to_make_found = true;
if ((cp[0] == (int) period_char) &&
(cp[1] == (int) slash_char)) {
cp += 2;
}
if((cp[0] == (int) ' ') &&
(cp[1] == (int) '-') &&
(cp[2] == (int) ' ') &&
(cp[3] == (int) '-')) {
argv[i] = NULL;
continue;
}
MBSTOWCS(wcs_buffer, cp);
default_target_to_build = normalize_name(wcs_buffer, wcslen(wcs_buffer));
top_level_target = get_wstring(default_target_to_build->string_mb);
report_recursion(default_target_to_build);
commands_done = false;
if (parallel) {
result = (Doname) default_target_to_build->state;
} else {
result = doname_check(default_target_to_build,
true,
false,
false);
}
gather_recursive_deps();
if (build_failed_seen) {
build_failed_ever_seen = true;
warning(gettext("Target `%s' not remade because of errors"),
default_target_to_build->string_mb);
}
build_failed_seen = false;
if (report_dependencies_level > 0) {
print_dependencies(default_target_to_build,
get_prop(default_target_to_build->prop,
line_prop));
}
default_target_to_build->stat.time =
file_no_time;
if (default_target_to_build->colon_splits > 0) {
default_target_to_build->state =
build_dont_know;
}
if (!parallel &&
(result == build_ok) &&
!quest &&
(report_dependencies_level == 0)
) {
if (posix) {
if (!commands_done) {
(void) printf(gettext("`%s' is updated.\n"),
default_target_to_build->string_mb);
} else {
if (no_action_was_taken) {
(void) printf(gettext("`%s': no action was taken.\n"),
default_target_to_build->string_mb);
}
}
} else {
if (!commands_done &&
(exists(default_target_to_build) > file_doesnt_exist)) {
(void) printf(gettext("`%s' is up to date.\n"),
default_target_to_build->string_mb);
}
}
}
}
}
if (!target_to_make_found) {
if (default_target_to_build == NULL) {
fatal(gettext("No arguments to build"));
}
commands_done = false;
top_level_target = get_wstring(default_target_to_build->string_mb);
report_recursion(default_target_to_build);
if (getenv("SPRO_EXPAND_ERRORS")){
(void) printf("::(%s)\n",
default_target_to_build->string_mb);
}
result = doname_parallel(default_target_to_build, true, false);
gather_recursive_deps();
if (build_failed_seen) {
build_failed_ever_seen = true;
warning(gettext("Target `%s' not remade because of errors"),
default_target_to_build->string_mb);
}
build_failed_seen = false;
if (report_dependencies_level > 0) {
print_dependencies(default_target_to_build,
get_prop(default_target_to_build->
prop,
line_prop));
}
default_target_to_build->stat.time = file_no_time;
if (default_target_to_build->colon_splits > 0) {
default_target_to_build->state = build_dont_know;
}
if (
(result == build_ok) &&
!quest &&
(report_dependencies_level == 0)
) {
if (posix) {
if (!commands_done) {
(void) printf(gettext("`%s' is updated.\n"),
default_target_to_build->string_mb);
} else {
if (no_action_was_taken) {
(void) printf(gettext("`%s': no action was taken.\n"),
default_target_to_build->string_mb);
}
}
} else {
if (!commands_done &&
(exists(default_target_to_build) > file_doesnt_exist)) {
(void) printf(gettext("`%s' is up to date.\n"),
default_target_to_build->string_mb);
}
}
}
}
}
static void
report_recursion(Name target)
{
FILE *report_file = get_report_file();
if ((report_file == NULL) || (report_file == (FILE*)-1)) {
return;
}
if (primary_makefile == NULL) {
return;
}
(void) fprintf(report_file,
"%s: %s ",
get_target_being_reported_for(),
recursive_name->string_mb);
report_dependency(get_current_path());
report_dependency(target->string_mb);
report_dependency(primary_makefile->string_mb);
(void) fprintf(report_file, "\n");
}
extern void
append_or_replace_macro_in_dyn_array(ASCII_Dyn_Array *Ar, char *macro)
{
char *cp0;
char *cp1;
char *cp2;
char *cp3;
char *name;
char *value;
int len_array;
int len_macro;
char * esc_value = NULL;
int esc_len;
if (!(len_macro = strlen(macro))) return;
name = macro;
while (isspace(*(name))) {
name++;
}
if (!(value = strchr(name, (int) equal_char))) {
goto ERROR_MACRO;
}
cp0 = value;
value++;
while (isspace(*(value))) {
value++;
}
while (isspace(*(cp0-1))) {
cp0--;
}
if (cp0 <= name) goto ERROR_MACRO;
if (!(Ar->size)) goto ALLOC_ARRAY;
cp1 = Ar->start;
LOOK_FOR_NAME:
if (!(cp1 = strchr(cp1, name[0]))) goto APPEND_MACRO;
if (!(cp2 = strchr(cp1, (int) equal_char))) goto APPEND_MACRO;
if (strncmp(cp1, name, (size_t)(cp0-name))) {
cp1++;
goto LOOK_FOR_NAME;
}
if (cp1 != Ar->start) {
if (!isspace(*(cp1-1))) {
cp1++;
goto LOOK_FOR_NAME;
}
}
for (cp3 = cp1 + (cp0-name); cp3 < cp2; cp3++) {
if (isspace(*cp3)) continue;
cp1++;
goto LOOK_FOR_NAME;
}
cp3 = cp2+1;
if (*cp3 != (int) doublequote_char) {
goto ERROR_MACRO;
}
if (!(cp3 = strchr(cp3+1, (int) doublequote_char))) {
goto ERROR_MACRO;
}
cp3++;
while (isspace(*cp3)) {
cp3++;
}
cp2 = cp1;
if ((*cp3) && (cp3 < Ar->start + Ar->size)) {
for (; cp3 < Ar->start + Ar->size; cp3++) {
*cp2++ = *cp3;
}
}
for (; cp2 < Ar->start + Ar->size; cp2++) {
*cp2 = 0;
}
if (*cp1) {
goto LOOK_FOR_NAME;
}
goto APPEND_MACRO;
ALLOC_ARRAY:
if (Ar->size) {
cp1 = Ar->start;
} else {
cp1 = 0;
}
Ar->size += 128;
Ar->start = getmem(Ar->size);
for (len_array=0; len_array < Ar->size; len_array++) {
Ar->start[len_array] = 0;
}
if (cp1) {
strcpy(Ar->start, cp1);
retmem((wchar_t *) cp1);
}
APPEND_MACRO:
len_array = strlen(Ar->start);
esc_value = (char*)malloc(strlen(value)*2 + 1);
quote_str(value, esc_value);
esc_len = strlen(esc_value) - strlen(value);
if (len_array + len_macro + esc_len + 5 >= Ar->size) goto ALLOC_ARRAY;
strcat(Ar->start, " ");
strncat(Ar->start, name, cp0-name);
strcat(Ar->start, "=");
strncat(Ar->start, esc_value, strlen(esc_value));
free(esc_value);
return;
ERROR_MACRO:
return;
}
static void
report_dir_enter_leave(Boolean entering)
{
char rcwd[MAXPATHLEN];
static char * mlev = NULL;
char * make_level_str = NULL;
int make_level_val = 0;
make_level_str = getenv("MAKELEVEL");
if(make_level_str) {
make_level_val = atoi(make_level_str);
}
if(mlev == NULL) {
mlev = (char*) malloc(MAXPATHLEN);
}
if(entering) {
sprintf(mlev, "MAKELEVEL=%d", make_level_val + 1);
} else {
make_level_val--;
sprintf(mlev, "MAKELEVEL=%d", make_level_val);
}
putenv(mlev);
if(report_cwd) {
if(make_level_val <= 0) {
if(entering) {
sprintf(rcwd,
gettext("%s: Entering directory `%s'\n"),
getprogname(),
get_current_path());
} else {
sprintf(rcwd,
gettext("%s: Leaving directory `%s'\n"),
getprogname(),
get_current_path());
}
} else {
if(entering) {
sprintf(rcwd,
gettext("%s[%d]: Entering directory `%s'\n"),
getprogname(),
make_level_val, get_current_path());
} else {
sprintf(rcwd,
gettext("%s[%d]: Leaving directory `%s'\n"),
getprogname(),
make_level_val, get_current_path());
}
}
printf("%s", rcwd);
}
}