"Fossies" - the Fresh Open Source Software Archive

Member "schily-2021-09-18/sunpro/Make/bin/make/common/main.cc" (30 Aug 2021, 115191 Bytes) of package /linux/privat/schily-2021-09-18.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "main.cc" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes reports: 2021-08-14_vs_2021-09-18 or 2021-07-29_vs_2021-09-18.

A hint: This file contains one or more very long lines, so maybe it is better readable using the pure text view mode that shows the contents as wrapped lines within the browser window.


    1 /*
    2  * CDDL HEADER START
    3  *
    4  * This file and its contents are supplied under the terms of the
    5  * Common Development and Distribution License ("CDDL"), version 1.0.
    6  * You may use this file only in accordance with the terms of version
    7  * 1.0 of the CDDL.
    8  *
    9  * A full copy of the text of the CDDL should have accompanied this
   10  * source.  A copy of the CDDL is also available via the Internet at
   11  * http://www.opensource.org/licenses/cddl1.txt
   12  * See the License for the specific language governing permissions
   13  * and limitations under the License.
   14  *
   15  * When distributing Covered Code, include this CDDL HEADER in each
   16  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
   17  * If applicable, add the following below this CDDL HEADER, with the
   18  * fields enclosed by brackets "[]" replaced with your own identifying
   19  * information: Portions Copyright [yyyy] [name of copyright owner]
   20  *
   21  * CDDL HEADER END
   22  */
   23 /*
   24  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
   25  * Use is subject to license terms.
   26  */
   27 /*
   28  * @(#)main.cc 1.158 06/12/12
   29  */
   30 
   31 #pragma ident   "@(#)main.cc    1.158   06/12/12"
   32 
   33 /*
   34  * Copyright 2017-2021 J. Schilling
   35  *
   36  * @(#)main.cc  1.60 21/08/30 2017-2021 J. Schilling
   37  */
   38 #include <schily/mconfig.h>
   39 #ifndef lint
   40 static  UConst char sccsid[] =
   41     "@(#)main.cc    1.60 21/08/30 2017-2021 J. Schilling";
   42 #endif
   43 
   44 /*
   45  *  main.cc
   46  *
   47  *  make program main routine plus some helper routines
   48  */
   49  
   50 /*
   51  * Included files
   52  */
   53 #if defined(TEAMWARE_MAKE_CMN)
   54 #       include <avo/intl.h>
   55 #       include <avo/libcli.h>          /* libcli_init() */
   56 #   include <avo/cli_license.h> /* avo_cli_get_license() */
   57 #   include <avo/find_dir.h>    /* avo_find_run_dir() */
   58 #   include <avo/version_string.h>
   59 #   include <avo/util.h>        /* avo_init() */
   60 #ifdef USE_DMS_CCR
   61 #   include <avo/usage_tracking.h>
   62 #else
   63 #   include <avo/cleanup.h>
   64 #endif
   65 #endif
   66 
   67 #if defined(TEAMWARE_MAKE_CMN)
   68 /* This is for dmake only (not for Solaris make).
   69  * Include code to check updates (dmake patches)
   70  */
   71 #ifdef _CHECK_UPDATE_H
   72 #include <libAU.h>
   73 #endif
   74 #endif
   75 
   76 #include <bsd/bsd.h>        /* bsd_signal() */
   77 
   78 #ifdef DISTRIBUTED
   79 #   include <dm/Avo_AcknowledgeMsg.h>
   80 #   include <rw/xdrstrea.h>
   81 #   include <dmrc/dmrc.h> /* dmakerc file processing */
   82 #endif
   83 
   84 #if defined(SCHILY_BUILD) || defined(SCHILY_INCLUDES)
   85 #include <schily/locale.h>  /* setlocale() */
   86 #else
   87 #include <locale.h>     /* setlocale() */
   88 #endif
   89 #include <mk/copyright.h>
   90 #include <mk/defs.h>
   91 #include <mksh/macro.h>     /* getvar() */
   92 #include <mksh/misc.h>      /* getmem(), setup_char_semantics() */
   93 
   94 #if defined(TEAMWARE_MAKE_CMN)
   95 #ifdef USE_DMS_CCR
   96 #   include <pubdmsi18n/pubdmsi18n.h>   /* libpubdmsi18n_init() */
   97 #endif
   98 #endif
   99 
  100 #if defined(SCHILY_BUILD) || defined(SCHILY_INCLUDES)
  101 #include <schily/pwd.h>     /* getpwnam() */
  102 #include <schily/setjmp.h>
  103 
  104 #include <schily/wait.h>    /* wait() */
  105 #else
  106 #include <pwd.h>        /* getpwnam() */
  107 #include <setjmp.h>
  108 
  109 #include <sys/wait.h>       /* wait() */
  110 #define WAIT_T  int
  111 #endif
  112 #include <vroot/report.h>   /* report_dependency(), get_report_file() */
  113 
  114 // From read2.cc
  115 extern  Name        normalize_name(register wchar_t *name_string, register int length);
  116 
  117 // From parallel.cc
  118 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
  119 #define MAXJOBS_ADJUST_RFE4694000
  120 
  121 #ifdef MAXJOBS_ADJUST_RFE4694000
  122 extern void job_adjust_fini();
  123 #endif /* MAXJOBS_ADJUST_RFE4694000 */
  124 #endif /* TEAMWARE_MAKE_CMN */
  125 
  126 #include <ctype.h>
  127 
  128 #ifdef  HAVE_LIBGEN_H
  129 #include <libgen.h>
  130 #endif
  131 #include <schily/schily.h>
  132 
  133 #ifdef  ultrix      /* No prototypes in SIG_DFL macro */
  134 #undef  SUN5_0
  135 #endif
  136 
  137 /*
  138  * Defined macros
  139  */
  140 #define LD_SUPPORT_ENV_VAR  NOCATGETS("SGS_SUPPORT")
  141 #define LD_SUPPORT_ENV_VAR_32   NOCATGETS("SGS_SUPPORT_32")
  142 #define LD_SUPPORT_ENV_VAR_64   NOCATGETS("SGS_SUPPORT_64")
  143 #define LD_SUPPORT_MAKE_LIB NOCATGETS("libmakestate.so.1")
  144 #ifdef  sun
  145 #ifdef  __i386
  146 #define LD_SUPPORT_MAKE_ARCH    "i386/"
  147 #endif
  148 #ifdef  __sparc
  149 #define LD_SUPPORT_MAKE_ARCH    "sparc/"
  150 #endif
  151 #endif  /* sun */
  152 
  153 /*
  154  * typedefs & structs
  155  */
  156 
  157 /*
  158  * Static variables
  159  */
  160 static  char        *argv_zero_string;
  161 static  char        *argv_zero_base;
  162 static  char        *dmake_compat_value;
  163 static  Boolean     build_failed_ever_seen;
  164 static  Boolean     continue_after_error_ever_seen; /* `-k' */
  165 static  Boolean     dmake_group_specified;      /* `-g' */
  166 static  Boolean     dmake_max_jobs_specified;   /* `-j' */
  167 static  Boolean     dmake_mode_specified;       /* `-m' */
  168 static  Boolean     dmake_add_mode_specified;   /* `-x' */
  169 static  Boolean     dmake_output_mode_specified;    /* `-x DMAKE_OUTPUT_MODE=' */
  170 static  Boolean     dmake_compat_mode_specified;    /* `-x SUN_MAKE_COMPAT_MODE=' */
  171 static  Boolean     dmake_odir_specified;       /* `-o' */
  172 static  Boolean     dmake_rcfile_specified;     /* `-c' */
  173 static  Boolean     env_wins;           /* `-e' */
  174 static  Boolean     ignore_default_mk;      /* `-r' */
  175 static  Boolean     list_all_targets;       /* `-T' */
  176 static  int     mf_argc;
  177 static  char        **mf_argv;
  178 static  Dependency_rec  not_auto_depen_struct;
  179 static  Dependency  not_auto_depen = &not_auto_depen_struct;
  180 static  Boolean     pmake_cap_r_specified;      /* `-R' */
  181 static  Boolean     pmake_machinesfile_specified;   /* `-M' */
  182 static  Boolean     stop_after_error_ever_seen; /* `-S' */
  183 static  Boolean     trace_status;           /* `-p' */
  184 
  185 #ifdef DMAKE_STATISTICS
  186 static  Boolean     getname_stat = false;
  187 #endif
  188 
  189     static  int     g_argc;
  190     static  char        **g_argv;
  191 #if defined(TEAMWARE_MAKE_CMN)
  192     static  time_t      start_time;
  193 #ifdef USE_DMS_CCR
  194     static  Avo_usage_tracking *usageTracking = NULL;
  195 #else
  196     static  Avo_cleanup *cleanup = NULL;
  197 #endif
  198 #endif
  199 
  200 /*
  201  * File table of contents
  202  */
  203 #ifdef  HAVE_ATEXIT
  204     extern "C" void     cleanup_after_exit(void);
  205 #else
  206     extern  void        cleanup_after_exit(int, ...);
  207 #endif
  208 
  209 #ifdef TEAMWARE_MAKE_CMN
  210 extern "C" {
  211     extern  void        dmake_exit_callback(void);
  212     extern  void        dmake_message_callback(char *);
  213 }
  214 #endif
  215 
  216 extern  Name        normalize_name(register wchar_t *name_string, register int length);
  217 
  218 extern  int     main(int, char * []);
  219 
  220 static  void        scan_dmake_compat_mode(char *);
  221 static  void        append_makeflags_string(Name, String);
  222 static  void        doalarm(int);
  223 static  void        enter_argv_values(int , char **, ASCII_Dyn_Array *);
  224 static  void        make_targets(int, char **, Boolean);
  225 static  int     parse_command_option(char);
  226 static  void        read_command_options(int, char **);
  227 static  void        read_environment(Boolean);
  228 static  void        read_files_and_state(int, char **);
  229 static  Boolean     read_makefile(Name, Boolean, Boolean, Boolean);
  230 static  void        report_recursion(Name);
  231 static  void        set_sgs_support(void);
  232 static  void        setup_for_projectdir(void);
  233 static  void        setup_makeflags_argv(void);
  234 static  void        dir_enter_leave(Boolean entering);
  235 static  void        report_dir_enter_leave(Boolean entering);
  236 
  237 
  238 #ifdef DISTRIBUTED
  239     extern  int     dmake_ofd;
  240     extern  FILE*       dmake_ofp;
  241     extern  int     rxmPid;
  242     extern  XDR         xdrs_out;
  243 #endif
  244 #ifdef TEAMWARE_MAKE_CMN
  245     extern  char        verstring[];
  246 #else
  247 #if defined(SCHILY_BUILD) || defined(SCHILY_INCLUDES)
  248     extern  char        verstring[];
  249 #endif
  250 #endif
  251 
  252 jmp_buf jmpbuffer;
  253 
  254 /*
  255  *  main(argc, argv)
  256  *
  257  *  Parameters:
  258  *      argc            You know what this is
  259  *      argv            You know what this is
  260  *
  261  *  Static variables used:
  262  *      list_all_targets    make -T seen
  263  *      trace_status        make -p seen
  264  *
  265  *  Global variables used:
  266  *      debug_level     Should we trace make actions?
  267  *      keep_state      Set if .KEEP_STATE seen
  268  *      makeflags       The Name "MAKEFLAGS", used to get macro
  269  *      remote_command_name Name of remote invocation cmd ("on")
  270  *      running_list        List of parallel running processes
  271  *      stdout_stderr_same  true if stdout and stderr are the same
  272  *      auto_dependencies   The Name "SUNPRO_DEPENDENCIES"
  273  *      temp_file_directory Set to the dir where we create tmp file
  274  *      trace_reader        Set to reflect tracing status
  275  *      working_on_targets  Set when building user targets
  276  */
  277 int
  278 main(int argc, char *argv[])
  279 {
  280     /*
  281      * cp is a -> to the value of the MAKEFLAGS env var,
  282      * which has to be regular chars.
  283      */
  284     register char       *cp;
  285     char            make_state_dir[MAXPATHLEN];
  286     Boolean         parallel_flag = false;
  287     char            *prognameptr;
  288     char            *slash_ptr;
  289     mode_t          um;
  290     int         i;
  291 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
  292     struct itimerval    value;
  293     char            def_dmakerc_path[MAXPATHLEN];
  294     Name            dmake_name, dmake_name2;
  295     Name            dmake_value, dmake_value2;
  296     Property        prop, prop2;
  297     struct stat     statbuf;
  298     int         statval;
  299 #endif
  300 
  301 #ifndef PARALLEL
  302     struct stat     out_stat, err_stat;
  303 #endif
  304     hostid = gethostid();
  305 #ifdef TEAMWARE_MAKE_CMN
  306     avo_get_user(NULL, NULL); // Initialize user name
  307 #endif
  308     bsd_signals();
  309 
  310     (void) setlocale(LC_ALL, "");
  311 
  312 #ifdef DMAKE_STATISTICS
  313     if (getenv(NOCATGETS("DMAKE_STATISTICS"))) {
  314         getname_stat = true;
  315     }
  316 #endif
  317 
  318 
  319     /*
  320      * avo_init() sets the umask to 0.  Save it here and restore
  321      * it after the avo_init() call.
  322      */
  323 #if defined(TEAMWARE_MAKE_CMN) || defined(MAKETOOL)
  324     um = umask(0);
  325     avo_init(argv[0]);
  326     umask(um);
  327 
  328 #ifdef USE_DMS_CCR
  329     usageTracking = new Avo_usage_tracking(NOCATGETS("dmake"), argc, argv);
  330 #else
  331     cleanup = new Avo_cleanup(NOCATGETS("dmake"), argc, argv);
  332 #endif
  333 #endif
  334 
  335 #if defined(TEAMWARE_MAKE_CMN)
  336     libcli_init();
  337 
  338 #ifdef _CHECK_UPDATE_H
  339     /* This is for dmake only (not for Solaris make).
  340      * Check (in background) if there is an update (dmake patch)
  341      * and inform user
  342      */
  343     {
  344         Avo_err     *err;
  345         char        *dir;
  346         err = avo_find_run_dir(&dir);
  347         if (AVO_OK == err) {
  348             AU_check_update_service(NOCATGETS("Dmake"), dir);
  349         }
  350     }
  351 #endif /* _CHECK_UPDATE_H */
  352 #endif
  353 
  354 // ---> fprintf(stderr, gettext("--- SUN make ---\n"));
  355 
  356 
  357 #if defined(TEAMWARE_MAKE_CMN) || defined(MAKETOOL)
  358 /*
  359  * I put libmksdmsi18n_init() under #ifdef because it requires avo_i18n_init()
  360  * from avo_util library. 
  361  */
  362     libmksdmsi18n_init();
  363 #ifdef USE_DMS_CCR
  364     libpubdmsi18n_init();
  365 #endif
  366 #endif
  367 
  368 #if !defined(TEXT_DOMAIN)   /* Should be defined by CC -D */
  369 #define TEXT_DOMAIN "SYS_TEST"  /* Use this only if it weren't */
  370 #endif
  371     textdomain(TEXT_DOMAIN);
  372 
  373     g_argc = argc;
  374     g_argv = (char **) malloc((g_argc + 1) * sizeof(char *));
  375     for (i = 0; i < argc; i++) {
  376         g_argv[i] = argv[i];
  377     }
  378     g_argv[i] = NULL;
  379 
  380     /*
  381      * Set argv_zero_string to some form of argv[0] for
  382      * recursive MAKE builds.
  383      */
  384 
  385     if (*argv[0] == (int) slash_char) {
  386         /* argv[0] starts with a slash */
  387         argv_zero_string = strdup(argv[0]);
  388     } else if (strchr(argv[0], (int) slash_char) == NULL) {
  389         /* argv[0] contains no slashes */
  390         argv_zero_string = strdup(argv[0]);
  391     } else {
  392         /*
  393          * argv[0] contains at least one slash,
  394          * but doesn't start with a slash
  395          * so it is relative to the current working directory.
  396          * Build an absolute path name for argv[0] to the called make
  397          * binary path before we may do a chdir() from a -C option.
  398          */
  399         char    *tmp_current_path;
  400         char    *tmp_string;
  401 
  402         tmp_current_path = get_current_path();
  403         tmp_string = getmem(strlen(tmp_current_path) + 1 +
  404                             strlen(argv[0]) + 1);
  405         (void) sprintf(tmp_string,
  406                        "%s/%s",
  407                        tmp_current_path,
  408                        argv[0]);
  409         argv_zero_string = strdup(tmp_string);
  410         retmem_mb(tmp_string);
  411     }
  412     if ((argv_zero_base = strrchr(argv_zero_string, '/')) == NULL)
  413         argv_zero_base = argv_zero_string;
  414     else
  415         argv_zero_base++;
  416 
  417     /* 
  418      * The following flags are reset if we don't have the 
  419      * (.nse_depinfo or .make.state) files locked and only set 
  420      * AFTER the file has been locked. This ensures that if the user
  421      * interrupts the program while file_lock() is waiting to lock
  422      * the file, the interrupt handler doesn't remove a lock 
  423      * that doesn't belong to us.
  424      */
  425     make_state_lockfile = NULL;
  426     make_state_locked = false;
  427 
  428 #ifdef NSE
  429     nse_depinfo_lockfile[0] = '\0';
  430     nse_depinfo_locked = false; 
  431 #endif
  432 
  433     /*
  434      * look for last slash char in the path to look at the binary 
  435      * name. This is to resolve the hard link and invoke make
  436      * in svr4 mode.
  437      *
  438      * WARNING: /usr/bin/make and /usr/xpg4/bin/make must be
  439      *  hardlinked or we will not be able to distinct them.
  440      */
  441 
  442     /* Sun OS make standard */
  443     svr4 = false;  
  444     posix = false;
  445     make_run_dir = find_run_dir();
  446     if(!strcmp(argv_zero_string, NOCATGETS("/usr/xpg4/bin/make"))) {
  447         svr4 = false;
  448         posix = true;
  449     } else if (make_run_dir && (cp = strstr(make_run_dir, "xpg4/bin")) &&
  450         strcmp(cp, "xpg4/bin") == 0) {
  451         svr4 = false;
  452         posix = true;
  453     } else if ((cp = strstr(argv_zero_string, "xpg4/bin/make")) &&
  454         strcmp(cp, "xpg4/bin/make") == 0) {
  455         svr4 = false;
  456         posix = true;
  457     } else {
  458         prognameptr = strrchr(argv[0], '/');
  459         if(prognameptr) {
  460             prognameptr++;
  461         } else {
  462             prognameptr = argv[0];
  463         }
  464         if(!strcmp(prognameptr, NOCATGETS("svr4.make"))) {
  465             svr4 = true;
  466             posix = false;
  467         }
  468     }
  469     if (getenv(USE_SVR4_MAKE) || getenv(NOCATGETS("USE_SVID"))){
  470        svr4 = true;
  471        posix = false;
  472     }
  473 
  474     /*
  475      * Find the dmake_compat_mode: posix, sun, svr4, or gnu_style.
  476      */
  477     scan_dmake_compat_mode(getenv(NOCATGETS("SUN_MAKE_COMPAT_MODE")));
  478 
  479     /*
  480      * Temporary directory set up.
  481      */
  482     char * tmpdir_var = getenv(NOCATGETS("TMPDIR"));
  483     if (tmpdir_var != NULL && *tmpdir_var == '/' && strlen(tmpdir_var) < MAXPATHLEN) {
  484         strcpy(mbs_buffer, tmpdir_var);
  485         for (tmpdir_var = mbs_buffer+strlen(mbs_buffer);
  486             *(--tmpdir_var) == '/' && tmpdir_var > mbs_buffer;
  487             *tmpdir_var = '\0');
  488         if (strlen(mbs_buffer) + 32 < MAXPATHLEN) { /* 32 = strlen("/dmake.stdout.%d.%d.XXXXXX") */
  489             sprintf(mbs_buffer2, NOCATGETS("%s/dmake.tst.%d.XXXXXX"),
  490                 mbs_buffer, getpid());
  491             int fd = mkstemp(mbs_buffer2);
  492             if (fd >= 0) {
  493                 close(fd);
  494                 unlink(mbs_buffer2);
  495                 tmpdir = strdup(mbs_buffer);
  496             }
  497         }
  498     }
  499 
  500 #ifndef PARALLEL
  501     /* find out if stdout and stderr point to the same place */
  502     if (fstat(1, &out_stat) < 0) {
  503         fatal(gettext("fstat of standard out failed: %s"), errmsg(errno));
  504     }
  505     if (fstat(2, &err_stat) < 0) {
  506         fatal(gettext("fstat of standard error failed: %s"), errmsg(errno));
  507     }
  508     if ((out_stat.st_dev == err_stat.st_dev) &&
  509         (out_stat.st_ino == err_stat.st_ino)) {
  510         stdout_stderr_same = true;
  511     } else {
  512         stdout_stderr_same = false;
  513     }
  514 #else
  515     stdout_stderr_same = false;
  516 #endif
  517     /* Make the vroot package scan the path using shell semantics */
  518     set_path_style(0);
  519 
  520     setup_char_semantics();
  521 
  522     /*
  523      * If running with .KEEP_STATE, curdir will be set with
  524      * the connected directory.
  525      */
  526 #ifdef  HAVE_ATEXIT
  527     (void) atexit(cleanup_after_exit);
  528 #else
  529     (void) on_exit(cleanup_after_exit, (char *) NULL);
  530 #endif
  531 
  532     load_cached_names();
  533 
  534 /*
  535  *  Set command line flags
  536  *
  537  *  Warning: Do not keep pointers from get_current_path() calls while
  538  *  parsing the options as they could become invalid from a -C option.
  539  */
  540     setup_makeflags_argv();
  541     read_command_options(mf_argc, mf_argv);
  542     read_command_options(argc, argv);
  543     if (debug_level > 0) {
  544         cp = getenv(makeflags->string_mb);
  545         (void) printf(gettext("MAKEFLAGS value: %s\n"), cp == NULL ? "" : cp);
  546     }
  547     if (dmake_compat_value) {   /* -x SUN_MAKE_COMPAT_MODE=xxx */
  548         char    *p = strchr(dmake_compat_value, '='); /* != NULL */
  549 
  550         scan_dmake_compat_mode(++p);
  551 
  552         /*
  553          * Calling setup_char_semantics() again is needed in case that
  554          * svr4 did change it's value.
  555          */
  556         for (i = 0; i < CHAR_SEMANTICS_ENTRIES; i++)
  557             char_semantics[i] = 0; 
  558         setup_char_semantics();
  559     }
  560 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
  561     if (posix)
  562         job_adjust_posix();     /* DMAKE_ADJUST_MAX_JOBS=M2 */
  563 #endif
  564 
  565     /*
  566      * If there have been -C options, they have been evaluated with the
  567      * last call to read_command_options() and we thus may need to
  568      * re-initialize CURDIR before we read the Makefiles in order to let
  569      * them overwrite CURDIR if they like.
  570      */
  571     if (current_path_reset)
  572         (void) get_current_path();
  573     /*
  574      * Need to set this up after parsing options and after a
  575      * possible -C option has been processed.
  576      */
  577     setup_for_projectdir();
  578 
  579     dir_enter_leave(true);          /* Must be before next call */
  580     setup_interrupt(handle_interrupt);
  581 
  582     read_files_and_state(argc, argv);
  583 
  584 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
  585     /*
  586      * Find the dmake_output_mode: TXT1, TXT2 or HTML1.
  587      */
  588     MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_OUTPUT_MODE"));
  589     dmake_name2 = GETNAME(wcs_buffer, FIND_LENGTH);
  590     prop2 = get_prop(dmake_name2->prop, macro_prop);
  591     if (prop2 == NULL) {
  592         /* DMAKE_OUTPUT_MODE not defined, default to TXT1 mode */
  593         output_mode = txt1_mode;
  594     } else {
  595         dmake_value2 = prop2->body.macro.value;
  596         if ((dmake_value2 == NULL) ||
  597             (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("TXT1")))) {
  598             output_mode = txt1_mode;
  599         } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("TXT2"))) {
  600             output_mode = txt2_mode;
  601         } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("HTML1"))) {
  602             output_mode = html1_mode;
  603         } else {
  604             warning(gettext("Unsupported value `%s' for DMAKE_OUTPUT_MODE after -x flag (ignored)"),
  605                   dmake_value2->string_mb);
  606         }
  607     }
  608     /*
  609      * Find the dmake_mode: distributed, parallel, or serial.
  610      */
  611 #ifdef  DO_NOTPARALLEL
  612     if (notparallel) {
  613     dmake_mode_type = serial_mode;
  614     no_parallel = true;
  615     } else
  616 #endif
  617     if ((!pmake_cap_r_specified) &&
  618         (!pmake_machinesfile_specified)) {
  619     MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE"));
  620     dmake_name2 = GETNAME(wcs_buffer, FIND_LENGTH);
  621     prop2 = get_prop(dmake_name2->prop, macro_prop);
  622 
  623     if ((IS_EQUAL(argv_zero_base, NOCATGETS("make")) ||
  624         IS_EQUAL(argv_zero_base, NOCATGETS("svr4.make"))) &&
  625         !dmake_max_jobs_specified) {
  626         /*
  627          * "make" and "svr4.make" default to serial mode, except when
  628          * -j was specified.
  629          */
  630         dmake_mode_type = serial_mode;
  631         no_parallel = true;
  632     } else if (prop2 == NULL) {
  633 #ifdef TEAMWARE_MAKE_CMN
  634         /* DMAKE_MODE not defined, default to distributed mode */
  635         dmake_mode_type = distributed_mode;
  636         no_parallel = false;
  637 #else
  638         /*
  639          * If we ever implement support for something like the TeamWare
  640          * .dmakerc, we need to move the printout down after the check
  641          * for the .dmakerc file.
  642          */
  643         if (getenv(NOCATGETS("DMAKE_DEF_PRINTED")) == NULL) {
  644             putenv((char *)NOCATGETS("DMAKE_DEF_PRINTED=TRUE"));
  645             (void) fprintf(stdout, gettext("dmake: defaulting to parallel mode.\n"));
  646         }
  647         dmake_mode_type = parallel_mode;
  648         no_parallel = false;        
  649 #endif
  650     } else {
  651         dmake_value2 = prop2->body.macro.value;
  652         if ((dmake_value2 == NULL) ||
  653             (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("distributed")))) {
  654             dmake_mode_type = distributed_mode;
  655             no_parallel = false;
  656         } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("parallel"))) {
  657             dmake_mode_type = parallel_mode;
  658             no_parallel = false;
  659 #ifdef SGE_SUPPORT
  660             grid = false;
  661         } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("grid"))) {
  662             dmake_mode_type = parallel_mode;
  663             no_parallel = false;
  664             grid = true;
  665 #endif
  666         } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("serial"))) {
  667             dmake_mode_type = serial_mode;
  668             no_parallel = true;
  669         } else {
  670             fatal(gettext("Unknown dmake mode argument `%s' after -m flag"), dmake_value2->string_mb);
  671         }
  672     }
  673 
  674     if ((!list_all_targets) &&
  675         (report_dependencies_level == 0)) {
  676         /*
  677          * Check to see if either DMAKE_RCFILE or DMAKE_MODE is defined.
  678          * They could be defined in the env, in the makefile, or on the
  679          * command line.
  680          * If neither is defined, and $(HOME)/.dmakerc does not exists,
  681          * then print a message, and default to parallel mode.
  682          */
  683 #ifdef DISTRIBUTED
  684         MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_RCFILE"));
  685         dmake_name = GETNAME(wcs_buffer, FIND_LENGTH);
  686         MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE"));
  687         dmake_name2 = GETNAME(wcs_buffer, FIND_LENGTH);
  688         if ((((prop = get_prop(dmake_name->prop, macro_prop)) == NULL) ||
  689              ((dmake_value = prop->body.macro.value) == NULL)) &&
  690             (((prop2 = get_prop(dmake_name2->prop, macro_prop)) == NULL) ||
  691              ((dmake_value2 = prop2->body.macro.value) == NULL))) {
  692             Boolean empty_dmakerc = true;
  693             char *homedir = getenv(NOCATGETS("HOME"));
  694             if ((homedir != NULL) && (strlen(homedir) < (sizeof(def_dmakerc_path) - 16))) {
  695                 sprintf(def_dmakerc_path, NOCATGETS("%s/.dmakerc"), homedir);
  696                 if ((((statval = stat(def_dmakerc_path, &statbuf)) != 0) && (errno == ENOENT)) ||
  697                     ((statval == 0) && (statbuf.st_size == 0))) {
  698                 } else {
  699                     Avo_dmakerc *rcfile = new Avo_dmakerc();
  700                     Avo_err     *err = rcfile->read(def_dmakerc_path, NULL, TRUE);
  701                     if (err) {
  702                         fatal(err->str);
  703                     }
  704                     empty_dmakerc = rcfile->was_empty();
  705                     delete rcfile;
  706                 }
  707             }
  708             if (empty_dmakerc) {
  709                 if (getenv(NOCATGETS("DMAKE_DEF_PRINTED")) == NULL) {
  710                     putenv((char *)NOCATGETS("DMAKE_DEF_PRINTED=TRUE"));
  711                     (void) fprintf(stdout, gettext("dmake: defaulting to parallel mode.\n"));
  712                     (void) fprintf(stdout, gettext("See the man page dmake(1) for more information on setting up the .dmakerc file.\n"));
  713                 }
  714                 dmake_mode_type = parallel_mode;
  715                 no_parallel = false;
  716             }
  717         }
  718 #else
  719         if(dmake_mode_type == distributed_mode) {
  720             (void) fprintf(stdout, NOCATGETS("dmake: Distributed mode not implemented.\n"));
  721             (void) fprintf(stdout, NOCATGETS("       Defaulting to parallel mode.\n"));
  722             dmake_mode_type = parallel_mode;
  723             no_parallel = false;
  724         }
  725 #endif  /* DISTRIBUTED */
  726     }
  727     }
  728 #endif
  729 
  730 #ifdef TEAMWARE_MAKE_CMN
  731     parallel_flag = true;
  732     /* XXX - This is a major hack for DMake/Licensing. */
  733     if (getenv(NOCATGETS("DMAKE_CHILD")) == NULL) {
  734         if (!avo_cli_search_license(argv[0], dmake_exit_callback, TRUE, dmake_message_callback)) {
  735             /*
  736              * If the user can not get a TeamWare license,
  737              * default to serial mode.
  738              */
  739             dmake_mode_type = serial_mode;
  740             no_parallel = true;
  741         } else {
  742             putenv((char *)NOCATGETS("DMAKE_CHILD=TRUE"));
  743         }
  744         start_time = time(NULL);
  745         /*
  746          * XXX - Hack to disable SIGALRM's from licensing library's
  747          *       setitimer().
  748          */
  749         value.it_interval.tv_sec = 0;
  750         value.it_interval.tv_usec = 0;
  751         value.it_value.tv_sec = 0;
  752         value.it_value.tv_usec = 0;
  753         (void) setitimer(ITIMER_REAL, &value, NULL);
  754     }
  755 
  756 //
  757 // If dmake is running with -t option, set dmake_mode_type to serial.
  758 // This is done because doname() calls touch_command() that runs serially.
  759 // If we do not do that, maketool will have problems. 
  760 //
  761     if(touch) {
  762         dmake_mode_type = serial_mode;
  763         no_parallel = true;
  764     }
  765 #else
  766 #ifdef  PMAKE
  767     if (IS_EQUAL(argv_zero_base, NOCATGETS("dmake")) ||
  768         dmake_max_jobs_specified) {
  769         parallel_flag = true;
  770     } else
  771 #endif
  772         parallel_flag = false;
  773 #ifdef  PMAKE
  774     /*
  775      * If dmake is running with -t option, set dmake_mode_type to serial.
  776      * This is done because doname() calls touch_command() that runs
  777      * serially.
  778      * If we do not do that, maketool will have problems. 
  779      */
  780     if (touch) {
  781         dmake_mode_type = serial_mode;
  782         no_parallel = true;
  783     }
  784 #endif
  785 #endif
  786 
  787 #if (defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)) && defined(REDIRECT_ERR)
  788     /*
  789      * Check whether stdout and stderr are physically same.
  790      * This is in order to decide whether we need to redirect
  791      * stderr separately from stdout.
  792      * This check is performed only if __DMAKE_SEPARATE_STDERR
  793      * is not set. This variable may be used in order to preserve
  794      * the 'old' behaviour.
  795      */
  796     out_err_same = true;
  797     char * dmake_sep_var = getenv(NOCATGETS("__DMAKE_SEPARATE_STDERR"));
  798     if (dmake_sep_var == NULL || (0 != strcasecmp(dmake_sep_var, NOCATGETS("NO")))) {
  799         struct stat stdout_stat;
  800         struct stat stderr_stat;
  801         if( (fstat(1, &stdout_stat) == 0)
  802          && (fstat(2, &stderr_stat) == 0) )
  803         {
  804             if( (stdout_stat.st_dev != stderr_stat.st_dev)
  805              || (stdout_stat.st_ino != stderr_stat.st_ino) )
  806             {
  807                 out_err_same = false;
  808             }
  809         }
  810     }
  811 #endif
  812 
  813 #ifdef DISTRIBUTED
  814     /*
  815      * At this point, DMake should startup an rxm with any and all
  816      * DMake command line options. Rxm will, among other things,
  817      * read the rc file.
  818      */
  819     if ((!list_all_targets) &&
  820         (report_dependencies_level == 0) &&
  821         (dmake_mode_type == distributed_mode)) {
  822         startup_rxm();
  823     }
  824 #endif
  825         
  826 /*
  827  *  Enable interrupt handler for alarms
  828  */
  829         (void) bsd_signal(SIGALRM, (SIG_PF)doalarm);
  830 
  831 /*
  832  *  Check if make should report
  833  */
  834     if (getenv(sunpro_dependencies->string_mb) != NULL) {
  835         FILE    *report_file;
  836 
  837         report_dependency("");
  838         report_file = get_report_file();
  839         if ((report_file != NULL) && (report_file != (FILE*)-1)) {
  840             (void) fprintf(report_file, "\n");
  841         }
  842     }
  843 
  844 /*
  845  *  Make sure SUNPRO_DEPENDENCIES is exported (or not) properly
  846  *      and NSE_DEP.
  847  */
  848     if (keep_state) {
  849         maybe_append_prop(sunpro_dependencies, macro_prop)->
  850           body.macro.exported = true;
  851 #ifdef NSE
  852         (void) setenv(NOCATGETS("NSE_DEP"), get_current_path());
  853 #endif
  854     } else {
  855         maybe_append_prop(sunpro_dependencies, macro_prop)->
  856           body.macro.exported = false;
  857     }
  858 
  859     working_on_targets = true;
  860     if (trace_status) {
  861         dump_make_state();
  862         fclose(stdout);
  863         fclose(stderr);
  864         exit_status = 0;
  865         exit(0);
  866     }
  867     if (list_all_targets) {
  868         dump_target_list();
  869         fclose(stdout);
  870         fclose(stderr);
  871         exit_status = 0;
  872         exit(0);
  873     }
  874     trace_reader = false;
  875 
  876     /*
  877      * Set temp_file_directory to the directory the .make.state
  878      * file is written to.
  879      */
  880     if ((slash_ptr = strrchr(make_state->string_mb, (int) slash_char)) == NULL) {
  881         temp_file_directory = strdup(get_current_path());
  882     } else {
  883         *slash_ptr = (int) nul_char;
  884         (void) strcpy(make_state_dir, make_state->string_mb);
  885         *slash_ptr = (int) slash_char;
  886            /* when there is only one slash and it's the first
  887            ** character, make_state_dir should point to '/'.
  888            */
  889         if(make_state_dir[0] == '\0') {
  890            make_state_dir[0] = '/';
  891            make_state_dir[1] = '\0';
  892         }
  893         if (make_state_dir[0] == (int) slash_char) {
  894             temp_file_directory = strdup(make_state_dir);
  895         } else {
  896             char    tmp_current_path2[MAXPATHLEN];
  897  
  898             (void) sprintf(tmp_current_path2,
  899                            "%s/%s",
  900                            get_current_path(),
  901                            make_state_dir);
  902             temp_file_directory = strdup(tmp_current_path2);
  903         }
  904     }
  905 
  906 #ifdef DISTRIBUTED
  907     building_serial = false;
  908 #endif
  909 
  910     report_dir_enter_leave(true);
  911 
  912     make_targets(argc, argv, parallel_flag);
  913 
  914     report_dir_enter_leave(false);
  915     dir_enter_leave(false);
  916 
  917 #ifdef NSE
  918         exit(nse_exit_status());
  919 #else
  920     if (build_failed_ever_seen) {
  921         if (posix) {
  922             exit_status = 1;
  923         }
  924         exit(1);
  925     }
  926     exit_status = 0;
  927     exit(0);
  928 #endif
  929     /* NOTREACHED */
  930 }
  931 
  932 /*
  933  * scan_dmake_compat_mode()
  934  *
  935  *  Called from main(), handles SUN_MAKE_COMPAT_MODE.
  936  *
  937  *  Parameters:
  938  *      dmake_compat_mode_var   The SUN_MAKE_COMPAT_MODE= environ
  939  *                  or the -x SUN_MAKE_COMPAT_MODE=
  940  *                  argument.
  941  *
  942  *  Global variables used:
  943  *      sunpro_compat
  944  *      gnu_style
  945  *      svr4
  946  *      posix
  947  */
  948 static void
  949 scan_dmake_compat_mode(char *dmake_compat_mode_var)
  950 {
  951     if (dmake_compat_mode_var != NULL) {
  952         sunpro_compat = true;
  953         if (0 == strcasecmp(dmake_compat_mode_var, NOCATGETS("GNU"))) {
  954             sunpro_compat = false;
  955             gnu_style = true;
  956             svr4 = false;
  957             posix = false;
  958         } else if (0 == strcasecmp(dmake_compat_mode_var,
  959                             NOCATGETS("POSIX"))) {
  960             sunpro_compat = false;
  961             gnu_style = false;
  962             svr4 = false;
  963             posix = true;
  964         } else if (0 == strcasecmp(dmake_compat_mode_var,
  965                             NOCATGETS("SUN"))) {
  966             sunpro_compat = true;
  967             gnu_style = false;
  968             svr4 = false;
  969             posix = false;
  970         } else if (0 == strcasecmp(dmake_compat_mode_var,
  971                             NOCATGETS("SVR4"))) {
  972             sunpro_compat = false;
  973             gnu_style = false;
  974             svr4 = true;
  975             posix = false;
  976         }
  977         //svr4 = false;
  978         //posix = false;
  979     }
  980 }
  981 
  982 /*
  983  *  cleanup_after_exit()
  984  *
  985  *  Called from exit(), performs cleanup actions.
  986  *
  987  *  Parameters:
  988  *      status      The argument exit() was called with
  989  *      arg     Address of an argument vector to
  990  *              cleanup_after_exit()
  991  *
  992  *  Global variables used:
  993  *      command_changed Set if we think .make.state should be rewritten
  994  *      current_line    Is set we set commands_changed
  995  *      do_not_exec_rule
  996  *              True if -n flag on
  997  *      done        The Name ".DONE", rule we run
  998  *      keep_state  Set if .KEEP_STATE seen
  999  *      parallel    True if building in parallel
 1000  *      quest       If -q is on we do not run .DONE
 1001  *      report_dependencies
 1002  *              True if -P flag on
 1003  *      running_list    List of parallel running processes
 1004  *      temp_file_name  The temp file is removed, if any
 1005  *      usage_tracking  Should have been constructed in main()
 1006  *                  should destroyed just before exiting
 1007  */
 1008 #ifdef  HAVE_ATEXIT
 1009 extern "C" void
 1010 cleanup_after_exit(void)
 1011 #else
 1012 void cleanup_after_exit(int status, ...)
 1013 #endif
 1014 {
 1015     Running     rp;
 1016 #ifdef NSE
 1017     char        push_cmd[NSE_TFS_PUSH_LEN + 3 +
 1018                      (MAXPATHLEN * MB_LEN_MAX) + 12];
 1019     char        *active;
 1020 #endif
 1021 
 1022 extern long getname_bytes_count;
 1023 extern long getname_names_count;
 1024 extern long getname_struct_count;
 1025 extern long freename_bytes_count;
 1026 extern long freename_names_count;
 1027 extern long freename_struct_count;
 1028 extern long other_alloc;
 1029 
 1030 extern long env_alloc_num;
 1031 extern long env_alloc_bytes;
 1032 
 1033 
 1034 #ifdef DMAKE_STATISTICS
 1035 if(getname_stat) {
 1036     printf(NOCATGETS(">>> Getname statistics:\n"));
 1037     printf(NOCATGETS("  Allocated:\n"));
 1038     printf(NOCATGETS("        Names: %ld\n"), getname_names_count);
 1039     printf(NOCATGETS("      Strings: %ld Kb (%ld bytes)\n"), getname_bytes_count/1000, getname_bytes_count);
 1040     printf(NOCATGETS("      Structs: %ld Kb (%ld bytes)\n"), getname_struct_count/1000, getname_struct_count);
 1041     printf(NOCATGETS("  Total bytes: %ld Kb (%ld bytes)\n"), getname_struct_count/1000 + getname_bytes_count/1000, getname_struct_count + getname_bytes_count);
 1042 
 1043     printf(NOCATGETS("\n  Unallocated: %ld\n"), freename_names_count);
 1044     printf(NOCATGETS("        Names: %ld\n"), freename_names_count);
 1045     printf(NOCATGETS("      Strings: %ld Kb (%ld bytes)\n"), freename_bytes_count/1000, freename_bytes_count);
 1046     printf(NOCATGETS("      Structs: %ld Kb (%ld bytes)\n"), freename_struct_count/1000, freename_struct_count);
 1047     printf(NOCATGETS("  Total bytes: %ld Kb (%ld bytes)\n"), freename_struct_count/1000 + freename_bytes_count/1000, freename_struct_count + freename_bytes_count);
 1048 
 1049     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));
 1050 
 1051     printf(NOCATGETS("\n>>> Other:\n"));
 1052     printf(
 1053         NOCATGETS("       Env (%ld): %ld Kb (%ld bytes)\n"),
 1054         env_alloc_num,
 1055         env_alloc_bytes/1000,
 1056         env_alloc_bytes
 1057     );
 1058 
 1059 }
 1060 #endif
 1061 
 1062 /*
 1063 #ifdef DISTRIBUTED
 1064     if (get_parent() == TRUE) {
 1065 #endif
 1066  */
 1067 
 1068     parallel = false;
 1069 #ifdef SUN5_0
 1070     /* If we used the SVR4_MAKE, don't build .DONE or .FAILED */
 1071     if (!getenv(USE_SVR4_MAKE)){
 1072 #endif
 1073         /* Build the target .DONE or .FAILED if we caught an error */
 1074         if (!quest && !list_all_targets) {
 1075         Name        failed_name;
 1076 
 1077         MBSTOWCS(wcs_buffer, NOCATGETS(".FAILED"));
 1078         failed_name = GETNAME(wcs_buffer, FIND_LENGTH);
 1079 #ifdef  HAVE_ATEXIT
 1080         if ((exit_status != 0) && (failed_name->prop != NULL)) {
 1081 #else
 1082         if ((status != 0) && (failed_name->prop != NULL)) {
 1083 #endif
 1084 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
 1085             /*
 1086              * [tolik] switch DMake to serial mode
 1087              */
 1088             dmake_mode_type = serial_mode;
 1089             no_parallel = true;
 1090 #endif
 1091             (void) doname(failed_name, false, true);
 1092         } else {
 1093             if (!trace_status) {
 1094 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
 1095             /*
 1096              * Switch DMake to serial mode
 1097              */
 1098             dmake_mode_type = serial_mode;
 1099             no_parallel = true;
 1100 #endif
 1101             (void) doname(done, false, true);
 1102             }
 1103         }
 1104         }
 1105 #ifdef SUN5_0
 1106     }
 1107 #endif
 1108     /*
 1109      * Remove the temp file utilities report dependencies thru if it
 1110      * is still around
 1111      */
 1112     if (temp_file_name != NULL) {
 1113         (void) unlink(temp_file_name->string_mb);
 1114     }
 1115     /*
 1116      * Do not save the current command in .make.state if make
 1117      * was interrupted.
 1118      */
 1119     if (current_line != NULL) {
 1120         command_changed = true;
 1121         current_line->body.line.command_used = NULL;
 1122     }
 1123     /*
 1124      * For each parallel build process running, remove the temp files
 1125      * and zap the command line so it won't be put in .make.state
 1126      */
 1127     for (rp = running_list; rp != NULL; rp = rp->next) {
 1128         if (rp->temp_file != NULL) {
 1129             (void) unlink(rp->temp_file->string_mb);
 1130         }
 1131         if (rp->stdout_file != NULL) {
 1132             (void) unlink(rp->stdout_file);
 1133             retmem_mb(rp->stdout_file);
 1134             rp->stdout_file = NULL;
 1135         }
 1136         if (rp->stderr_file != NULL) {
 1137             (void) unlink(rp->stderr_file);
 1138             retmem_mb(rp->stderr_file);
 1139             rp->stderr_file = NULL;
 1140         }
 1141         command_changed = true;
 1142 /*
 1143         line = get_prop(rp->target->prop, line_prop);
 1144         if (line != NULL) {
 1145             line->body.line.command_used = NULL;
 1146         }
 1147  */
 1148     }
 1149     /* Remove the statefile lock file if the file has been locked */
 1150     if ((make_state_lockfile != NULL) && (make_state_locked)) {
 1151         (void) unlink(make_state_lockfile);
 1152         make_state_lockfile = NULL;
 1153         make_state_locked = false;
 1154     }
 1155     /* Write .make.state */
 1156     write_state_file(1, (Boolean) 1);
 1157 
 1158 #ifdef TEAMWARE_MAKE_CMN
 1159     // Deleting the usage tracking object sends the usage mail 
 1160 #ifdef USE_DMS_CCR
 1161     //usageTracking->setExitStatus(exit_status, NULL);
 1162     //delete usageTracking;
 1163 #else
 1164     cleanup->set_exit_status(exit_status);
 1165     delete cleanup;
 1166 #endif
 1167 #endif
 1168 
 1169 #ifdef NSE
 1170         /* If running inside an activated environment, push the */
 1171     /* .nse_depinfo file (if written) */
 1172     active = getenv(NSE_VARIANT_ENV);
 1173     if (keep_state &&
 1174         (active != NULL) &&
 1175         !IS_EQUAL(active, NSE_RT_SOURCE_NAME) &&
 1176         !do_not_exec_rule &&
 1177         (report_dependencies_level == 0)) {
 1178         (void) sprintf(push_cmd,
 1179                    "%s %s/%s",
 1180                    NSE_TFS_PUSH,
 1181                    get_current_path(),
 1182                    NSE_DEPINFO);
 1183         (void) system(push_cmd);
 1184     }
 1185 #endif
 1186 
 1187 /*
 1188 #ifdef DISTRIBUTED
 1189     }
 1190 #endif
 1191  */
 1192 
 1193 #if (defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)) && \
 1194     defined (MAXJOBS_ADJUST_RFE4694000)
 1195     job_adjust_fini();
 1196 #endif
 1197 
 1198 #ifdef DISTRIBUTED
 1199     if (rxmPid > 0) {
 1200         // Tell rxm to exit by sending it an Avo_AcknowledgeMsg
 1201         Avo_AcknowledgeMsg acknowledgeMsg;
 1202         RWCollectable *msg = (RWCollectable *)&acknowledgeMsg;
 1203 
 1204         int xdrResult = xdr(&xdrs_out, msg);
 1205 
 1206         if (xdrResult) {
 1207             fflush(dmake_ofp);
 1208         } else {
 1209 /*
 1210             fatal(gettext("couldn't tell rxm to exit"));
 1211  */
 1212             kill(rxmPid, SIGTERM);
 1213         }
 1214 
 1215         waitpid(rxmPid, NULL, 0);
 1216         rxmPid = 0;
 1217     }
 1218 #endif
 1219 }
 1220 
 1221 /*
 1222  *  handle_interrupt()
 1223  *
 1224  *  This is where C-C traps are caught.
 1225  *
 1226  *  Parameters:
 1227  *
 1228  *  Global variables used (except DMake 1.0):
 1229  *      current_target      Sometimes the current target is removed
 1230  *      do_not_exec_rule    But not if -n is on
 1231  *      quest           or -q
 1232  *      running_list        List of parallel running processes
 1233  *      touch           Current target is not removed if -t on
 1234  */
 1235 void
 1236 handle_interrupt(int)
 1237 {
 1238     Property        member;
 1239     Running         rp;
 1240 
 1241     (void) fflush(stdout);
 1242 #ifdef DISTRIBUTED
 1243     if (rxmPid > 0) {
 1244         // Tell rxm to exit by sending it an Avo_AcknowledgeMsg
 1245         Avo_AcknowledgeMsg acknowledgeMsg;
 1246         RWCollectable *msg = (RWCollectable *)&acknowledgeMsg;
 1247 
 1248         int xdrResult = xdr(&xdrs_out, msg);
 1249 
 1250         if (xdrResult) {
 1251             fflush(dmake_ofp);
 1252         } else {
 1253             kill(rxmPid, SIGTERM);
 1254             rxmPid = 0;
 1255         }
 1256     }
 1257 #endif
 1258     if (childPid > 0) {
 1259         kill(childPid, SIGTERM);
 1260         childPid = -1;
 1261     }
 1262     for (rp = running_list; rp != NULL; rp = rp->next) {
 1263         if (rp->state != build_running) {
 1264             continue;
 1265         }
 1266         if (rp->pid > 0) {
 1267             kill(rp->pid, SIGTERM);
 1268             rp->pid = -1;
 1269         }
 1270     }
 1271     if (getpid() == getpgrp()) {
 1272 #ifdef  SUN5_0
 1273         bsd_signal(SIGTERM, SIG_IGN);
 1274 #else
 1275         bsd_signal(SIGTERM, (void (*)(int)) SIG_IGN);
 1276 #endif
 1277         kill (-getpid(), SIGTERM);
 1278     }
 1279 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
 1280     /* Clean up all parallel/distributed children already finished */
 1281         finish_children(false);
 1282 #endif
 1283 
 1284     /* Make sure the processes running under us terminate first */
 1285 
 1286     while (wait((WAIT_T *) NULL) != -1);
 1287     /* Delete the current targets unless they are precious or phony */
 1288     if ((current_target != NULL) &&
 1289         current_target->is_member &&
 1290         ((member = get_prop(current_target->prop, member_prop)) != NULL)) {
 1291         current_target = member->body.member.library;
 1292     }
 1293     if (!do_not_exec_rule &&
 1294         !touch &&
 1295         !quest &&
 1296         (current_target != NULL) &&
 1297         !(current_target->stat.is_precious || all_precious ||
 1298         current_target->stat.is_phony)) {
 1299 
 1300 /* BID_1030811 */
 1301 /* azv 16 Oct 95 */
 1302         current_target->stat.time = file_no_time; 
 1303 
 1304         if (exists(current_target) != file_doesnt_exist) {
 1305             (void) fprintf(stderr,
 1306                        "\n*** %s ",
 1307                        current_target->string_mb);
 1308             if (current_target->stat.is_dir) {
 1309                 (void) fprintf(stderr,
 1310                            gettext("not removed.\n"));
 1311             } else if (unlink(current_target->string_mb) == 0) {
 1312                 (void) fprintf(stderr,
 1313                            gettext("removed.\n"));
 1314             } else {
 1315                 (void) fprintf(stderr,
 1316                            gettext("could not be removed: %s.\n"),
 1317                            errmsg(errno));
 1318             }
 1319         }
 1320     }
 1321     for (rp = running_list; rp != NULL; rp = rp->next) {
 1322         if (rp->state != build_running) {
 1323             continue;
 1324         }
 1325         if (rp->target->is_member &&
 1326             ((member = get_prop(rp->target->prop, member_prop)) !=
 1327              NULL)) {
 1328             rp->target = member->body.member.library;
 1329         }
 1330         if (!do_not_exec_rule &&
 1331             !touch &&
 1332             !quest &&
 1333             !(rp->target->stat.is_precious || all_precious ||
 1334             rp->target->stat.is_phony)) {
 1335 
 1336             rp->target->stat.time = file_no_time; 
 1337             if (exists(rp->target) != file_doesnt_exist) {
 1338                 (void) fprintf(stderr,
 1339                            "\n*** %s ",
 1340                            rp->target->string_mb);
 1341                 if (rp->target->stat.is_dir) {
 1342                     (void) fprintf(stderr,
 1343                                gettext("not removed.\n"));
 1344                 } else if (unlink(rp->target->string_mb) == 0) {
 1345                     (void) fprintf(stderr,
 1346                                gettext("removed.\n"));
 1347                 } else {
 1348                     (void) fprintf(stderr,
 1349                                gettext("could not be removed: %s.\n"),
 1350                                errmsg(errno));
 1351                 }
 1352             }
 1353         }
 1354     }
 1355 
 1356 #ifdef SGE_SUPPORT
 1357     /* Remove SGE script file */
 1358     if (grid) {
 1359         unlink(script_file);
 1360     }
 1361 #endif
 1362 
 1363     /* Have we locked .make.state or .nse_depinfo? */
 1364     if ((make_state_lockfile != NULL) && (make_state_locked)) {
 1365         unlink(make_state_lockfile);
 1366         make_state_lockfile = NULL;
 1367         make_state_locked = false;
 1368     }
 1369 #ifdef NSE
 1370     if ((nse_depinfo_lockfile[0] != '\0') && (nse_depinfo_locked)) {
 1371         unlink(nse_depinfo_lockfile);
 1372         nse_depinfo_lockfile[0] = '\0';
 1373         nse_depinfo_locked = false;
 1374     }
 1375 #endif
 1376     /*
 1377      * Re-read .make.state file (it might be changed by recursive make)
 1378      */
 1379     check_state(NULL);
 1380 
 1381     report_dir_enter_leave(false);
 1382 
 1383     exit_status = 2;
 1384     exit(2);
 1385 }
 1386 
 1387 /*
 1388  *  doalarm(sig, ...)
 1389  *
 1390  *  Handle the alarm interrupt but do nothing.  Side effect is to
 1391  *  cause return from wait3.
 1392  *
 1393  *  Parameters:
 1394  *      sig
 1395  *
 1396  *  Global variables used:
 1397  */
 1398 /*ARGSUSED*/
 1399 static void
 1400 doalarm(int)
 1401 {
 1402     return;
 1403 }
 1404 
 1405 
 1406 /*
 1407  *  read_command_options(argc, argv)
 1408  *
 1409  *  Scan the cmd line options and process the ones that start with "-"
 1410  *
 1411  *  Return value:
 1412  *              -M argument, if any
 1413  *
 1414  *  Parameters:
 1415  *      argc        You know what this is
 1416  *      argv        You know what this is
 1417  *
 1418  *  Global variables used:
 1419  */
 1420 static void
 1421 read_command_options(register int argc, register char **argv)
 1422 {
 1423     register int        ch;
 1424     int         current_optind = 1;
 1425     int         last_optind_with_double_hyphen = 0;
 1426     int         last_optind;
 1427     int         last_current_optind;
 1428     register int        i;
 1429     register int        j;
 1430     register int        k;
 1431     register int        makefile_next = 0; /*
 1432                             * flag to note options:
 1433                             * -c, f, g, j, m, o
 1434                             */
 1435     const char      *tptr;
 1436     const char      *CMD_OPTS;
 1437 
 1438     extern char     *optarg;
 1439     extern int      optind, opterr, optopt;
 1440 
 1441 #define SUNPRO_CMD_OPTS "-~aBbC:c:Ddef:g:ij:K:kM:m:NnO:o:PpqRrSsTtuVvwx:"
 1442 
 1443 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
 1444 #   define SVR4_CMD_OPTS   "-C:c:ef:g:ij:km:nO:o:pqrsTtVv"
 1445 #else
 1446 #   define SVR4_CMD_OPTS   "-C:ef:iknpqrstV"
 1447 #endif
 1448 
 1449     /*
 1450      * Added V in SVR4_CMD_OPTS also, which is going to be a hidden
 1451      * option, just to make sure that the getopt doesn't fail when some
 1452      * users leave their USE_SVR4_MAKE set and try to use the makefiles
 1453      * that are designed to issue commands like $(MAKE) -V. Anyway it
 1454      * sets the same flag but ensures that getopt doesn't fail.
 1455      */
 1456 
 1457     opterr = 0;
 1458     optind = 1;
 1459     while (1) {
 1460         last_optind=optind;         /* Save optind and current_optind values */
 1461         last_current_optind=current_optind; /* in case we have to repeat this round. */
 1462         if (svr4) {
 1463             CMD_OPTS=SVR4_CMD_OPTS;
 1464             ch = getopt(argc, argv, SVR4_CMD_OPTS);
 1465         } else {
 1466             CMD_OPTS=SUNPRO_CMD_OPTS;
 1467             ch = getopt(argc, argv, SUNPRO_CMD_OPTS);
 1468         }
 1469         if (ch == EOF) {
 1470             if(optind < argc) {
 1471                 /*
 1472                  * Fixing bug 4102537:
 1473                  *    Strange behaviour of command make using -- option.
 1474                  * Not all argv have been processed
 1475                  * Skip non-flag argv and continue processing.
 1476                  */
 1477                 optind++;
 1478                 current_optind++;
 1479                 continue;
 1480             } else {
 1481                 break;
 1482             }
 1483 
 1484         }
 1485         if (ch == '?') {
 1486             if (optopt == '-') {
 1487                 /* Bug 5060758: getopt() changed behavior (s10_60),
 1488                  * and now we have to deal with cases when options
 1489                  * with double hyphen appear here, from -$(MAKEFLAGS)
 1490                  */
 1491                 i = current_optind;
 1492                 if (argv[i][0] == '-') {
 1493                   if (argv[i][1] == '-') {
 1494                     if (argv[i][2] != '\0') {
 1495                       /* Check if this option is allowed */
 1496                       tptr = strchr(CMD_OPTS, argv[i][2]);
 1497                       if (tptr) {
 1498                         if (last_optind_with_double_hyphen != current_optind) {
 1499                           /* This is first time we are trying to fix "--"
 1500                            * problem with this option. If we come here second 
 1501                            * time, we will go to fatal error.
 1502                            */
 1503                           last_optind_with_double_hyphen = current_optind;
 1504                           
 1505                           /* Eliminate first hyphen character */
 1506                           for (j=0; argv[i][j] != '\0'; j++) {
 1507                             argv[i][j] = argv[i][j+1];
 1508                           }
 1509                           
 1510                           /* Repeat the processing of this argument */
 1511                           optind=last_optind;
 1512                           current_optind=last_current_optind;
 1513                           continue;
 1514                         }
 1515                       }
 1516                     }
 1517                   }
 1518                 }
 1519             }
 1520         }
 1521 
 1522         if (ch == '?') {
 1523             if (svr4) {
 1524 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
 1525                 fprintf(stderr,
 1526                     gettext("Usage : dmake [ -f makefile ][ -c dmake_rcfile ][ -g dmake_group ][ -C directory ]\n"));
 1527                 fprintf(stderr,
 1528                     gettext("              [ -j dmake_max_jobs ][ -m dmake_mode ][ -o dmake_odir ]...\n"));
 1529                 fprintf(stderr,
 1530                     gettext("              [ -e ][ -i ][ -k ][ -n ][ -p ][ -q ][ -r ][ -s ][ -t ][ -v ]\n"));
 1531 #else
 1532                 fprintf(stderr,
 1533                     gettext("Usage : make [ -f makefile ]... [ -e ][ -i ][ -k ][ -n ][ -p ][ -q ][ -r ]\n"));
 1534                 fprintf(stderr,
 1535                     gettext("             [ -s ][ -t ]\n"));
 1536 #endif
 1537                 tptr = strchr(SVR4_CMD_OPTS, optopt);
 1538             } else {
 1539 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
 1540                 if (IS_EQUAL(argv_zero_base, NOCATGETS("dmake"))) {
 1541                 fprintf(stderr,
 1542                     gettext("Usage : dmake [ -f makefile ][ -c dmake_rcfile ][ -g dmake_group ][ -C directory ]\n"));
 1543                 fprintf(stderr,
 1544                     gettext("              [ -j dmake_max_jobs ][ -K statefile ][ -m dmake_mode ][ -x MODE_NAME=VALUE ][ -o dmake_odir ]...\n"));
 1545                 fprintf(stderr,
 1546                     gettext("              [ -a] [ -d ][ -dd ][ -D ][ -DD ]\n"));
 1547                 fprintf(stderr,
 1548                     gettext("              [ -e ][ -i ][ -k ][ -n ][ -p ][ -P ][ -u ][ -w ]\n"));
 1549                 fprintf(stderr,
 1550                     gettext("              [ -q ][ -r ][ -s ][ -S ][ -t ][ -v ][ -V ][ target... ][ macro=value... ][ \"macro +=value\"... ]\n"));
 1551                 } else
 1552 #endif
 1553                 {
 1554                 fprintf(stderr,
 1555                     gettext("Usage : make [ -f makefile ][ -K statefile ]...\n"));
 1556                 fprintf(stderr,
 1557                     gettext("             [ -a ][ -d ][ -dd ][ -D ][ -DD ] [ -C directory]\n"));
 1558                 fprintf(stderr,
 1559                     gettext("             [ -e ][ -i ][ -k ][ -n ][ -p ][ -P ][ -q ][ -r ][ -s ][ -S ][ -t ]\n"));
 1560                 fprintf(stderr,
 1561                     gettext("             [ -u ][ -w ][ -V ][ target... ][ macro=value... ][ \"macro +=value\"... ]\n"));
 1562                 }
 1563                 tptr = strchr(SUNPRO_CMD_OPTS, optopt);
 1564             }
 1565             if (!tptr) {
 1566                 fatal(gettext("Unknown option `-%c'"), optopt);
 1567             } else {
 1568                 fatal(gettext("Missing argument after `-%c'"), optopt);
 1569             }
 1570         }
 1571 
 1572         makefile_next |= parse_command_option(ch);
 1573         /*
 1574          * If we're done processing all of the options of
 1575          * ONE argument string...
 1576          */
 1577         if (current_optind < optind) {
 1578             i = current_optind;
 1579             k = 0;
 1580             /* If there's an argument for an option... */
 1581             if ((optind - current_optind) > 1) {
 1582                 k = i + 1;
 1583             }
 1584             switch (makefile_next) {
 1585             case 0:
 1586                 argv[i] = NULL;
 1587                 /* This shouldn't happen */
 1588                 if (k) {
 1589                     argv[k] = NULL;
 1590                 }
 1591                 break;
 1592             case 1: /* -f seen */
 1593                 argv[i] = (char *)NOCATGETS("-f");
 1594                 break;
 1595             case 2: /* -c seen */
 1596                 argv[i] = (char *)NOCATGETS("-c");
 1597 #ifndef TEAMWARE_MAKE_CMN
 1598                 warning(gettext("Ignoring DistributedMake -c option"));
 1599 #endif
 1600                 break;
 1601             case 4: /* -g seen */
 1602                 argv[i] = (char *)NOCATGETS("-g");
 1603 #ifndef TEAMWARE_MAKE_CMN
 1604                 warning(gettext("Ignoring DistributedMake -g option"));
 1605 #endif
 1606                 break;
 1607             case 8: /* -j seen */
 1608                 if (sunpro_compat)  /* Disallow -j5 */
 1609                     argv[i] = (char *)NOCATGETS("-j");
 1610 #if !defined(TEAMWARE_MAKE_CMN) && !defined(PMAKE)
 1611                 warning(gettext("Ignoring DistributedMake -j option"));
 1612 #endif
 1613                 break;
 1614             case 16: /* -M seen */
 1615                 argv[i] = (char *)NOCATGETS("-M");
 1616 #ifndef TEAMWARE_MAKE_CMN
 1617                 warning(gettext("Ignoring ParallelMake -M option"));
 1618 #endif
 1619                 break;
 1620             case 32: /* -m seen */
 1621                 argv[i] = (char *)NOCATGETS("-m");
 1622 #if !defined(TEAMWARE_MAKE_CMN) && !defined(PMAKE)
 1623                 warning(gettext("Ignoring DistributedMake -m option"));
 1624 #endif
 1625                 break;
 1626 #ifndef PARALLEL
 1627             case 128: /* -O seen */
 1628                 argv[i] = (char *)NOCATGETS("-O");
 1629                 break;
 1630 #endif
 1631             case 256: /* -K seen */
 1632                 argv[i] = (char *)NOCATGETS("-K");
 1633                     break;
 1634             case 512:   /* -o seen */
 1635                 argv[i] = (char *)NOCATGETS("-o");
 1636 #ifndef TEAMWARE_MAKE_CMN
 1637                 warning(gettext("Ignoring DistributedMake -o option"));
 1638 #endif
 1639                 break;
 1640             case 1024: /* -x seen */
 1641                 argv[i] = (char *)NOCATGETS("-x");
 1642                 if (argv[i+1] &&
 1643                     strstr(argv[i+1],
 1644                     NOCATGETS("SUN_MAKE_COMPAT_MODE=")) ==
 1645                                 argv[i+1]) {
 1646                     if (dmake_add_mode_specified)
 1647                         dmake_compat_value = argv[i+1];
 1648                     else
 1649                         dmake_compat_value = NULL;
 1650                 }
 1651 #if !defined(TEAMWARE_MAKE_CMN) && !defined(PMAKE)
 1652                 warning(gettext("Ignoring DistributedMake -x option"));
 1653 #endif
 1654                 break;
 1655             case 2048: {
 1656                 char    *ap = argv[i+1];
 1657 
 1658                 if (argv[i][2])     /* e.g. -Cdir */
 1659                     ap = &argv[i][2];
 1660                 if (ap == NULL) {
 1661                     fatal(gettext("No argument after -C flag"));
 1662                 }
 1663                 if (chdir(ap) != 0) {
 1664                     fatal(gettext("Failed to change to directory %s: %s"),
 1665                         ap, strerror(errno));
 1666                 }
 1667                 current_path_reset = true;
 1668                 }
 1669                 break;
 1670             default: /* > 1 of -c, f, g, j, K, M, m, O, o, x seen */
 1671                 fatal(gettext("Illegal command line. More than one option requiring\nan argument given in the same argument group"));
 1672             }
 1673 
 1674             makefile_next = 0;
 1675             current_optind = optind;
 1676         }
 1677     }
 1678 }
 1679 
 1680 static void
 1681 quote_str(char *str, char *qstr)
 1682 {
 1683     char        *to;
 1684     char        *from;
 1685 
 1686     to = qstr;
 1687     for (from = str; *from; from++) {
 1688         switch (*from) {
 1689         case ';':   /* End of command */
 1690         case '(':   /* Start group */
 1691         case ')':   /* End group */
 1692         case '{':   /* Start group */
 1693         case '}':   /* End group */
 1694         case '[':   /* Reg expr - any of a set of chars */
 1695         case ']':   /* End of set of chars */
 1696         case '|':   /* Pipe or logical-or */
 1697         case '^':   /* Old-fashioned pipe */
 1698         case '&':   /* Background or logical-and */
 1699         case '<':   /* Redirect stdin */
 1700         case '>':   /* Redirect stdout */
 1701         case '*':   /* Reg expr - any sequence of chars */
 1702         case '?':   /* Reg expr - any single char */
 1703         case '$':   /* Variable substitution */
 1704         case '\'':  /* Singe quote - turn off all magic */
 1705         case '"':   /* Double quote - span whitespace */
 1706         case '`':   /* Backquote - run a command */
 1707         case '#':   /* Comment */
 1708         case ' ':   /* Space (for MACRO=value1 value2  */
 1709         case '\\':  /* Escape char - turn off magic of next char */
 1710             *to++ = '\\';
 1711             break;
 1712 
 1713         default:
 1714             break;
 1715         }
 1716         *to++ = *from;
 1717     }
 1718     *to = '\0';
 1719 }
 1720 
 1721 static void
 1722 unquote_str(char *str, char *qstr)
 1723 {
 1724     char        *to;
 1725     char        *from;
 1726 
 1727     to = qstr;
 1728     for (from = str; *from; from++) {
 1729         if (*from == '\\' && from[1] != '\0') {
 1730             from++;
 1731         }
 1732         *to++ = *from;
 1733     }
 1734     *to = '\0';
 1735 }
 1736 
 1737 /*
 1738  * Convert the MAKEFLAGS string value into a vector of char *, similar
 1739  * to argv.
 1740  */
 1741 static void
 1742 setup_makeflags_argv()
 1743 {
 1744     char        *cp;
 1745     char        *cp1;
 1746     char        *cp2;
 1747     char        *cp3;
 1748     char        *cp_orig;
 1749     Boolean     add_hyphen;
 1750     int     i;
 1751     char        tmp_char;
 1752 
 1753     mf_argc = 1;
 1754     cp = getenv(makeflags->string_mb);
 1755     cp_orig = cp;
 1756 
 1757     if (cp) {
 1758         /*
 1759          * If new MAKEFLAGS format, no need to add hyphen.
 1760          * If old MAKEFLAGS format, add hyphen before flags.
 1761          */
 1762 
 1763         if ((strchr(cp, (int) hyphen_char) != NULL) ||
 1764             (strchr(cp, (int) equal_char) != NULL)) {
 1765 
 1766             /* New MAKEFLAGS format */
 1767 
 1768             add_hyphen = false;
 1769 #ifdef ADDFIX5060758            
 1770             /* Check if MAKEFLAGS value begins with multiple
 1771              * hyphen characters, and remove all duplicates.
 1772              * Usually it happens when the next command is
 1773              * used: $(MAKE) -$(MAKEFLAGS)
 1774              * This is a workaround for BugID 5060758.
 1775              */
 1776             while (*cp) {
 1777                 if (*cp != (int) hyphen_char) {
 1778                     break;
 1779                 }
 1780                 cp++;
 1781                 if (*cp == (int) hyphen_char) {
 1782                     /* There are two hyphens. Skip one */
 1783                     cp_orig = cp;
 1784                     cp++;
 1785                 }
 1786                 if (!(*cp)) {
 1787                     /* There are hyphens only. Skip all */
 1788                     cp_orig = cp;
 1789                     break;
 1790                 }
 1791             }
 1792 #endif
 1793         } else {
 1794 
 1795             /* Old MAKEFLAGS format */
 1796 
 1797             add_hyphen = true;
 1798         }
 1799     }
 1800 
 1801     /* Find the number of arguments in MAKEFLAGS */
 1802     while (cp && *cp) {
 1803         /* Skip white spaces */
 1804         while (cp && *cp && isspace(*cp)) {
 1805             cp++;
 1806         }
 1807         if (cp && *cp) {
 1808             /* Increment arg count */
 1809             mf_argc++;
 1810             /* Go to next white space */
 1811             while (cp && *cp && !isspace(*cp)) {
 1812                 if(*cp == (int) backslash_char) {
 1813                     cp++;
 1814                 }
 1815                 cp++;
 1816             }
 1817         }
 1818     }
 1819     /* Allocate memory for the new MAKEFLAGS argv */
 1820     mf_argv = (char **) malloc((mf_argc + 1) * sizeof(char *));
 1821     mf_argv[0] = (char *)NOCATGETS("MAKEFLAGS");
 1822     /*
 1823      * Convert the MAKEFLAGS string value into a vector of char *,
 1824      * similar to argv.
 1825      */
 1826     cp = cp_orig;
 1827     for (i = 1; i < mf_argc; i++) {
 1828         /* Skip white spaces */
 1829         while (cp && *cp && isspace(*cp)) {
 1830             cp++;
 1831         }
 1832         if (cp && *cp) {
 1833             cp_orig = cp;
 1834             /* Go to next white space */
 1835             while (cp && *cp && !isspace(*cp)) {
 1836                 if(*cp == (int) backslash_char) {
 1837                     cp++;
 1838                 }
 1839                 cp++;
 1840             }
 1841             tmp_char = *cp;
 1842             *cp = (int) nul_char;
 1843             if (add_hyphen) {
 1844                 mf_argv[i] = getmem(2 + strlen(cp_orig));
 1845                 mf_argv[i][0] = '\0';
 1846                 (void) strcat(mf_argv[i], "-");
 1847                 // (void) strcat(mf_argv[i], cp_orig);
 1848                 unquote_str(cp_orig, mf_argv[i]+1);
 1849             } else {
 1850                 mf_argv[i] = getmem(2 + strlen(cp_orig));
 1851                 //mf_argv[i] = strdup(cp_orig);
 1852                 unquote_str(cp_orig, mf_argv[i]);
 1853             }
 1854             *cp = tmp_char;
 1855         } else {
 1856             mf_argv[i] = NULL;
 1857         }
 1858     }
 1859     mf_argv[i] = NULL;
 1860 
 1861     for (i = 1; i < mf_argc; i++) {
 1862         if (strncmp(mf_argv[i], NOCATGETS("-C"), 2) == 0) {
 1863             int j = i;
 1864 
 1865             /*
 1866              * Ignore -C and argument.
 1867              */
 1868             if (mf_argv[i][2]) {
 1869                 j += 1;
 1870                 mf_argc -= 1;
 1871             } else {
 1872                 j += 2;
 1873                 mf_argc -= 2;
 1874             }
 1875             for ( ; i <= mf_argc; i++, j++)
 1876                 mf_argv[i] = mf_argv[j];
 1877         }
 1878     }
 1879 }
 1880 
 1881 /*
 1882  *  parse_command_option(ch)
 1883  *
 1884  *  Parse make command line options.
 1885  *
 1886  *  Return value:
 1887  *              Indicates if any -f -c or -M were seen
 1888  *
 1889  *  Parameters:
 1890  *      ch      The character to parse
 1891  *
 1892  *  Static variables used:
 1893  *      dmake_group_specified   Set for make -g
 1894  *      dmake_max_jobs_specified    Set for make -j
 1895  *      dmake_mode_specified    Set for make -m
 1896  *      dmake_add_mode_specified    Set for make -x
 1897  *      dmake_compat_mode_specified Set for make -x SUN_MAKE_COMPAT_MODE=
 1898  *      dmake_output_mode_specified Set for make -x DMAKE_OUTPUT_MODE=
 1899  *      dmake_odir_specified    Set for make -o
 1900  *      dmake_rcfile_specified  Set for make -c
 1901  *      env_wins        Set for make -e
 1902  *      ignore_default_mk   Set for make -r
 1903  *      trace_status        Set for make -p
 1904  *
 1905  *  Global variables used:
 1906  *      .make.state path & name set for make -K
 1907  *      continue_after_error    Set for make -k
 1908  *      debug_level     Set for make -d
 1909  *      do_not_exec_rule    Set for make -n
 1910  *      filter_stderr       Set for make -X
 1911  *      ignore_errors_all   Set for make -i
 1912  *      no_parallel     Set for make -R
 1913  *      quest           Set for make -q
 1914  *      read_trace_level    Set for make -D
 1915  *      report_dependencies Set for make -P
 1916  *      send_mtool_msgs     Set for make -K
 1917  *      silent_all      Set for make -s
 1918  *      touch           Set for make -t
 1919  */
 1920 static int
 1921 parse_command_option(register char ch)
 1922 {
 1923     static int      invert_next = 0;
 1924     int         invert_this = invert_next;
 1925 
 1926     invert_next = 0;
 1927     switch (ch) {
 1928     case '-':            /* Ignore "--" */
 1929         return 0;
 1930     case '~':            /* Invert next option */
 1931         invert_next = 1;
 1932         return 0;
 1933 #ifdef  DO_ARCHCONF
 1934     case 'a':            /* Do not set up uname, ... vars */
 1935         if (invert_this) {
 1936             no_archconf = false;
 1937         } else {
 1938             no_archconf = true;
 1939         }
 1940         return 0;
 1941 #endif
 1942     case 'B':            /* Obsolete */
 1943         return 0;
 1944     case 'b':            /* Obsolete */
 1945         return 0;
 1946     case 'c':            /* Read alternative dmakerc file */
 1947         if (invert_this) {
 1948             dmake_rcfile_specified = false;
 1949         } else {
 1950             dmake_rcfile_specified = true;
 1951         }
 1952         return 2;
 1953     case 'C':           /* Change directory */
 1954         return 2048;
 1955     case 'D':            /* Show lines read */
 1956         if (invert_this) {
 1957             read_trace_level--;
 1958         } else {
 1959             read_trace_level++;
 1960         }
 1961         return 0;
 1962     case 'd':            /* Debug flag */
 1963         if (invert_this) {
 1964             debug_level--;
 1965         } else {
 1966 #if defined( HP_UX) || defined(linux)
 1967               if (debug_level < 2)  /* Fixes a bug on HP-UX */
 1968 #endif
 1969             debug_level++;
 1970         }
 1971         return 0;
 1972 #ifdef NSE
 1973     case 'E':
 1974         if (invert_this) {
 1975             nse = false;
 1976         } else {
 1977             nse = true;
 1978         }
 1979         nse_init_source_suffixes();
 1980         return 0;
 1981 #endif
 1982     case 'e':            /* Environment override flag */
 1983         if (invert_this) {
 1984             env_wins = false;
 1985         } else {
 1986             env_wins = true;
 1987         }
 1988         return 0;
 1989     case 'f':            /* Read alternative makefile(s) */
 1990         return 1;
 1991     case 'g':            /* Use alternative DMake group */
 1992         if (invert_this) {
 1993             dmake_group_specified = false;
 1994         } else {
 1995             dmake_group_specified = true;
 1996         }
 1997         return 4;
 1998     case 'i':            /* Ignore errors */
 1999         if (invert_this) {
 2000             ignore_errors_all = false;
 2001         } else {
 2002             ignore_errors_all = true;
 2003         }
 2004         return 0;
 2005     case 'j':            /* Use alternative DMake max jobs */
 2006         if (invert_this) {
 2007             dmake_max_jobs_specified = false;
 2008         } else {
 2009             dmake_max_jobs_specified = true;
 2010         }
 2011         return 8;
 2012     case 'K':            /* Read alternative .make.state */
 2013         return 256;
 2014     case 'k':            /* Keep making even after errors */
 2015         if (invert_this) {
 2016             continue_after_error = false;
 2017         } else {
 2018             continue_after_error = true;
 2019             continue_after_error_ever_seen = true;
 2020         }
 2021         return 0;
 2022     case 'M':            /* Read alternative make.machines file */
 2023         if (invert_this) {
 2024             pmake_machinesfile_specified = false;
 2025         } else {
 2026             pmake_machinesfile_specified = true;
 2027             dmake_mode_type = parallel_mode;
 2028             no_parallel = false;
 2029         }
 2030         return 16;
 2031     case 'm':            /* Use alternative DMake build mode */
 2032         if (invert_this) {
 2033             dmake_mode_specified = false;
 2034         } else {
 2035             dmake_mode_specified = true;
 2036         }
 2037         return 32;
 2038     case 'x':            /* Use alternative DMake mode */
 2039         if (invert_this) {
 2040             dmake_add_mode_specified = false;
 2041         } else {
 2042             dmake_add_mode_specified = true;
 2043         }
 2044         return 1024;
 2045     case 'N':            /* Reverse -n */
 2046         if (invert_this) {
 2047             do_not_exec_rule = true;
 2048         } else {
 2049             do_not_exec_rule = false;
 2050         }
 2051         return 0;
 2052     case 'n':            /* Print, not exec commands */
 2053         if (invert_this) {
 2054             do_not_exec_rule = false;
 2055         } else {
 2056             do_not_exec_rule = true;
 2057         }
 2058         return 0;
 2059 #ifndef PARALLEL
 2060     case 'O':            /* Send job start & result msgs */
 2061         if (invert_this) {
 2062             send_mtool_msgs = false;
 2063         } else {
 2064 #ifdef DISTRIBUTED
 2065             send_mtool_msgs = true;
 2066 #endif
 2067         }
 2068         return 128;
 2069 #endif
 2070     case 'o':            /* Use alternative dmake output dir */
 2071         if (invert_this) {
 2072             dmake_odir_specified = false;
 2073         } else {
 2074             dmake_odir_specified = true;
 2075         }
 2076         return 512;
 2077     case 'P':            /* Print for selected targets */
 2078         if (invert_this) {
 2079             report_dependencies_level--;
 2080         } else {
 2081             report_dependencies_level++;
 2082         }
 2083         return 0;
 2084     case 'p':            /* Print description */
 2085         if (invert_this) {
 2086             trace_status = false;
 2087             do_not_exec_rule = false;
 2088         } else {
 2089             trace_status = true;
 2090             do_not_exec_rule = true;
 2091         }
 2092         return 0;
 2093     case 'q':            /* Question flag */
 2094         if (invert_this) {
 2095             quest = false;
 2096         } else {
 2097             quest = true;
 2098         }
 2099         return 0;
 2100     case 'R':            /* Don't run in parallel */
 2101 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
 2102         if (invert_this) {
 2103             pmake_cap_r_specified = false;
 2104             no_parallel = false;
 2105         } else {
 2106             pmake_cap_r_specified = true;
 2107             dmake_mode_type = serial_mode;
 2108             no_parallel = true;
 2109         }
 2110 #else
 2111         warning(gettext("Ignoring ParallelMake -R option"));
 2112 #endif
 2113         return 0;
 2114     case 'r':            /* Turn off internal rules */
 2115         if (invert_this) {
 2116             ignore_default_mk = false;
 2117         } else {
 2118             ignore_default_mk = true;
 2119         }
 2120         return 0;
 2121     case 'S':            /* Reverse -k */
 2122         if (invert_this) {
 2123             continue_after_error = true;
 2124         } else {
 2125             continue_after_error = false;
 2126             stop_after_error_ever_seen = true;
 2127         }
 2128         return 0;
 2129     case 's':            /* Silent flag */
 2130         if (invert_this) {
 2131             silent_all = false;
 2132         } else {
 2133             silent_all = true;
 2134         }
 2135         return 0;
 2136     case 'T':            /* Print target list */
 2137         if (invert_this) {
 2138             list_all_targets = false;
 2139             do_not_exec_rule = false;
 2140         } else {
 2141             list_all_targets = true;
 2142             do_not_exec_rule = true;
 2143         }
 2144         return 0;
 2145     case 't':            /* Touch flag */
 2146         if (invert_this) {
 2147             touch = false;
 2148         } else {
 2149             touch = true;
 2150         }
 2151         return 0;
 2152     case 'u':            /* Unconditional flag */
 2153         if (invert_this) {
 2154             build_unconditional = false;
 2155         } else {
 2156             build_unconditional = true;
 2157         }
 2158         return 0;
 2159     case 'V':           /* SVR4 mode */
 2160         svr4 = true;
 2161         return 0;
 2162     case 'v':           /* Version flag */
 2163         if (invert_this) {
 2164         } else {
 2165 #ifdef TEAMWARE_MAKE_CMN
 2166             fprintf(stdout, NOCATGETS("dmake: %s\n"), verstring);
 2167 #ifdef SUN5_0
 2168             exit_status = 0;
 2169 #endif
 2170             exit(0);
 2171 #else
 2172 #if defined(SCHILY_BUILD) || defined(SCHILY_INCLUDES)
 2173             fprintf(stdout, NOCATGETS("%s: %s\n"),
 2174                 argv_zero_base, verstring);
 2175             fprintf(stdout, "\n");
 2176             fprintf(stdout, "Copyright (C) 1987-2006 Sun Microsystems\n");
 2177             fprintf(stdout, "Copyright (C) 1996-2021 Joerg Schilling\n");
 2178             exit_status = 0;
 2179             exit(0);
 2180 #else
 2181             warning(gettext("Ignoring DistributedMake -v option"));
 2182 #endif
 2183 #endif
 2184         }
 2185         return 0;
 2186     case 'w':            /* Report working directory flag */
 2187         if (invert_this) {
 2188             report_cwd = false;
 2189         } else {
 2190             report_cwd = true;
 2191         }
 2192         return 0;
 2193 #if 0
 2194     case 'X':           /* Filter stdout */
 2195         if (invert_this) {
 2196             filter_stderr = false;
 2197         } else {
 2198             filter_stderr = true;
 2199         }
 2200         return 0;
 2201 #endif
 2202     default:
 2203         break;
 2204     }
 2205     return 0;
 2206 }
 2207 
 2208 /*
 2209  *  setup_for_projectdir()
 2210  *
 2211  *  Read the PROJECTDIR variable, if defined, and set the sccs path
 2212  *
 2213  *  Parameters:
 2214  *
 2215  *  Global variables used:
 2216  *      sccs_dir_path   Set to point to SCCS dir to use
 2217  */
 2218 static void
 2219 setup_for_projectdir(void)
 2220 {
 2221 static char path[MAXPATHLEN];
 2222 char        cwdpath[MAXPATHLEN];
 2223 uid_t uid;
 2224 int   done=0;
 2225 
 2226     /* Check if we should use PROJECTDIR when reading the SCCS dir. */
 2227     sccs_dir_path = getenv(NOCATGETS("PROJECTDIR"));
 2228     if ((sccs_dir_path != NULL) &&
 2229         (sccs_dir_path[0] != (int) slash_char)) {
 2230         struct passwd *pwent;
 2231 
 2232          {
 2233         uid = getuid();
 2234         pwent = getpwuid(uid);
 2235         if (pwent == NULL) {
 2236            fatal(gettext("Bogus USERID "));
 2237         }
 2238         if ((pwent = getpwnam(sccs_dir_path)) == NULL) {
 2239             /*empty block : it'll go & check cwd  */
 2240         }
 2241         else {
 2242           (void) sprintf(path, NOCATGETS("%s/src"), pwent->pw_dir);
 2243           if (access(path, F_OK) == 0) {
 2244             sccs_dir_path = path;
 2245             done = 1;
 2246           } else {
 2247             (void) sprintf(path, NOCATGETS("%s/source"), pwent->pw_dir);
 2248             if (access(path, F_OK) == 0) {
 2249                 sccs_dir_path = path;
 2250                 done = 1;
 2251             }
 2252              }
 2253         }
 2254         if (!done) {
 2255             if (getcwd(cwdpath, MAXPATHLEN - 1 )) {
 2256 
 2257                (void) sprintf(path, NOCATGETS("%s/%s"), cwdpath,sccs_dir_path);
 2258                if (access(path, F_OK) == 0) {
 2259                     sccs_dir_path = path;
 2260                 done = 1;
 2261                 } else {
 2262                     fatal(gettext("Bogus PROJECTDIR '%s'"), sccs_dir_path);
 2263                 }
 2264             }
 2265         }
 2266        }
 2267     }
 2268 }
 2269 
 2270 static char *
 2271 append_to_env(const char *env, const char *value, const char *deflt)
 2272 {
 2273     size_t  len;
 2274     char    *oldpath = getenv(env);
 2275     char    *newpath;
 2276 
 2277     if (value == NULL)
 2278         value = deflt;
 2279 
 2280     if (oldpath == NULL) {
 2281         len = strlen(env) + 1 +
 2282             strlen(value) + 1;
 2283         newpath = (char *) malloc(len);
 2284         if (newpath)
 2285             sprintf(newpath, "%s=", env);
 2286     } else {
 2287         len = strlen(env) + 1 + strlen(oldpath) + 1 +
 2288             strlen(value) + 1;
 2289         newpath = (char *) malloc(len);
 2290         if (newpath)
 2291             sprintf(newpath, "%s=%s", env, oldpath);
 2292     }
 2293     if (newpath == NULL)
 2294         return (newpath);
 2295 
 2296 #if defined(TEAMWARE_MAKE_CMN)
 2297 
 2298     /* function maybe_append_str_to_env_var() is defined in avo_util library
 2299      * Serial make should not use this library !!!
 2300      */
 2301     maybe_append_str_to_env_var(newpath, value);
 2302 #else
 2303     if (oldpath == NULL) {
 2304         strcat(newpath, value);
 2305     } else {
 2306         strcat(newpath, ":");
 2307         strcat(newpath, value);
 2308     }
 2309 #endif
 2310 
 2311     return (newpath);
 2312 }
 2313 
 2314 static char *
 2315 get_run_lib(const char *run_dir, const char *subdir)
 2316 {
 2317     size_t      len;
 2318     char        *lib;
 2319     struct stat stb;
 2320 
 2321     if (run_dir == NULL)
 2322         return (NULL);
 2323 
 2324     len = strlen(run_dir) + 1 + 5   /* Nul + strlen("/lib/") */
 2325         + (subdir ? strlen(subdir) : 0)
 2326         + strlen(LD_SUPPORT_MAKE_LIB);
 2327     lib = (char *) malloc(len);
 2328     if (lib) {
 2329         strcpy(lib, run_dir);
 2330         strcat(lib, "/lib/");
 2331         if (subdir)
 2332             strcat(lib, subdir);
 2333         strcat(lib, LD_SUPPORT_MAKE_LIB);
 2334         if (stat(lib, &stb) < 0) {
 2335             free(lib);
 2336             lib = NULL;
 2337         }
 2338     }
 2339 #ifdef  LD_SUPPORT_MAKE_ARCH
 2340     if (lib == NULL) {      /* Try tools path */
 2341         len += 3 + strlen(LD_SUPPORT_MAKE_ARCH);
 2342 
 2343         lib = (char *) malloc(len);
 2344         if (lib) {
 2345             /*
 2346              * OpenSolaris ON tools path:
 2347              * tools/..../bin/i386/make
 2348              * tools/..../lib/i386/libmakestate.so.1
 2349              * or
 2350              * tools/..../lib/i386/64/libmakestate.so.1
 2351              */
 2352             strcpy(lib, run_dir);
 2353             strcat(lib, "/../lib/");
 2354             strcat(lib, LD_SUPPORT_MAKE_ARCH);
 2355             if (subdir)
 2356                 strcat(lib, subdir);
 2357             strcat(lib, LD_SUPPORT_MAKE_LIB);
 2358             if (stat(lib, &stb) < 0) {
 2359                 free(lib);
 2360                 lib = NULL;
 2361             }
 2362         }
 2363     }
 2364 #endif
 2365     return (lib);
 2366 }
 2367 
 2368 /*
 2369  *  set_sgs_support()
 2370  *
 2371  *  Add the libmakestate.so.1 lib to the env var SGS_SUPPORT
 2372  *    if it's not already in there.
 2373  *  The SGS_SUPPORT env var and libmakestate.so.1 is used by
 2374  *    the linker ld to report .make.state info back to make.
 2375  *
 2376  *  In case there is a slash in the path for libmakestate.so.1,
 2377  *  we cannot use SGS_SUPPORT, but need SGS_SUPPORT_32 and SGS_SUPPORT_64.
 2378  *
 2379  *  If SGS_SUPPORT_32 or SGS_SUPPORT_64 is present, we manage these
 2380  *  variables as well.
 2381  */
 2382 static void
 2383 set_sgs_support()
 2384 {
 2385     char        *newpath;
 2386     char        *lib;
 2387     static char *prev_path;
 2388     static char *prev_path_32;
 2389     static char *prev_path_64;
 2390     char        *run_dir = strdup(make_run_dir);
 2391 
 2392     if (run_dir && strstr(run_dir, "xpg4/bin"))
 2393         run_dir = dirname(run_dir); /* Strip last dir component */
 2394     run_dir = dirname(run_dir);     /* Strip last dir component */
 2395 
 2396     lib = get_run_lib(run_dir, NULL);
 2397     newpath = append_to_env(LD_SUPPORT_ENV_VAR, lib, LD_SUPPORT_MAKE_LIB);
 2398 
 2399     /*
 2400      * Newer Solaris linker versions may switch to 64 bit binaries.
 2401      * A simple SGS_SUPPORT entry would not work in case it contains
 2402      * a slash. So do not create a SGS_SUPPORT entry in this case but
 2403      * rather directly create SGS_SUPPORT_32 and SGS_SUPPORT_64.
 2404      */
 2405     if (newpath && strchr(newpath, (int) slash_char)) {
 2406         free(newpath);
 2407         if (lib)
 2408             free(lib);
 2409         goto need_specific;
 2410     }
 2411 
 2412     if (newpath)
 2413         putenv(newpath);
 2414     if (prev_path) {
 2415         free(prev_path);
 2416     }
 2417     prev_path = newpath;
 2418     if (lib)
 2419         free(lib);
 2420 
 2421     if (getenv(LD_SUPPORT_ENV_VAR_32) == NULL &&
 2422         getenv(LD_SUPPORT_ENV_VAR_64) == NULL)
 2423         return;
 2424 
 2425 need_specific:
 2426 
 2427     lib = get_run_lib(run_dir, NULL);
 2428     newpath = append_to_env(LD_SUPPORT_ENV_VAR_32, lib, LD_SUPPORT_MAKE_LIB);
 2429 
 2430     if (newpath)
 2431         putenv(newpath);
 2432     if (prev_path_32) {
 2433         free(prev_path_32);
 2434     }
 2435     prev_path_32 = newpath;
 2436     if (lib)
 2437         free(lib);
 2438 
 2439     lib = get_run_lib(run_dir, "64/");
 2440     newpath = append_to_env(LD_SUPPORT_ENV_VAR_64, lib, LD_SUPPORT_MAKE_LIB);
 2441 
 2442     if (newpath)
 2443         putenv(newpath);
 2444     if (prev_path_64) {
 2445         free(prev_path_64);
 2446     }
 2447     prev_path_64 = newpath;
 2448     if (lib)
 2449         free(lib);
 2450 }
 2451 
 2452 /*
 2453  *  read_files_and_state(argc, argv)
 2454  *
 2455  *  Read the makefiles we care about and the environment
 2456  *  Also read the = style command line options
 2457  *
 2458  *  Parameters:
 2459  *      argc        You know what this is
 2460  *      argv        You know what this is
 2461  *
 2462  *  Static variables used:
 2463  *      env_wins    make -e, determines if env vars are RO
 2464  *      ignore_default_mk make -r, determines if make.rules is read
 2465  *      not_auto_depen  dwight
 2466  *
 2467  *  Global variables used:
 2468  *      default_target_to_build Set to first proper target from file
 2469  *      do_not_exec_rule Set to false when makfile is made
 2470  *      dot     The Name ".", used to read current dir
 2471  *      empty_name  The Name "", use as macro value
 2472  *      keep_state  Set if KEEP_STATE is in environment
 2473  *      make_state  The Name ".make.state", used to read file
 2474  *      makefile_type   Set to type of file being read
 2475  *      makeflags   The Name "MAKEFLAGS", used to set macro value
 2476  *      not_auto    dwight
 2477  *      nse     Set if NSE_ENV is in the environment
 2478  *      read_trace_level Checked to se if the reader should trace
 2479  *      report_dependencies If -P is on we do not read .make.state
 2480  *      trace_reader    Set if reader should trace
 2481  *      virtual_root    The Name "VIRTUAL_ROOT", used to check value
 2482  */
 2483 static void
 2484 read_files_and_state(int argc, char **argv)
 2485 {
 2486     wchar_t         buffer[1000];
 2487     wchar_t         buffer_posix[1000];
 2488     register char       ch;
 2489     register char       *cp;
 2490     Property        def_make_macro = NULL;
 2491     Name            def_make_name;
 2492     Name            default_makefile;
 2493     String_rec      dest;
 2494     wchar_t         destbuffer[STRING_BUFFER_LENGTH];
 2495     register int        i;
 2496     register int        j;
 2497     Name            keep_state_name;
 2498     int         length;
 2499     Name            Makefile;
 2500     register Property   macro;
 2501     struct stat     make_state_stat;
 2502     Name            makefile_name;
 2503         register int        makefile_next = 0;
 2504     register Boolean    makefile_read = false;
 2505     String_rec      makeflags_string;
 2506     String_rec      makeflags_string_posix;
 2507     String_rec *        makeflags_string_current;
 2508     Name            makeflags_value_saved;
 2509     register Name       name;
 2510     Name            new_make_value;
 2511     Boolean         save_do_not_exec_rule;
 2512     Name            sdotMakefile;
 2513     Name            sdotmakefile_name;
 2514     static wchar_t      state_file_str;
 2515     static char     state_file_str_mb[MAXPATHLEN];
 2516     static struct _Name state_filename;
 2517     Boolean         temp;
 2518     char            tmp_char;
 2519     wchar_t         *tmp_wcs_buffer;
 2520     register Name       value;
 2521     ASCII_Dyn_Array     makeflags_and_macro;
 2522     Boolean         is_xpg4;
 2523 
 2524 /*
 2525  *  Remember current mode. It may be changed after reading makefile
 2526  *  and we will have to correct MAKEFLAGS variable.
 2527  */
 2528     is_xpg4 = posix;
 2529 
 2530     MBSTOWCS(wcs_buffer, NOCATGETS("KEEP_STATE"));
 2531     keep_state_name = GETNAME(wcs_buffer, FIND_LENGTH);
 2532     MBSTOWCS(wcs_buffer, NOCATGETS("Makefile"));
 2533     Makefile = GETNAME(wcs_buffer, FIND_LENGTH);
 2534     MBSTOWCS(wcs_buffer, NOCATGETS("makefile"));
 2535     makefile_name = GETNAME(wcs_buffer, FIND_LENGTH);
 2536     MBSTOWCS(wcs_buffer, NOCATGETS("s.makefile"));
 2537     sdotmakefile_name = GETNAME(wcs_buffer, FIND_LENGTH);
 2538     MBSTOWCS(wcs_buffer, NOCATGETS("s.Makefile"));
 2539     sdotMakefile = GETNAME(wcs_buffer, FIND_LENGTH);
 2540 
 2541 /*
 2542  *  Set flag if NSE is active
 2543  */
 2544 #ifdef NSE
 2545     if (getenv(NOCATGETS("NSE_ENV")) != NULL) {
 2546         nse = true;
 2547     }
 2548 #endif
 2549 
 2550 /*
 2551  *  initialize global dependency entry for .NOT_AUTO
 2552  */
 2553     not_auto_depen->next = NULL;
 2554     not_auto_depen->name = not_auto;
 2555     not_auto_depen->automatic = not_auto_depen->stale = false;
 2556 
 2557 /*
 2558  *  Read internal definitions and rules.
 2559  */
 2560     if (read_trace_level > 1) {
 2561         trace_reader = true;
 2562     }
 2563     if (!ignore_default_mk) {
 2564 #if defined(SUN5_0) || defined(HP_UX) || defined(linux)
 2565         if (svr4) {
 2566             MBSTOWCS(wcs_buffer, NOCATGETS("svr4.make.rules"));
 2567             default_makefile = GETNAME(wcs_buffer, FIND_LENGTH);
 2568         } else {
 2569             MBSTOWCS(wcs_buffer, NOCATGETS("make.rules"));
 2570             default_makefile = GETNAME(wcs_buffer, FIND_LENGTH);
 2571         }
 2572 #else       
 2573         MBSTOWCS(wcs_buffer, NOCATGETS("default.mk"));
 2574         default_makefile = GETNAME(wcs_buffer, FIND_LENGTH);
 2575 #endif
 2576         default_makefile->stat.is_file = true;
 2577 
 2578         (void) read_makefile(default_makefile,
 2579                      true,
 2580                      false,
 2581                      true);
 2582     }
 2583 
 2584     /*
 2585      * If the user did not redefine the MAKE macro in the
 2586      * default makefile (make.rules), then we'd like to
 2587      * change the macro value of MAKE to be some form
 2588      * of argv[0] for recursive MAKE builds.
 2589      * Since POSIX claims for the option -r:
 2590      *  Clear the suffix list and do not use the built-in rules.
 2591      * $(MAKE) should not be affected by -r. We need to provide a
 2592      * useful default in case $(MAKE) has not been defined at all.
 2593      */
 2594     MBSTOWCS(wcs_buffer, NOCATGETS("MAKE"));
 2595     def_make_name = GETNAME(wcs_buffer, wcslen(wcs_buffer));
 2596     def_make_macro = get_prop(def_make_name->prop, macro_prop);
 2597     if ((def_make_macro == NULL) ||
 2598         ((def_make_macro != NULL) &&
 2599         (IS_EQUAL(def_make_macro->body.macro.value->string_mb,
 2600                   NOCATGETS("make"))))) {
 2601         MBSTOWCS(wcs_buffer, argv_zero_string);
 2602         new_make_value = GETNAME(wcs_buffer, wcslen(wcs_buffer));
 2603         (void) SETVAR(def_make_name,
 2604                       new_make_value,
 2605                       false);
 2606     }
 2607 
 2608 #ifdef  DO_MAKE_NAME
 2609     if (!sunpro_compat && !svr4) {
 2610         MBSTOWCS(wcs_buffer, NOCATGETS("sunpro"));
 2611         SETVAR(sunpro_make_name,
 2612             GETNAME(wcs_buffer, FIND_LENGTH),
 2613             false);
 2614     }
 2615 #endif
 2616 #ifdef  DO_ARCHCONF
 2617     if (!sunpro_compat && !svr4 && !no_archconf) {
 2618         setup_arch();
 2619     }
 2620 #endif
 2621 
 2622     default_target_to_build = NULL;
 2623     trace_reader = false;
 2624 
 2625 /*
 2626  *  Read environment args. Let file args which follow override unless
 2627  *  -e option seen. If -e option is not mentioned.
 2628  */
 2629     read_environment(env_wins);
 2630     if (getvar(virtual_root)->hash.length == 0) {
 2631         maybe_append_prop(virtual_root, macro_prop)
 2632           ->body.macro.exported = true;
 2633         MBSTOWCS(wcs_buffer, "/");
 2634         (void) SETVAR(virtual_root,
 2635                   GETNAME(wcs_buffer, FIND_LENGTH),
 2636                   false);
 2637     }
 2638 
 2639 /*
 2640  * We now scan mf_argv and argv to see if we need to set
 2641  * any of the DMake-added options/variables in MAKEFLAGS.
 2642  */
 2643 
 2644     makeflags_and_macro.start = 0;
 2645     makeflags_and_macro.size = 0;
 2646     enter_argv_values(mf_argc, mf_argv, &makeflags_and_macro);
 2647     enter_argv_values(argc, argv, &makeflags_and_macro);
 2648 
 2649 /*
 2650  *  Set MFLAGS and MAKEFLAGS
 2651  *  
 2652  *  Before reading makefile we do not know exactly which mode
 2653  *  (posix or not) is used. So prepare two MAKEFLAGS strings
 2654  *  for both posix and solaris modes because they are different.
 2655  */
 2656     INIT_STRING_FROM_STACK(makeflags_string, buffer);
 2657     INIT_STRING_FROM_STACK(makeflags_string_posix, buffer_posix);
 2658     append_char((int) hyphen_char, &makeflags_string);
 2659     append_char((int) hyphen_char, &makeflags_string_posix);
 2660 
 2661 #ifdef  DO_ARCHCONF
 2662     if (no_archconf) {
 2663         append_char('a', &makeflags_string);
 2664         append_char('a', &makeflags_string_posix);
 2665     }
 2666 #endif
 2667     switch (read_trace_level) {
 2668     case 2:
 2669         append_char('D', &makeflags_string);
 2670         append_char('D', &makeflags_string_posix);
 2671     case 1:
 2672         append_char('D', &makeflags_string);
 2673         append_char('D', &makeflags_string_posix);
 2674     }
 2675     switch (debug_level) {
 2676     case 2:
 2677         append_char('d', &makeflags_string);
 2678         append_char('d', &makeflags_string_posix);
 2679     case 1:
 2680         append_char('d', &makeflags_string);
 2681         append_char('d', &makeflags_string_posix);
 2682     }
 2683 #ifdef NSE
 2684     if (nse) {
 2685         append_char('E', &makeflags_string);
 2686     }
 2687 #endif
 2688     if (env_wins) {
 2689         append_char('e', &makeflags_string);
 2690         append_char('e', &makeflags_string_posix);
 2691     }
 2692     if (ignore_errors_all) {
 2693         append_char('i', &makeflags_string);
 2694         append_char('i', &makeflags_string_posix);
 2695     }
 2696     if (continue_after_error) {
 2697         if (stop_after_error_ever_seen) {
 2698             append_char('S', &makeflags_string_posix);
 2699             append_char((int) space_char, &makeflags_string_posix);
 2700             append_char((int) hyphen_char, &makeflags_string_posix);
 2701         }
 2702         append_char('k', &makeflags_string);
 2703         append_char('k', &makeflags_string_posix);
 2704     } else {
 2705         if (stop_after_error_ever_seen 
 2706             && continue_after_error_ever_seen) {
 2707             append_char('k', &makeflags_string_posix);
 2708             append_char((int) space_char, &makeflags_string_posix);
 2709             append_char((int) hyphen_char, &makeflags_string_posix);
 2710             append_char('S', &makeflags_string_posix);
 2711         }
 2712     }
 2713     if (do_not_exec_rule) {
 2714         append_char('n', &makeflags_string);
 2715         append_char('n', &makeflags_string_posix);
 2716     }
 2717     switch (report_dependencies_level) {
 2718     case 4:
 2719         append_char('P', &makeflags_string);
 2720         append_char('P', &makeflags_string_posix);
 2721     case 3:
 2722         append_char('P', &makeflags_string);
 2723         append_char('P', &makeflags_string_posix);
 2724     case 2:
 2725         append_char('P', &makeflags_string);
 2726         append_char('P', &makeflags_string_posix);
 2727     case 1:
 2728         append_char('P', &makeflags_string);
 2729         append_char('P', &makeflags_string_posix);
 2730     }
 2731     if (trace_status) {
 2732         append_char('p', &makeflags_string);
 2733         append_char('p', &makeflags_string_posix);
 2734     }
 2735     if (quest) {
 2736         append_char('q', &makeflags_string);
 2737         append_char('q', &makeflags_string_posix);
 2738     }
 2739     if (ignore_default_mk) {
 2740         append_char('r', &makeflags_string);
 2741         append_char('r', &makeflags_string_posix);
 2742     }
 2743     if (silent_all) {
 2744         append_char('s', &makeflags_string);
 2745         append_char('s', &makeflags_string_posix);
 2746     }
 2747     if (touch) {
 2748         append_char('t', &makeflags_string);
 2749         append_char('t', &makeflags_string_posix);
 2750     }
 2751     if (build_unconditional) {
 2752         append_char('u', &makeflags_string);
 2753         append_char('u', &makeflags_string_posix);
 2754     }
 2755     if (report_cwd) {
 2756         append_char('w', &makeflags_string);
 2757         append_char('w', &makeflags_string_posix);
 2758     }
 2759 #ifndef PARALLEL
 2760     /* -c dmake_rcfile */
 2761     if (dmake_rcfile_specified) {
 2762         MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_RCFILE"));
 2763         dmake_rcfile = GETNAME(wcs_buffer, FIND_LENGTH);
 2764         append_makeflags_string(dmake_rcfile, &makeflags_string);
 2765         append_makeflags_string(dmake_rcfile, &makeflags_string_posix);
 2766     }
 2767     /* -g dmake_group */
 2768     if (dmake_group_specified) {
 2769         MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_GROUP"));
 2770         dmake_group = GETNAME(wcs_buffer, FIND_LENGTH);
 2771         append_makeflags_string(dmake_group, &makeflags_string);
 2772         append_makeflags_string(dmake_group, &makeflags_string_posix);
 2773     }
 2774     /* -j dmake_max_jobs */
 2775     if (dmake_max_jobs_specified) {
 2776         MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MAX_JOBS"));
 2777         dmake_max_jobs = GETNAME(wcs_buffer, FIND_LENGTH);
 2778         append_makeflags_string(dmake_max_jobs, &makeflags_string);
 2779         append_makeflags_string(dmake_max_jobs, &makeflags_string_posix);
 2780     }
 2781     /* -m dmake_mode */
 2782     if (dmake_mode_specified) {
 2783         MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE"));
 2784         dmake_mode = GETNAME(wcs_buffer, FIND_LENGTH);
 2785         append_makeflags_string(dmake_mode, &makeflags_string);
 2786         append_makeflags_string(dmake_mode, &makeflags_string_posix);
 2787     }
 2788     /* -x dmake_compat_mode */
 2789     if (dmake_compat_mode_specified) {
 2790         MBSTOWCS(wcs_buffer, NOCATGETS("SUN_MAKE_COMPAT_MODE"));
 2791         dmake_compat_mode = GETNAME(wcs_buffer, FIND_LENGTH);
 2792         append_makeflags_string(dmake_compat_mode, &makeflags_string);
 2793         append_makeflags_string(dmake_compat_mode, &makeflags_string_posix);
 2794     }
 2795     /* -x dmake_output_mode */
 2796     if (dmake_output_mode_specified) {
 2797         MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_OUTPUT_MODE"));
 2798         dmake_output_mode = GETNAME(wcs_buffer, FIND_LENGTH);
 2799         append_makeflags_string(dmake_output_mode, &makeflags_string);
 2800         append_makeflags_string(dmake_output_mode, &makeflags_string_posix);
 2801     }
 2802     /* -o dmake_odir */
 2803     if (dmake_odir_specified) {
 2804         MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_ODIR"));
 2805         dmake_odir = GETNAME(wcs_buffer, FIND_LENGTH);
 2806         append_makeflags_string(dmake_odir, &makeflags_string);
 2807         append_makeflags_string(dmake_odir, &makeflags_string_posix);
 2808     }
 2809     /* -M pmake_machinesfile */
 2810     if (pmake_machinesfile_specified) {
 2811         MBSTOWCS(wcs_buffer, NOCATGETS("PMAKE_MACHINESFILE"));
 2812         pmake_machinesfile = GETNAME(wcs_buffer, FIND_LENGTH);
 2813         append_makeflags_string(pmake_machinesfile, &makeflags_string);
 2814         append_makeflags_string(pmake_machinesfile, &makeflags_string_posix);
 2815     }
 2816     /* -R */
 2817     if (pmake_cap_r_specified) {
 2818         append_char((int) space_char, &makeflags_string);
 2819         append_char((int) hyphen_char, &makeflags_string);
 2820         append_char('R', &makeflags_string);
 2821         append_char((int) space_char, &makeflags_string_posix);
 2822         append_char((int) hyphen_char, &makeflags_string_posix);
 2823         append_char('R', &makeflags_string_posix);
 2824     }
 2825 #endif
 2826 
 2827 /*
 2828  *  Make sure MAKEFLAGS is exported
 2829  */
 2830     maybe_append_prop(makeflags, macro_prop)->
 2831       body.macro.exported = true;
 2832 
 2833     if (makeflags_string.buffer.start[1] != (int) nul_char) {
 2834         if (makeflags_string.buffer.start[1] != (int) space_char) {
 2835             MBSTOWCS(wcs_buffer, NOCATGETS("MFLAGS"));
 2836             (void) SETVAR(GETNAME(wcs_buffer, FIND_LENGTH),
 2837                       GETNAME(makeflags_string.buffer.start,
 2838                           FIND_LENGTH),
 2839                       false);
 2840         } else {
 2841             MBSTOWCS(wcs_buffer, NOCATGETS("MFLAGS"));
 2842             (void) SETVAR(GETNAME(wcs_buffer, FIND_LENGTH),
 2843                       GETNAME(makeflags_string.buffer.start + 2,
 2844                           FIND_LENGTH),
 2845                       false);
 2846         }
 2847     }
 2848 
 2849 /* 
 2850  *  Add command line macro to POSIX makeflags_string  
 2851  */
 2852     if (makeflags_and_macro.start) {
 2853         tmp_char = (char) space_char;
 2854         cp = makeflags_and_macro.start;
 2855         do {
 2856             if (!sunpro_compat && !svr4)
 2857                 append_char(tmp_char, &makeflags_string);
 2858             append_char(tmp_char, &makeflags_string_posix);
 2859         } while ((tmp_char = *cp++) != '\0'); 
 2860         retmem_mb(makeflags_and_macro.start);
 2861     }
 2862 
 2863 /*
 2864  *  Now set the value of MAKEFLAGS macro in accordance
 2865  *  with current mode.
 2866  */
 2867     macro = maybe_append_prop(makeflags, macro_prop);
 2868     temp = (Boolean) macro->body.macro.read_only;
 2869     macro->body.macro.read_only = false;
 2870     if(posix || gnu_style) {
 2871         makeflags_string_current = &makeflags_string_posix;
 2872     } else {
 2873         makeflags_string_current = &makeflags_string;
 2874     }
 2875     if (makeflags_string_current->buffer.start[1] == (int) nul_char) {
 2876         makeflags_value_saved =
 2877             GETNAME( makeflags_string_current->buffer.start + 1
 2878                    , FIND_LENGTH
 2879                    );
 2880     } else {
 2881         if (makeflags_string_current->buffer.start[1] != (int) space_char) {
 2882             makeflags_value_saved =
 2883                 GETNAME( makeflags_string_current->buffer.start
 2884                        , FIND_LENGTH
 2885                        );
 2886         } else {
 2887             makeflags_value_saved =
 2888                 GETNAME( makeflags_string_current->buffer.start + 2
 2889                        , FIND_LENGTH
 2890                        );
 2891         }
 2892     }
 2893     (void) SETVAR( makeflags
 2894                  , makeflags_value_saved
 2895                  , false
 2896                  );
 2897     macro->body.macro.read_only = temp;
 2898 
 2899 /*
 2900  *  Read command line "-f" arguments and ignore -c, g, j, K, M, m, O and o args.
 2901  */
 2902     save_do_not_exec_rule = do_not_exec_rule;
 2903     do_not_exec_rule = false;
 2904     if (read_trace_level > 0) {
 2905         trace_reader = true;
 2906     }
 2907 
 2908     for (i = 1; i < argc; i++) {
 2909         if (argv[i] &&
 2910             (argv[i][0] == (int) hyphen_char) &&
 2911             (argv[i][1] == 'f') &&
 2912             (argv[i][2] == (int) nul_char)) {
 2913             argv[i] = NULL;     /* Remove -f */
 2914             if (i >= argc - 1) {
 2915                 fatal(gettext("No filename argument after -f flag"));
 2916             }
 2917             MBSTOWCS(wcs_buffer, argv[++i]);
 2918             primary_makefile = GETNAME(wcs_buffer, FIND_LENGTH);
 2919             (void) read_makefile(primary_makefile, true, true, true);
 2920             argv[i] = NULL;     /* Remove filename */
 2921             makefile_read = true;
 2922         } else if (argv[i] &&
 2923                (argv[i][0] == (int) hyphen_char) &&
 2924                (argv[i][1] == 'C' ||
 2925                 argv[i][1] == 'c' ||
 2926                 argv[i][1] == 'g' ||
 2927                 argv[i][1] == 'j' ||
 2928                 argv[i][1] == 'K' ||
 2929                 argv[i][1] == 'M' ||
 2930                 argv[i][1] == 'm' ||
 2931                 argv[i][1] == 'O' ||
 2932                 argv[i][1] == 'o') &&
 2933                (argv[i][2] == (int) nul_char)) {
 2934             argv[i] = NULL;
 2935             argv[++i] = NULL;
 2936         }
 2937     }
 2938 
 2939 /*
 2940  *  If no command line "-f" args then look for "makefile", and then for
 2941  *  "Makefile" if "makefile" isn't found.
 2942  */
 2943     if (!makefile_read) {
 2944         (void) read_dir(dot,
 2945                 (wchar_t *) NULL,
 2946                 (Property) NULL,
 2947                 (wchar_t *) NULL);
 2948         if (!posix) {
 2949         if (makefile_name->stat.is_file) {
 2950             if (Makefile->stat.is_file) {
 2951                 warning(gettext("Both `makefile' and `Makefile' exist"));
 2952             }
 2953             primary_makefile = makefile_name;
 2954             makefile_read = read_makefile(makefile_name,
 2955                               false,
 2956                               false,
 2957                               true);
 2958         }
 2959         if (!makefile_read &&
 2960             Makefile->stat.is_file) {
 2961             primary_makefile = Makefile;
 2962             makefile_read = read_makefile(Makefile,
 2963                               false,
 2964                               false,
 2965                               true);
 2966         }
 2967         } else {
 2968 
 2969         enum sccs_stat save_m_has_sccs = NO_SCCS;
 2970         enum sccs_stat save_M_has_sccs = NO_SCCS;
 2971 
 2972         if (makefile_name->stat.is_file) {
 2973             if (Makefile->stat.is_file) {
 2974                 warning(gettext("Both `makefile' and `Makefile' exist"));
 2975             }
 2976         }
 2977         if (makefile_name->stat.is_file) {
 2978             if (makefile_name->stat.has_sccs == NO_SCCS) {
 2979                primary_makefile = makefile_name;
 2980                makefile_read = read_makefile(makefile_name,
 2981                               false,
 2982                               false,
 2983                               true);
 2984             } else {
 2985               save_m_has_sccs = makefile_name->stat.has_sccs;
 2986               makefile_name->stat.has_sccs = NO_SCCS;
 2987               primary_makefile = makefile_name;
 2988               makefile_read = read_makefile(makefile_name,
 2989                               false,
 2990                               false,
 2991                               true);
 2992             }
 2993         }
 2994         if (!makefile_read &&
 2995             Makefile->stat.is_file) {
 2996             if (Makefile->stat.has_sccs == NO_SCCS) {
 2997                primary_makefile = Makefile;
 2998                makefile_read = read_makefile(Makefile,
 2999                               false,
 3000                               false,
 3001                               true);
 3002             } else {
 3003               save_M_has_sccs = Makefile->stat.has_sccs;
 3004               Makefile->stat.has_sccs = NO_SCCS;
 3005               primary_makefile = Makefile;
 3006               makefile_read = read_makefile(Makefile,
 3007                               false,
 3008                               false,
 3009                               true);
 3010             }
 3011         }
 3012         if (!makefile_read &&
 3013                 makefile_name->stat.is_file) {
 3014                makefile_name->stat.has_sccs = save_m_has_sccs;
 3015                primary_makefile = makefile_name;
 3016                makefile_read = read_makefile(makefile_name,
 3017                               false,
 3018                               false,
 3019                               true);
 3020         }
 3021         if (!makefile_read &&
 3022             Makefile->stat.is_file) {
 3023                Makefile->stat.has_sccs = save_M_has_sccs;
 3024                primary_makefile = Makefile;
 3025                makefile_read = read_makefile(Makefile,
 3026                               false,
 3027                               false,
 3028                               true);
 3029         }
 3030         }
 3031     }
 3032     do_not_exec_rule = save_do_not_exec_rule;
 3033     allrules_read = makefile_read;
 3034     trace_reader = false;
 3035 
 3036 /*
 3037  *  Now get current value of MAKEFLAGS and compare it with
 3038  *  the saved value we set before reading makefile.
 3039  *  If they are different then MAKEFLAGS is subsequently set by
 3040  *  makefile, just leave it there. Otherwise, if make mode
 3041  *  is changed by using .POSIX target in makefile we need
 3042  *  to correct MAKEFLAGS value.
 3043  */
 3044     Name mf_val = getvar(makeflags);
 3045     if( (posix != is_xpg4)
 3046      && (!strcmp(mf_val->string_mb, makeflags_value_saved->string_mb)))
 3047     {
 3048         if (makeflags_string_posix.buffer.start[1] == (int) nul_char) {
 3049             (void) SETVAR(makeflags,
 3050                       GETNAME(makeflags_string_posix.buffer.start + 1,
 3051                           FIND_LENGTH),
 3052                       false);
 3053         } else {
 3054             if (makeflags_string_posix.buffer.start[1] != (int) space_char) {
 3055                 (void) SETVAR(makeflags,
 3056                           GETNAME(makeflags_string_posix.buffer.start,
 3057                               FIND_LENGTH),
 3058                           false);
 3059             } else {
 3060                 (void) SETVAR(makeflags,
 3061                           GETNAME(makeflags_string_posix.buffer.start + 2,
 3062                               FIND_LENGTH),
 3063                           false);
 3064             }
 3065         }
 3066     }
 3067 
 3068     if (makeflags_string.free_after_use) {
 3069         retmem(makeflags_string.buffer.start);
 3070     }
 3071     if (makeflags_string_posix.free_after_use) {
 3072         retmem(makeflags_string_posix.buffer.start);
 3073     }
 3074     makeflags_string.buffer.start = NULL;
 3075     makeflags_string_posix.buffer.start = NULL;
 3076 
 3077     if (posix) {
 3078         /*
 3079          * If the user did not redefine the ARFLAGS macro in the
 3080          * default makefile (make.rules), then we'd like to
 3081          * change the macro value of ARFLAGS to be in accordance
 3082          * with "POSIX" requirements.
 3083          */
 3084         MBSTOWCS(wcs_buffer, NOCATGETS("ARFLAGS"));
 3085         name = GETNAME(wcs_buffer, wcslen(wcs_buffer));
 3086         macro = get_prop(name->prop, macro_prop);
 3087         if ((macro != NULL) && /* Maybe (macro == NULL) || ? */
 3088             (IS_EQUAL(macro->body.macro.value->string_mb,
 3089                       NOCATGETS("rv")))) {
 3090             MBSTOWCS(wcs_buffer, NOCATGETS("-rv"));
 3091             value = GETNAME(wcs_buffer, wcslen(wcs_buffer));
 3092             (void) SETVAR(name,
 3093                           value,
 3094                           false);
 3095         }
 3096     }
 3097 
 3098     if (!posix && !svr4) {
 3099         set_sgs_support();
 3100     }
 3101 
 3102 
 3103 /*
 3104  *  Make sure KEEP_STATE is in the environment if KEEP_STATE is on.
 3105  */
 3106     macro = get_prop(keep_state_name->prop, macro_prop);
 3107     if ((macro != NULL) &&
 3108         macro->body.macro.exported) {
 3109         keep_state = true;
 3110     }
 3111     if (keep_state) {
 3112         if (macro == NULL) {
 3113             macro = maybe_append_prop(keep_state_name,
 3114                           macro_prop);
 3115         }
 3116         macro->body.macro.exported = true;
 3117         (void) SETVAR(keep_state_name,
 3118                   empty_name,
 3119                   false);
 3120 
 3121         /*
 3122          *  Read state file
 3123          */
 3124 
 3125         /* Before we read state, let's make sure we have
 3126         ** right state file.
 3127         */
 3128         /* just in case macro references are used in make_state file
 3129         ** name, we better expand them at this stage using expand_value.
 3130         */
 3131         INIT_STRING_FROM_STACK(dest, destbuffer);
 3132         expand_value(make_state, &dest, false);
 3133 
 3134         make_state = GETNAME(dest.buffer.start, FIND_LENGTH);
 3135 
 3136         if(!stat(make_state->string_mb, &make_state_stat)) {
 3137            if(!(make_state_stat.st_mode & S_IFREG) ) {
 3138             /* copy the make_state structure to the other
 3139             ** and then let make_state point to the new
 3140             ** one.
 3141             */
 3142               memcpy(&state_filename, make_state,sizeof(state_filename));
 3143               state_filename.string_mb = state_file_str_mb;
 3144         /* Just a kludge to avoid two slashes back to back */           
 3145               if((make_state->hash.length == 1)&&
 3146                     (make_state->string_mb[0] == '/')) {
 3147              make_state->hash.length = 0;
 3148              make_state->string_mb[0] = '\0';
 3149               }
 3150               sprintf(state_file_str_mb,NOCATGETS("%s%s"),
 3151                make_state->string_mb,NOCATGETS("/.make.state"));
 3152               make_state = &state_filename;
 3153             /* adjust the length to reflect the appended string */
 3154               make_state->hash.length += 12;
 3155            }
 3156         } else { /* the file doesn't exist or no permission */
 3157            char tmp_path[MAXPATHLEN];
 3158            char *slashp;
 3159 
 3160            if ((slashp = strrchr(make_state->string_mb, '/')) != 0) {
 3161               strncpy(tmp_path, make_state->string_mb, 
 3162                 (slashp - make_state->string_mb));
 3163             tmp_path[slashp - make_state->string_mb]=0;
 3164               if(strlen(tmp_path)) {
 3165                 if(stat(tmp_path, &make_state_stat)) {
 3166               warning(gettext("directory %s for .KEEP_STATE_FILE does not exist"),tmp_path);
 3167                 }
 3168                 if (access(tmp_path, F_OK) != 0) {
 3169               warning(gettext("can't access dir %s"),tmp_path);
 3170                 }
 3171               }
 3172            }
 3173         }
 3174         if (report_dependencies_level != 1) {
 3175             Makefile_type   makefile_type_temp = makefile_type;
 3176             makefile_type = reading_statefile;
 3177             if (read_trace_level > 1) {
 3178                 trace_reader = true;
 3179             }
 3180             (void) read_simple_file(make_state,
 3181                         false,
 3182                         false,
 3183                         false,
 3184                         false,
 3185                         false,
 3186                         true);
 3187             trace_reader = false;
 3188             makefile_type = makefile_type_temp;
 3189         }
 3190     }
 3191 }
 3192 
 3193 /*
 3194  * Scan the argv for options and "=" type args and make them readonly.
 3195  */
 3196 static void
 3197 enter_argv_values(int argc, char *argv[], ASCII_Dyn_Array *makeflags_and_macro)
 3198 {
 3199     register char       *cp;
 3200     register int        i;
 3201     int         length;
 3202     register Name       name;
 3203     int         opt_separator = argc; 
 3204     char            tmp_char;
 3205     wchar_t         *tmp_wcs_buffer;
 3206     register Name       value;
 3207     Boolean         append = false;
 3208     Boolean         gnuassign = false;
 3209     Property        macro;
 3210     struct stat     statbuf;
 3211 
 3212 
 3213     /* Read argv options and "=" type args and make them readonly. */
 3214     makefile_type = reading_nothing;
 3215     for (i = 1; i < argc; ++i) {
 3216         append = false;
 3217         if (argv[i] == NULL) {
 3218             continue;
 3219         } else if (((argv[i][0] == '-') && (argv[i][1] == '-')) ||
 3220                ((argv[i][0] == (int) ' ') &&
 3221                 (argv[i][1] == (int) '-') &&
 3222                 (argv[i][2] == (int) ' ') &&
 3223                 (argv[i][3] == (int) '-'))) {
 3224             argv[i] = NULL;
 3225             opt_separator = i;
 3226             continue;
 3227         } else if ((i < opt_separator) && (argv[i][0] == (int) hyphen_char)) {
 3228             char    *ap = argv[i+1];
 3229 
 3230             switch (parse_command_option(argv[i][1])) {
 3231             case 1: /* -f seen */
 3232                 ++i;
 3233                 continue;
 3234             case 2: /* -c seen */
 3235                 if (argv[i+1] == NULL) {
 3236                     fatal(gettext("No dmake rcfile argument after -c flag"));
 3237                 }
 3238                 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_RCFILE"));
 3239                 name = GETNAME(wcs_buffer, FIND_LENGTH);
 3240                 break;
 3241             case 4: /* -g seen */
 3242                 if (argv[i+1] == NULL) {
 3243                     fatal(gettext("No dmake group argument after -g flag"));
 3244                 }
 3245                 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_GROUP"));
 3246                 name = GETNAME(wcs_buffer, FIND_LENGTH);
 3247                 break;
 3248             case 8: /* -j seen */
 3249                 if (argv[i][2])     /* e.g. -j5 */
 3250                     ap = &argv[i][2];
 3251                 if (ap == NULL) {
 3252                     fatal(gettext("No dmake max jobs argument after -j flag"));
 3253                 }
 3254                 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MAX_JOBS"));
 3255                 name = GETNAME(wcs_buffer, FIND_LENGTH);
 3256                 break;
 3257             case 16: /* -M seen */
 3258                 if (argv[i+1] == NULL) {
 3259                     fatal(gettext("No pmake machinesfile argument after -M flag"));
 3260                 }
 3261                 MBSTOWCS(wcs_buffer, NOCATGETS("PMAKE_MACHINESFILE"));
 3262                 name = GETNAME(wcs_buffer, FIND_LENGTH);
 3263                 break;
 3264             case 32: /* -m seen */
 3265                 if (argv[i+1] == NULL) {
 3266                     fatal(gettext("No dmake mode argument after -m flag"));
 3267                 }
 3268                 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE"));
 3269                 name = GETNAME(wcs_buffer, FIND_LENGTH);
 3270                 break;
 3271             case 128: /* -O seen */
 3272                 if (argv[i+1] == NULL) {
 3273                     fatal(gettext("No file descriptor argument after -O flag"));
 3274                 }
 3275                 mtool_msgs_fd = atoi(argv[i+1]);
 3276                 /* find out if mtool_msgs_fd is a valid file descriptor */
 3277                 if (fstat(mtool_msgs_fd, &statbuf) < 0) {
 3278                     fatal(gettext("Invalid file descriptor %d after -O flag"), mtool_msgs_fd);
 3279                 }
 3280                 argv[i] = NULL;
 3281                 argv[i+1] = NULL;
 3282                 continue;
 3283             case 256: /* -K seen */
 3284                 if (argv[i+1] == NULL) {
 3285                     fatal(gettext("No makestate filename argument after -K flag"));
 3286                 }
 3287                 MBSTOWCS(wcs_buffer, argv[i+1]);
 3288                 make_state = GETNAME(wcs_buffer, FIND_LENGTH);
 3289                 keep_state = true;
 3290                 argv[i] = NULL;
 3291                 argv[i+1] = NULL;
 3292                 continue;
 3293             case 512:   /* -o seen */
 3294                 if (argv[i+1] == NULL) {
 3295                     fatal(gettext("No dmake output dir argument after -o flag"));
 3296                 }
 3297                 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_ODIR"));
 3298                 name = GETNAME(wcs_buffer, FIND_LENGTH);
 3299                 break;
 3300             case 1024: /* -x seen */
 3301                 if (argv[i+1] == NULL) {
 3302                     fatal(gettext("No argument after -x flag"));
 3303                 }
 3304                 length = strlen( NOCATGETS("SUN_MAKE_COMPAT_MODE="));
 3305                 if (strncmp(argv[i+1], NOCATGETS("SUN_MAKE_COMPAT_MODE="), length) == 0) {
 3306                     argv[i+1] = ap = &argv[i+1][length];
 3307                     MBSTOWCS(wcs_buffer, NOCATGETS("SUN_MAKE_COMPAT_MODE"));
 3308                     name = GETNAME(wcs_buffer, FIND_LENGTH);
 3309                     dmake_compat_mode_specified = dmake_add_mode_specified;
 3310                     break;
 3311                 }
 3312                 length = strlen( NOCATGETS("DMAKE_OUTPUT_MODE="));
 3313                 if (strncmp(argv[i+1], NOCATGETS("DMAKE_OUTPUT_MODE="), length) == 0) {
 3314                     argv[i+1] = ap = &argv[i+1][length];
 3315                     MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_OUTPUT_MODE"));
 3316                     name = GETNAME(wcs_buffer, FIND_LENGTH);
 3317                     dmake_output_mode_specified = dmake_add_mode_specified;
 3318                 } else {
 3319                     warning(gettext("Unknown argument `%s' after -x flag (ignored)"),
 3320                           argv[i+1]);
 3321                     argv[i] = argv[i + 1] = NULL;
 3322                     continue;
 3323                 }
 3324                 break;
 3325             case 2048: /* -C seen */
 3326                 if (argv[i][2])     /* e.g. -Cdir */
 3327                     ap = &argv[i][2];
 3328                 else
 3329                     argv[i+1] = NULL;
 3330                 argv[i] = NULL;
 3331                 continue;
 3332             default: /* Shouldn't reach here */
 3333                 argv[i] = NULL;
 3334                 continue;
 3335             }
 3336             argv[i] = NULL;
 3337             if (argv[i+1] == ap)    /* If optarg is separate */
 3338                 argv[i+1] = NULL;
 3339             else
 3340                 i--;
 3341             if (i == (argc - 1)) {
 3342                 break;
 3343             }
 3344             if ((length = strlen(ap)) >= MAXPATHLEN) {
 3345                 tmp_wcs_buffer = ALLOC_WC(length + 1);
 3346                 (void) mbstowcs(tmp_wcs_buffer, ap, length + 1);
 3347                 value = GETNAME(tmp_wcs_buffer, FIND_LENGTH);
 3348                 retmem(tmp_wcs_buffer);
 3349             } else {
 3350                 MBSTOWCS(wcs_buffer, ap);
 3351                 value = GETNAME(wcs_buffer, FIND_LENGTH);
 3352             }
 3353         } else if ((cp = strchr(argv[i], (int) equal_char)) != NULL) {
 3354             Boolean expand = false;
 3355             Boolean gnuassign = false;
 3356 
 3357             if (*(cp-1) == (int) plus_char) {
 3358                 if (isspace(*(cp-2))) {     /* += */
 3359                     append = true;
 3360                     cp--;
 3361                 }
 3362             } else if (*(cp-1) == (int) colon_char) {
 3363                 if (*(cp-2) == (int) plus_char &&
 3364                     isspace(*(cp-3))) {     /* +:= */
 3365                     append = true;
 3366                     expand = true;
 3367                     cp -= 2;
 3368                 } else if (*(cp-2) == (int) colon_char) {
 3369                     if (*(cp-3) == (int) colon_char) {
 3370                         /* :::= */
 3371                         cp -= 3;
 3372                         expand = true;
 3373 #ifdef  GNU_ASSIGN_BY_DEFAULT
 3374                     } else {
 3375 #else
 3376                     } else if (posix || gnu_style) {
 3377 #endif
 3378                         /* ::= */
 3379                         cp -= 2;
 3380                         expand = true;
 3381                         gnuassign = true;
 3382                     }
 3383                 }
 3384             }
 3385 
 3386             /*
 3387              * Combine all macro in dynamic array
 3388              */
 3389             if (!append)
 3390                 append_or_replace_macro_in_dyn_array(makeflags_and_macro, argv[i]);
 3391 
 3392             while (isspace(*(cp-1))) {
 3393                 cp--;
 3394             }
 3395             tmp_char = *cp;
 3396             *cp = (int) nul_char;
 3397             MBSTOWCS(wcs_buffer, argv[i]);
 3398             *cp = tmp_char;
 3399             name = GETNAME(wcs_buffer, wcslen(wcs_buffer));
 3400             if (gnuassign &&
 3401                 name->stat.macro_type == unknown_macro_type)
 3402                 name->stat.macro_type = gnu_assign;
 3403             while (*cp != (int) equal_char) {
 3404                 cp++;
 3405             }
 3406             cp++;
 3407             while (isspace(*cp) && (*cp != (int) nul_char)) {
 3408                 cp++;
 3409             }
 3410             if ((length = strlen(cp)) >= MAXPATHLEN) {
 3411                 tmp_wcs_buffer = ALLOC_WC(length + 1);
 3412                 (void) mbstowcs(tmp_wcs_buffer, cp, length + 1);
 3413                 value = GETNAME(tmp_wcs_buffer, FIND_LENGTH);
 3414                 retmem(tmp_wcs_buffer);
 3415             } else {
 3416                 MBSTOWCS(wcs_buffer, cp);
 3417                 value = GETNAME(wcs_buffer, FIND_LENGTH);
 3418             }
 3419             if (expand) {
 3420                 String_rec  val; 
 3421                 wchar_t     buffer[STRING_BUFFER_LENGTH]; 
 3422 
 3423                 INIT_STRING_FROM_STACK(val, buffer);
 3424                 expand_value(value, &val, false);
 3425                 value = GETNAME(val.buffer.start, FIND_LENGTH);
 3426             }
 3427             argv[i] = NULL;
 3428         } else {
 3429             /* Illegal MAKEFLAGS argument */
 3430             continue;
 3431         }
 3432         if(append) {
 3433             setvar_append(name, value);
 3434             append = false;
 3435         } else {
 3436             macro = maybe_append_prop(name, macro_prop);
 3437             macro->body.macro.exported = true;
 3438             SETVAR(name, value, false)->body.macro.read_only = true;
 3439         }
 3440     }
 3441 }
 3442 
 3443 /*
 3444  * Append the DMake option and value to the MAKEFLAGS string.
 3445  */
 3446 static void
 3447 append_makeflags_string(Name name, register String makeflags_string)
 3448 {
 3449     char        *option;
 3450 
 3451     if (strcmp(name->string_mb, NOCATGETS("DMAKE_GROUP")) == 0) {
 3452         option = (char *)NOCATGETS(" -g ");
 3453     } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_MAX_JOBS")) == 0) {
 3454         option = (char *)NOCATGETS(" -j ");
 3455     } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_MODE")) == 0) {
 3456         option = (char *)NOCATGETS(" -m ");
 3457     } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_ODIR")) == 0) {
 3458         option = (char *)NOCATGETS(" -o ");
 3459     } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_RCFILE")) == 0) {
 3460         option = (char *)NOCATGETS(" -c ");
 3461     } else if (strcmp(name->string_mb, NOCATGETS("PMAKE_MACHINESFILE")) == 0) {
 3462         option = (char *)NOCATGETS(" -M ");
 3463     } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_OUTPUT_MODE")) == 0) {
 3464         option = (char *)NOCATGETS(" -x DMAKE_OUTPUT_MODE=");
 3465     } else if (strcmp(name->string_mb, NOCATGETS("SUN_MAKE_COMPAT_MODE")) == 0) {
 3466         option = (char *)NOCATGETS(" -x SUN_MAKE_COMPAT_MODE=");
 3467     } else {
 3468         fatal(gettext("Internal error: name not recognized in append_makeflags_string()"));
 3469     }
 3470     Property prop = maybe_append_prop(name, macro_prop);
 3471     if( prop == 0 || prop->body.macro.value == 0 ||
 3472         prop->body.macro.value->string_mb == 0 ) {
 3473         return;
 3474     }
 3475     char mbs_value[MAXPATHLEN + 100];
 3476     strcpy(mbs_value, option);
 3477     strcat(mbs_value, prop->body.macro.value->string_mb);
 3478     MBSTOWCS(wcs_buffer, mbs_value);
 3479     append_string(wcs_buffer, makeflags_string, FIND_LENGTH);
 3480 }
 3481 
 3482 /*
 3483  *  read_environment(read_only)
 3484  *
 3485  *  This routine reads the process environment when make starts and enters
 3486  *  it as make macros. The environment variable SHELL is ignored.
 3487  *
 3488  *  Parameters:
 3489  *      read_only   Should we make env vars read only?
 3490  *
 3491  *  Global variables used:
 3492  *      report_pwd  Set if this make was started by other make
 3493  */
 3494 static void
 3495 read_environment(Boolean read_only)
 3496 {
 3497     register char       **environment;
 3498     int         length;
 3499     wchar_t         *tmp_wcs_buffer;
 3500     Boolean         alloced_tmp_wcs_buffer = false;
 3501     register wchar_t    *name;
 3502     register wchar_t    *value;
 3503     register Name       macro;
 3504     Property        val;
 3505     Boolean         read_only_saved;
 3506 
 3507     reading_environment = true;
 3508     environment = environ;
 3509     for (; *environment; environment++) {
 3510         read_only_saved = read_only;
 3511         if ((length = strlen(*environment)) >= MAXPATHLEN) {
 3512             tmp_wcs_buffer = ALLOC_WC(length + 1);
 3513             alloced_tmp_wcs_buffer = true;
 3514             (void) mbstowcs(tmp_wcs_buffer, *environment, length + 1);
 3515             name = tmp_wcs_buffer;
 3516         } else {
 3517             MBSTOWCS(wcs_buffer, *environment);
 3518             name = wcs_buffer;
 3519         }
 3520         value = (wchar_t *) wcschr(name, (int) equal_char);
 3521 
 3522         /*
 3523          * Looks like there's a bug in the system, but sometimes
 3524          * you can get blank lines in *environment.
 3525          */
 3526         if (!value) {
 3527             continue;
 3528         }
 3529         MBSTOWCS(wcs_buffer2, NOCATGETS("SHELL="));
 3530         if (IS_WEQUALN(name, wcs_buffer2, wcslen(wcs_buffer2))) {
 3531             continue;
 3532         }
 3533         MBSTOWCS(wcs_buffer2, NOCATGETS("MAKEFLAGS="));
 3534         if (IS_WEQUALN(name, wcs_buffer2, wcslen(wcs_buffer2))) {
 3535             report_pwd = true;
 3536             /*
 3537              * In POSIX mode we do not want MAKEFLAGS to be readonly.
 3538              * If the MAKEFLAGS macro is subsequently set by the makefile,
 3539              * it replaces the MAKEFLAGS variable currently found in the
 3540              * environment.
 3541              * See Assertion 50 in section 6.2.5.3 of standard P1003.3.2/D8.
 3542              */
 3543             if(posix) {
 3544                 read_only_saved = false;
 3545             }
 3546         }
 3547 
 3548         /*
 3549          * We ignore SUNPRO_DEPENDENCIES and NSE_DEP. Those
 3550          * environment variables are set by make and read by 
 3551          * cpp which then writes info to .make.dependency.xxx and 
 3552          * .nse_depinfo. When make is invoked by another make 
 3553          * (recursive make), we don't want to read this because 
 3554          * then the child make will end up writing to the parent 
 3555          * directory's .make.state and .nse_depinfo and clobbering
 3556          * them. 
 3557          */
 3558         MBSTOWCS(wcs_buffer2, NOCATGETS("SUNPRO_DEPENDENCIES"));
 3559         if (IS_WEQUALN(name, wcs_buffer2, wcslen(wcs_buffer2))) {
 3560             continue;
 3561         }
 3562 #ifdef NSE
 3563         MBSTOWCS(wcs_buffer2, NOCATGETS("NSE_DEP"));
 3564         if (IS_WEQUALN(name, wcs_buffer2, wcslen(wcs_buffer2))) {
 3565             continue;
 3566         }
 3567 #endif
 3568 
 3569         macro = GETNAME(name, value - name);
 3570         maybe_append_prop(macro, macro_prop)->body.macro.exported =
 3571           true;
 3572         if ((value == NULL) || ((value + 1)[0] == (int) nul_char)) {
 3573             val = setvar_daemon(macro,
 3574                         (Name) NULL,
 3575                         false, no_daemon, false, debug_level);
 3576         } else {
 3577             val = setvar_daemon(macro,
 3578                         GETNAME(value + 1, FIND_LENGTH),
 3579                         false, no_daemon, false, debug_level);
 3580         }
 3581 #ifdef NSE
 3582                 /*
 3583              * Must be after the call to setvar() as it sets
 3584              * imported to false.
 3585              */
 3586         maybe_append_prop(macro, macro_prop)->body.macro.imported = true;
 3587 #endif
 3588         val->body.macro.read_only = read_only_saved;
 3589         if (alloced_tmp_wcs_buffer) {
 3590             retmem(tmp_wcs_buffer);
 3591             alloced_tmp_wcs_buffer = false;
 3592         }
 3593     }
 3594     reading_environment = false;
 3595 }
 3596 
 3597 /*
 3598  *  read_makefile(makefile, complain, must_exist, report_file)
 3599  *
 3600  *  Read one makefile and check the result
 3601  *
 3602  *  Return value:
 3603  *              false is the read failed
 3604  *
 3605  *  Parameters:
 3606  *      makefile    The file to read
 3607  *      complain    Passed thru to read_simple_file()
 3608  *      must_exist  Passed thru to read_simple_file()
 3609  *      report_file Passed thru to read_simple_file()
 3610  *
 3611  *  Global variables used:
 3612  *      makefile_type   Set to indicate we are reading main file
 3613  *      recursion_level Initialized
 3614  */
 3615 static Boolean
 3616 read_makefile(register Name makefile, Boolean complain, Boolean must_exist, Boolean report_file)
 3617 {
 3618     Boolean         b;
 3619     
 3620     makefile_type = reading_makefile;
 3621     recursion_level = 0;
 3622 #ifdef NSE
 3623     wcscpy(current_makefile, makefile->string);
 3624 #endif
 3625     reading_dependencies = true;
 3626     b = read_simple_file(makefile, true, true, complain,
 3627                  must_exist, report_file, false);
 3628     reading_dependencies = false;
 3629     return b;
 3630 }
 3631 
 3632 /*
 3633  *  make_targets(argc, argv, parallel_flag)
 3634  *
 3635  *  Call doname on the specified targets
 3636  *
 3637  *  Parameters:
 3638  *      argc        You know what this is
 3639  *      argv        You know what this is
 3640  *      parallel_flag   True if building in parallel
 3641  *
 3642  *  Global variables used:
 3643  *      build_failed_seen Used to generated message after failed -k
 3644  *      commands_done   Used to generate message "Up to date"
 3645  *      default_target_to_build First proper target in makefile
 3646  *      init        The Name ".INIT", use to run command
 3647  *      parallel    Global parallel building flag
 3648  *      quest       make -q, suppresses messages
 3649  *      recursion_level Initialized, used for tracing
 3650  *      report_dependencies make -P, regroves whole process
 3651  */
 3652 static void
 3653 make_targets(int argc, char **argv, Boolean parallel_flag)
 3654 {
 3655     int         i;
 3656     char            *cp;
 3657     Doname          result;
 3658     register Boolean    target_to_make_found = false;
 3659 
 3660     (void) doname(init, true, true);
 3661     recursion_level = 1;
 3662     parallel = parallel_flag;
 3663 /*
 3664  *  make remaining args
 3665  */
 3666 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
 3667 /*
 3668     if ((report_dependencies_level == 0) && parallel) {
 3669  */
 3670     if (parallel) {
 3671         /*
 3672          * If building targets in parallel, start all of the
 3673          * remaining args to build in parallel.
 3674          */
 3675         for (i = 1; i < argc; i++) {
 3676             if ((cp = argv[i]) != NULL) {
 3677                 commands_done = false;
 3678                 if ((cp[0] == (int) period_char) &&
 3679                     (cp[1] == (int) slash_char)) {
 3680                     cp += 2;
 3681                 }
 3682                  if((cp[0] == (int) ' ') &&
 3683                     (cp[1] == (int) '-') &&
 3684                     (cp[2] == (int) ' ') &&
 3685                     (cp[3] == (int) '-')) {
 3686                         argv[i] = NULL;
 3687                     continue;
 3688                 }
 3689                 MBSTOWCS(wcs_buffer, cp);
 3690                 //default_target_to_build = GETNAME(wcs_buffer,
 3691                 //                FIND_LENGTH);
 3692                 default_target_to_build = normalize_name(wcs_buffer,
 3693                                   wcslen(wcs_buffer));
 3694                 if (default_target_to_build == wait_name) {
 3695                     if (parallel_process_cnt > 0) {
 3696                         finish_running();
 3697                     }
 3698                     continue;
 3699                 }
 3700                 top_level_target = get_wstring(default_target_to_build->string_mb);
 3701                 /*
 3702                  * If we can't execute the current target in
 3703                  * parallel, hold off the target processing
 3704                  * to preserve the order of the targets as they appeared
 3705                  * in command line.
 3706                  */
 3707                 if (!parallel_ok(default_target_to_build, false)
 3708                         && parallel_process_cnt > 0) {
 3709                     finish_running();
 3710                 }
 3711                 result = doname_check(default_target_to_build,
 3712                               true,
 3713                               false,
 3714                               false);
 3715                 gather_recursive_deps();
 3716                 if (/* !commands_done && */
 3717                     (result == build_ok) &&
 3718                     !quest &&
 3719                     (report_dependencies_level == 0) /*  &&
 3720                     (exists(default_target_to_build) > file_doesnt_exist)  */) {
 3721                     if (posix) {
 3722                         if (!commands_done) {
 3723                             (void) printf(gettext("`%s' is updated.\n"),
 3724                                       default_target_to_build->string_mb);
 3725                         } else {
 3726                             if (no_action_was_taken) {
 3727                                 (void) printf(gettext("`%s': no action was taken.\n"),
 3728                                           default_target_to_build->string_mb);
 3729                             }
 3730                         }
 3731                     } else {
 3732                         default_target_to_build->stat.time = file_no_time;
 3733                         if (!commands_done &&
 3734                             !default_target_to_build->stat.is_phony &&
 3735                             (exists(default_target_to_build) > file_doesnt_exist)) {
 3736                             (void) printf(gettext("`%s' is up to date.\n"),
 3737                                       default_target_to_build->string_mb);
 3738                         }
 3739                     }
 3740                 }
 3741             }
 3742         }
 3743         /* Now wait for all of the targets to finish running */
 3744         finish_running();
 3745         //      setjmp(jmpbuffer);
 3746         
 3747     }
 3748 #endif
 3749     for (i = 1; i < argc; i++) {
 3750         if ((cp = argv[i]) != NULL) {
 3751             target_to_make_found = true;
 3752             if ((cp[0] == (int) period_char) &&
 3753                 (cp[1] == (int) slash_char)) {
 3754                 cp += 2;
 3755             }
 3756                  if((cp[0] == (int) ' ') &&
 3757                     (cp[1] == (int) '-') &&
 3758                     (cp[2] == (int) ' ') &&
 3759                     (cp[3] == (int) '-')) {
 3760                         argv[i] = NULL;
 3761                     continue;
 3762                 }
 3763             MBSTOWCS(wcs_buffer, cp);
 3764             default_target_to_build = normalize_name(wcs_buffer, wcslen(wcs_buffer));
 3765             top_level_target = get_wstring(default_target_to_build->string_mb);
 3766             report_recursion(default_target_to_build);
 3767             commands_done = false;
 3768             if (parallel) {
 3769                 result = (Doname) default_target_to_build->state;
 3770             } else {
 3771                 result = doname_check(default_target_to_build,
 3772                               true,
 3773                               false,
 3774                               false);
 3775             }
 3776             gather_recursive_deps();
 3777             if (build_failed_seen) {
 3778                 build_failed_ever_seen = true;
 3779                 warning(gettext("Target `%s' not remade because of errors"),
 3780                     default_target_to_build->string_mb);
 3781             }
 3782             build_failed_seen = false;
 3783             if (report_dependencies_level > 0) {
 3784                 print_dependencies(default_target_to_build,
 3785                            get_prop(default_target_to_build->prop,
 3786                                 line_prop));
 3787             }
 3788             default_target_to_build->stat.time =
 3789               file_no_time;
 3790             if (default_target_to_build->colon_splits > 0) {
 3791                 default_target_to_build->state =
 3792                   build_dont_know;
 3793             }
 3794             if (!parallel &&
 3795                 /* !commands_done && */
 3796                 (result == build_ok) &&
 3797                 !quest &&
 3798                 (report_dependencies_level == 0) /*  &&
 3799                 (exists(default_target_to_build) > file_doesnt_exist)  */) {
 3800                 if (posix) {
 3801                     if (!commands_done) {
 3802                         (void) printf(gettext("`%s' is updated.\n"),
 3803                                   default_target_to_build->string_mb);
 3804                     } else {
 3805                         if (no_action_was_taken) {
 3806                             (void) printf(gettext("`%s': no action was taken.\n"),
 3807                                       default_target_to_build->string_mb);
 3808                         }
 3809                     }
 3810                 } else {
 3811                     if (!commands_done &&
 3812                         !default_target_to_build->stat.is_phony &&
 3813                         (exists(default_target_to_build) > file_doesnt_exist)) {
 3814                         (void) printf(gettext("`%s' is up to date.\n"),
 3815                                   default_target_to_build->string_mb);
 3816                     }
 3817                 }
 3818             }
 3819         }
 3820     }
 3821 
 3822 /*
 3823  *  If no file arguments have been encountered,
 3824  *  make the first name encountered that doesnt start with a dot
 3825  */
 3826     if (!target_to_make_found) {
 3827         if (default_target_to_build == NULL) {
 3828             fatal(gettext("No arguments to build"));
 3829         }
 3830         commands_done = false;
 3831         top_level_target = get_wstring(default_target_to_build->string_mb);
 3832         report_recursion(default_target_to_build);
 3833 
 3834 
 3835         if (getenv(NOCATGETS("SPRO_EXPAND_ERRORS"))){
 3836             (void) printf(NOCATGETS("::(%s)\n"),
 3837                       default_target_to_build->string_mb);
 3838         }
 3839 
 3840 
 3841 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)
 3842         result = doname_parallel(default_target_to_build, true, false);
 3843 #else
 3844         result = doname_check(default_target_to_build, true,
 3845                       false, false);
 3846 #endif
 3847         gather_recursive_deps();
 3848         if (build_failed_seen) {
 3849             build_failed_ever_seen = true;
 3850             warning(gettext("Target `%s' not remade because of errors"),
 3851                 default_target_to_build->string_mb);
 3852         }
 3853         build_failed_seen = false;
 3854         if (report_dependencies_level > 0) {
 3855             print_dependencies(default_target_to_build,
 3856                        get_prop(default_target_to_build->
 3857                             prop,
 3858                             line_prop));
 3859         }
 3860         default_target_to_build->stat.time = file_no_time;
 3861         if (default_target_to_build->colon_splits > 0) {
 3862             default_target_to_build->state = build_dont_know;
 3863         }
 3864         if (/* !commands_done && */
 3865             (result == build_ok) &&
 3866             !quest &&
 3867             (report_dependencies_level == 0) /*  &&
 3868             (exists(default_target_to_build) > file_doesnt_exist)  */) {
 3869             if (posix) {
 3870                 if (!commands_done) {
 3871                     (void) printf(gettext("`%s' is updated.\n"),
 3872                               default_target_to_build->string_mb);
 3873                 } else {
 3874                     if (no_action_was_taken) {
 3875                         (void) printf(gettext("`%s': no action was taken.\n"),
 3876                                   default_target_to_build->string_mb);
 3877                     }
 3878                 }
 3879             } else {
 3880                 if (!commands_done &&
 3881                     !default_target_to_build->stat.is_phony &&
 3882                     (exists(default_target_to_build) > file_doesnt_exist)) {
 3883                     (void) printf(gettext("`%s' is up to date.\n"),
 3884                               default_target_to_build->string_mb);
 3885                 }
 3886             }
 3887         }
 3888     }
 3889 }
 3890 
 3891 /*
 3892  *  report_recursion(target)
 3893  *
 3894  *  If this is a recursive make and the parent make has KEEP_STATE on
 3895  *  this routine reports the dependency to the parent make
 3896  *
 3897  *  Parameters:
 3898  *      target      Target to report
 3899  *
 3900  *  Global variables used:
 3901  *      makefiles_used      List of makefiles read
 3902  *      recursive_name      The Name ".RECURSIVE", printed
 3903  *      report_dependency   dwight
 3904  */
 3905 static void
 3906 report_recursion(register Name target)
 3907 {
 3908     register FILE       *report_file = get_report_file();
 3909 
 3910     if ((report_file == NULL) || (report_file == (FILE*)-1)) {
 3911         return;
 3912     }
 3913     if (primary_makefile == NULL) {
 3914         /*
 3915          * This can happen when there is no makefile and
 3916          * only implicit rules are being used.
 3917          */
 3918 #ifdef NSE
 3919         nse_no_makefile(target);
 3920 #endif
 3921         return;
 3922     }
 3923     (void) fprintf(report_file,
 3924                "%s: %s ",
 3925                get_target_being_reported_for(),
 3926                recursive_name->string_mb);
 3927     report_dependency(get_current_path());
 3928     report_dependency(target->string_mb);
 3929     report_dependency(primary_makefile->string_mb);
 3930     (void) fprintf(report_file, "\n");
 3931 }
 3932 
 3933 /* Next function "append_or_replace_macro_in_dyn_array" must be in "misc.cc". */
 3934 /* NIKMOL */
 3935 extern void
 3936 append_or_replace_macro_in_dyn_array(ASCII_Dyn_Array *Ar, char *macro)
 3937 {
 3938     register char   *cp0;   /* work pointer in macro */
 3939     register char   *cp1;   /* work pointer in array */
 3940     register char   *cp2;   /* work pointer in array */
 3941     register char   *cp3;   /* work pointer in array */
 3942     register char   *name;  /* macro name */
 3943     register char   *value; /* macro value */
 3944     register int    len_array;
 3945     register int    len_macro;
 3946         Boolean isassign = false;
 3947         Boolean isgnuassign = false;
 3948 
 3949     char * esc_value = NULL;
 3950     int esc_len;
 3951 
 3952     if (!(len_macro = strlen(macro))) return;
 3953     name = macro;
 3954     while (isspace(*(name))) {
 3955         name++;
 3956     }
 3957     if (!(value = strchr(name, (int) equal_char))) {
 3958         /* no '=' in macro */
 3959         goto ERROR_MACRO;
 3960     }
 3961     cp0 = value;
 3962     value++;
 3963     while (isspace(*(value))) {
 3964         value++;
 3965     }
 3966 
 3967     if (cp0[-1] == ':' && cp0[-2] == ':') {
 3968         cp0 -= 2;
 3969         if (cp0[-1] == ':') {
 3970             cp0--;
 3971             isassign = true;
 3972 #ifdef  GNU_ASSIGN_BY_DEFAULT
 3973         } else {
 3974             isgnuassign = true;
 3975         }
 3976 #else
 3977         } else if (posix || gnu_style) {
 3978             isgnuassign = true;
 3979         } else {
 3980             cp0 += 2;
 3981         }
 3982 #endif
 3983     }
 3984     while (isspace(*(cp0-1))) {
 3985         cp0--;
 3986     }
 3987     if (cp0 <= name) goto ERROR_MACRO; /* no name */
 3988     if (!(Ar->size)) goto ALLOC_ARRAY;
 3989     cp1 = Ar->start;
 3990 
 3991 LOOK_FOR_NAME:
 3992     if (!(cp1 = strchr(cp1, name[0]))) goto APPEND_MACRO;
 3993     if (!(cp2 = strchr(cp1, (int) equal_char))) goto APPEND_MACRO;
 3994     if (strncmp(cp1, name, (size_t)(cp0-name))) {
 3995         /* another name */
 3996         cp1++;
 3997         goto LOOK_FOR_NAME;
 3998     }
 3999     if (cp1 != Ar->start) {
 4000         if (!isspace(*(cp1-1))) {
 4001             /* another name */
 4002             cp1++;
 4003             goto LOOK_FOR_NAME;
 4004         }
 4005     }
 4006     for (cp3 = cp1 + (cp0-name); cp3 < cp2; cp3++) {
 4007         if (isspace(*cp3)) continue;
 4008         /* else: another name */
 4009         cp1++;
 4010         goto LOOK_FOR_NAME;
 4011     }
 4012     /* Look for the next macro name in array */
 4013     cp3 = cp2+1;
 4014     if (*cp3 != (int) doublequote_char) {
 4015         /* internal error */
 4016         goto ERROR_MACRO;
 4017     }
 4018     if (!(cp3 = strchr(cp3+1, (int) doublequote_char))) {
 4019         /* internal error */
 4020         goto ERROR_MACRO;
 4021     }
 4022     cp3++;
 4023     while (isspace(*cp3)) {
 4024         cp3++;
 4025     }
 4026     
 4027     cp2 = cp1;  /* remove old macro */
 4028     if ((*cp3) && (cp3 < Ar->start + Ar->size)) {
 4029         for (; cp3 < Ar->start + Ar->size; cp3++) {
 4030             *cp2++ = *cp3;
 4031         }
 4032     } 
 4033     for (; cp2 < Ar->start + Ar->size; cp2++) {
 4034         *cp2 = 0;
 4035     }
 4036     if (*cp1) {
 4037         /* check next name */
 4038         goto LOOK_FOR_NAME;
 4039     }
 4040     goto APPEND_MACRO;
 4041 
 4042 ALLOC_ARRAY:
 4043     if (Ar->size) {
 4044         cp1 = Ar->start;
 4045     } else {
 4046         cp1 = 0;
 4047     }
 4048     Ar->size += 128;
 4049     Ar->start = getmem(Ar->size);
 4050     for (len_array=0; len_array < Ar->size; len_array++) {
 4051         Ar->start[len_array] = 0;
 4052     }
 4053     if (cp1) {
 4054         strcpy(Ar->start, cp1);
 4055         retmem((wchar_t *) cp1);
 4056     }
 4057 
 4058 APPEND_MACRO:
 4059     len_array = strlen(Ar->start);
 4060     esc_value = (char*)malloc(strlen(value)*2 + 1);
 4061     quote_str(value, esc_value);
 4062     esc_len = strlen(esc_value) - strlen(value);
 4063     if (len_array + len_macro + esc_len + 5 >= Ar->size) goto  ALLOC_ARRAY;
 4064     strcat(Ar->start, " ");
 4065     strncat(Ar->start, name, cp0-name);
 4066     if (isassign)
 4067         strcat(Ar->start, ":::=");
 4068     else if (isgnuassign)
 4069         strcat(Ar->start, "::=");
 4070     else
 4071         strcat(Ar->start, "=");
 4072     strncat(Ar->start, esc_value, strlen(esc_value));
 4073     free(esc_value);
 4074     return;
 4075 ERROR_MACRO:    
 4076     /* Macro without '=' or with invalid left/right part */
 4077     return;
 4078 }
 4079 
 4080 #ifdef TEAMWARE_MAKE_CMN
 4081 /*
 4082  * This function, if registered w/ avo_cli_get_license(), will be called
 4083  * if the application is about to exit because:
 4084  *   1) there has been certain unrecoverable error(s) that cause the
 4085  *      application to exit immediately.
 4086  *   2) the user has lost a license while the application is running.
 4087  */
 4088 extern "C" void
 4089 dmake_exit_callback(void)
 4090 {
 4091     fatal(gettext("can not get a license, exiting..."));
 4092     exit(1);
 4093 }
 4094 
 4095 /*
 4096  * This function, if registered w/ avo_cli_get_license(), will be called
 4097  * if the application can not get a license.
 4098  */
 4099 extern "C" void
 4100 dmake_message_callback(char *err_msg)
 4101 {
 4102     static Boolean  first = true;
 4103 
 4104     if (!first) {
 4105         return;
 4106     }
 4107     first = false;
 4108     if ((!list_all_targets) &&
 4109         (report_dependencies_level == 0) &&
 4110         (dmake_mode_type != serial_mode)) {
 4111         warning(gettext("can not get a TeamWare license, defaulting to serial mode..."));
 4112     }
 4113 }
 4114 #endif
 4115 
 4116 #ifdef DISTRIBUTED
 4117 /*
 4118  * Returns whether -c is set or not.
 4119  */
 4120 Boolean
 4121 get_dmake_rcfile_specified(void)
 4122 {
 4123     return(dmake_rcfile_specified);
 4124 }
 4125 
 4126 /*
 4127  * Returns whether -g is set or not.
 4128  */
 4129 Boolean
 4130 get_dmake_group_specified(void)
 4131 {
 4132     return(dmake_group_specified);
 4133 }
 4134 
 4135 /*
 4136  * Returns whether -j is set or not.
 4137  */
 4138 Boolean
 4139 get_dmake_max_jobs_specified(void)
 4140 {
 4141     return(dmake_max_jobs_specified);
 4142 }
 4143 
 4144 /*
 4145  * Returns whether -m is set or not.
 4146  */
 4147 Boolean
 4148 get_dmake_mode_specified(void)
 4149 {
 4150     return(dmake_mode_specified);
 4151 }
 4152 
 4153 /*
 4154  * Returns whether -o is set or not.
 4155  */
 4156 Boolean
 4157 get_dmake_odir_specified(void)
 4158 {
 4159     return(dmake_odir_specified);
 4160 }
 4161 
 4162 #endif
 4163 
 4164 static void
 4165 dir_enter_leave(Boolean entering)
 4166 {
 4167 static  char *  mlev = NULL;
 4168     char *  make_level_str = NULL;
 4169     int make_level_val = 0;
 4170 
 4171     make_level_str = getenv(NOCATGETS("MAKELEVEL"));
 4172     if (make_level_str) {
 4173         make_level_val = atoi(make_level_str);
 4174     }
 4175     if (mlev == NULL) {
 4176         mlev = (char*) malloc(MAXPATHLEN);
 4177     }
 4178     if (entering) {
 4179         sprintf(mlev, NOCATGETS("MAKELEVEL=%d"), make_level_val + 1);
 4180     } else {
 4181         make_level_val--;
 4182         sprintf(mlev, NOCATGETS("MAKELEVEL=%d"), make_level_val);
 4183     }
 4184     putenv(mlev);
 4185 }
 4186 
 4187 static void
 4188 report_dir_enter_leave(Boolean entering)
 4189 {
 4190     char    rcwd[MAXPATHLEN];
 4191     char *  make_level_str = NULL;
 4192     int make_level_val = 0;
 4193 
 4194     make_level_str = getenv(NOCATGETS("MAKELEVEL"));
 4195     if (make_level_str) {
 4196         make_level_val = atoi(make_level_str);
 4197     }
 4198     /*
 4199      * We previously did increment our environment, so we need to
 4200      * correct this to get the correct value for this level.
 4201      */
 4202     make_level_val--;
 4203 
 4204     if (report_cwd) {
 4205         if (make_level_val <= 0) {
 4206             if (entering) {
 4207 #ifdef TEAMWARE_MAKE_CMN
 4208                 sprintf( rcwd
 4209                        , gettext("dmake: Entering directory `%s'\n")
 4210                        , get_current_path());
 4211 #else
 4212                 sprintf( rcwd
 4213                        , gettext("make: Entering directory `%s'\n")
 4214                        , get_current_path());
 4215 #endif
 4216             } else {
 4217 #ifdef TEAMWARE_MAKE_CMN
 4218                 sprintf( rcwd
 4219                        , gettext("dmake: Leaving directory `%s'\n")
 4220                        , get_current_path());
 4221 #else
 4222                 sprintf( rcwd
 4223                        , gettext("make: Leaving directory `%s'\n")
 4224                        , get_current_path());
 4225 #endif
 4226             }
 4227         } else {
 4228             if (entering) {
 4229 #ifdef TEAMWARE_MAKE_CMN
 4230                 sprintf( rcwd
 4231                        , gettext("dmake[%d]: Entering directory `%s'\n")
 4232                        , make_level_val, get_current_path());
 4233 #else
 4234                 sprintf( rcwd
 4235                        , gettext("make[%d]: Entering directory `%s'\n")
 4236                        , make_level_val, get_current_path());
 4237 #endif
 4238             } else {
 4239 #ifdef TEAMWARE_MAKE_CMN
 4240                 sprintf( rcwd
 4241                        , gettext("dmake[%d]: Leaving directory `%s'\n")
 4242                        , make_level_val, get_current_path());
 4243 #else
 4244                 sprintf( rcwd
 4245                        , gettext("make[%d]: Leaving directory `%s'\n")
 4246                        , make_level_val, get_current_path());
 4247 #endif
 4248             }
 4249         }
 4250         printf(NOCATGETS("%s"), rcwd);
 4251     }
 4252 }
 4253 
 4254 char *
 4255 find_run_dir()
 4256 {
 4257 #ifdef  HAVE_GETEXECNAME
 4258     /*
 4259      * This is the easy method but it works only on Solaris.
 4260      * Try to use it as it helps us to avoid linking against libschily.
 4261      */
 4262     const char  *exname = getexecname();
 4263     char        xpath[MAXPATHLEN];
 4264     int     amt;
 4265 
 4266     /*
 4267      * If getexecname() exists, it always returns a name for dynamically
 4268      * linked processes.
 4269      */
 4270     if (exname == NULL || *exname != '/') {
 4271         if ((amt = readlink("/proc/self/path/a.out",
 4272             xpath, MAXPATHLEN-1)) < 0) {
 4273             return (NULL);
 4274         }
 4275         xpath[amt] = '\0';
 4276     } else {
 4277         strlcpy(xpath, exname, MAXPATHLEN);
 4278     }
 4279     return (strdup(dirname(xpath)));
 4280 #else
 4281     char        *exname = getexecpath();
 4282     char        *ret;
 4283 
 4284     if (exname == NULL) {
 4285         if (strchr(g_argv[0], (int) slash_char) == NULL) {
 4286             /*
 4287              * Do pathname search only if we have been
 4288              * called via PATH.
 4289              */
 4290             exname = findinpath(g_argv[0], X_OK, TRUE, NULL);
 4291         } else {
 4292             /*
 4293              * If arvg[0] starts with a slash, use it,
 4294              * else use its concatenation with `pwd`.
 4295              */
 4296             if (*g_argv[0] == slash_char)
 4297                 exname = strdup(g_argv[0]);
 4298             else
 4299                 exname = strdup(argv_zero_string);
 4300         }
 4301     }
 4302     if (exname == NULL)
 4303         return (NULL);
 4304     ret = strdup(dirname(exname));
 4305     free(exname);
 4306     return (ret);
 4307 #endif
 4308 }