/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * @(#)main.cc 1.158 06/12/12 */ #pragma ident "@(#)main.cc 1.158 06/12/12" /* * main.cc * * make program main routine plus some helper routines */ /* * Included files */ #if defined(TEAMWARE_MAKE_CMN) # include # include /* libcli_init() */ # include /* avo_cli_get_license() */ # include /* avo_find_run_dir() */ # include # include /* avo_init() */ #ifdef USE_DMS_CCR # include #else # include #endif #endif #if defined(TEAMWARE_MAKE_CMN) /* This is for dmake only (not for Solaris make). * Include code to check updates (dmake patches) */ #ifdef _CHECK_UPDATE_H #include #endif #endif #include /* bsd_signal() */ #ifdef DISTRIBUTED # include # include # include /* dmakerc file processing */ #endif #include /* setlocale() */ #include #include #include /* libmksdmsi18n_init() */ #include /* getvar() */ #include /* getmem(), setup_char_semantics() */ #if defined(TEAMWARE_MAKE_CMN) #ifdef USE_DMS_CCR # include /* libpubdmsi18n_init() */ #endif #endif #include /* getpwnam() */ #include #include #include #include /* ENOENT */ #include /* fstat() */ #include /* open() */ #ifdef SUN5_0 # include /* sysinfo() */ #endif #include /* stat() */ #include /* wait() */ #include /* execv(), unlink(), access() */ #include /* report_dependency(), get_report_file() */ // From read2.cc extern Name normalize_name(register wchar_t *name_string, register int length); // From parallel.cc #if defined(TEAMWARE_MAKE_CMN) #define MAXJOBS_ADJUST_RFE4694000 #ifdef MAXJOBS_ADJUST_RFE4694000 extern void job_adjust_fini(); #endif /* MAXJOBS_ADJUST_RFE4694000 */ #endif /* TEAMWARE_MAKE_CMN */ #if defined(linux) #include #endif /* * Defined macros */ #define LD_SUPPORT_ENV_VAR NOCATGETS("SGS_SUPPORT") #define LD_SUPPORT_MAKE_LIB NOCATGETS("libmakestate.so.1") /* * typedefs & structs */ /* * Static variables */ static char *argv_zero_string; static Boolean build_failed_ever_seen; static Boolean continue_after_error_ever_seen; /* `-k' */ static Boolean dmake_group_specified; /* `-g' */ static Boolean dmake_max_jobs_specified; /* `-j' */ static Boolean dmake_mode_specified; /* `-m' */ static Boolean dmake_add_mode_specified; /* `-x' */ static Boolean dmake_output_mode_specified; /* `-x DMAKE_OUTPUT_MODE=' */ static Boolean dmake_compat_mode_specified; /* `-x SUN_MAKE_COMPAT_MODE=' */ static Boolean dmake_odir_specified; /* `-o' */ static Boolean dmake_rcfile_specified; /* `-c' */ static Boolean env_wins; /* `-e' */ static Boolean ignore_default_mk; /* `-r' */ static Boolean list_all_targets; /* `-T' */ 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; /* `-R' */ static Boolean pmake_machinesfile_specified; /* `-M' */ static Boolean stop_after_error_ever_seen; /* `-S' */ static Boolean trace_status; /* `-p' */ #ifdef DMAKE_STATISTICS static Boolean getname_stat = false; #endif #if defined(TEAMWARE_MAKE_CMN) static time_t start_time; static int g_argc; static char **g_argv; #ifdef USE_DMS_CCR static Avo_usage_tracking *usageTracking = NULL; #else static Avo_cleanup *cleanup = NULL; #endif #endif /* * File table of contents */ #if defined(SUN5_0) || defined(HP_UX) || defined(linux) extern "C" void cleanup_after_exit(void); #else extern void cleanup_after_exit(int, ...); #endif #ifdef TEAMWARE_MAKE_CMN extern "C" { extern void dmake_exit_callback(void); extern void dmake_message_callback(char *); } #endif extern Name normalize_name(register wchar_t *name_string, register 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, register String , Boolean); #ifdef DISTRIBUTED extern int dmake_ofd; extern FILE* dmake_ofp; extern int rxmPid; extern XDR xdrs_out; #endif #ifdef TEAMWARE_MAKE_CMN extern char verstring[]; #endif jmp_buf jmpbuffer; #if !defined(linux) nl_catd catd; #endif /* * main(argc, argv) * * Parameters: * argc You know what this is * argv You know what this is * * Static variables used: * list_all_targets make -T seen * trace_status make -p seen * * Global variables used: * debug_level Should we trace make actions? * keep_state Set if .KEEP_STATE seen * makeflags The Name "MAKEFLAGS", used to get macro * remote_command_name Name of remote invocation cmd ("on") * running_list List of parallel running processes * stdout_stderr_same true if stdout and stderr are the same * auto_dependencies The Name "SUNPRO_DEPENDENCIES" * temp_file_directory Set to the dir where we create tmp file * trace_reader Set to reflect tracing status * working_on_targets Set when building user targets */ int main(int argc, char *argv[]) { /* * cp is a -> to the value of the MAKEFLAGS env var, * which has to be regular chars. */ register char *cp; char make_state_dir[MAXPATHLEN]; Boolean parallel_flag = false; char *prognameptr; char *slash_ptr; mode_t um; int i; #ifdef TEAMWARE_MAKE_CMN 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; #endif #ifndef PARALLEL struct stat out_stat, err_stat; #endif hostid = gethostid(); #ifdef TEAMWARE_MAKE_CMN avo_get_user(NULL, NULL); // Initialize user name #endif bsd_signals(); (void) setlocale(LC_ALL, ""); #if defined (HP_UX) || defined(linux) /* HP-UX users typically will not have NLSPATH set, and this binary * requires that it be set. On HP-UX 9.0x, /usr/lib/nls/%L/%N.cat is * the path to set it to. */ if (getenv(NOCATGETS("NLSPATH")) == NULL) { putenv(NOCATGETS("NLSPATH=/usr/lib/nls/%L/%N.cat")); } #endif #ifdef DMAKE_STATISTICS if (getenv(NOCATGETS("DMAKE_STATISTICS"))) { getname_stat = true; } #endif /* * avo_init() sets the umask to 0. Save it here and restore * it after the avo_init() call. */ #if defined(TEAMWARE_MAKE_CMN) || defined(MAKETOOL) um = umask(0); avo_init(argv[0]); umask(um); #ifdef USE_DMS_CCR usageTracking = new Avo_usage_tracking(NOCATGETS("dmake"), argc, argv); #else cleanup = new Avo_cleanup(NOCATGETS("dmake"), argc, argv); #endif #endif #if defined(TEAMWARE_MAKE_CMN) catd = catopen(AVO_DOMAIN_DMAKE, NL_CAT_LOCALE); libcli_init(); #ifdef _CHECK_UPDATE_H /* This is for dmake only (not for Solaris make). * Check (in background) if there is an update (dmake patch) * and inform user */ { Avo_err *err; char *dir; err = avo_find_run_dir(&dir); if (AVO_OK == err) { AU_check_update_service(NOCATGETS("Dmake"), dir); } } #endif /* _CHECK_UPDATE_H */ #endif // ---> fprintf(stderr, catgets(catd, 15, 666, "--- SUN make ---\n")); #if defined(TEAMWARE_MAKE_CMN) || defined(MAKETOOL) /* * I put libmksdmsi18n_init() under #ifdef because it requires avo_i18n_init() * from avo_util library. */ libmksdmsi18n_init(); #ifdef USE_DMS_CCR libpubdmsi18n_init(); #endif #endif #ifndef TEAMWARE_MAKE_CMN textdomain(NOCATGETS("SUNW_SPRO_MAKE")); #endif /* TEAMWARE_MAKE_CMN */ #ifdef TEAMWARE_MAKE_CMN 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; #endif /* TEAMWARE_MAKE_CMN */ /* * Set argv_zero_string to some form of argv[0] for * recursive MAKE builds. */ if (*argv[0] == (int) slash_char) { /* argv[0] starts with a slash */ argv_zero_string = strdup(argv[0]); } else if (strchr(argv[0], (int) slash_char) == NULL) { /* argv[0] contains no slashes */ argv_zero_string = strdup(argv[0]); } else { /* * argv[0] contains at least one slash, * but doesn't start with a slash */ 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); } /* * The following flags are reset if we don't have the * (.nse_depinfo or .make.state) files locked and only set * AFTER the file has been locked. This ensures that if the user * interrupts the program while file_lock() is waiting to lock * the file, the interrupt handler doesn't remove a lock * that doesn't belong to us. */ make_state_lockfile = NULL; make_state_locked = false; #ifdef NSE nse_depinfo_lockfile[0] = '\0'; nse_depinfo_locked = false; #endif /* * look for last slash char in the path to look at the binary * name. This is to resolve the hard link and invoke make * in svr4 mode. */ /* Sun OS make standart */ svr4 = false; posix = false; if(!strcmp(argv_zero_string, NOCATGETS("/usr/xpg4/bin/make"))) { svr4 = false; posix = true; } else { prognameptr = strrchr(argv[0], '/'); if(prognameptr) { prognameptr++; } else { prognameptr = argv[0]; } if(!strcmp(prognameptr, NOCATGETS("svr4.make"))) { svr4 = true; posix = false; } } #if !defined(HP_UX) && !defined(linux) if (getenv(USE_SVR4_MAKE) || getenv(NOCATGETS("USE_SVID"))){ svr4 = true; posix = false; } #endif /* * Find the dmake_compat_mode: posix, sun, svr4, or gnu_style, . */ char * dmake_compat_mode_var = getenv(NOCATGETS("SUN_MAKE_COMPAT_MODE")); if (dmake_compat_mode_var != NULL) { if (0 == strcasecmp(dmake_compat_mode_var, NOCATGETS("GNU"))) { gnu_style = true; } //svr4 = false; //posix = false; } /* * Temporary directory set up. */ char * tmpdir_var = getenv(NOCATGETS("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) { /* 32 = strlen("/dmake.stdout.%d.%d.XXXXXX") */ sprintf(mbs_buffer2, NOCATGETS("%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); } } } #ifndef PARALLEL /* find out if stdout and stderr point to the same place */ if (fstat(1, &out_stat) < 0) { fatal(catgets(catd, 1, 165, "fstat of standard out failed: %s"), errmsg(errno)); } if (fstat(2, &err_stat) < 0) { fatal(catgets(catd, 1, 166, "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; } #else stdout_stderr_same = false; #endif /* Make the vroot package scan the path using shell semantics */ set_path_style(0); setup_char_semantics(); setup_for_projectdir(); /* * If running with .KEEP_STATE, curdir will be set with * the connected directory. */ #if defined(SUN5_0) || defined(HP_UX) || defined(linux) (void) atexit(cleanup_after_exit); #else (void) on_exit(cleanup_after_exit, (char *) NULL); #endif load_cached_names(); /* * Set command line flags */ 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(catgets(catd, 1, 167, "MAKEFLAGS value: %s\n"), cp == NULL ? "" : cp); } setup_interrupt(handle_interrupt); read_files_and_state(argc, argv); #ifdef TEAMWARE_MAKE_CMN /* * Find the dmake_output_mode: TXT1, TXT2 or HTML1. */ MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_OUTPUT_MODE")); dmake_name2 = GETNAME(wcs_buffer, FIND_LENGTH); prop2 = get_prop(dmake_name2->prop, macro_prop); if (prop2 == NULL) { /* DMAKE_OUTPUT_MODE not defined, default to TXT1 mode */ output_mode = txt1_mode; } else { dmake_value2 = prop2->body.macro.value; if ((dmake_value2 == NULL) || (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("TXT1")))) { output_mode = txt1_mode; } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("TXT2"))) { output_mode = txt2_mode; } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("HTML1"))) { output_mode = html1_mode; } else { warning(catgets(catd, 1, 352, "Unsupported value `%s' for DMAKE_OUTPUT_MODE after -x flag (ignored)"), dmake_value2->string_mb); } } /* * Find the dmake_mode: distributed, parallel, or serial. */ if ((!pmake_cap_r_specified) && (!pmake_machinesfile_specified)) { MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE")); dmake_name2 = GETNAME(wcs_buffer, FIND_LENGTH); prop2 = get_prop(dmake_name2->prop, macro_prop); if (prop2 == NULL) { /* DMAKE_MODE not defined, default to distributed mode */ dmake_mode_type = distributed_mode; no_parallel = false; } else { dmake_value2 = prop2->body.macro.value; if ((dmake_value2 == NULL) || (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("distributed")))) { dmake_mode_type = distributed_mode; no_parallel = false; } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("parallel"))) { dmake_mode_type = parallel_mode; no_parallel = false; #ifdef SGE_SUPPORT grid = false; } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("grid"))) { dmake_mode_type = parallel_mode; no_parallel = false; grid = true; #endif } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("serial"))) { dmake_mode_type = serial_mode; no_parallel = true; } else { fatal(catgets(catd, 1, 307, "Unknown dmake mode argument `%s' after -m flag"), dmake_value2->string_mb); } } if ((!list_all_targets) && (report_dependencies_level == 0)) { /* * Check to see if either DMAKE_RCFILE or DMAKE_MODE is defined. * They could be defined in the env, in the makefile, or on the * command line. * If neither is defined, and $(HOME)/.dmakerc does not exists, * then print a message, and default to parallel mode. */ #ifdef DISTRIBUTED MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_RCFILE")); dmake_name = GETNAME(wcs_buffer, FIND_LENGTH); MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE")); dmake_name2 = GETNAME(wcs_buffer, FIND_LENGTH); if ((((prop = get_prop(dmake_name->prop, macro_prop)) == NULL) || ((dmake_value = prop->body.macro.value) == NULL)) && (((prop2 = get_prop(dmake_name2->prop, macro_prop)) == NULL) || ((dmake_value2 = prop2->body.macro.value) == NULL))) { Boolean empty_dmakerc = true; char *homedir = getenv(NOCATGETS("HOME")); if ((homedir != NULL) && (strlen(homedir) < (sizeof(def_dmakerc_path) - 16))) { sprintf(def_dmakerc_path, NOCATGETS("%s/.dmakerc"), homedir); if ((((statval = stat(def_dmakerc_path, &statbuf)) != 0) && (errno == ENOENT)) || ((statval == 0) && (statbuf.st_size == 0))) { } else { Avo_dmakerc *rcfile = new Avo_dmakerc(); Avo_err *err = rcfile->read(def_dmakerc_path, NULL, TRUE); if (err) { fatal(err->str); } empty_dmakerc = rcfile->was_empty(); delete rcfile; } } if (empty_dmakerc) { if (getenv(NOCATGETS("DMAKE_DEF_PRINTED")) == NULL) { putenv(NOCATGETS("DMAKE_DEF_PRINTED=TRUE")); (void) fprintf(stdout, catgets(catd, 1, 302, "dmake: defaulting to parallel mode.\n")); (void) fprintf(stdout, catgets(catd, 1, 303, "See the man page dmake(1) for more information on setting up the .dmakerc file.\n")); } dmake_mode_type = parallel_mode; no_parallel = false; } } #else if(dmake_mode_type == distributed_mode) { (void) fprintf(stdout, NOCATGETS("dmake: Distributed mode not implemented.\n")); (void) fprintf(stdout, NOCATGETS(" Defaulting to parallel mode.\n")); dmake_mode_type = parallel_mode; no_parallel = false; } #endif /* DISTRIBUTED */ } } #endif #ifdef TEAMWARE_MAKE_CMN parallel_flag = true; /* XXX - This is a major hack for DMake/Licensing. */ if (getenv(NOCATGETS("DMAKE_CHILD")) == NULL) { if (!avo_cli_search_license(argv[0], dmake_exit_callback, TRUE, dmake_message_callback)) { /* * If the user can not get a TeamWare license, * default to serial mode. */ dmake_mode_type = serial_mode; no_parallel = true; } else { putenv(NOCATGETS("DMAKE_CHILD=TRUE")); } start_time = time(NULL); /* * XXX - Hack to disable SIGALRM's from licensing library's * setitimer(). */ value.it_interval.tv_sec = 0; value.it_interval.tv_usec = 0; value.it_value.tv_sec = 0; value.it_value.tv_usec = 0; (void) setitimer(ITIMER_REAL, &value, NULL); } // // If dmake is running with -t option, set dmake_mode_type to serial. // This is done because doname() calls touch_command() that runs serially. // If we do not do that, maketool will have problems. // if(touch) { dmake_mode_type = serial_mode; no_parallel = true; } #else parallel_flag = false; #endif #if defined (TEAMWARE_MAKE_CMN) && defined(REDIRECT_ERR) /* * Check whether stdout and stderr are physically same. * This is in order to decide whether we need to redirect * stderr separately from stdout. * This check is performed only if __DMAKE_SEPARATE_STDERR * is not set. This variable may be used in order to preserve * the 'old' behaviour. */ out_err_same = true; char * dmake_sep_var = getenv(NOCATGETS("__DMAKE_SEPARATE_STDERR")); if (dmake_sep_var == NULL || (0 != strcasecmp(dmake_sep_var, NOCATGETS("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; } } } #endif #ifdef DISTRIBUTED /* * At this point, DMake should startup an rxm with any and all * DMake command line options. Rxm will, among other things, * read the rc file. */ if ((!list_all_targets) && (report_dependencies_level == 0) && (dmake_mode_type == distributed_mode)) { startup_rxm(); } #endif /* * Enable interrupt handler for alarms */ (void) bsd_signal(SIGALRM, (SIG_PF)doalarm); /* * Check if make should report */ 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"); } } /* * Make sure SUNPRO_DEPENDENCIES is exported (or not) properly * and NSE_DEP. */ if (keep_state) { maybe_append_prop(sunpro_dependencies, macro_prop)-> body.macro.exported = true; #ifdef NSE (void) setenv(NOCATGETS("NSE_DEP"), get_current_path()); #endif } else { maybe_append_prop(sunpro_dependencies, macro_prop)-> body.macro.exported = false; } working_on_targets = true; if (trace_status) { dump_make_state(); #if defined(SUN5_0) || defined(HP_UX) || defined(linux) fclose(stdout); fclose(stderr); exit_status = 0; #endif exit(0); } if (list_all_targets) { dump_target_list(); #if defined(SUN5_0) || defined(HP_UX) || defined(linux) fclose(stdout); fclose(stderr); exit_status = 0; #endif exit(0); } trace_reader = false; /* * Set temp_file_directory to the directory the .make.state * file is written to. */ 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; /* when there is only one slash and it's the first ** character, make_state_dir should point to '/'. */ 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); } } #ifdef DISTRIBUTED building_serial = false; #endif report_dir_enter_leave(true); make_targets(argc, argv, parallel_flag); report_dir_enter_leave(false); #ifdef NSE exit(nse_exit_status()); #else if (build_failed_ever_seen) { #if defined(SUN5_0) || defined(HP_UX) || defined(linux) if (posix) { exit_status = 1; } #endif exit(1); } #if defined(SUN5_0) || defined(HP_UX) || defined(linux) exit_status = 0; #endif exit(0); #endif /* NOTREACHED */ } /* * cleanup_after_exit() * * Called from exit(), performs cleanup actions. * * Parameters: * status The argument exit() was called with * arg Address of an argument vector to * cleanup_after_exit() * * Global variables used: * command_changed Set if we think .make.state should be rewritten * current_line Is set we set commands_changed * do_not_exec_rule * True if -n flag on * done The Name ".DONE", rule we run * keep_state Set if .KEEP_STATE seen * parallel True if building in parallel * quest If -q is on we do not run .DONE * report_dependencies * True if -P flag on * running_list List of parallel running processes * temp_file_name The temp file is removed, if any * catd the message catalog file * usage_tracking Should have been constructed in main() * should destroyed just before exiting */ #if defined(SUN5_0) || defined(HP_UX) || defined(linux) extern "C" void cleanup_after_exit(void) #else void cleanup_after_exit(int status, ...) #endif { Running rp; #ifdef NSE char push_cmd[NSE_TFS_PUSH_LEN + 3 + (MAXPATHLEN * MB_LEN_MAX) + 12]; char *active; #endif 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(NOCATGETS(">>> Getname statistics:\n")); printf(NOCATGETS(" Allocated:\n")); printf(NOCATGETS(" Names: %ld\n"), getname_names_count); printf(NOCATGETS(" Strings: %ld Kb (%ld bytes)\n"), getname_bytes_count/1000, getname_bytes_count); printf(NOCATGETS(" Structs: %ld Kb (%ld bytes)\n"), getname_struct_count/1000, getname_struct_count); printf(NOCATGETS(" Total bytes: %ld Kb (%ld bytes)\n"), getname_struct_count/1000 + getname_bytes_count/1000, getname_struct_count + getname_bytes_count); printf(NOCATGETS("\n Unallocated: %ld\n"), freename_names_count); printf(NOCATGETS(" Names: %ld\n"), freename_names_count); printf(NOCATGETS(" Strings: %ld Kb (%ld bytes)\n"), freename_bytes_count/1000, freename_bytes_count); printf(NOCATGETS(" Structs: %ld Kb (%ld bytes)\n"), freename_struct_count/1000, freename_struct_count); printf(NOCATGETS(" Total bytes: %ld Kb (%ld bytes)\n"), freename_struct_count/1000 + freename_bytes_count/1000, freename_struct_count + freename_bytes_count); printf(NOCATGETS("\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(NOCATGETS("\n>>> Other:\n")); printf( NOCATGETS(" Env (%ld): %ld Kb (%ld bytes)\n"), env_alloc_num, env_alloc_bytes/1000, env_alloc_bytes ); } #endif /* #ifdef DISTRIBUTED if (get_parent() == TRUE) { #endif */ parallel = false; #ifdef SUN5_0 /* If we used the SVR4_MAKE, don't build .DONE or .FAILED */ if (!getenv(USE_SVR4_MAKE)){ #endif /* Build the target .DONE or .FAILED if we caught an error */ if (!quest && !list_all_targets) { Name failed_name; MBSTOWCS(wcs_buffer, NOCATGETS(".FAILED")); failed_name = GETNAME(wcs_buffer, FIND_LENGTH); #if defined(SUN5_0) || defined(HP_UX) || defined(linux) if ((exit_status != 0) && (failed_name->prop != NULL)) { #else if ((status != 0) && (failed_name->prop != NULL)) { #endif #ifdef TEAMWARE_MAKE_CMN /* * [tolik] switch DMake to serial mode */ dmake_mode_type = serial_mode; no_parallel = true; #endif (void) doname(failed_name, false, true); } else { if (!trace_status) { #ifdef TEAMWARE_MAKE_CMN /* * Switch DMake to serial mode */ dmake_mode_type = serial_mode; no_parallel = true; #endif (void) doname(done, false, true); } } } #ifdef SUN5_0 } #endif /* * Remove the temp file utilities report dependencies thru if it * is still around */ if (temp_file_name != NULL) { (void) unlink(temp_file_name->string_mb); } /* * Do not save the current command in .make.state if make * was interrupted. */ if (current_line != NULL) { command_changed = true; current_line->body.line.command_used = NULL; } /* * For each parallel build process running, remove the temp files * and zap the command line so it won't be put in .make.state */ 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; /* line = get_prop(rp->target->prop, line_prop); if (line != NULL) { line->body.line.command_used = NULL; } */ } /* Remove the statefile lock file if the file has been locked */ if ((make_state_lockfile != NULL) && (make_state_locked)) { (void) unlink(make_state_lockfile); make_state_lockfile = NULL; make_state_locked = false; } /* Write .make.state */ write_state_file(1, (Boolean) 1); #ifdef TEAMWARE_MAKE_CMN // Deleting the usage tracking object sends the usage mail #ifdef USE_DMS_CCR //usageTracking->setExitStatus(exit_status, NULL); //delete usageTracking; #else cleanup->set_exit_status(exit_status); delete cleanup; #endif #endif #ifdef NSE /* If running inside an activated environment, push the */ /* .nse_depinfo file (if written) */ active = getenv(NSE_VARIANT_ENV); if (keep_state && (active != NULL) && !IS_EQUAL(active, NSE_RT_SOURCE_NAME) && !do_not_exec_rule && (report_dependencies_level == 0)) { (void) sprintf(push_cmd, "%s %s/%s", NSE_TFS_PUSH, get_current_path(), NSE_DEPINFO); (void) system(push_cmd); } #endif /* #ifdef DISTRIBUTED } #endif */ #if defined (TEAMWARE_MAKE_CMN) && defined (MAXJOBS_ADJUST_RFE4694000) job_adjust_fini(); #endif #ifdef TEAMWARE_MAKE_CMN catclose(catd); #endif #ifdef DISTRIBUTED if (rxmPid > 0) { // Tell rxm to exit by sending it an Avo_AcknowledgeMsg Avo_AcknowledgeMsg acknowledgeMsg; RWCollectable *msg = (RWCollectable *)&acknowledgeMsg; int xdrResult = xdr(&xdrs_out, msg); if (xdrResult) { fflush(dmake_ofp); } else { /* fatal(catgets(catd, 1, 266, "couldn't tell rxm to exit")); */ kill(rxmPid, SIGTERM); } waitpid(rxmPid, NULL, 0); rxmPid = 0; } #endif } /* * handle_interrupt() * * This is where C-C traps are caught. * * Parameters: * * Global variables used (except DMake 1.0): * current_target Sometimes the current target is removed * do_not_exec_rule But not if -n is on * quest or -q * running_list List of parallel running processes * touch Current target is not removed if -t on */ void handle_interrupt(int) { Property member; Running rp; (void) fflush(stdout); #ifdef DISTRIBUTED if (rxmPid > 0) { // Tell rxm to exit by sending it an Avo_AcknowledgeMsg Avo_AcknowledgeMsg acknowledgeMsg; RWCollectable *msg = (RWCollectable *)&acknowledgeMsg; int xdrResult = xdr(&xdrs_out, msg); if (xdrResult) { fflush(dmake_ofp); } else { kill(rxmPid, SIGTERM); rxmPid = 0; } } #endif 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); } #ifdef TEAMWARE_MAKE_CMN /* Clean up all parallel/distributed children already finished */ finish_children(false); #endif /* Make sure the processes running under us terminate first */ #if defined(SUN5_0) || defined(HP_UX) || defined(linux) while (wait((int *) NULL) != -1); #else while (wait((union wait*) NULL) != -1); #endif /* Delete the current targets unless they are precious */ 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)) { /* BID_1030811 */ /* azv 16 Oct 95 */ 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, catgets(catd, 1, 168, "not removed.\n"), current_target->string_mb); } else if (unlink(current_target->string_mb) == 0) { (void) fprintf(stderr, catgets(catd, 1, 169, "removed.\n"), current_target->string_mb); } else { (void) fprintf(stderr, catgets(catd, 1, 170, "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, catgets(catd, 1, 171, "not removed.\n"), rp->target->string_mb); } else if (unlink(rp->target->string_mb) == 0) { (void) fprintf(stderr, catgets(catd, 1, 172, "removed.\n"), rp->target->string_mb); } else { (void) fprintf(stderr, catgets(catd, 1, 173, "could not be removed: %s.\n"), rp->target->string_mb, errmsg(errno)); } } } } #ifdef SGE_SUPPORT /* Remove SGE script file */ if (grid) { unlink(script_file); } #endif /* Have we locked .make.state or .nse_depinfo? */ if ((make_state_lockfile != NULL) && (make_state_locked)) { unlink(make_state_lockfile); make_state_lockfile = NULL; make_state_locked = false; } #ifdef NSE if ((nse_depinfo_lockfile[0] != '\0') && (nse_depinfo_locked)) { unlink(nse_depinfo_lockfile); nse_depinfo_lockfile[0] = '\0'; nse_depinfo_locked = false; } #endif /* * Re-read .make.state file (it might be changed by recursive make) */ check_state(NULL); report_dir_enter_leave(false); #if defined(SUN5_0) || defined(HP_UX) || defined(linux) exit_status = 2; #endif exit(2); } /* * doalarm(sig, ...) * * Handle the alarm interrupt but do nothing. Side effect is to * cause return from wait3. * * Parameters: * sig * * Global variables used: */ /*ARGSUSED*/ static void doalarm(int) { return; } /* * read_command_options(argc, argv) * * Scan the cmd line options and process the ones that start with "-" * * Return value: * -M argument, if any * * Parameters: * argc You know what this is * argv You know what this is * * Global variables used: */ static void read_command_options(register int argc, register char **argv) { register int ch; int current_optind = 1; int last_optind_with_double_hyphen = 0; int last_optind; int last_current_optind; register int i; register int j; register int k; register int makefile_next = 0; /* * flag to note options: * -c, f, g, j, m, o */ const char *tptr; const char *CMD_OPTS; extern char *optarg; extern int optind, opterr, optopt; #define SUNPRO_CMD_OPTS "-~Bbc:Ddef:g:ij:K:kM:m:NnO:o:PpqRrSsTtuVvwx:" #ifdef TEAMWARE_MAKE_CMN # define SVR4_CMD_OPTS "-c:ef:g:ij:km:nO:o:pqrsTtVv" #else # define SVR4_CMD_OPTS "-ef:iknpqrstV" #endif /* * Added V in SVR4_CMD_OPTS also, which is going to be a hidden * option, just to make sure that the getopt doesn't fail when some * users leave their USE_SVR4_MAKE set and try to use the makefiles * that are designed to issue commands like $(MAKE) -V. Anyway it * sets the same flag but ensures that getopt doesn't fail. */ opterr = 0; optind = 1; while (1) { last_optind=optind; /* Save optind and current_optind values */ last_current_optind=current_optind; /* in case we have to repeat this round. */ 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) { /* * Fixing bug 4102537: * Strange behaviour of command make using -- option. * Not all argv have been processed * Skip non-flag argv and continue processing. */ optind++; current_optind++; continue; } else { break; } } if (ch == '?') { if (optopt == '-') { /* Bug 5060758: getopt() changed behavior (s10_60), * and now we have to deal with cases when options * with double hyphen appear here, from -$(MAKEFLAGS) */ i = current_optind; if (argv[i][0] == '-') { if (argv[i][1] == '-') { if (argv[i][2] != '\0') { /* Check if this option is allowed */ tptr = strchr(CMD_OPTS, argv[i][2]); if (tptr) { if (last_optind_with_double_hyphen != current_optind) { /* This is first time we are trying to fix "--" * problem with this option. If we come here second * time, we will go to fatal error. */ last_optind_with_double_hyphen = current_optind; /* Eliminate first hyphen character */ for (j=0; argv[i][j] != '\0'; j++) { argv[i][j] = argv[i][j+1]; } /* Repeat the processing of this argument */ optind=last_optind; current_optind=last_current_optind; continue; } } } } } } } if (ch == '?') { if (svr4) { #ifdef TEAMWARE_MAKE_CMN fprintf(stderr, catgets(catd, 1, 267, "Usage : dmake [ -f makefile ][ -c dmake_rcfile ][ -g dmake_group ]\n")); fprintf(stderr, catgets(catd, 1, 268, " [ -j dmake_max_jobs ][ -m dmake_mode ][ -o dmake_odir ]...\n")); fprintf(stderr, catgets(catd, 1, 269, " [ -e ][ -i ][ -k ][ -n ][ -p ][ -q ][ -r ][ -s ][ -t ][ -v ]\n")); #else fprintf(stderr, catgets(catd, 1, 270, "Usage : make [ -f makefile ]... [ -e ][ -i ][ -k ][ -n ][ -p ][ -q ][ -r ]\n")); fprintf(stderr, catgets(catd, 1, 271, " [ -s ][ -t ]\n")); #endif tptr = strchr(SVR4_CMD_OPTS, optopt); } else { #ifdef TEAMWARE_MAKE_CMN fprintf(stderr, catgets(catd, 1, 272, "Usage : dmake [ -f makefile ][ -c dmake_rcfile ][ -g dmake_group ]\n")); fprintf(stderr, catgets(catd, 1, 273, " [ -j dmake_max_jobs ][ -K statefile ][ -m dmake_mode ][ -x MODE_NAME=VALUE ][ -o dmake_odir ]...\n")); fprintf(stderr, catgets(catd, 1, 274, " [ -d ][ -dd ][ -D ][ -DD ][ -e ][ -i ][ -k ][ -n ][ -p ][ -P ][ -u ][ -w ]\n")); fprintf(stderr, catgets(catd, 1, 275, " [ -q ][ -r ][ -s ][ -S ][ -t ][ -v ][ -V ][ target... ][ macro=value... ][ \"macro +=value\"... ]\n")); #else fprintf(stderr, catgets(catd, 1, 276, "Usage : make [ -f makefile ][ -K statefile ]... [ -d ][ -dd ][ -D ][ -DD ]\n")); fprintf(stderr, catgets(catd, 1, 277, " [ -e ][ -i ][ -k ][ -n ][ -p ][ -P ][ -q ][ -r ][ -s ][ -S ][ -t ]\n")); fprintf(stderr, catgets(catd, 1, 278, " [ -u ][ -w ][ -V ][ target... ][ macro=value... ][ \"macro +=value\"... ]\n")); #endif tptr = strchr(SUNPRO_CMD_OPTS, optopt); } if (!tptr) { fatal(catgets(catd, 1, 279, "Unknown option `-%c'"), optopt); } else { fatal(catgets(catd, 1, 280, "Missing argument after `-%c'"), optopt); } } #if defined(linux) if (ch == 1) { if(optind < argc) { //optind++; //current_optind++; makefile_next = 0; current_optind = optind; continue; } else { break; } } #endif makefile_next |= parse_command_option(ch); /* * If we're done processing all of the options of * ONE argument string... */ if (current_optind < optind) { i = current_optind; k = 0; /* If there's an argument for an option... */ if ((optind - current_optind) > 1) { k = i + 1; } switch (makefile_next) { case 0: argv[i] = NULL; /* This shouldn't happen */ if (k) { argv[k] = NULL; } break; case 1: /* -f seen */ argv[i] = NOCATGETS("-f"); break; case 2: /* -c seen */ argv[i] = NOCATGETS("-c"); #ifndef TEAMWARE_MAKE_CMN warning(catgets(catd, 1, 281, "Ignoring DistributedMake -c option")); #endif break; case 4: /* -g seen */ argv[i] = NOCATGETS("-g"); #ifndef TEAMWARE_MAKE_CMN warning(catgets(catd, 1, 282, "Ignoring DistributedMake -g option")); #endif break; case 8: /* -j seen */ argv[i] = NOCATGETS("-j"); #ifndef TEAMWARE_MAKE_CMN warning(catgets(catd, 1, 283, "Ignoring DistributedMake -j option")); #endif break; case 16: /* -M seen */ argv[i] = NOCATGETS("-M"); #ifndef TEAMWARE_MAKE_CMN warning(catgets(catd, 1, 284, "Ignoring ParallelMake -M option")); #endif break; case 32: /* -m seen */ argv[i] = NOCATGETS("-m"); #ifndef TEAMWARE_MAKE_CMN warning(catgets(catd, 1, 285, "Ignoring DistributedMake -m option")); #endif break; #ifndef PARALLEL case 128: /* -O seen */ argv[i] = NOCATGETS("-O"); break; #endif case 256: /* -K seen */ argv[i] = NOCATGETS("-K"); break; case 512: /* -o seen */ argv[i] = NOCATGETS("-o"); #ifndef TEAMWARE_MAKE_CMN warning(catgets(catd, 1, 311, "Ignoring DistributedMake -o option")); #endif break; case 1024: /* -x seen */ argv[i] = NOCATGETS("-x"); #ifndef TEAMWARE_MAKE_CMN warning(catgets(catd, 1, 353, "Ignoring DistributedMake -x option")); #endif break; default: /* > 1 of -c, f, g, j, K, M, m, O, o, x seen */ fatal(catgets(catd, 1, 286, "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 ';': /* End of command */ case '(': /* Start group */ case ')': /* End group */ case '{': /* Start group */ case '}': /* End group */ case '[': /* Reg expr - any of a set of chars */ case ']': /* End of set of chars */ case '|': /* Pipe or logical-or */ case '^': /* Old-fashioned pipe */ case '&': /* Background or logical-and */ case '<': /* Redirect stdin */ case '>': /* Redirect stdout */ case '*': /* Reg expr - any sequence of chars */ case '?': /* Reg expr - any single char */ case '$': /* Variable substitution */ case '\'': /* Singe quote - turn off all magic */ case '"': /* Double quote - span whitespace */ case '`': /* Backquote - run a command */ case '#': /* Comment */ case ' ': /* Space (for MACRO=value1 value2 */ case '\\': /* Escape char - turn off magic of next char */ *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'; } /* * Convert the MAKEFLAGS string value into a vector of char *, similar * to argv. */ 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 new MAKEFLAGS format, no need to add hyphen. * If old MAKEFLAGS format, add hyphen before flags. */ if ((strchr(cp, (int) hyphen_char) != NULL) || (strchr(cp, (int) equal_char) != NULL)) { /* New MAKEFLAGS format */ add_hyphen = false; #ifdef ADDFIX5060758 /* Check if MAKEFLAGS value begins with multiple * hyphen characters, and remove all duplicates. * Usually it happens when the next command is * used: $(MAKE) -$(MAKEFLAGS) * This is a workaround for BugID 5060758. */ while (*cp) { if (*cp != (int) hyphen_char) { break; } cp++; if (*cp == (int) hyphen_char) { /* There are two hyphens. Skip one */ cp_orig = cp; cp++; } if (!(*cp)) { /* There are hyphens only. Skip all */ cp_orig = cp; break; } } #endif } else { /* Old MAKEFLAGS format */ add_hyphen = true; } } /* Find the number of arguments in MAKEFLAGS */ while (cp && *cp) { /* Skip white spaces */ while (cp && *cp && isspace(*cp)) { cp++; } if (cp && *cp) { /* Increment arg count */ mf_argc++; /* Go to next white space */ while (cp && *cp && !isspace(*cp)) { if(*cp == (int) backslash_char) { cp++; } cp++; } } } /* Allocate memory for the new MAKEFLAGS argv */ mf_argv = (char **) malloc((mf_argc + 1) * sizeof(char *)); mf_argv[0] = NOCATGETS("MAKEFLAGS"); /* * Convert the MAKEFLAGS string value into a vector of char *, * similar to argv. */ cp = cp_orig; for (i = 1; i < mf_argc; i++) { /* Skip white spaces */ while (cp && *cp && isspace(*cp)) { cp++; } if (cp && *cp) { cp_orig = cp; /* Go to next white space */ 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], "-"); // (void) strcat(mf_argv[i], cp_orig); unquote_str(cp_orig, mf_argv[i]+1); } else { mf_argv[i] = getmem(2 + strlen(cp_orig)); //mf_argv[i] = strdup(cp_orig); unquote_str(cp_orig, mf_argv[i]); } *cp = tmp_char; } } mf_argv[i] = NULL; } /* * parse_command_option(ch) * * Parse make command line options. * * Return value: * Indicates if any -f -c or -M were seen * * Parameters: * ch The character to parse * * Static variables used: * dmake_group_specified Set for make -g * dmake_max_jobs_specified Set for make -j * dmake_mode_specified Set for make -m * dmake_add_mode_specified Set for make -x * dmake_compat_mode_specified Set for make -x SUN_MAKE_COMPAT_MODE= * dmake_output_mode_specified Set for make -x DMAKE_OUTPUT_MODE= * dmake_odir_specified Set for make -o * dmake_rcfile_specified Set for make -c * env_wins Set for make -e * ignore_default_mk Set for make -r * trace_status Set for make -p * * Global variables used: * .make.state path & name set for make -K * continue_after_error Set for make -k * debug_level Set for make -d * do_not_exec_rule Set for make -n * filter_stderr Set for make -X * ignore_errors_all Set for make -i * no_parallel Set for make -R * quest Set for make -q * read_trace_level Set for make -D * report_dependencies Set for make -P * send_mtool_msgs Set for make -K * silent_all Set for make -s * touch Set for make -t */ static int parse_command_option(register char ch) { static int invert_next = 0; int invert_this = invert_next; invert_next = 0; switch (ch) { case '-': /* Ignore "--" */ return 0; case '~': /* Invert next option */ invert_next = 1; return 0; case 'B': /* Obsolete */ return 0; case 'b': /* Obsolete */ return 0; case 'c': /* Read alternative dmakerc file */ if (invert_this) { dmake_rcfile_specified = false; } else { dmake_rcfile_specified = true; } return 2; case 'D': /* Show lines read */ if (invert_this) { read_trace_level--; } else { read_trace_level++; } return 0; case 'd': /* Debug flag */ if (invert_this) { debug_level--; } else { #if defined( HP_UX) || defined(linux) if (debug_level < 2) /* Fixes a bug on HP-UX */ #endif debug_level++; } return 0; #ifdef NSE case 'E': if (invert_this) { nse = false; } else { nse = true; } nse_init_source_suffixes(); return 0; #endif case 'e': /* Environment override flag */ if (invert_this) { env_wins = false; } else { env_wins = true; } return 0; case 'f': /* Read alternative makefile(s) */ return 1; case 'g': /* Use alternative DMake group */ if (invert_this) { dmake_group_specified = false; } else { dmake_group_specified = true; } return 4; case 'i': /* Ignore errors */ if (invert_this) { ignore_errors_all = false; } else { ignore_errors_all = true; } return 0; case 'j': /* Use alternative DMake max jobs */ if (invert_this) { dmake_max_jobs_specified = false; } else { dmake_max_jobs_specified = true; } return 8; case 'K': /* Read alternative .make.state */ return 256; case 'k': /* Keep making even after errors */ if (invert_this) { continue_after_error = false; } else { continue_after_error = true; continue_after_error_ever_seen = true; } return 0; case 'M': /* Read alternative make.machines file */ if (invert_this) { pmake_machinesfile_specified = false; } else { pmake_machinesfile_specified = true; dmake_mode_type = parallel_mode; no_parallel = false; } return 16; case 'm': /* Use alternative DMake build mode */ if (invert_this) { dmake_mode_specified = false; } else { dmake_mode_specified = true; } return 32; case 'x': /* Use alternative DMake mode */ if (invert_this) { dmake_add_mode_specified = false; } else { dmake_add_mode_specified = true; } return 1024; case 'N': /* Reverse -n */ if (invert_this) { do_not_exec_rule = true; } else { do_not_exec_rule = false; } return 0; case 'n': /* Print, not exec commands */ if (invert_this) { do_not_exec_rule = false; } else { do_not_exec_rule = true; } return 0; #ifndef PARALLEL case 'O': /* Send job start & result msgs */ if (invert_this) { send_mtool_msgs = false; } else { #ifdef DISTRIBUTED send_mtool_msgs = true; #endif } return 128; #endif case 'o': /* Use alternative dmake output dir */ if (invert_this) { dmake_odir_specified = false; } else { dmake_odir_specified = true; } return 512; case 'P': /* Print for selected targets */ if (invert_this) { report_dependencies_level--; } else { report_dependencies_level++; } return 0; case 'p': /* Print description */ if (invert_this) { trace_status = false; do_not_exec_rule = false; } else { trace_status = true; do_not_exec_rule = true; } return 0; case 'q': /* Question flag */ if (invert_this) { quest = false; } else { quest = true; } return 0; case 'R': /* Don't run in parallel */ #ifdef TEAMWARE_MAKE_CMN 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; } #else warning(catgets(catd, 1, 182, "Ignoring ParallelMake -R option")); #endif return 0; case 'r': /* Turn off internal rules */ if (invert_this) { ignore_default_mk = false; } else { ignore_default_mk = true; } return 0; case 'S': /* Reverse -k */ if (invert_this) { continue_after_error = true; } else { continue_after_error = false; stop_after_error_ever_seen = true; } return 0; case 's': /* Silent flag */ if (invert_this) { silent_all = false; } else { silent_all = true; } return 0; case 'T': /* Print target list */ 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': /* Touch flag */ if (invert_this) { touch = false; } else { touch = true; } return 0; case 'u': /* Unconditional flag */ if (invert_this) { build_unconditional = false; } else { build_unconditional = true; } return 0; case 'V': /* SVR4 mode */ svr4 = true; return 0; case 'v': /* Version flag */ if (invert_this) { } else { #ifdef TEAMWARE_MAKE_CMN fprintf(stdout, NOCATGETS("dmake: %s\n"), verstring); #ifdef SUN5_0 exit_status = 0; #endif exit(0); #else warning(catgets(catd, 1, 324, "Ignoring DistributedMake -v option")); #endif } return 0; case 'w': /* Unconditional flag */ if (invert_this) { report_cwd = false; } else { report_cwd = true; } return 0; #if 0 case 'X': /* Filter stdout */ if (invert_this) { filter_stderr = false; } else { filter_stderr = true; } return 0; #endif default: break; } return 0; } /* * setup_for_projectdir() * * Read the PROJECTDIR variable, if defined, and set the sccs path * * Parameters: * * Global variables used: * sccs_dir_path Set to point to SCCS dir to use */ static void setup_for_projectdir(void) { static char path[MAXPATHLEN]; char cwdpath[MAXPATHLEN]; uid_t uid; int done=0; /* Check if we should use PROJECTDIR when reading the SCCS dir. */ sccs_dir_path = getenv(NOCATGETS("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(catgets(catd, 1, 188, "Bogus USERID ")); } if ((pwent = getpwnam(sccs_dir_path)) == NULL) { /*empty block : it'll go & check cwd */ } else { (void) sprintf(path, NOCATGETS("%s/src"), pwent->pw_dir); if (access(path, F_OK) == 0) { sccs_dir_path = path; done = 1; } else { (void) sprintf(path, NOCATGETS("%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, NOCATGETS("%s/%s"), cwdpath,sccs_dir_path); if (access(path, F_OK) == 0) { sccs_dir_path = path; done = 1; } else { fatal(catgets(catd, 1, 189, "Bogus PROJECTDIR '%s'"), sccs_dir_path); } } } } } } /* * set_sgs_support() * * Add the libmakestate.so.1 lib to the env var SGS_SUPPORT * if it's not already in there. * The SGS_SUPPORT env var and libmakestate.so.1 is used by * the linker ld to report .make.state info back to make. */ static void set_sgs_support() { int len; char *newpath; char *oldpath; static char *prev_path; oldpath = getenv(LD_SUPPORT_ENV_VAR); if (oldpath == NULL) { len = strlen(LD_SUPPORT_ENV_VAR) + 1 + strlen(LD_SUPPORT_MAKE_LIB) + 1; newpath = (char *) malloc(len); sprintf(newpath, "%s=", LD_SUPPORT_ENV_VAR); } else { len = strlen(LD_SUPPORT_ENV_VAR) + 1 + strlen(oldpath) + 1 + strlen(LD_SUPPORT_MAKE_LIB) + 1; newpath = (char *) malloc(len); sprintf(newpath, "%s=%s", LD_SUPPORT_ENV_VAR, oldpath); } #if defined(TEAMWARE_MAKE_CMN) /* function maybe_append_str_to_env_var() is defined in avo_util library * Serial make should not use this library !!! */ maybe_append_str_to_env_var(newpath, LD_SUPPORT_MAKE_LIB); #else if (oldpath == NULL) { sprintf(newpath, "%s%s", newpath, LD_SUPPORT_MAKE_LIB); } else { sprintf(newpath, "%s:%s", newpath, LD_SUPPORT_MAKE_LIB); } #endif putenv(newpath); if (prev_path) { free(prev_path); } prev_path = newpath; } /* * read_files_and_state(argc, argv) * * Read the makefiles we care about and the environment * Also read the = style command line options * * Parameters: * argc You know what this is * argv You know what this is * * Static variables used: * env_wins make -e, determines if env vars are RO * ignore_default_mk make -r, determines if make.rules is read * not_auto_depen dwight * * Global variables used: * default_target_to_build Set to first proper target from file * do_not_exec_rule Set to false when makfile is made * dot The Name ".", used to read current dir * empty_name The Name "", use as macro value * keep_state Set if KEEP_STATE is in environment * make_state The Name ".make.state", used to read file * makefile_type Set to type of file being read * makeflags The Name "MAKEFLAGS", used to set macro value * not_auto dwight * nse Set if NSE_ENV is in the environment * read_trace_level Checked to se if the reader should trace * report_dependencies If -P is on we do not read .make.state * trace_reader Set if reader should trace * virtual_root The Name "VIRTUAL_ROOT", used to check value */ static void read_files_and_state(int argc, char **argv) { wchar_t buffer[1000]; wchar_t buffer_posix[1000]; register char ch; register char *cp; Property def_make_macro = NULL; Name def_make_name; Name default_makefile; String_rec dest; wchar_t destbuffer[STRING_BUFFER_LENGTH]; register int i; register int j; Name keep_state_name; int length; Name Makefile; register Property macro; struct stat make_state_stat; Name makefile_name; register int makefile_next = 0; register Boolean makefile_read = false; String_rec makeflags_string; String_rec makeflags_string_posix; String_rec * makeflags_string_current; Name makeflags_value_saved; register Name name; Name new_make_value; Boolean save_do_not_exec_rule; Name sdotMakefile; Name sdotmakefile_name; 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; register Name value; ASCII_Dyn_Array makeflags_and_macro; Boolean is_xpg4; /* * Remember current mode. It may be changed after reading makefile * and we will have to correct MAKEFLAGS variable. */ is_xpg4 = posix; MBSTOWCS(wcs_buffer, NOCATGETS("KEEP_STATE")); keep_state_name = GETNAME(wcs_buffer, FIND_LENGTH); MBSTOWCS(wcs_buffer, NOCATGETS("Makefile")); Makefile = GETNAME(wcs_buffer, FIND_LENGTH); MBSTOWCS(wcs_buffer, NOCATGETS("makefile")); makefile_name = GETNAME(wcs_buffer, FIND_LENGTH); MBSTOWCS(wcs_buffer, NOCATGETS("s.makefile")); sdotmakefile_name = GETNAME(wcs_buffer, FIND_LENGTH); MBSTOWCS(wcs_buffer, NOCATGETS("s.Makefile")); sdotMakefile = GETNAME(wcs_buffer, FIND_LENGTH); /* * Set flag if NSE is active */ #ifdef NSE if (getenv(NOCATGETS("NSE_ENV")) != NULL) { nse = true; } #endif /* * initialize global dependency entry for .NOT_AUTO */ not_auto_depen->next = NULL; not_auto_depen->name = not_auto; not_auto_depen->automatic = not_auto_depen->stale = false; /* * Read internal definitions and rules. */ if (read_trace_level > 1) { trace_reader = true; } if (!ignore_default_mk) { #if defined(SUN5_0) || defined(HP_UX) || defined(linux) if (svr4) { MBSTOWCS(wcs_buffer, NOCATGETS("svr4.make.rules")); default_makefile = GETNAME(wcs_buffer, FIND_LENGTH); } else { MBSTOWCS(wcs_buffer, NOCATGETS("make.rules")); default_makefile = GETNAME(wcs_buffer, FIND_LENGTH); } #else MBSTOWCS(wcs_buffer, NOCATGETS("default.mk")); default_makefile = GETNAME(wcs_buffer, FIND_LENGTH); #endif default_makefile->stat.is_file = true; (void) read_makefile(default_makefile, true, false, true); } /* * If the user did not redefine the MAKE macro in the * default makefile (make.rules), then we'd like to * change the macro value of MAKE to be some form * of argv[0] for recursive MAKE builds. */ MBSTOWCS(wcs_buffer, NOCATGETS("MAKE")); def_make_name = GETNAME(wcs_buffer, wslen(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, NOCATGETS("make")))) { MBSTOWCS(wcs_buffer, argv_zero_string); new_make_value = GETNAME(wcs_buffer, wslen(wcs_buffer)); (void) SETVAR(def_make_name, new_make_value, false); } default_target_to_build = NULL; trace_reader = false; /* * Read environment args. Let file args which follow override unless * -e option seen. If -e option is not mentioned. */ 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); } /* * We now scan mf_argv and argv to see if we need to set * any of the DMake-added options/variables in MAKEFLAGS. */ 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); /* * Set MFLAGS and MAKEFLAGS * * Before reading makefile we do not know exactly which mode * (posix or not) is used. So prepare two MAKEFLAGS strings * for both posix and solaris modes because they are different. */ 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); } #ifdef NSE if (nse) { append_char('E', &makeflags_string); } #endif 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); } #ifndef PARALLEL /* -c dmake_rcfile */ if (dmake_rcfile_specified) { MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_RCFILE")); dmake_rcfile = GETNAME(wcs_buffer, FIND_LENGTH); append_makeflags_string(dmake_rcfile, &makeflags_string); append_makeflags_string(dmake_rcfile, &makeflags_string_posix); } /* -g dmake_group */ if (dmake_group_specified) { MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_GROUP")); dmake_group = GETNAME(wcs_buffer, FIND_LENGTH); append_makeflags_string(dmake_group, &makeflags_string); append_makeflags_string(dmake_group, &makeflags_string_posix); } /* -j dmake_max_jobs */ if (dmake_max_jobs_specified) { MBSTOWCS(wcs_buffer, NOCATGETS("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); } /* -m dmake_mode */ if (dmake_mode_specified) { MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE")); dmake_mode = GETNAME(wcs_buffer, FIND_LENGTH); append_makeflags_string(dmake_mode, &makeflags_string); append_makeflags_string(dmake_mode, &makeflags_string_posix); } /* -x dmake_compat_mode */ // if (dmake_compat_mode_specified) { // MBSTOWCS(wcs_buffer, NOCATGETS("SUN_MAKE_COMPAT_MODE")); // dmake_compat_mode = GETNAME(wcs_buffer, FIND_LENGTH); // append_makeflags_string(dmake_compat_mode, &makeflags_string); // append_makeflags_string(dmake_compat_mode, &makeflags_string_posix); // } /* -x dmake_output_mode */ if (dmake_output_mode_specified) { MBSTOWCS(wcs_buffer, NOCATGETS("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); } /* -o dmake_odir */ if (dmake_odir_specified) { MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_ODIR")); dmake_odir = GETNAME(wcs_buffer, FIND_LENGTH); append_makeflags_string(dmake_odir, &makeflags_string); append_makeflags_string(dmake_odir, &makeflags_string_posix); } /* -M pmake_machinesfile */ if (pmake_machinesfile_specified) { MBSTOWCS(wcs_buffer, NOCATGETS("PMAKE_MACHINESFILE")); pmake_machinesfile = GETNAME(wcs_buffer, FIND_LENGTH); append_makeflags_string(pmake_machinesfile, &makeflags_string); append_makeflags_string(pmake_machinesfile, &makeflags_string_posix); } /* -R */ 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); } #endif /* * Make sure MAKEFLAGS is exported */ 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, NOCATGETS("MFLAGS")); (void) SETVAR(GETNAME(wcs_buffer, FIND_LENGTH), GETNAME(makeflags_string.buffer.start, FIND_LENGTH), false); } else { MBSTOWCS(wcs_buffer, NOCATGETS("MFLAGS")); (void) SETVAR(GETNAME(wcs_buffer, FIND_LENGTH), GETNAME(makeflags_string.buffer.start + 2, FIND_LENGTH), false); } } /* * Add command line macro to POSIX makeflags_string */ 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); } /* * Now set the value of MAKEFLAGS macro in accordance * with current mode. */ 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; /* * Read command line "-f" arguments and ignore -c, g, j, K, M, m, O and o args. */ 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; /* Remove -f */ if (i >= argc - 1) { fatal(catgets(catd, 1, 190, "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; /* Remove filename */ 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 no command line "-f" args then look for "makefile", and then for * "Makefile" if "makefile" isn't found. */ 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(catgets(catd, 1, 310, "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(catgets(catd, 1, 191, "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; /* * Now get current value of MAKEFLAGS and compare it with * the saved value we set before reading makefile. * If they are different then MAKEFLAGS is subsequently set by * makefile, just leave it there. Otherwise, if make mode * is changed by using .POSIX target in makefile we need * to correct MAKEFLAGS value. */ 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) { /* * If the user did not redefine the ARFLAGS macro in the * default makefile (make.rules), then we'd like to * change the macro value of ARFLAGS to be in accordance * with "POSIX" requirements. */ MBSTOWCS(wcs_buffer, NOCATGETS("ARFLAGS")); name = GETNAME(wcs_buffer, wslen(wcs_buffer)); macro = get_prop(name->prop, macro_prop); if ((macro != NULL) && /* Maybe (macro == NULL) || ? */ (IS_EQUAL(macro->body.macro.value->string_mb, NOCATGETS("rv")))) { MBSTOWCS(wcs_buffer, NOCATGETS("-rv")); value = GETNAME(wcs_buffer, wslen(wcs_buffer)); (void) SETVAR(name, value, false); } } if (!posix && !svr4) { set_sgs_support(); } /* * Make sure KEEP_STATE is in the environment if KEEP_STATE is on. */ 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); /* * Read state file */ /* Before we read state, let's make sure we have ** right state file. */ /* just in case macro references are used in make_state file ** name, we better expand them at this stage using expand_value. */ 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) ) { /* copy the make_state structure to the other ** and then let make_state point to the new ** one. */ memcpy(&state_filename, make_state,sizeof(state_filename)); state_filename.string_mb = state_file_str_mb; /* Just a kludge to avoid two slashes back to back */ 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,NOCATGETS("%s%s"), make_state->string_mb,NOCATGETS("/.make.state")); make_state = &state_filename; /* adjust the length to reflect the appended string */ make_state->hash.length += 12; } } else { /* the file doesn't exist or no permission */ 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(catgets(catd, 1, 192, "directory %s for .KEEP_STATE_FILE does not exist"),tmp_path); } if (access(tmp_path, F_OK) != 0) { warning(catgets(catd, 1, 193, "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; } } } /* * Scan the argv for options and "=" type args and make them readonly. */ static void enter_argv_values(int argc, char *argv[], ASCII_Dyn_Array *makeflags_and_macro) { register char *cp; register int i; int length; register Name name; int opt_separator = argc; char tmp_char; wchar_t *tmp_wcs_buffer; register Name value; Boolean append = false; Property macro; struct stat statbuf; /* Read argv options and "=" type args and make them readonly. */ 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: /* -f seen */ ++i; continue; case 2: /* -c seen */ if (argv[i+1] == NULL) { fatal(catgets(catd, 1, 194, "No dmake rcfile argument after -c flag")); } MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_RCFILE")); name = GETNAME(wcs_buffer, FIND_LENGTH); break; case 4: /* -g seen */ if (argv[i+1] == NULL) { fatal(catgets(catd, 1, 195, "No dmake group argument after -g flag")); } MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_GROUP")); name = GETNAME(wcs_buffer, FIND_LENGTH); break; case 8: /* -j seen */ if (argv[i+1] == NULL) { fatal(catgets(catd, 1, 196, "No dmake max jobs argument after -j flag")); } MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MAX_JOBS")); name = GETNAME(wcs_buffer, FIND_LENGTH); break; case 16: /* -M seen */ if (argv[i+1] == NULL) { fatal(catgets(catd, 1, 323, "No pmake machinesfile argument after -M flag")); } MBSTOWCS(wcs_buffer, NOCATGETS("PMAKE_MACHINESFILE")); name = GETNAME(wcs_buffer, FIND_LENGTH); break; case 32: /* -m seen */ if (argv[i+1] == NULL) { fatal(catgets(catd, 1, 197, "No dmake mode argument after -m flag")); } MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE")); name = GETNAME(wcs_buffer, FIND_LENGTH); break; case 128: /* -O seen */ if (argv[i+1] == NULL) { fatal(catgets(catd, 1, 287, "No file descriptor argument after -O flag")); } mtool_msgs_fd = atoi(argv[i+1]); /* find out if mtool_msgs_fd is a valid file descriptor */ if (fstat(mtool_msgs_fd, &statbuf) < 0) { fatal(catgets(catd, 1, 355, "Invalid file descriptor %d after -O flag"), mtool_msgs_fd); } argv[i] = NULL; argv[i+1] = NULL; continue; case 256: /* -K seen */ if (argv[i+1] == NULL) { fatal(catgets(catd, 1, 288, "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: /* -o seen */ if (argv[i+1] == NULL) { fatal(catgets(catd, 1, 312, "No dmake output dir argument after -o flag")); } MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_ODIR")); name = GETNAME(wcs_buffer, FIND_LENGTH); break; case 1024: /* -x seen */ if (argv[i+1] == NULL) { fatal(catgets(catd, 1, 351, "No argument after -x flag")); } length = strlen( NOCATGETS("SUN_MAKE_COMPAT_MODE=")); if (strncmp(argv[i+1], NOCATGETS("SUN_MAKE_COMPAT_MODE="), length) == 0) { argv[i+1] = &argv[i+1][length]; MBSTOWCS(wcs_buffer, NOCATGETS("SUN_MAKE_COMPAT_MODE")); name = GETNAME(wcs_buffer, FIND_LENGTH); dmake_compat_mode_specified = dmake_add_mode_specified; break; } length = strlen( NOCATGETS("DMAKE_OUTPUT_MODE=")); if (strncmp(argv[i+1], NOCATGETS("DMAKE_OUTPUT_MODE="), length) == 0) { argv[i+1] = &argv[i+1][length]; MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_OUTPUT_MODE")); name = GETNAME(wcs_buffer, FIND_LENGTH); dmake_output_mode_specified = dmake_add_mode_specified; } else { warning(catgets(catd, 1, 354, "Unknown argument `%s' after -x flag (ignored)"), argv[i+1]); argv[i] = argv[i + 1] = NULL; continue; } break; default: /* Shouldn't reach here */ 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) { /* * Combine all macro in dynamic array */ 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, wslen(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 { /* Illegal MAKEFLAGS argument */ 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; } } } /* * Append the DMake option and value to the MAKEFLAGS string. */ static void append_makeflags_string(Name name, register String makeflags_string) { char *option; if (strcmp(name->string_mb, NOCATGETS("DMAKE_GROUP")) == 0) { option = NOCATGETS(" -g "); } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_MAX_JOBS")) == 0) { option = NOCATGETS(" -j "); } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_MODE")) == 0) { option = NOCATGETS(" -m "); } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_ODIR")) == 0) { option = NOCATGETS(" -o "); } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_RCFILE")) == 0) { option = NOCATGETS(" -c "); } else if (strcmp(name->string_mb, NOCATGETS("PMAKE_MACHINESFILE")) == 0) { option = NOCATGETS(" -M "); } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_OUTPUT_MODE")) == 0) { option = NOCATGETS(" -x DMAKE_OUTPUT_MODE="); } else if (strcmp(name->string_mb, NOCATGETS("SUN_MAKE_COMPAT_MODE")) == 0) { option = NOCATGETS(" -x SUN_MAKE_COMPAT_MODE="); } else { fatal(catgets(catd, 1, 289, "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); } /* * read_environment(read_only) * * This routine reads the process environment when make starts and enters * it as make macros. The environment variable SHELL is ignored. * * Parameters: * read_only Should we make env vars read only? * * Global variables used: * report_pwd Set if this make was started by other make */ static void read_environment(Boolean read_only) { register char **environment; int length; wchar_t *tmp_wcs_buffer; Boolean alloced_tmp_wcs_buffer = false; register wchar_t *name; register wchar_t *value; register 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 *) wschr(name, (int) equal_char); /* * Looks like there's a bug in the system, but sometimes * you can get blank lines in *environment. */ if (!value) { continue; } MBSTOWCS(wcs_buffer2, NOCATGETS("SHELL=")); if (IS_WEQUALN(name, wcs_buffer2, wslen(wcs_buffer2))) { continue; } MBSTOWCS(wcs_buffer2, NOCATGETS("MAKEFLAGS=")); if (IS_WEQUALN(name, wcs_buffer2, wslen(wcs_buffer2))) { report_pwd = true; /* * In POSIX mode we do not want MAKEFLAGS to be readonly. * If the MAKEFLAGS macro is subsequently set by the makefile, * it replaces the MAKEFLAGS variable currently found in the * environment. * See Assertion 50 in section 6.2.5.3 of standard P1003.3.2/D8. */ if(posix) { read_only_saved = false; } } /* * We ignore SUNPRO_DEPENDENCIES and NSE_DEP. Those * environment variables are set by make and read by * cpp which then writes info to .make.dependency.xxx and * .nse_depinfo. When make is invoked by another make * (recursive make), we don't want to read this because * then the child make will end up writing to the parent * directory's .make.state and .nse_depinfo and clobbering * them. */ MBSTOWCS(wcs_buffer2, NOCATGETS("SUNPRO_DEPENDENCIES")); if (IS_WEQUALN(name, wcs_buffer2, wslen(wcs_buffer2))) { continue; } #ifdef NSE MBSTOWCS(wcs_buffer2, NOCATGETS("NSE_DEP")); if (IS_WEQUALN(name, wcs_buffer2, wslen(wcs_buffer2))) { continue; } #endif 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); } #ifdef NSE /* * Must be after the call to setvar() as it sets * imported to false. */ maybe_append_prop(macro, macro_prop)->body.macro.imported = true; #endif 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; } /* * read_makefile(makefile, complain, must_exist, report_file) * * Read one makefile and check the result * * Return value: * false is the read failed * * Parameters: * makefile The file to read * complain Passed thru to read_simple_file() * must_exist Passed thru to read_simple_file() * report_file Passed thru to read_simple_file() * * Global variables used: * makefile_type Set to indicate we are reading main file * recursion_level Initialized */ static Boolean read_makefile(register Name makefile, Boolean complain, Boolean must_exist, Boolean report_file) { Boolean b; makefile_type = reading_makefile; recursion_level = 0; #ifdef NSE wscpy(current_makefile, makefile->string); #endif reading_dependencies = true; b = read_simple_file(makefile, true, true, complain, must_exist, report_file, false); reading_dependencies = false; return b; } /* * make_targets(argc, argv, parallel_flag) * * Call doname on the specified targets * * Parameters: * argc You know what this is * argv You know what this is * parallel_flag True if building in parallel * * Global variables used: * build_failed_seen Used to generated message after failed -k * commands_done Used to generate message "Up to date" * default_target_to_build First proper target in makefile * init The Name ".INIT", use to run command * parallel Global parallel building flag * quest make -q, suppresses messages * recursion_level Initialized, used for tracing * report_dependencies make -P, regroves whole process */ static void make_targets(int argc, char **argv, Boolean parallel_flag) { int i; char *cp; Doname result; register Boolean target_to_make_found = false; (void) doname(init, true, true); recursion_level = 1; parallel = parallel_flag; /* * make remaining args */ #ifdef TEAMWARE_MAKE_CMN /* if ((report_dependencies_level == 0) && parallel) { */ if (parallel) { /* * If building targets in parallel, start all of the * remaining args to build in 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 = GETNAME(wcs_buffer, // FIND_LENGTH); default_target_to_build = normalize_name(wcs_buffer, wslen(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 we can't execute the current target in * parallel, hold off the target processing * to preserve the order of the targets as they appeared * in command line. */ 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 (/* !commands_done && */ (result == build_ok) && !quest && (report_dependencies_level == 0) /* && (exists(default_target_to_build) > file_doesnt_exist) */) { if (posix) { if (!commands_done) { (void) printf(catgets(catd, 1, 293, "`%s' is updated.\n"), default_target_to_build->string_mb); } else { if (no_action_was_taken) { (void) printf(catgets(catd, 1, 294, "`%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(catgets(catd, 1, 295, "`%s' is up to date.\n"), default_target_to_build->string_mb); } } } } } /* Now wait for all of the targets to finish running */ finish_running(); // setjmp(jmpbuffer); } #endif 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, wslen(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(catgets(catd, 1, 200, "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 && /* !commands_done && */ (result == build_ok) && !quest && (report_dependencies_level == 0) /* && (exists(default_target_to_build) > file_doesnt_exist) */) { if (posix) { if (!commands_done) { (void) printf(catgets(catd, 1, 296, "`%s' is updated.\n"), default_target_to_build->string_mb); } else { if (no_action_was_taken) { (void) printf(catgets(catd, 1, 297, "`%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(catgets(catd, 1, 298, "`%s' is up to date.\n"), default_target_to_build->string_mb); } } } } } /* * If no file arguments have been encountered, * make the first name encountered that doesnt start with a dot */ if (!target_to_make_found) { if (default_target_to_build == NULL) { fatal(catgets(catd, 1, 202, "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(NOCATGETS("SPRO_EXPAND_ERRORS"))){ (void) printf(NOCATGETS("::(%s)\n"), default_target_to_build->string_mb); } #ifdef TEAMWARE_MAKE_CMN result = doname_parallel(default_target_to_build, true, false); #else result = doname_check(default_target_to_build, true, false, false); #endif gather_recursive_deps(); if (build_failed_seen) { build_failed_ever_seen = true; warning(catgets(catd, 1, 203, "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 (/* !commands_done && */ (result == build_ok) && !quest && (report_dependencies_level == 0) /* && (exists(default_target_to_build) > file_doesnt_exist) */) { if (posix) { if (!commands_done) { (void) printf(catgets(catd, 1, 299, "`%s' is updated.\n"), default_target_to_build->string_mb); } else { if (no_action_was_taken) { (void) printf(catgets(catd, 1, 300, "`%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(catgets(catd, 1, 301, "`%s' is up to date.\n"), default_target_to_build->string_mb); } } } } } /* * report_recursion(target) * * If this is a recursive make and the parent make has KEEP_STATE on * this routine reports the dependency to the parent make * * Parameters: * target Target to report * * Global variables used: * makefiles_used List of makefiles read * recursive_name The Name ".RECURSIVE", printed * report_dependency dwight */ static void report_recursion(register Name target) { register FILE *report_file = get_report_file(); if ((report_file == NULL) || (report_file == (FILE*)-1)) { return; } if (primary_makefile == NULL) { /* * This can happen when there is no makefile and * only implicit rules are being used. */ #ifdef NSE nse_no_makefile(target); #endif 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"); } /* Next function "append_or_replace_macro_in_dyn_array" must be in "misc.cc". */ /* NIKMOL */ extern void append_or_replace_macro_in_dyn_array(ASCII_Dyn_Array *Ar, char *macro) { register char *cp0; /* work pointer in macro */ register char *cp1; /* work pointer in array */ register char *cp2; /* work pointer in array */ register char *cp3; /* work pointer in array */ register char *name; /* macro name */ register char *value; /* macro value */ register int len_array; register 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))) { /* no '=' in macro */ goto ERROR_MACRO; } cp0 = value; value++; while (isspace(*(value))) { value++; } while (isspace(*(cp0-1))) { cp0--; } if (cp0 <= name) goto ERROR_MACRO; /* no name */ 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))) { /* another name */ cp1++; goto LOOK_FOR_NAME; } if (cp1 != Ar->start) { if (!isspace(*(cp1-1))) { /* another name */ cp1++; goto LOOK_FOR_NAME; } } for (cp3 = cp1 + (cp0-name); cp3 < cp2; cp3++) { if (isspace(*cp3)) continue; /* else: another name */ cp1++; goto LOOK_FOR_NAME; } /* Look for the next macro name in array */ cp3 = cp2+1; if (*cp3 != (int) doublequote_char) { /* internal error */ goto ERROR_MACRO; } if (!(cp3 = strchr(cp3+1, (int) doublequote_char))) { /* internal error */ goto ERROR_MACRO; } cp3++; while (isspace(*cp3)) { cp3++; } cp2 = cp1; /* remove old macro */ 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) { /* check next name */ 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: /* Macro without '=' or with invalid left/right part */ return; } #ifdef TEAMWARE_MAKE_CMN /* * This function, if registered w/ avo_cli_get_license(), will be called * if the application is about to exit because: * 1) there has been certain unrecoverable error(s) that cause the * application to exit immediately. * 2) the user has lost a license while the application is running. */ extern "C" void dmake_exit_callback(void) { fatal(catgets(catd, 1, 306, "can not get a license, exiting...")); exit(1); } /* * This function, if registered w/ avo_cli_get_license(), will be called * if the application can not get a license. */ extern "C" void dmake_message_callback(char *err_msg) { static Boolean first = true; if (!first) { return; } first = false; if ((!list_all_targets) && (report_dependencies_level == 0) && (dmake_mode_type != serial_mode)) { warning(catgets(catd, 1, 313, "can not get a TeamWare license, defaulting to serial mode...")); } } #endif #ifdef DISTRIBUTED /* * Returns whether -c is set or not. */ Boolean get_dmake_rcfile_specified(void) { return(dmake_rcfile_specified); } /* * Returns whether -g is set or not. */ Boolean get_dmake_group_specified(void) { return(dmake_group_specified); } /* * Returns whether -j is set or not. */ Boolean get_dmake_max_jobs_specified(void) { return(dmake_max_jobs_specified); } /* * Returns whether -m is set or not. */ Boolean get_dmake_mode_specified(void) { return(dmake_mode_specified); } /* * Returns whether -o is set or not. */ Boolean get_dmake_odir_specified(void) { return(dmake_odir_specified); } #endif 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(NOCATGETS("MAKELEVEL")); if(make_level_str) { make_level_val = atoi(make_level_str); } if(mlev == NULL) { mlev = (char*) malloc(MAXPATHLEN); } if(entering) { sprintf(mlev, NOCATGETS("MAKELEVEL=%d"), make_level_val + 1); } else { make_level_val--; sprintf(mlev, NOCATGETS("MAKELEVEL=%d"), make_level_val); } putenv(mlev); if(report_cwd) { if(make_level_val <= 0) { if(entering) { #ifdef TEAMWARE_MAKE_CMN sprintf( rcwd , catgets(catd, 1, 329, "dmake: Entering directory `%s'\n") , get_current_path()); #else sprintf( rcwd , catgets(catd, 1, 330, "make: Entering directory `%s'\n") , get_current_path()); #endif } else { #ifdef TEAMWARE_MAKE_CMN sprintf( rcwd , catgets(catd, 1, 331, "dmake: Leaving directory `%s'\n") , get_current_path()); #else sprintf( rcwd , catgets(catd, 1, 332, "make: Leaving directory `%s'\n") , get_current_path()); #endif } } else { if(entering) { #ifdef TEAMWARE_MAKE_CMN sprintf( rcwd , catgets(catd, 1, 333, "dmake[%d]: Entering directory `%s'\n") , make_level_val, get_current_path()); #else sprintf( rcwd , catgets(catd, 1, 334, "make[%d]: Entering directory `%s'\n") , make_level_val, get_current_path()); #endif } else { #ifdef TEAMWARE_MAKE_CMN sprintf( rcwd , catgets(catd, 1, 335, "dmake[%d]: Leaving directory `%s'\n") , make_level_val, get_current_path()); #else sprintf( rcwd , catgets(catd, 1, 336, "make[%d]: Leaving directory `%s'\n") , make_level_val, get_current_path()); #endif } } printf(NOCATGETS("%s"), rcwd); } }