1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  *      main.cc
  28  *
  29  *      make program main routine plus some helper routines
  30  */
  31  
  32 /*
  33  * Included files
  34  */
  35 #if defined(TEAMWARE_MAKE_CMN)
  36 #       include <avo/intl.h>
  37 #endif
  38 
  39 #include <bsd/bsd.h>              /* bsd_signal() */
  40 
  41 
  42 #include <locale.h>               /* setlocale() */
  43 #include <mk/defs.h>
  44 #include <mksdmsi18n/mksdmsi18n.h>        /* libmksdmsi18n_init() */
  45 #include <mksh/macro.h>           /* getvar() */
  46 #include <mksh/misc.h>            /* getmem(), setup_char_semantics() */
  47 
  48 #if defined(TEAMWARE_MAKE_CMN)
  49 #endif
  50 
  51 #include <pwd.h>          /* getpwnam() */
  52 #include <setjmp.h>
  53 #include <signal.h>
  54 #include <stdlib.h>
  55 #include <sys/errno.h>            /* ENOENT */
  56 #include <sys/stat.h>             /* fstat() */
  57 #include <fcntl.h>                /* open() */
  58 
  59 #       include <sys/systeminfo.h>        /* sysinfo() */
  60 
  61 #include <sys/types.h>            /* stat() */
  62 #include <sys/wait.h>             /* wait() */
  63 #include <unistd.h>               /* execv(), unlink(), access() */
  64 #include <vroot/report.h> /* report_dependency(), get_report_file() */
  65 
  66 // From read2.cc
  67 extern  Name            normalize_name(register wchar_t *name_string, register int length);
  68 
  69 // From parallel.cc
  70 #if defined(TEAMWARE_MAKE_CMN)
  71 #define MAXJOBS_ADJUST_RFE4694000
  72 
  73 #ifdef MAXJOBS_ADJUST_RFE4694000
  74 extern void job_adjust_fini();
  75 #endif /* MAXJOBS_ADJUST_RFE4694000 */
  76 #endif /* TEAMWARE_MAKE_CMN */
  77 
  78 
  79 /*
  80  * Defined macros
  81  */
  82 #define MAKE_PREFIX             NOCATGETS("/usr")
  83 #define LD_SUPPORT_ENV_VAR      NOCATGETS("SGS_SUPPORT_32")
  84 #define LD_SUPPORT_ENV_VAR_32   NOCATGETS("SGS_SUPPORT_32")
  85 #define LD_SUPPORT_ENV_VAR_64   NOCATGETS("SGS_SUPPORT_64")
  86 #define LD_SUPPORT_MAKE_LIB     NOCATGETS("libmakestate.so.1")
  87 #define LD_SUPPORT_MAKE_LIB_DIR NOCATGETS("/lib")
  88 #define LD_SUPPORT_MAKE_LIB_DIR_64      NOCATGETS("/64")
  89 
  90 /*
  91  * typedefs & structs
  92  */
  93 
  94 /*
  95  * Static variables
  96  */
  97 static  char            *argv_zero_string;
  98 static  Boolean         build_failed_ever_seen;
  99 static  Boolean         continue_after_error_ever_seen; /* `-k' */
 100 static  Boolean         dmake_group_specified;          /* `-g' */
 101 static  Boolean         dmake_max_jobs_specified;       /* `-j' */
 102 static  Boolean         dmake_mode_specified;           /* `-m' */
 103 static  Boolean         dmake_add_mode_specified;       /* `-x' */
 104 static  Boolean         dmake_output_mode_specified;    /* `-x DMAKE_OUTPUT_MODE=' */
 105 static  Boolean         dmake_compat_mode_specified;    /* `-x SUN_MAKE_COMPAT_MODE=' */
 106 static  Boolean         dmake_odir_specified;           /* `-o' */
 107 static  Boolean         dmake_rcfile_specified;         /* `-c' */
 108 static  Boolean         env_wins;                       /* `-e' */
 109 static  Boolean         ignore_default_mk;              /* `-r' */
 110 static  Boolean         list_all_targets;               /* `-T' */
 111 static  int             mf_argc;
 112 static  char            **mf_argv;
 113 static  Dependency_rec  not_auto_depen_struct;
 114 static  Dependency      not_auto_depen = &not_auto_depen_struct;
 115 static  Boolean         pmake_cap_r_specified;          /* `-R' */
 116 static  Boolean         pmake_machinesfile_specified;   /* `-M' */
 117 static  Boolean         stop_after_error_ever_seen;     /* `-S' */
 118 static  Boolean         trace_status;                   /* `-p' */
 119 
 120 #ifdef DMAKE_STATISTICS
 121 static  Boolean         getname_stat = false;
 122 #endif
 123 
 124 #if defined(TEAMWARE_MAKE_CMN)
 125         static  time_t          start_time;
 126         static  int             g_argc;
 127         static  char            **g_argv;
 128 #endif
 129 
 130 /*
 131  * File table of contents
 132  */
 133         extern "C" void         cleanup_after_exit(void);
 134 
 135 #ifdef TEAMWARE_MAKE_CMN
 136 extern "C" {
 137         extern  void            dmake_exit_callback(void);
 138         extern  void            dmake_message_callback(char *);
 139 }
 140 #endif
 141 
 142 extern  Name            normalize_name(register wchar_t *name_string, register int length);
 143 
 144 extern  int             main(int, char * []);
 145 
 146 static  void            append_makeflags_string(Name, String);
 147 static  void            doalarm(int);
 148 static  void            enter_argv_values(int , char **, ASCII_Dyn_Array *);
 149 static  void            make_targets(int, char **, Boolean);
 150 static  int             parse_command_option(char);
 151 static  void            read_command_options(int, char **);
 152 static  void            read_environment(Boolean);
 153 static  void            read_files_and_state(int, char **);
 154 static  Boolean         read_makefile(Name, Boolean, Boolean, Boolean);
 155 static  void            report_recursion(Name);
 156 static  void            set_sgs_support(void);
 157 static  void            setup_for_projectdir(void);
 158 static  void            setup_makeflags_argv(void);
 159 static  void            report_dir_enter_leave(Boolean entering);
 160 
 161 extern void expand_value(Name, register String , Boolean);
 162 
 163 #ifdef TEAMWARE_MAKE_CMN
 164         static const char       verstring[] = "illumos make";
 165 #endif
 166 
 167 jmp_buf jmpbuffer;
 168 extern nl_catd catd;
 169 
 170 /*
 171  *      main(argc, argv)
 172  *
 173  *      Parameters:
 174  *              argc                    You know what this is
 175  *              argv                    You know what this is
 176  *
 177  *      Static variables used:
 178  *              list_all_targets        make -T seen
 179  *              trace_status            make -p seen
 180  *
 181  *      Global variables used:
 182  *              debug_level             Should we trace make actions?
 183  *              keep_state              Set if .KEEP_STATE seen
 184  *              makeflags               The Name "MAKEFLAGS", used to get macro
 185  *              remote_command_name     Name of remote invocation cmd ("on")
 186  *              running_list            List of parallel running processes
 187  *              stdout_stderr_same      true if stdout and stderr are the same
 188  *              auto_dependencies       The Name "SUNPRO_DEPENDENCIES"
 189  *              temp_file_directory     Set to the dir where we create tmp file
 190  *              trace_reader            Set to reflect tracing status
 191  *              working_on_targets      Set when building user targets
 192  */
 193 int
 194 main(int argc, char *argv[])
 195 {
 196         /*
 197          * cp is a -> to the value of the MAKEFLAGS env var,
 198          * which has to be regular chars.
 199          */
 200         register char           *cp;
 201         char                    make_state_dir[MAXPATHLEN];
 202         Boolean                 parallel_flag = false;
 203         char                    *prognameptr;
 204         char                    *slash_ptr;
 205         mode_t                  um;
 206         int                     i;
 207 #ifdef TEAMWARE_MAKE_CMN
 208         struct itimerval        value;
 209         char                    def_dmakerc_path[MAXPATHLEN];
 210         Name                    dmake_name, dmake_name2;
 211         Name                    dmake_value, dmake_value2;
 212         Property                prop, prop2;
 213         struct stat             statbuf;
 214         int                     statval;
 215 #endif
 216 
 217         struct stat             out_stat, err_stat;
 218         hostid = gethostid();
 219         bsd_signals();
 220 
 221         (void) setlocale(LC_ALL, "");
 222 
 223 
 224 #ifdef DMAKE_STATISTICS
 225         if (getenv(NOCATGETS("DMAKE_STATISTICS"))) {
 226                 getname_stat = true;
 227         }
 228 #endif
 229 
 230 #if defined(TEAMWARE_MAKE_CMN)
 231         catd = catopen(AVO_DOMAIN_DMAKE, NL_CAT_LOCALE);
 232 #endif
 233 
 234 // ---> fprintf(stderr, catgets(catd, 15, 666, "--- SUN make ---\n"));
 235 
 236 
 237 #if defined(TEAMWARE_MAKE_CMN)
 238 /*
 239  * I put libmksdmsi18n_init() under #ifdef because it requires avo_i18n_init()
 240  * from avo_util library. 
 241  */
 242         libmksdmsi18n_init();
 243 #endif
 244 
 245 
 246 #ifndef TEAMWARE_MAKE_CMN
 247         textdomain(NOCATGETS("SUNW_SPRO_MAKE"));
 248 #endif /* TEAMWARE_MAKE_CMN */
 249 
 250 #ifdef TEAMWARE_MAKE_CMN
 251         g_argc = argc;
 252         g_argv = (char **) malloc((g_argc + 1) * sizeof(char *));
 253         for (i = 0; i < argc; i++) {
 254                 g_argv[i] = argv[i];
 255         }
 256         g_argv[i] = NULL;
 257 #endif /* TEAMWARE_MAKE_CMN */
 258 
 259         /*
 260          * Set argv_zero_string to some form of argv[0] for
 261          * recursive MAKE builds.
 262          */
 263 
 264         if (*argv[0] == (int) slash_char) {
 265                 /* argv[0] starts with a slash */
 266                 argv_zero_string = strdup(argv[0]);
 267         } else if (strchr(argv[0], (int) slash_char) == NULL) {
 268                 /* argv[0] contains no slashes */
 269                 argv_zero_string = strdup(argv[0]);
 270         } else {
 271                 /*
 272                  * argv[0] contains at least one slash,
 273                  * but doesn't start with a slash
 274                  */
 275                 char    *tmp_current_path;
 276                 char    *tmp_string;
 277 
 278                 tmp_current_path = get_current_path();
 279                 tmp_string = getmem(strlen(tmp_current_path) + 1 +
 280                                     strlen(argv[0]) + 1);
 281                 (void) sprintf(tmp_string,
 282                                "%s/%s",
 283                                tmp_current_path,
 284                                argv[0]);
 285                 argv_zero_string = strdup(tmp_string);
 286                 retmem_mb(tmp_string);
 287         }
 288 
 289         /* 
 290          * The following flags are reset if we don't have the 
 291          * (.nse_depinfo or .make.state) files locked and only set 
 292          * AFTER the file has been locked. This ensures that if the user
 293          * interrupts the program while file_lock() is waiting to lock
 294          * the file, the interrupt handler doesn't remove a lock 
 295          * that doesn't belong to us.
 296          */
 297         make_state_lockfile = NULL;
 298         make_state_locked = false;
 299 
 300 
 301         /*
 302          * look for last slash char in the path to look at the binary 
 303          * name. This is to resolve the hard link and invoke make
 304          * in svr4 mode.
 305          */
 306 
 307         /* Sun OS make standart */
 308         svr4 = false;  
 309         posix = false;
 310         if(!strcmp(argv_zero_string, NOCATGETS("/usr/xpg4/bin/make"))) {
 311                 svr4 = false;
 312                 posix = true;
 313         } else {
 314                 prognameptr = strrchr(argv[0], '/');
 315                 if(prognameptr) {
 316                         prognameptr++;
 317                 } else {
 318                         prognameptr = argv[0];
 319                 }
 320                 if(!strcmp(prognameptr, NOCATGETS("svr4.make"))) {
 321                         svr4 = true;
 322                         posix = false;
 323                 }
 324         }
 325         if (getenv(USE_SVR4_MAKE) || getenv(NOCATGETS("USE_SVID"))){
 326            svr4 = true;
 327            posix = false;
 328         }
 329 
 330         /*
 331          * Find the dmake_compat_mode: posix, sun, svr4, or gnu_style, .
 332          */
 333         char * dmake_compat_mode_var = getenv(NOCATGETS("SUN_MAKE_COMPAT_MODE"));
 334         if (dmake_compat_mode_var != NULL) {
 335                 if (0 == strcasecmp(dmake_compat_mode_var, NOCATGETS("GNU"))) {
 336                         gnu_style = true;
 337                 }
 338                 //svr4 = false;
 339                 //posix = false;
 340         }
 341 
 342         /*
 343          * Temporary directory set up.
 344          */
 345         char * tmpdir_var = getenv(NOCATGETS("TMPDIR"));
 346         if (tmpdir_var != NULL && *tmpdir_var == '/' && strlen(tmpdir_var) < MAXPATHLEN) {
 347                 strcpy(mbs_buffer, tmpdir_var);
 348                 for (tmpdir_var = mbs_buffer+strlen(mbs_buffer);
 349                         *(--tmpdir_var) == '/' && tmpdir_var > mbs_buffer;
 350                         *tmpdir_var = '\0');
 351                 if (strlen(mbs_buffer) + 32 < MAXPATHLEN) { /* 32 = strlen("/dmake.stdout.%d.%d.XXXXXX") */
 352                         sprintf(mbs_buffer2, NOCATGETS("%s/dmake.tst.%d.XXXXXX"),
 353                                 mbs_buffer, getpid());
 354                         int fd = mkstemp(mbs_buffer2);
 355                         if (fd >= 0) {
 356                                 close(fd);
 357                                 unlink(mbs_buffer2);
 358                                 tmpdir = strdup(mbs_buffer);
 359                         }
 360                 }
 361         }
 362 
 363         /* find out if stdout and stderr point to the same place */
 364         if (fstat(1, &out_stat) < 0) {
 365                 fatal(catgets(catd, 1, 165, "fstat of standard out failed: %s"), errmsg(errno));
 366         }
 367         if (fstat(2, &err_stat) < 0) {
 368                 fatal(catgets(catd, 1, 166, "fstat of standard error failed: %s"), errmsg(errno));
 369         }
 370         if ((out_stat.st_dev == err_stat.st_dev) &&
 371             (out_stat.st_ino == err_stat.st_ino)) {
 372                 stdout_stderr_same = true;
 373         } else {
 374                 stdout_stderr_same = false;
 375         }
 376         /* Make the vroot package scan the path using shell semantics */
 377         set_path_style(0);
 378 
 379         setup_char_semantics();
 380 
 381         setup_for_projectdir();
 382 
 383         /*
 384          * If running with .KEEP_STATE, curdir will be set with
 385          * the connected directory.
 386          */
 387         (void) atexit(cleanup_after_exit);
 388 
 389         load_cached_names();
 390 
 391 /*
 392  *      Set command line flags
 393  */
 394         setup_makeflags_argv();
 395         read_command_options(mf_argc, mf_argv);
 396         read_command_options(argc, argv);
 397         if (debug_level > 0) {
 398                 cp = getenv(makeflags->string_mb);
 399                 (void) printf(catgets(catd, 1, 167, "MAKEFLAGS value: %s\n"), cp == NULL ? "" : cp);
 400         }
 401 
 402         setup_interrupt(handle_interrupt);
 403 
 404         read_files_and_state(argc, argv);
 405 
 406 #ifdef TEAMWARE_MAKE_CMN
 407         /*
 408          * Find the dmake_output_mode: TXT1, TXT2 or HTML1.
 409          */
 410         MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_OUTPUT_MODE"));
 411         dmake_name2 = GETNAME(wcs_buffer, FIND_LENGTH);
 412         prop2 = get_prop(dmake_name2->prop, macro_prop);
 413         if (prop2 == NULL) {
 414                 /* DMAKE_OUTPUT_MODE not defined, default to TXT1 mode */
 415                 output_mode = txt1_mode;
 416         } else {
 417                 dmake_value2 = prop2->body.macro.value;
 418                 if ((dmake_value2 == NULL) ||
 419                     (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("TXT1")))) {
 420                         output_mode = txt1_mode;
 421                 } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("TXT2"))) {
 422                         output_mode = txt2_mode;
 423                 } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("HTML1"))) {
 424                         output_mode = html1_mode;
 425                 } else {
 426                         warning(catgets(catd, 1, 352, "Unsupported value `%s' for DMAKE_OUTPUT_MODE after -x flag (ignored)"),
 427                               dmake_value2->string_mb);
 428                 }
 429         }
 430         /*
 431          * Find the dmake_mode: distributed, parallel, or serial.
 432          */
 433     if ((!pmake_cap_r_specified) &&
 434         (!pmake_machinesfile_specified)) {
 435         MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE"));
 436         dmake_name2 = GETNAME(wcs_buffer, FIND_LENGTH);
 437         prop2 = get_prop(dmake_name2->prop, macro_prop);
 438         if (prop2 == NULL) {
 439                 /* DMAKE_MODE not defined, default to distributed mode */
 440                 dmake_mode_type = distributed_mode;
 441                 no_parallel = false;
 442         } else {
 443                 dmake_value2 = prop2->body.macro.value;
 444                 if ((dmake_value2 == NULL) ||
 445                     (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("distributed")))) {
 446                         dmake_mode_type = distributed_mode;
 447                         no_parallel = false;
 448                 } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("parallel"))) {
 449                         dmake_mode_type = parallel_mode;
 450                         no_parallel = false;
 451                 } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("serial"))) {
 452                         dmake_mode_type = serial_mode;
 453                         no_parallel = true;
 454                 } else {
 455                         fatal(catgets(catd, 1, 307, "Unknown dmake mode argument `%s' after -m flag"), dmake_value2->string_mb);
 456                 }
 457         }
 458 
 459         if ((!list_all_targets) &&
 460             (report_dependencies_level == 0)) {
 461                 /*
 462                  * Check to see if either DMAKE_RCFILE or DMAKE_MODE is defined.
 463                  * They could be defined in the env, in the makefile, or on the
 464                  * command line.
 465                  * If neither is defined, and $(HOME)/.dmakerc does not exists,
 466                  * then print a message, and default to parallel mode.
 467                  */
 468                 if(dmake_mode_type == distributed_mode) {
 469                         dmake_mode_type = parallel_mode;
 470                         no_parallel = false;
 471                 }
 472         }
 473     }
 474 #endif
 475 
 476 #ifdef TEAMWARE_MAKE_CMN
 477         parallel_flag = true;
 478         putenv(strdup(NOCATGETS("DMAKE_CHILD=TRUE")));
 479 
 480 //
 481 // If dmake is running with -t option, set dmake_mode_type to serial.
 482 // This is done because doname() calls touch_command() that runs serially.
 483 // If we do not do that, maketool will have problems. 
 484 //
 485         if(touch) {
 486                 dmake_mode_type = serial_mode;
 487                 no_parallel = true;
 488         }
 489 #else
 490         parallel_flag = false;
 491 #endif
 492 
 493 #if defined (TEAMWARE_MAKE_CMN)
 494         /*
 495          * Check whether stdout and stderr are physically same.
 496          * This is in order to decide whether we need to redirect
 497          * stderr separately from stdout.
 498          * This check is performed only if __DMAKE_SEPARATE_STDERR
 499          * is not set. This variable may be used in order to preserve
 500          * the 'old' behaviour.
 501          */
 502         out_err_same = true;
 503         char * dmake_sep_var = getenv(NOCATGETS("__DMAKE_SEPARATE_STDERR"));
 504         if (dmake_sep_var == NULL || (0 != strcasecmp(dmake_sep_var, NOCATGETS("NO")))) {
 505                 struct stat stdout_stat;
 506                 struct stat stderr_stat;
 507                 if( (fstat(1, &stdout_stat) == 0)
 508                  && (fstat(2, &stderr_stat) == 0) )
 509                 {
 510                         if( (stdout_stat.st_dev != stderr_stat.st_dev)
 511                          || (stdout_stat.st_ino != stderr_stat.st_ino) )
 512                         {
 513                                 out_err_same = false;
 514                         }
 515                 }
 516         }
 517 #endif
 518 
 519                 
 520 /*
 521  *      Enable interrupt handler for alarms
 522  */
 523         (void) bsd_signal(SIGALRM, (SIG_PF)doalarm);
 524 
 525 /*
 526  *      Check if make should report
 527  */
 528         if (getenv(sunpro_dependencies->string_mb) != NULL) {
 529                 FILE    *report_file;
 530 
 531                 report_dependency("");
 532                 report_file = get_report_file();
 533                 if ((report_file != NULL) && (report_file != (FILE*)-1)) {
 534                         (void) fprintf(report_file, "\n");
 535                 }
 536         }
 537 
 538 /*
 539  *      Make sure SUNPRO_DEPENDENCIES is exported (or not) properly.
 540  */
 541         if (keep_state) {
 542                 maybe_append_prop(sunpro_dependencies, macro_prop)->
 543                   body.macro.exported = true;
 544         } else {
 545                 maybe_append_prop(sunpro_dependencies, macro_prop)->
 546                   body.macro.exported = false;
 547         }
 548 
 549         working_on_targets = true;
 550         if (trace_status) {
 551                 dump_make_state();
 552                 fclose(stdout);
 553                 fclose(stderr);
 554                 exit_status = 0;
 555                 exit(0);
 556         }
 557         if (list_all_targets) {
 558                 dump_target_list();
 559                 fclose(stdout);
 560                 fclose(stderr);
 561                 exit_status = 0;
 562                 exit(0);
 563         }
 564         trace_reader = false;
 565 
 566         /*
 567          * Set temp_file_directory to the directory the .make.state
 568          * file is written to.
 569          */
 570         if ((slash_ptr = strrchr(make_state->string_mb, (int) slash_char)) == NULL) {
 571                 temp_file_directory = strdup(get_current_path());
 572         } else {
 573                 *slash_ptr = (int) nul_char;
 574                 (void) strcpy(make_state_dir, make_state->string_mb);
 575                 *slash_ptr = (int) slash_char;
 576                    /* when there is only one slash and it's the first
 577                    ** character, make_state_dir should point to '/'.
 578                    */
 579                 if(make_state_dir[0] == '\0') {
 580                    make_state_dir[0] = '/';
 581                    make_state_dir[1] = '\0';
 582                 }
 583                 if (make_state_dir[0] == (int) slash_char) {
 584                         temp_file_directory = strdup(make_state_dir);
 585                 } else {
 586                         char    tmp_current_path2[MAXPATHLEN];
 587  
 588                         (void) sprintf(tmp_current_path2,
 589                                        "%s/%s",
 590                                        get_current_path(),
 591                                        make_state_dir);
 592                         temp_file_directory = strdup(tmp_current_path2);
 593                 }
 594         }
 595 
 596 
 597         report_dir_enter_leave(true);
 598 
 599         make_targets(argc, argv, parallel_flag);
 600 
 601         report_dir_enter_leave(false);
 602 
 603         if (build_failed_ever_seen) {
 604                 if (posix) {
 605                         exit_status = 1;
 606                 }
 607                 exit(1);
 608         }
 609         exit_status = 0;
 610         exit(0);
 611         /* NOTREACHED */
 612 }
 613 
 614 /*
 615  *      cleanup_after_exit()
 616  *
 617  *      Called from exit(), performs cleanup actions.
 618  *
 619  *      Parameters:
 620  *              status          The argument exit() was called with
 621  *              arg             Address of an argument vector to
 622  *                              cleanup_after_exit()
 623  *
 624  *      Global variables used:
 625  *              command_changed Set if we think .make.state should be rewritten
 626  *              current_line    Is set we set commands_changed
 627  *              do_not_exec_rule
 628  *                              True if -n flag on
 629  *              done            The Name ".DONE", rule we run
 630  *              keep_state      Set if .KEEP_STATE seen
 631  *              parallel        True if building in parallel
 632  *              quest           If -q is on we do not run .DONE
 633  *              report_dependencies
 634  *                              True if -P flag on
 635  *              running_list    List of parallel running processes
 636  *              temp_file_name  The temp file is removed, if any
 637  *              catd    the message catalog file
 638  */
 639 extern "C" void
 640 cleanup_after_exit(void)
 641 {
 642         Running         rp;
 643 
 644 extern long     getname_bytes_count;
 645 extern long     getname_names_count;
 646 extern long     getname_struct_count;
 647 extern long     freename_bytes_count;
 648 extern long     freename_names_count;
 649 extern long     freename_struct_count;
 650 extern long     other_alloc;
 651 
 652 extern long     env_alloc_num;
 653 extern long     env_alloc_bytes;
 654 
 655 
 656 #ifdef DMAKE_STATISTICS
 657 if(getname_stat) {
 658         printf(NOCATGETS(">>> Getname statistics:\n"));
 659         printf(NOCATGETS("  Allocated:\n"));
 660         printf(NOCATGETS("        Names: %ld\n"), getname_names_count);
 661         printf(NOCATGETS("      Strings: %ld Kb (%ld bytes)\n"), getname_bytes_count/1000, getname_bytes_count);
 662         printf(NOCATGETS("      Structs: %ld Kb (%ld bytes)\n"), getname_struct_count/1000, getname_struct_count);
 663         printf(NOCATGETS("  Total bytes: %ld Kb (%ld bytes)\n"), getname_struct_count/1000 + getname_bytes_count/1000, getname_struct_count + getname_bytes_count);
 664 
 665         printf(NOCATGETS("\n  Unallocated: %ld\n"), freename_names_count);
 666         printf(NOCATGETS("        Names: %ld\n"), freename_names_count);
 667         printf(NOCATGETS("      Strings: %ld Kb (%ld bytes)\n"), freename_bytes_count/1000, freename_bytes_count);
 668         printf(NOCATGETS("      Structs: %ld Kb (%ld bytes)\n"), freename_struct_count/1000, freename_struct_count);
 669         printf(NOCATGETS("  Total bytes: %ld Kb (%ld bytes)\n"), freename_struct_count/1000 + freename_bytes_count/1000, freename_struct_count + freename_bytes_count);
 670 
 671         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));
 672 
 673         printf(NOCATGETS("\n>>> Other:\n"));
 674         printf(
 675                 NOCATGETS("       Env (%ld): %ld Kb (%ld bytes)\n"),
 676                 env_alloc_num,
 677                 env_alloc_bytes/1000,
 678                 env_alloc_bytes
 679         );
 680 
 681 }
 682 #endif
 683 
 684         parallel = false;
 685         /* If we used the SVR4_MAKE, don't build .DONE or .FAILED */
 686         if (!getenv(USE_SVR4_MAKE)){
 687             /* Build the target .DONE or .FAILED if we caught an error */
 688             if (!quest && !list_all_targets) {
 689                 Name            failed_name;
 690 
 691                 MBSTOWCS(wcs_buffer, NOCATGETS(".FAILED"));
 692                 failed_name = GETNAME(wcs_buffer, FIND_LENGTH);
 693                 if ((exit_status != 0) && (failed_name->prop != NULL)) {
 694 #ifdef TEAMWARE_MAKE_CMN
 695                         /*
 696                          * [tolik] switch DMake to serial mode
 697                          */
 698                         dmake_mode_type = serial_mode;
 699                         no_parallel = true;
 700 #endif
 701                         (void) doname(failed_name, false, true);
 702                 } else {
 703                     if (!trace_status) {
 704 #ifdef TEAMWARE_MAKE_CMN
 705                         /*
 706                          * Switch DMake to serial mode
 707                          */
 708                         dmake_mode_type = serial_mode;
 709                         no_parallel = true;
 710 #endif
 711                         (void) doname(done, false, true);
 712                     }
 713                 }
 714             }
 715         }
 716         /*
 717          * Remove the temp file utilities report dependencies thru if it
 718          * is still around
 719          */
 720         if (temp_file_name != NULL) {
 721                 (void) unlink(temp_file_name->string_mb);
 722         }
 723         /*
 724          * Do not save the current command in .make.state if make
 725          * was interrupted.
 726          */
 727         if (current_line != NULL) {
 728                 command_changed = true;
 729                 current_line->body.line.command_used = NULL;
 730         }
 731         /*
 732          * For each parallel build process running, remove the temp files
 733          * and zap the command line so it won't be put in .make.state
 734          */
 735         for (rp = running_list; rp != NULL; rp = rp->next) {
 736                 if (rp->temp_file != NULL) {
 737                         (void) unlink(rp->temp_file->string_mb);
 738                 }
 739                 if (rp->stdout_file != NULL) {
 740                         (void) unlink(rp->stdout_file);
 741                         retmem_mb(rp->stdout_file);
 742                         rp->stdout_file = NULL;
 743                 }
 744                 if (rp->stderr_file != NULL) {
 745                         (void) unlink(rp->stderr_file);
 746                         retmem_mb(rp->stderr_file);
 747                         rp->stderr_file = NULL;
 748                 }
 749                 command_changed = true;
 750 /*
 751                 line = get_prop(rp->target->prop, line_prop);
 752                 if (line != NULL) {
 753                         line->body.line.command_used = NULL;
 754                 }
 755  */
 756         }
 757         /* Remove the statefile lock file if the file has been locked */
 758         if ((make_state_lockfile != NULL) && (make_state_locked)) {
 759                 (void) unlink(make_state_lockfile);
 760                 make_state_lockfile = NULL;
 761                 make_state_locked = false;
 762         }
 763         /* Write .make.state */
 764         write_state_file(1, (Boolean) 1);
 765 
 766 #if defined (TEAMWARE_MAKE_CMN) && defined (MAXJOBS_ADJUST_RFE4694000)
 767         job_adjust_fini();
 768 #endif
 769 
 770 #ifdef TEAMWARE_MAKE_CMN
 771         catclose(catd);
 772 #endif
 773 }
 774 
 775 /*
 776  *      handle_interrupt()
 777  *
 778  *      This is where C-C traps are caught.
 779  *
 780  *      Parameters:
 781  *
 782  *      Global variables used (except DMake 1.0):
 783  *              current_target          Sometimes the current target is removed
 784  *              do_not_exec_rule        But not if -n is on
 785  *              quest                   or -q
 786  *              running_list            List of parallel running processes
 787  *              touch                   Current target is not removed if -t on
 788  */
 789 void
 790 handle_interrupt(int)
 791 {
 792         Property                member;
 793         Running                 rp;
 794 
 795         (void) fflush(stdout);
 796         if (childPid > 0) {
 797                 kill(childPid, SIGTERM);
 798                 childPid = -1;
 799         }
 800         for (rp = running_list; rp != NULL; rp = rp->next) {
 801                 if (rp->state != build_running) {
 802                         continue;
 803                 }
 804                 if (rp->pid > 0) {
 805                         kill(rp->pid, SIGTERM);
 806                         rp->pid = -1;
 807                 }
 808         }
 809         if (getpid() == getpgrp()) {
 810                 bsd_signal(SIGTERM, SIG_IGN);
 811                 kill (-getpid(), SIGTERM);
 812         }
 813 #ifdef TEAMWARE_MAKE_CMN
 814         /* Clean up all parallel/distributed children already finished */
 815         finish_children(false);
 816 #endif
 817 
 818         /* Make sure the processes running under us terminate first */
 819 
 820         while (wait((int *) NULL) != -1);
 821         /* Delete the current targets unless they are precious */
 822         if ((current_target != NULL) &&
 823             current_target->is_member &&
 824             ((member = get_prop(current_target->prop, member_prop)) != NULL)) {
 825                 current_target = member->body.member.library;
 826         }
 827         if (!do_not_exec_rule &&
 828             !touch &&
 829             !quest &&
 830             (current_target != NULL) &&
 831             !(current_target->stat.is_precious || all_precious)) {
 832 
 833 /* BID_1030811 */
 834 /* azv 16 Oct 95 */
 835                 current_target->stat.time = file_no_time; 
 836 
 837                 if (exists(current_target) != file_doesnt_exist) {
 838                         (void) fprintf(stderr,
 839                                        "\n*** %s ",
 840                                        current_target->string_mb);
 841                         if (current_target->stat.is_dir) {
 842                                 (void) fprintf(stderr,
 843                                                catgets(catd, 1, 168, "not removed.\n"),
 844                                                current_target->string_mb);
 845                         } else if (unlink(current_target->string_mb) == 0) {
 846                                 (void) fprintf(stderr,
 847                                                catgets(catd, 1, 169, "removed.\n"),
 848                                                current_target->string_mb);
 849                         } else {
 850                                 (void) fprintf(stderr,
 851                                                catgets(catd, 1, 170, "could not be removed: %s.\n"),
 852                                                current_target->string_mb,
 853                                                errmsg(errno));
 854                         }
 855                 }
 856         }
 857         for (rp = running_list; rp != NULL; rp = rp->next) {
 858                 if (rp->state != build_running) {
 859                         continue;
 860                 }
 861                 if (rp->target->is_member &&
 862                     ((member = get_prop(rp->target->prop, member_prop)) !=
 863                      NULL)) {
 864                         rp->target = member->body.member.library;
 865                 }
 866                 if (!do_not_exec_rule &&
 867                     !touch &&
 868                     !quest &&
 869                     !(rp->target->stat.is_precious || all_precious)) {
 870 
 871                         rp->target->stat.time = file_no_time; 
 872                         if (exists(rp->target) != file_doesnt_exist) {
 873                                 (void) fprintf(stderr,
 874                                                "\n*** %s ",
 875                                                rp->target->string_mb);
 876                                 if (rp->target->stat.is_dir) {
 877                                         (void) fprintf(stderr,
 878                                                        catgets(catd, 1, 171, "not removed.\n"),
 879                                                        rp->target->string_mb);
 880                                 } else if (unlink(rp->target->string_mb) == 0) {
 881                                         (void) fprintf(stderr,
 882                                                        catgets(catd, 1, 172, "removed.\n"),
 883                                                        rp->target->string_mb);
 884                                 } else {
 885                                         (void) fprintf(stderr,
 886                                                        catgets(catd, 1, 173, "could not be removed: %s.\n"),
 887                                                        rp->target->string_mb,
 888                                                        errmsg(errno));
 889                                 }
 890                         }
 891                 }
 892         }
 893 
 894 
 895         /* Have we locked .make.state or .nse_depinfo? */
 896         if ((make_state_lockfile != NULL) && (make_state_locked)) {
 897                 unlink(make_state_lockfile);
 898                 make_state_lockfile = NULL;
 899                 make_state_locked = false;
 900         }
 901         /*
 902          * Re-read .make.state file (it might be changed by recursive make)
 903          */
 904         check_state(NULL);
 905 
 906         report_dir_enter_leave(false);
 907 
 908         exit_status = 2;
 909         exit(2);
 910 }
 911 
 912 /*
 913  *      doalarm(sig, ...)
 914  *
 915  *      Handle the alarm interrupt but do nothing.  Side effect is to
 916  *      cause return from wait3.
 917  *
 918  *      Parameters:
 919  *              sig
 920  *
 921  *      Global variables used:
 922  */
 923 /*ARGSUSED*/
 924 static void
 925 doalarm(int)
 926 {
 927         return;
 928 }
 929 
 930 
 931 /*
 932  *      read_command_options(argc, argv)
 933  *
 934  *      Scan the cmd line options and process the ones that start with "-"
 935  *
 936  *      Return value:
 937  *                              -M argument, if any
 938  *
 939  *      Parameters:
 940  *              argc            You know what this is
 941  *              argv            You know what this is
 942  *
 943  *      Global variables used:
 944  */
 945 static void
 946 read_command_options(register int argc, register char **argv)
 947 {
 948         register int            ch;
 949         int                     current_optind = 1;
 950         int                     last_optind_with_double_hyphen = 0;
 951         int                     last_optind;
 952         int                     last_current_optind;
 953         register int            i;
 954         register int            j;
 955         register int            k;
 956         register int            makefile_next = 0; /*
 957                                                     * flag to note options:
 958                                                     * -c, f, g, j, m, o
 959                                                     */
 960         const char              *tptr;
 961         const char              *CMD_OPTS;
 962 
 963         extern char             *optarg;
 964         extern int              optind, opterr, optopt;
 965 
 966 #define SUNPRO_CMD_OPTS "-~Bbc:Ddef:g:ij:K:kM:m:NnO:o:PpqRrSsTtuVvwx:"
 967 
 968 #ifdef TEAMWARE_MAKE_CMN
 969 #       define SVR4_CMD_OPTS   "-c:ef:g:ij:km:nO:o:pqrsTtVv"
 970 #else
 971 #       define SVR4_CMD_OPTS   "-ef:iknpqrstV"
 972 #endif
 973 
 974         /*
 975          * Added V in SVR4_CMD_OPTS also, which is going to be a hidden
 976          * option, just to make sure that the getopt doesn't fail when some
 977          * users leave their USE_SVR4_MAKE set and try to use the makefiles
 978          * that are designed to issue commands like $(MAKE) -V. Anyway it
 979          * sets the same flag but ensures that getopt doesn't fail.
 980          */
 981 
 982         opterr = 0;
 983         optind = 1;
 984         while (1) {
 985                 last_optind=optind;                     /* Save optind and current_optind values */
 986                 last_current_optind=current_optind;     /* in case we have to repeat this round. */
 987                 if (svr4) {
 988                         CMD_OPTS=SVR4_CMD_OPTS;
 989                         ch = getopt(argc, argv, SVR4_CMD_OPTS);
 990                 } else {
 991                         CMD_OPTS=SUNPRO_CMD_OPTS;
 992                         ch = getopt(argc, argv, SUNPRO_CMD_OPTS);
 993                 }
 994                 if (ch == EOF) {
 995                         if(optind < argc) {
 996                                 /*
 997                                  * Fixing bug 4102537:
 998                                  *    Strange behaviour of command make using -- option.
 999                                  * Not all argv have been processed
1000                                  * Skip non-flag argv and continue processing.
1001                                  */
1002                                 optind++;
1003                                 current_optind++;
1004                                 continue;
1005                         } else {
1006                                 break;
1007                         }
1008 
1009                 }
1010                 if (ch == '?') {
1011                         if (optopt == '-') {
1012                                 /* Bug 5060758: getopt() changed behavior (s10_60),
1013                                  * and now we have to deal with cases when options
1014                                  * with double hyphen appear here, from -$(MAKEFLAGS)
1015                                  */
1016                                 i = current_optind;
1017                                 if (argv[i][0] == '-') {
1018                                   if (argv[i][1] == '-') {
1019                                     if (argv[i][2] != '\0') {
1020                                       /* Check if this option is allowed */
1021                                       tptr = strchr(CMD_OPTS, argv[i][2]);
1022                                       if (tptr) {
1023                                         if (last_optind_with_double_hyphen != current_optind) {
1024                                           /* This is first time we are trying to fix "--"
1025                                            * problem with this option. If we come here second 
1026                                            * time, we will go to fatal error.
1027                                            */
1028                                           last_optind_with_double_hyphen = current_optind;
1029                                           
1030                                           /* Eliminate first hyphen character */
1031                                           for (j=0; argv[i][j] != '\0'; j++) {
1032                                             argv[i][j] = argv[i][j+1];
1033                                           }
1034                                           
1035                                           /* Repeat the processing of this argument */
1036                                           optind=last_optind;
1037                                           current_optind=last_current_optind;
1038                                           continue;
1039                                         }
1040                                       }
1041                                     }
1042                                   }
1043                                 }
1044                         }
1045                 }
1046 
1047                 if (ch == '?') {
1048                         if (svr4) {
1049 #ifdef TEAMWARE_MAKE_CMN
1050                                 fprintf(stderr,
1051                                         catgets(catd, 1, 267, "Usage : dmake [ -f makefile ][ -c dmake_rcfile ][ -g dmake_group ]\n"));
1052                                 fprintf(stderr,
1053                                         catgets(catd, 1, 268, "              [ -j dmake_max_jobs ][ -m dmake_mode ][ -o dmake_odir ]...\n"));
1054                                 fprintf(stderr,
1055                                         catgets(catd, 1, 269, "              [ -e ][ -i ][ -k ][ -n ][ -p ][ -q ][ -r ][ -s ][ -t ][ -v ]\n"));
1056 #else
1057                                 fprintf(stderr,
1058                                         catgets(catd, 1, 270, "Usage : make [ -f makefile ]... [ -e ][ -i ][ -k ][ -n ][ -p ][ -q ][ -r ]\n"));
1059                                 fprintf(stderr,
1060                                         catgets(catd, 1, 271, "             [ -s ][ -t ]\n"));
1061 #endif
1062                                 tptr = strchr(SVR4_CMD_OPTS, optopt);
1063                         } else {
1064 #ifdef TEAMWARE_MAKE_CMN
1065                                 fprintf(stderr,
1066                                         catgets(catd, 1, 272, "Usage : dmake [ -f makefile ][ -c dmake_rcfile ][ -g dmake_group ]\n"));
1067                                 fprintf(stderr,
1068                                         catgets(catd, 1, 273, "              [ -j dmake_max_jobs ][ -K statefile ][ -m dmake_mode ][ -x MODE_NAME=VALUE ][ -o dmake_odir ]...\n"));
1069                                 fprintf(stderr,
1070                                         catgets(catd, 1, 274, "              [ -d ][ -dd ][ -D ][ -DD ][ -e ][ -i ][ -k ][ -n ][ -p ][ -P ][ -u ][ -w ]\n"));
1071                                 fprintf(stderr,
1072                                         catgets(catd, 1, 275, "              [ -q ][ -r ][ -s ][ -S ][ -t ][ -v ][ -V ][ target... ][ macro=value... ][ \"macro +=value\"... ]\n"));
1073 #else
1074                                 fprintf(stderr,
1075                                         catgets(catd, 1, 276, "Usage : make [ -f makefile ][ -K statefile ]... [ -d ][ -dd ][ -D ][ -DD ]\n"));
1076                                 fprintf(stderr,
1077                                         catgets(catd, 1, 277, "             [ -e ][ -i ][ -k ][ -n ][ -p ][ -P ][ -q ][ -r ][ -s ][ -S ][ -t ]\n"));
1078                                 fprintf(stderr,
1079                                         catgets(catd, 1, 278, "             [ -u ][ -w ][ -V ][ target... ][ macro=value... ][ \"macro +=value\"... ]\n"));
1080 #endif
1081                                 tptr = strchr(SUNPRO_CMD_OPTS, optopt);
1082                         }
1083                         if (!tptr) {
1084                                 fatal(catgets(catd, 1, 279, "Unknown option `-%c'"), optopt);
1085                         } else {
1086                                 fatal(catgets(catd, 1, 280, "Missing argument after `-%c'"), optopt);
1087                         }
1088                 }
1089 
1090 
1091 
1092                 makefile_next |= parse_command_option(ch);
1093                 /*
1094                  * If we're done processing all of the options of
1095                  * ONE argument string...
1096                  */
1097                 if (current_optind < optind) {
1098                         i = current_optind;
1099                         k = 0;
1100                         /* If there's an argument for an option... */
1101                         if ((optind - current_optind) > 1) {
1102                                 k = i + 1;
1103                         }
1104                         switch (makefile_next) {
1105                         case 0:
1106                                 argv[i] = NULL;
1107                                 /* This shouldn't happen */
1108                                 if (k) {
1109                                         argv[k] = NULL;
1110                                 }
1111                                 break;
1112                         case 1: /* -f seen */
1113                                 argv[i] = (char *)NOCATGETS("-f");
1114                                 break;
1115                         case 2: /* -c seen */
1116                                 argv[i] = (char *)NOCATGETS("-c");
1117 #ifndef TEAMWARE_MAKE_CMN
1118                                 warning(catgets(catd, 1, 281, "Ignoring DistributedMake -c option"));
1119 #endif
1120                                 break;
1121                         case 4: /* -g seen */
1122                                 argv[i] = (char *)NOCATGETS("-g");
1123 #ifndef TEAMWARE_MAKE_CMN
1124                                 warning(catgets(catd, 1, 282, "Ignoring DistributedMake -g option"));
1125 #endif
1126                                 break;
1127                         case 8: /* -j seen */
1128                                 argv[i] = (char *)NOCATGETS("-j");
1129 #ifndef TEAMWARE_MAKE_CMN
1130                                 warning(catgets(catd, 1, 283, "Ignoring DistributedMake -j option"));
1131 #endif
1132                                 break;
1133                         case 16: /* -M seen */
1134                                 argv[i] = (char *)NOCATGETS("-M");
1135 #ifndef TEAMWARE_MAKE_CMN
1136                                 warning(catgets(catd, 1, 284, "Ignoring ParallelMake -M option"));
1137 #endif
1138                                 break;
1139                         case 32: /* -m seen */
1140                                 argv[i] = (char *)NOCATGETS("-m");
1141 #ifndef TEAMWARE_MAKE_CMN
1142                                 warning(catgets(catd, 1, 285, "Ignoring DistributedMake -m option"));
1143 #endif
1144                                 break;
1145                         case 128: /* -O seen */
1146                                 argv[i] = (char *)NOCATGETS("-O");
1147                                 break;
1148                         case 256: /* -K seen */
1149                                 argv[i] = (char *)NOCATGETS("-K");
1150                                 break;
1151                         case 512:       /* -o seen */
1152                                 argv[i] = (char *)NOCATGETS("-o");
1153 #ifndef TEAMWARE_MAKE_CMN
1154                                 warning(catgets(catd, 1, 311, "Ignoring DistributedMake -o option"));
1155 #endif
1156                                 break;
1157                         case 1024: /* -x seen */
1158                                 argv[i] = (char *)NOCATGETS("-x");
1159 #ifndef TEAMWARE_MAKE_CMN
1160                                 warning(catgets(catd, 1, 353, "Ignoring DistributedMake -x option"));
1161 #endif
1162                                 break;
1163                         default: /* > 1 of -c, f, g, j, K, M, m, O, o, x seen */
1164                                 fatal(catgets(catd, 1, 286, "Illegal command line. More than one option requiring\nan argument given in the same argument group"));
1165                         }
1166 
1167                         makefile_next = 0;
1168                         current_optind = optind;
1169                 }
1170         }
1171 }
1172 
1173 static void
1174 quote_str(char *str, char *qstr)
1175 {
1176         char            *to;
1177         char            *from;
1178 
1179         to = qstr;
1180         for (from = str; *from; from++) {
1181                 switch (*from) {
1182                 case ';':       /* End of command */
1183                 case '(':       /* Start group */
1184                 case ')':       /* End group */
1185                 case '{':       /* Start group */
1186                 case '}':       /* End group */
1187                 case '[':       /* Reg expr - any of a set of chars */
1188                 case ']':       /* End of set of chars */
1189                 case '|':       /* Pipe or logical-or */
1190                 case '^':       /* Old-fashioned pipe */
1191                 case '&':   /* Background or logical-and */
1192                 case '<':    /* Redirect stdin */
1193                 case '>':    /* Redirect stdout */
1194                 case '*':       /* Reg expr - any sequence of chars */
1195                 case '?':       /* Reg expr - any single char */
1196                 case '$':       /* Variable substitution */
1197                 case '\'':      /* Singe quote - turn off all magic */
1198                 case '"':       /* Double quote - span whitespace */
1199                 case '`':       /* Backquote - run a command */
1200                 case '#':       /* Comment */
1201                 case ' ':       /* Space (for MACRO=value1 value2  */
1202                 case '\\':      /* Escape char - turn off magic of next char */
1203                         *to++ = '\\';
1204                         break;
1205 
1206                 default:
1207                         break;
1208                 }
1209                 *to++ = *from;
1210         }
1211         *to = '\0';
1212 }
1213 
1214 static void
1215 unquote_str(char *str, char *qstr)
1216 {
1217         char            *to;
1218         char            *from;
1219 
1220         to = qstr;
1221         for (from = str; *from; from++) {
1222                 if (*from == '\\') {
1223                         from++;
1224                 }
1225                 *to++ = *from;
1226         }
1227         *to = '\0';
1228 }
1229 
1230 /*
1231  * Convert the MAKEFLAGS string value into a vector of char *, similar
1232  * to argv.
1233  */
1234 static void
1235 setup_makeflags_argv()
1236 {
1237         char            *cp;
1238         char            *cp1;
1239         char            *cp2;
1240         char            *cp3;
1241         char            *cp_orig;
1242         Boolean         add_hyphen;
1243         int             i;
1244         char            tmp_char;
1245 
1246         mf_argc = 1;
1247         cp = getenv(makeflags->string_mb);
1248         cp_orig = cp;
1249 
1250         if (cp) {
1251                 /*
1252                  * If new MAKEFLAGS format, no need to add hyphen.
1253                  * If old MAKEFLAGS format, add hyphen before flags.
1254                  */
1255 
1256                 if ((strchr(cp, (int) hyphen_char) != NULL) ||
1257                     (strchr(cp, (int) equal_char) != NULL)) {
1258 
1259                         /* New MAKEFLAGS format */
1260 
1261                         add_hyphen = false;
1262 #ifdef ADDFIX5060758                    
1263                         /* Check if MAKEFLAGS value begins with multiple
1264                          * hyphen characters, and remove all duplicates.
1265                          * Usually it happens when the next command is
1266                          * used: $(MAKE) -$(MAKEFLAGS)
1267                          * This is a workaround for BugID 5060758.
1268                          */
1269                         while (*cp) {
1270                                 if (*cp != (int) hyphen_char) {
1271                                         break;
1272                                 }
1273                                 cp++;
1274                                 if (*cp == (int) hyphen_char) {
1275                                         /* There are two hyphens. Skip one */
1276                                         cp_orig = cp;
1277                                         cp++;
1278                                 }
1279                                 if (!(*cp)) {
1280                                         /* There are hyphens only. Skip all */
1281                                         cp_orig = cp;
1282                                         break;
1283                                 }
1284                         }
1285 #endif
1286                 } else {
1287 
1288                         /* Old MAKEFLAGS format */
1289 
1290                         add_hyphen = true;
1291                 }
1292         }
1293 
1294         /* Find the number of arguments in MAKEFLAGS */
1295         while (cp && *cp) {
1296                 /* Skip white spaces */
1297                 while (cp && *cp && isspace(*cp)) {
1298                         cp++;
1299                 }
1300                 if (cp && *cp) {
1301                         /* Increment arg count */
1302                         mf_argc++;
1303                         /* Go to next white space */
1304                         while (cp && *cp && !isspace(*cp)) {
1305                                 if(*cp == (int) backslash_char) {
1306                                         cp++;
1307                                 }
1308                                 cp++;
1309                         }
1310                 }
1311         }
1312         /* Allocate memory for the new MAKEFLAGS argv */
1313         mf_argv = (char **) malloc((mf_argc + 1) * sizeof(char *));
1314         mf_argv[0] = (char *)NOCATGETS("MAKEFLAGS");
1315         /*
1316          * Convert the MAKEFLAGS string value into a vector of char *,
1317          * similar to argv.
1318          */
1319         cp = cp_orig;
1320         for (i = 1; i < mf_argc; i++) {
1321                 /* Skip white spaces */
1322                 while (cp && *cp && isspace(*cp)) {
1323                         cp++;
1324                 }
1325                 if (cp && *cp) {
1326                         cp_orig = cp;
1327                         /* Go to next white space */
1328                         while (cp && *cp && !isspace(*cp)) {
1329                                 if(*cp == (int) backslash_char) {
1330                                         cp++;
1331                                 }
1332                                 cp++;
1333                         }
1334                         tmp_char = *cp;
1335                         *cp = (int) nul_char;
1336                         if (add_hyphen) {
1337                                 mf_argv[i] = getmem(2 + strlen(cp_orig));
1338                                 mf_argv[i][0] = '\0';
1339                                 (void) strcat(mf_argv[i], "-");
1340                                 // (void) strcat(mf_argv[i], cp_orig);
1341                                 unquote_str(cp_orig, mf_argv[i]+1);
1342                         } else {
1343                                 mf_argv[i] = getmem(2 + strlen(cp_orig));
1344                                 //mf_argv[i] = strdup(cp_orig);
1345                                 unquote_str(cp_orig, mf_argv[i]);
1346                         }
1347                         *cp = tmp_char;
1348                 }
1349         }
1350         mf_argv[i] = NULL;
1351 }
1352 
1353 /*
1354  *      parse_command_option(ch)
1355  *
1356  *      Parse make command line options.
1357  *
1358  *      Return value:
1359  *                              Indicates if any -f -c or -M were seen
1360  *
1361  *      Parameters:
1362  *              ch              The character to parse
1363  *
1364  *      Static variables used:
1365  *              dmake_group_specified   Set for make -g
1366  *              dmake_max_jobs_specified        Set for make -j
1367  *              dmake_mode_specified    Set for make -m
1368  *              dmake_add_mode_specified        Set for make -x
1369  *              dmake_compat_mode_specified     Set for make -x SUN_MAKE_COMPAT_MODE=
1370  *              dmake_output_mode_specified     Set for make -x DMAKE_OUTPUT_MODE=
1371  *              dmake_odir_specified    Set for make -o
1372  *              dmake_rcfile_specified  Set for make -c
1373  *              env_wins                Set for make -e
1374  *              ignore_default_mk       Set for make -r
1375  *              trace_status            Set for make -p
1376  *
1377  *      Global variables used:
1378  *              .make.state path & name set for make -K
1379  *              continue_after_error    Set for make -k
1380  *              debug_level             Set for make -d
1381  *              do_not_exec_rule        Set for make -n
1382  *              filter_stderr           Set for make -X
1383  *              ignore_errors_all       Set for make -i
1384  *              no_parallel             Set for make -R
1385  *              quest                   Set for make -q
1386  *              read_trace_level        Set for make -D
1387  *              report_dependencies     Set for make -P
1388  *              send_mtool_msgs         Set for make -K
1389  *              silent_all              Set for make -s
1390  *              touch                   Set for make -t
1391  */
1392 static int
1393 parse_command_option(register char ch)
1394 {
1395         static int              invert_next = 0;
1396         int                     invert_this = invert_next;
1397 
1398         invert_next = 0;
1399         switch (ch) {
1400         case '-':                        /* Ignore "--" */
1401                 return 0;
1402         case '~':                        /* Invert next option */
1403                 invert_next = 1;
1404                 return 0;
1405         case 'B':                        /* Obsolete */
1406                 return 0;
1407         case 'b':                        /* Obsolete */
1408                 return 0;
1409         case 'c':                        /* Read alternative dmakerc file */
1410                 if (invert_this) {
1411                         dmake_rcfile_specified = false;
1412                 } else {
1413                         dmake_rcfile_specified = true;
1414                 }
1415                 return 2;
1416         case 'D':                        /* Show lines read */
1417                 if (invert_this) {
1418                         read_trace_level--;
1419                 } else {
1420                         read_trace_level++;
1421                 }
1422                 return 0;
1423         case 'd':                        /* Debug flag */
1424                 if (invert_this) {
1425                         debug_level--;
1426                 } else {
1427                         debug_level++;
1428                 }
1429                 return 0;
1430         case 'e':                        /* Environment override flag */
1431                 if (invert_this) {
1432                         env_wins = false;
1433                 } else {
1434                         env_wins = true;
1435                 }
1436                 return 0;
1437         case 'f':                        /* Read alternative makefile(s) */
1438                 return 1;
1439         case 'g':                        /* Use alternative DMake group */
1440                 if (invert_this) {
1441                         dmake_group_specified = false;
1442                 } else {
1443                         dmake_group_specified = true;
1444                 }
1445                 return 4;
1446         case 'i':                        /* Ignore errors */
1447                 if (invert_this) {
1448                         ignore_errors_all = false;
1449                 } else {
1450                         ignore_errors_all = true;
1451                 }
1452                 return 0;
1453         case 'j':                        /* Use alternative DMake max jobs */
1454                 if (invert_this) {
1455                         dmake_max_jobs_specified = false;
1456                 } else {
1457                         dmake_max_jobs_specified = true;
1458                 }
1459                 return 8;
1460         case 'K':                        /* Read alternative .make.state */
1461                 return 256;
1462         case 'k':                        /* Keep making even after errors */
1463                 if (invert_this) {
1464                         continue_after_error = false;
1465                 } else {
1466                         continue_after_error = true;
1467                         continue_after_error_ever_seen = true;
1468                 }
1469                 return 0;
1470         case 'M':                        /* Read alternative make.machines file */
1471                 if (invert_this) {
1472                         pmake_machinesfile_specified = false;
1473                 } else {
1474                         pmake_machinesfile_specified = true;
1475                         dmake_mode_type = parallel_mode;
1476                         no_parallel = false;
1477                 }
1478                 return 16;
1479         case 'm':                        /* Use alternative DMake build mode */
1480                 if (invert_this) {
1481                         dmake_mode_specified = false;
1482                 } else {
1483                         dmake_mode_specified = true;
1484                 }
1485                 return 32;
1486         case 'x':                        /* Use alternative DMake mode */
1487                 if (invert_this) {
1488                         dmake_add_mode_specified = false;
1489                 } else {
1490                         dmake_add_mode_specified = true;
1491                 }
1492                 return 1024;
1493         case 'N':                        /* Reverse -n */
1494                 if (invert_this) {
1495                         do_not_exec_rule = true;
1496                 } else {
1497                         do_not_exec_rule = false;
1498                 }
1499                 return 0;
1500         case 'n':                        /* Print, not exec commands */
1501                 if (invert_this) {
1502                         do_not_exec_rule = false;
1503                 } else {
1504                         do_not_exec_rule = true;
1505                 }
1506                 return 0;
1507         case 'O':                        /* Send job start & result msgs */
1508                 if (invert_this) {
1509                         send_mtool_msgs = false;
1510                 } else {
1511                 }
1512                 return 128;
1513         case 'o':                        /* Use alternative dmake output dir */
1514                 if (invert_this) {
1515                         dmake_odir_specified = false;
1516                 } else {
1517                         dmake_odir_specified = true;
1518                 }
1519                 return 512;
1520         case 'P':                        /* Print for selected targets */
1521                 if (invert_this) {
1522                         report_dependencies_level--;
1523                 } else {
1524                         report_dependencies_level++;
1525                 }
1526                 return 0;
1527         case 'p':                        /* Print description */
1528                 if (invert_this) {
1529                         trace_status = false;
1530                         do_not_exec_rule = false;
1531                 } else {
1532                         trace_status = true;
1533                         do_not_exec_rule = true;
1534                 }
1535                 return 0;
1536         case 'q':                        /* Question flag */
1537                 if (invert_this) {
1538                         quest = false;
1539                 } else {
1540                         quest = true;
1541                 }
1542                 return 0;
1543         case 'R':                        /* Don't run in parallel */
1544 #ifdef TEAMWARE_MAKE_CMN
1545                 if (invert_this) {
1546                         pmake_cap_r_specified = false;
1547                         no_parallel = false;
1548                 } else {
1549                         pmake_cap_r_specified = true;
1550                         dmake_mode_type = serial_mode;
1551                         no_parallel = true;
1552                 }
1553 #else
1554                 warning(catgets(catd, 1, 182, "Ignoring ParallelMake -R option"));
1555 #endif
1556                 return 0;
1557         case 'r':                        /* Turn off internal rules */
1558                 if (invert_this) {
1559                         ignore_default_mk = false;
1560                 } else {
1561                         ignore_default_mk = true;
1562                 }
1563                 return 0;
1564         case 'S':                        /* Reverse -k */
1565                 if (invert_this) {
1566                         continue_after_error = true;
1567                 } else {
1568                         continue_after_error = false;
1569                         stop_after_error_ever_seen = true;
1570                 }
1571                 return 0;
1572         case 's':                        /* Silent flag */
1573                 if (invert_this) {
1574                         silent_all = false;
1575                 } else {
1576                         silent_all = true;
1577                 }
1578                 return 0;
1579         case 'T':                        /* Print target list */
1580                 if (invert_this) {
1581                         list_all_targets = false;
1582                         do_not_exec_rule = false;
1583                 } else {
1584                         list_all_targets = true;
1585                         do_not_exec_rule = true;
1586                 }
1587                 return 0;
1588         case 't':                        /* Touch flag */
1589                 if (invert_this) {
1590                         touch = false;
1591                 } else {
1592                         touch = true;
1593                 }
1594                 return 0;
1595         case 'u':                        /* Unconditional flag */
1596                 if (invert_this) {
1597                         build_unconditional = false;
1598                 } else {
1599                         build_unconditional = true;
1600                 }
1601                 return 0;
1602         case 'V':                       /* SVR4 mode */
1603                 svr4 = true;
1604                 return 0;
1605         case 'v':                       /* Version flag */
1606                 if (invert_this) {
1607                 } else {
1608 #ifdef TEAMWARE_MAKE_CMN
1609                         fprintf(stdout, NOCATGETS("dmake: %s\n"), verstring);
1610                         exit_status = 0;
1611                         exit(0);
1612 #else
1613                         warning(catgets(catd, 1, 324, "Ignoring DistributedMake -v option"));
1614 #endif
1615                 }
1616                 return 0;
1617         case 'w':                        /* Unconditional flag */
1618                 if (invert_this) {
1619                         report_cwd = false;
1620                 } else {
1621                         report_cwd = true;
1622                 }
1623                 return 0;
1624 #if 0
1625         case 'X':                       /* Filter stdout */
1626                 if (invert_this) {
1627                         filter_stderr = false;
1628                 } else {
1629                         filter_stderr = true;
1630                 }
1631                 return 0;
1632 #endif
1633         default:
1634                 break;
1635         }
1636         return 0;
1637 }
1638 
1639 /*
1640  *      setup_for_projectdir()
1641  *
1642  *      Read the PROJECTDIR variable, if defined, and set the sccs path
1643  *
1644  *      Parameters:
1645  *
1646  *      Global variables used:
1647  *              sccs_dir_path   Set to point to SCCS dir to use
1648  */
1649 static void
1650 setup_for_projectdir(void)
1651 {
1652 static char     path[MAXPATHLEN];
1653 char            cwdpath[MAXPATHLEN];
1654 uid_t uid;
1655 int   done=0;
1656 
1657         /* Check if we should use PROJECTDIR when reading the SCCS dir. */
1658         sccs_dir_path = getenv(NOCATGETS("PROJECTDIR"));
1659         if ((sccs_dir_path != NULL) &&
1660             (sccs_dir_path[0] != (int) slash_char)) {
1661                 struct passwd *pwent;
1662 
1663              {
1664                 uid = getuid();
1665                 pwent = getpwuid(uid);
1666                 if (pwent == NULL) {
1667                    fatal(catgets(catd, 1, 188, "Bogus USERID "));
1668                 }
1669                 if ((pwent = getpwnam(sccs_dir_path)) == NULL) {
1670                         /*empty block : it'll go & check cwd  */
1671                 }
1672                 else {
1673                   (void) sprintf(path, NOCATGETS("%s/src"), pwent->pw_dir);
1674                   if (access(path, F_OK) == 0) {
1675                         sccs_dir_path = path;
1676                         done = 1;
1677                   } else {
1678                         (void) sprintf(path, NOCATGETS("%s/source"), pwent->pw_dir);
1679                         if (access(path, F_OK) == 0) {
1680                                 sccs_dir_path = path;
1681                                 done = 1;
1682                         }
1683                      }
1684                 }
1685                 if (!done) {
1686                     if (getcwd(cwdpath, MAXPATHLEN - 1 )) {
1687 
1688                        (void) sprintf(path, NOCATGETS("%s/%s"), cwdpath,sccs_dir_path);
1689                        if (access(path, F_OK) == 0) {
1690                                 sccs_dir_path = path;
1691                                 done = 1;
1692                         } else {
1693                                 fatal(catgets(catd, 1, 189, "Bogus PROJECTDIR '%s'"), sccs_dir_path);
1694                         }
1695                     }
1696                 }
1697            }
1698         }
1699 }
1700 
1701 /*
1702  *      set_sgs_support()
1703  *
1704  *      Add the libmakestate.so.1 lib to the env var SGS_SUPPORT
1705  *        if it's not already in there.
1706  *      The SGS_SUPPORT env var and libmakestate.so.1 is used by
1707  *        the linker ld to report .make.state info back to make.
1708  *
1709  * In the new world we always will set the 32-bit and 64-bit versions of this
1710  * variable explicitly so that we can take into account the correct isa and our
1711  * prefix. So say that the prefix was /opt/local. Then we would want to search
1712  * /opt/local/lib/libmakestate.so.1:libmakestate.so.1. We still want to search
1713  * the original location just as a safety measure.
1714  */
1715 static void
1716 set_sgs_support()
1717 {
1718         int             len;
1719         char            *newpath, *newpath64;
1720         char            *oldpath, *oldpath64;
1721         static char     *prev_path, *prev_path64;
1722 
1723         oldpath = getenv(LD_SUPPORT_ENV_VAR_32);
1724         if (oldpath == NULL) {
1725                 len = snprintf(NULL, 0, "%s=%s/%s/%s:%s",
1726                     LD_SUPPORT_ENV_VAR_32,
1727                     MAKE_PREFIX,
1728                     LD_SUPPORT_MAKE_LIB_DIR,
1729                     LD_SUPPORT_MAKE_LIB, LD_SUPPORT_MAKE_LIB) + 1;
1730                 newpath = (char *) malloc(len);
1731                 sprintf(newpath, "%s=%s/%s/%s:%s",
1732                     LD_SUPPORT_ENV_VAR_32,
1733                     MAKE_PREFIX,
1734                     LD_SUPPORT_MAKE_LIB_DIR,
1735                     LD_SUPPORT_MAKE_LIB, LD_SUPPORT_MAKE_LIB);
1736         } else {
1737                 len = snprintf(NULL, 0, "%s=%s:%s/%s/%s:%s",
1738                     LD_SUPPORT_ENV_VAR_32, oldpath, MAKE_PREFIX,
1739                     LD_SUPPORT_MAKE_LIB_DIR, LD_SUPPORT_MAKE_LIB,
1740                     LD_SUPPORT_MAKE_LIB) + 1;
1741                 newpath = (char *) malloc(len);
1742                 sprintf(newpath, "%s=%s:%s/%s/%s:%s",
1743                     LD_SUPPORT_ENV_VAR_32, oldpath, MAKE_PREFIX,
1744                     LD_SUPPORT_MAKE_LIB_DIR, LD_SUPPORT_MAKE_LIB,
1745                     LD_SUPPORT_MAKE_LIB);
1746         }
1747 
1748         oldpath64 = getenv(LD_SUPPORT_ENV_VAR_64);
1749         if (oldpath64 == NULL) {
1750                 len = snprintf(NULL, 0, "%s=%s/%s/%s/%s:%s",
1751                     LD_SUPPORT_ENV_VAR_64, MAKE_PREFIX, LD_SUPPORT_MAKE_LIB_DIR,
1752                     LD_SUPPORT_MAKE_LIB_DIR_64, LD_SUPPORT_MAKE_LIB,
1753                     LD_SUPPORT_MAKE_LIB) + 1;
1754                 newpath64 = (char *) malloc(len);
1755                 sprintf(newpath64, "%s=%s/%s/%s/%s:%s",
1756                     LD_SUPPORT_ENV_VAR_64, MAKE_PREFIX, LD_SUPPORT_MAKE_LIB_DIR,
1757                     LD_SUPPORT_MAKE_LIB_DIR_64, LD_SUPPORT_MAKE_LIB,
1758                     LD_SUPPORT_MAKE_LIB);
1759         } else {
1760                 len = snprintf(NULL, 0, "%s=%s:%s/%s/%s/%s:%s",
1761                     LD_SUPPORT_ENV_VAR_64, oldpath64, MAKE_PREFIX,
1762                     LD_SUPPORT_MAKE_LIB_DIR, LD_SUPPORT_MAKE_LIB_DIR_64,
1763                     LD_SUPPORT_MAKE_LIB, LD_SUPPORT_MAKE_LIB) + 1;
1764                 newpath64 = (char *) malloc(len);
1765                 sprintf(newpath64, "%s=%s:%s/%s/%s/%s:%s",
1766                     LD_SUPPORT_ENV_VAR_64, oldpath64, MAKE_PREFIX,
1767                     LD_SUPPORT_MAKE_LIB_DIR, LD_SUPPORT_MAKE_LIB_DIR_64,
1768                     LD_SUPPORT_MAKE_LIB, LD_SUPPORT_MAKE_LIB);
1769         }
1770 
1771         putenv(newpath);
1772         if (prev_path) {
1773                 free(prev_path);
1774         }
1775         prev_path = newpath;
1776 
1777         putenv(newpath64);
1778         if (prev_path64) {
1779                 free(prev_path64);
1780         }
1781         prev_path64 = newpath64;
1782 }
1783 
1784 /*
1785  *      read_files_and_state(argc, argv)
1786  *
1787  *      Read the makefiles we care about and the environment
1788  *      Also read the = style command line options
1789  *
1790  *      Parameters:
1791  *              argc            You know what this is
1792  *              argv            You know what this is
1793  *
1794  *      Static variables used:
1795  *              env_wins        make -e, determines if env vars are RO
1796  *              ignore_default_mk make -r, determines if make.rules is read
1797  *              not_auto_depen  dwight
1798  *
1799  *      Global variables used:
1800  *              default_target_to_build Set to first proper target from file
1801  *              do_not_exec_rule Set to false when makfile is made
1802  *              dot             The Name ".", used to read current dir
1803  *              empty_name      The Name "", use as macro value
1804  *              keep_state      Set if KEEP_STATE is in environment
1805  *              make_state      The Name ".make.state", used to read file
1806  *              makefile_type   Set to type of file being read
1807  *              makeflags       The Name "MAKEFLAGS", used to set macro value
1808  *              not_auto        dwight
1809  *              read_trace_level Checked to se if the reader should trace
1810  *              report_dependencies If -P is on we do not read .make.state
1811  *              trace_reader    Set if reader should trace
1812  *              virtual_root    The Name "VIRTUAL_ROOT", used to check value
1813  */
1814 static void
1815 read_files_and_state(int argc, char **argv)
1816 {
1817         wchar_t                 buffer[1000];
1818         wchar_t                 buffer_posix[1000];
1819         register char           ch;
1820         register char           *cp;
1821         Property                def_make_macro = NULL;
1822         Name                    def_make_name;
1823         Name                    default_makefile;
1824         String_rec              dest;
1825         wchar_t                 destbuffer[STRING_BUFFER_LENGTH];
1826         register int            i;
1827         register int            j;
1828         Name                    keep_state_name;
1829         int                     length;
1830         Name                    Makefile;
1831         register Property       macro;
1832         struct stat             make_state_stat;
1833         Name                    makefile_name;
1834         register int            makefile_next = 0;
1835         register Boolean        makefile_read = false;
1836         String_rec              makeflags_string;
1837         String_rec              makeflags_string_posix;
1838         String_rec *            makeflags_string_current;
1839         Name                    makeflags_value_saved;
1840         register Name           name;
1841         Name                    new_make_value;
1842         Boolean                 save_do_not_exec_rule;
1843         Name                    sdotMakefile;
1844         Name                    sdotmakefile_name;
1845         static wchar_t          state_file_str;
1846         static char             state_file_str_mb[MAXPATHLEN];
1847         static struct _Name     state_filename;
1848         Boolean                 temp;
1849         char                    tmp_char;
1850         wchar_t                 *tmp_wcs_buffer;
1851         register Name           value;
1852         ASCII_Dyn_Array         makeflags_and_macro;
1853         Boolean                 is_xpg4;
1854 
1855 /*
1856  *      Remember current mode. It may be changed after reading makefile
1857  *      and we will have to correct MAKEFLAGS variable.
1858  */
1859         is_xpg4 = posix;
1860 
1861         MBSTOWCS(wcs_buffer, NOCATGETS("KEEP_STATE"));
1862         keep_state_name = GETNAME(wcs_buffer, FIND_LENGTH);
1863         MBSTOWCS(wcs_buffer, NOCATGETS("Makefile"));
1864         Makefile = GETNAME(wcs_buffer, FIND_LENGTH);
1865         MBSTOWCS(wcs_buffer, NOCATGETS("makefile"));
1866         makefile_name = GETNAME(wcs_buffer, FIND_LENGTH);
1867         MBSTOWCS(wcs_buffer, NOCATGETS("s.makefile"));
1868         sdotmakefile_name = GETNAME(wcs_buffer, FIND_LENGTH);
1869         MBSTOWCS(wcs_buffer, NOCATGETS("s.Makefile"));
1870         sdotMakefile = GETNAME(wcs_buffer, FIND_LENGTH);
1871 
1872 /*
1873  *      Set flag if NSE is active
1874  */
1875 
1876 /*
1877  *      initialize global dependency entry for .NOT_AUTO
1878  */
1879         not_auto_depen->next = NULL;
1880         not_auto_depen->name = not_auto;
1881         not_auto_depen->automatic = not_auto_depen->stale = false;
1882 
1883 /*
1884  *      Read internal definitions and rules.
1885  */
1886         if (read_trace_level > 1) {
1887                 trace_reader = true;
1888         }
1889         if (!ignore_default_mk) {
1890                 if (svr4) {
1891                         MBSTOWCS(wcs_buffer, NOCATGETS("svr4.make.rules"));
1892                         default_makefile = GETNAME(wcs_buffer, FIND_LENGTH);
1893                 } else {
1894                         MBSTOWCS(wcs_buffer, NOCATGETS("make.rules"));
1895                         default_makefile = GETNAME(wcs_buffer, FIND_LENGTH);
1896                 }
1897                 default_makefile->stat.is_file = true;
1898 
1899                 (void) read_makefile(default_makefile,
1900                                      true,
1901                                      false,
1902                                      true);
1903         }
1904 
1905         /*
1906          * If the user did not redefine the MAKE macro in the
1907          * default makefile (make.rules), then we'd like to
1908          * change the macro value of MAKE to be some form
1909          * of argv[0] for recursive MAKE builds.
1910          */
1911         MBSTOWCS(wcs_buffer, NOCATGETS("MAKE"));
1912         def_make_name = GETNAME(wcs_buffer, wslen(wcs_buffer));
1913         def_make_macro = get_prop(def_make_name->prop, macro_prop);
1914         if ((def_make_macro != NULL) &&
1915             (IS_EQUAL(def_make_macro->body.macro.value->string_mb,
1916                       NOCATGETS("make")))) {
1917                 MBSTOWCS(wcs_buffer, argv_zero_string);
1918                 new_make_value = GETNAME(wcs_buffer, wslen(wcs_buffer));
1919                 (void) SETVAR(def_make_name,
1920                               new_make_value,
1921                               false);
1922         }
1923 
1924         default_target_to_build = NULL;
1925         trace_reader = false;
1926 
1927 /*
1928  *      Read environment args. Let file args which follow override unless
1929  *      -e option seen. If -e option is not mentioned.
1930  */
1931         read_environment(env_wins);
1932         if (getvar(virtual_root)->hash.length == 0) {
1933                 maybe_append_prop(virtual_root, macro_prop)
1934                   ->body.macro.exported = true;
1935                 MBSTOWCS(wcs_buffer, "/");
1936                 (void) SETVAR(virtual_root,
1937                               GETNAME(wcs_buffer, FIND_LENGTH),
1938                               false);
1939         }
1940 
1941 /*
1942  * We now scan mf_argv and argv to see if we need to set
1943  * any of the DMake-added options/variables in MAKEFLAGS.
1944  */
1945 
1946         makeflags_and_macro.start = 0;
1947         makeflags_and_macro.size = 0;
1948         enter_argv_values(mf_argc, mf_argv, &makeflags_and_macro);
1949         enter_argv_values(argc, argv, &makeflags_and_macro);
1950 
1951 /*
1952  *      Set MFLAGS and MAKEFLAGS
1953  *      
1954  *      Before reading makefile we do not know exactly which mode
1955  *      (posix or not) is used. So prepare two MAKEFLAGS strings
1956  *      for both posix and solaris modes because they are different.
1957  */
1958         INIT_STRING_FROM_STACK(makeflags_string, buffer);
1959         INIT_STRING_FROM_STACK(makeflags_string_posix, buffer_posix);
1960         append_char((int) hyphen_char, &makeflags_string);
1961         append_char((int) hyphen_char, &makeflags_string_posix);
1962 
1963         switch (read_trace_level) {
1964         case 2:
1965                 append_char('D', &makeflags_string);
1966                 append_char('D', &makeflags_string_posix);
1967         case 1:
1968                 append_char('D', &makeflags_string);
1969                 append_char('D', &makeflags_string_posix);
1970         }
1971         switch (debug_level) {
1972         case 2:
1973                 append_char('d', &makeflags_string);
1974                 append_char('d', &makeflags_string_posix);
1975         case 1:
1976                 append_char('d', &makeflags_string);
1977                 append_char('d', &makeflags_string_posix);
1978         }
1979         if (env_wins) {
1980                 append_char('e', &makeflags_string);
1981                 append_char('e', &makeflags_string_posix);
1982         }
1983         if (ignore_errors_all) {
1984                 append_char('i', &makeflags_string);
1985                 append_char('i', &makeflags_string_posix);
1986         }
1987         if (continue_after_error) {
1988                 if (stop_after_error_ever_seen) {
1989                         append_char('S', &makeflags_string_posix);
1990                         append_char((int) space_char, &makeflags_string_posix);
1991                         append_char((int) hyphen_char, &makeflags_string_posix);
1992                 }
1993                 append_char('k', &makeflags_string);
1994                 append_char('k', &makeflags_string_posix);
1995         } else {
1996                 if (stop_after_error_ever_seen 
1997                     && continue_after_error_ever_seen) {
1998                         append_char('k', &makeflags_string_posix);
1999                         append_char((int) space_char, &makeflags_string_posix);
2000                         append_char((int) hyphen_char, &makeflags_string_posix);
2001                         append_char('S', &makeflags_string_posix);
2002                 }
2003         }
2004         if (do_not_exec_rule) {
2005                 append_char('n', &makeflags_string);
2006                 append_char('n', &makeflags_string_posix);
2007         }
2008         switch (report_dependencies_level) {
2009         case 4:
2010                 append_char('P', &makeflags_string);
2011                 append_char('P', &makeflags_string_posix);
2012         case 3:
2013                 append_char('P', &makeflags_string);
2014                 append_char('P', &makeflags_string_posix);
2015         case 2:
2016                 append_char('P', &makeflags_string);
2017                 append_char('P', &makeflags_string_posix);
2018         case 1:
2019                 append_char('P', &makeflags_string);
2020                 append_char('P', &makeflags_string_posix);
2021         }
2022         if (trace_status) {
2023                 append_char('p', &makeflags_string);
2024                 append_char('p', &makeflags_string_posix);
2025         }
2026         if (quest) {
2027                 append_char('q', &makeflags_string);
2028                 append_char('q', &makeflags_string_posix);
2029         }
2030         if (silent_all) {
2031                 append_char('s', &makeflags_string);
2032                 append_char('s', &makeflags_string_posix);
2033         }
2034         if (touch) {
2035                 append_char('t', &makeflags_string);
2036                 append_char('t', &makeflags_string_posix);
2037         }
2038         if (build_unconditional) {
2039                 append_char('u', &makeflags_string);
2040                 append_char('u', &makeflags_string_posix);
2041         }
2042         if (report_cwd) {
2043                 append_char('w', &makeflags_string);
2044                 append_char('w', &makeflags_string_posix);
2045         }
2046         /* -c dmake_rcfile */
2047         if (dmake_rcfile_specified) {
2048                 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_RCFILE"));
2049                 dmake_rcfile = GETNAME(wcs_buffer, FIND_LENGTH);
2050                 append_makeflags_string(dmake_rcfile, &makeflags_string);
2051                 append_makeflags_string(dmake_rcfile, &makeflags_string_posix);
2052         }
2053         /* -g dmake_group */
2054         if (dmake_group_specified) {
2055                 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_GROUP"));
2056                 dmake_group = GETNAME(wcs_buffer, FIND_LENGTH);
2057                 append_makeflags_string(dmake_group, &makeflags_string);
2058                 append_makeflags_string(dmake_group, &makeflags_string_posix);
2059         }
2060         /* -j dmake_max_jobs */
2061         if (dmake_max_jobs_specified) {
2062                 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MAX_JOBS"));
2063                 dmake_max_jobs = GETNAME(wcs_buffer, FIND_LENGTH);
2064                 append_makeflags_string(dmake_max_jobs, &makeflags_string);
2065                 append_makeflags_string(dmake_max_jobs, &makeflags_string_posix);
2066         }
2067         /* -m dmake_mode */
2068         if (dmake_mode_specified) {
2069                 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE"));
2070                 dmake_mode = GETNAME(wcs_buffer, FIND_LENGTH);
2071                 append_makeflags_string(dmake_mode, &makeflags_string);
2072                 append_makeflags_string(dmake_mode, &makeflags_string_posix);
2073         }
2074         /* -x dmake_compat_mode */
2075 //      if (dmake_compat_mode_specified) {
2076 //              MBSTOWCS(wcs_buffer, NOCATGETS("SUN_MAKE_COMPAT_MODE"));
2077 //              dmake_compat_mode = GETNAME(wcs_buffer, FIND_LENGTH);
2078 //              append_makeflags_string(dmake_compat_mode, &makeflags_string);
2079 //              append_makeflags_string(dmake_compat_mode, &makeflags_string_posix);
2080 //      }
2081         /* -x dmake_output_mode */
2082         if (dmake_output_mode_specified) {
2083                 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_OUTPUT_MODE"));
2084                 dmake_output_mode = GETNAME(wcs_buffer, FIND_LENGTH);
2085                 append_makeflags_string(dmake_output_mode, &makeflags_string);
2086                 append_makeflags_string(dmake_output_mode, &makeflags_string_posix);
2087         }
2088         /* -o dmake_odir */
2089         if (dmake_odir_specified) {
2090                 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_ODIR"));
2091                 dmake_odir = GETNAME(wcs_buffer, FIND_LENGTH);
2092                 append_makeflags_string(dmake_odir, &makeflags_string);
2093                 append_makeflags_string(dmake_odir, &makeflags_string_posix);
2094         }
2095         /* -M pmake_machinesfile */
2096         if (pmake_machinesfile_specified) {
2097                 MBSTOWCS(wcs_buffer, NOCATGETS("PMAKE_MACHINESFILE"));
2098                 pmake_machinesfile = GETNAME(wcs_buffer, FIND_LENGTH);
2099                 append_makeflags_string(pmake_machinesfile, &makeflags_string);
2100                 append_makeflags_string(pmake_machinesfile, &makeflags_string_posix);
2101         }
2102         /* -R */
2103         if (pmake_cap_r_specified) {
2104                 append_char((int) space_char, &makeflags_string);
2105                 append_char((int) hyphen_char, &makeflags_string);
2106                 append_char('R', &makeflags_string);
2107                 append_char((int) space_char, &makeflags_string_posix);
2108                 append_char((int) hyphen_char, &makeflags_string_posix);
2109                 append_char('R', &makeflags_string_posix);
2110         }
2111 
2112 /*
2113  *      Make sure MAKEFLAGS is exported
2114  */
2115         maybe_append_prop(makeflags, macro_prop)->
2116           body.macro.exported = true;
2117 
2118         if (makeflags_string.buffer.start[1] != (int) nul_char) {
2119                 if (makeflags_string.buffer.start[1] != (int) space_char) {
2120                         MBSTOWCS(wcs_buffer, NOCATGETS("MFLAGS"));
2121                         (void) SETVAR(GETNAME(wcs_buffer, FIND_LENGTH),
2122                                       GETNAME(makeflags_string.buffer.start,
2123                                               FIND_LENGTH),
2124                                       false);
2125                 } else {
2126                         MBSTOWCS(wcs_buffer, NOCATGETS("MFLAGS"));
2127                         (void) SETVAR(GETNAME(wcs_buffer, FIND_LENGTH),
2128                                       GETNAME(makeflags_string.buffer.start + 2,
2129                                               FIND_LENGTH),
2130                                       false);
2131                 }
2132         }
2133 
2134 /* 
2135  *      Add command line macro to POSIX makeflags_string  
2136  */
2137         if (makeflags_and_macro.start) {
2138                 tmp_char = (char) space_char;
2139                 cp = makeflags_and_macro.start;
2140                 do {
2141                         append_char(tmp_char, &makeflags_string_posix);
2142                 } while ( tmp_char = *cp++ ); 
2143                 retmem_mb(makeflags_and_macro.start);
2144         }
2145 
2146 /*
2147  *      Now set the value of MAKEFLAGS macro in accordance
2148  *      with current mode.
2149  */
2150         macro = maybe_append_prop(makeflags, macro_prop);
2151         temp = (Boolean) macro->body.macro.read_only;
2152         macro->body.macro.read_only = false;
2153         if(posix || gnu_style) {
2154                 makeflags_string_current = &makeflags_string_posix;
2155         } else {
2156                 makeflags_string_current = &makeflags_string;
2157         }
2158         if (makeflags_string_current->buffer.start[1] == (int) nul_char) {
2159                 makeflags_value_saved =
2160                         GETNAME( makeflags_string_current->buffer.start + 1
2161                                , FIND_LENGTH
2162                                );
2163         } else {
2164                 if (makeflags_string_current->buffer.start[1] != (int) space_char) {
2165                         makeflags_value_saved =
2166                                 GETNAME( makeflags_string_current->buffer.start
2167                                        , FIND_LENGTH
2168                                        );
2169                 } else {
2170                         makeflags_value_saved =
2171                                 GETNAME( makeflags_string_current->buffer.start + 2
2172                                        , FIND_LENGTH
2173                                        );
2174                 }
2175         }
2176         (void) SETVAR( makeflags
2177                      , makeflags_value_saved
2178                      , false
2179                      );
2180         macro->body.macro.read_only = temp;
2181 
2182 /*
2183  *      Read command line "-f" arguments and ignore -c, g, j, K, M, m, O and o args.
2184  */
2185         save_do_not_exec_rule = do_not_exec_rule;
2186         do_not_exec_rule = false;
2187         if (read_trace_level > 0) {
2188                 trace_reader = true;
2189         }
2190 
2191         for (i = 1; i < argc; i++) {
2192                 if (argv[i] &&
2193                     (argv[i][0] == (int) hyphen_char) &&
2194                     (argv[i][1] == 'f') &&
2195                     (argv[i][2] == (int) nul_char)) {
2196                         argv[i] = NULL;         /* Remove -f */
2197                         if (i >= argc - 1) {
2198                                 fatal(catgets(catd, 1, 190, "No filename argument after -f flag"));
2199                         }
2200                         MBSTOWCS(wcs_buffer, argv[++i]);
2201                         primary_makefile = GETNAME(wcs_buffer, FIND_LENGTH);
2202                         (void) read_makefile(primary_makefile, true, true, true);
2203                         argv[i] = NULL;         /* Remove filename */
2204                         makefile_read = true;
2205                 } else if (argv[i] &&
2206                            (argv[i][0] == (int) hyphen_char) &&
2207                            (argv[i][1] == 'c' ||
2208                             argv[i][1] == 'g' ||
2209                             argv[i][1] == 'j' ||
2210                             argv[i][1] == 'K' ||
2211                             argv[i][1] == 'M' ||
2212                             argv[i][1] == 'm' ||
2213                             argv[i][1] == 'O' ||
2214                             argv[i][1] == 'o') &&
2215                            (argv[i][2] == (int) nul_char)) {
2216                         argv[i] = NULL;
2217                         argv[++i] = NULL;
2218                 }
2219         }
2220 
2221 /*
2222  *      If no command line "-f" args then look for "makefile", and then for
2223  *      "Makefile" if "makefile" isn't found.
2224  */
2225         if (!makefile_read) {
2226                 (void) read_dir(dot,
2227                                 (wchar_t *) NULL,
2228                                 (Property) NULL,
2229                                 (wchar_t *) NULL);
2230             if (!posix) {
2231                 if (makefile_name->stat.is_file) {
2232                         if (Makefile->stat.is_file) {
2233                                 warning(catgets(catd, 1, 310, "Both `makefile' and `Makefile' exist"));
2234                         }
2235                         primary_makefile = makefile_name;
2236                         makefile_read = read_makefile(makefile_name,
2237                                                       false,
2238                                                       false,
2239                                                       true);
2240                 }
2241                 if (!makefile_read &&
2242                     Makefile->stat.is_file) {
2243                         primary_makefile = Makefile;
2244                         makefile_read = read_makefile(Makefile,
2245                                                       false,
2246                                                       false,
2247                                                       true);
2248                 }
2249             } else {
2250 
2251                 enum sccs_stat save_m_has_sccs = NO_SCCS;
2252                 enum sccs_stat save_M_has_sccs = NO_SCCS;
2253 
2254                 if (makefile_name->stat.is_file) {
2255                         if (Makefile->stat.is_file) {
2256                                 warning(catgets(catd, 1, 191, "Both `makefile' and `Makefile' exist"));
2257                         }
2258                 }
2259                 if (makefile_name->stat.is_file) {
2260                         if (makefile_name->stat.has_sccs == NO_SCCS) {
2261                            primary_makefile = makefile_name;
2262                            makefile_read = read_makefile(makefile_name,
2263                                                       false,
2264                                                       false,
2265                                                       true);
2266                         } else {
2267                           save_m_has_sccs = makefile_name->stat.has_sccs;
2268                           makefile_name->stat.has_sccs = NO_SCCS;
2269                           primary_makefile = makefile_name;
2270                           makefile_read = read_makefile(makefile_name,
2271                                                       false,
2272                                                       false,
2273                                                       true);
2274                         }
2275                 }
2276                 if (!makefile_read &&
2277                     Makefile->stat.is_file) {
2278                         if (Makefile->stat.has_sccs == NO_SCCS) {
2279                            primary_makefile = Makefile;
2280                            makefile_read = read_makefile(Makefile,
2281                                                       false,
2282                                                       false,
2283                                                       true);
2284                         } else {
2285                           save_M_has_sccs = Makefile->stat.has_sccs;
2286                           Makefile->stat.has_sccs = NO_SCCS;
2287                           primary_makefile = Makefile;
2288                           makefile_read = read_makefile(Makefile,
2289                                                       false,
2290                                                       false,
2291                                                       true);
2292                         }
2293                 }
2294                 if (!makefile_read &&
2295                         makefile_name->stat.is_file) {
2296                            makefile_name->stat.has_sccs = save_m_has_sccs;
2297                            primary_makefile = makefile_name;
2298                            makefile_read = read_makefile(makefile_name,
2299                                                       false,
2300                                                       false,
2301                                                       true);
2302                 }
2303                 if (!makefile_read &&
2304                     Makefile->stat.is_file) {
2305                            Makefile->stat.has_sccs = save_M_has_sccs;
2306                            primary_makefile = Makefile;
2307                            makefile_read = read_makefile(Makefile,
2308                                                       false,
2309                                                       false,
2310                                                       true);
2311                 }
2312             }
2313         }
2314         do_not_exec_rule = save_do_not_exec_rule;
2315         allrules_read = makefile_read;
2316         trace_reader = false;
2317 
2318 /*
2319  *      Now get current value of MAKEFLAGS and compare it with
2320  *      the saved value we set before reading makefile.
2321  *      If they are different then MAKEFLAGS is subsequently set by
2322  *      makefile, just leave it there. Otherwise, if make mode
2323  *      is changed by using .POSIX target in makefile we need
2324  *      to correct MAKEFLAGS value.
2325  */
2326         Name mf_val = getvar(makeflags);
2327         if( (posix != is_xpg4)
2328          && (!strcmp(mf_val->string_mb, makeflags_value_saved->string_mb)))
2329         {
2330                 if (makeflags_string_posix.buffer.start[1] == (int) nul_char) {
2331                         (void) SETVAR(makeflags,
2332                                       GETNAME(makeflags_string_posix.buffer.start + 1,
2333                                               FIND_LENGTH),
2334                                       false);
2335                 } else {
2336                         if (makeflags_string_posix.buffer.start[1] != (int) space_char) {
2337                                 (void) SETVAR(makeflags,
2338                                               GETNAME(makeflags_string_posix.buffer.start,
2339                                                       FIND_LENGTH),
2340                                               false);
2341                         } else {
2342                                 (void) SETVAR(makeflags,
2343                                               GETNAME(makeflags_string_posix.buffer.start + 2,
2344                                                       FIND_LENGTH),
2345                                               false);
2346                         }
2347                 }
2348         }
2349 
2350         if (makeflags_string.free_after_use) {
2351                 retmem(makeflags_string.buffer.start);
2352         }
2353         if (makeflags_string_posix.free_after_use) {
2354                 retmem(makeflags_string_posix.buffer.start);
2355         }
2356         makeflags_string.buffer.start = NULL;
2357         makeflags_string_posix.buffer.start = NULL;
2358 
2359         if (posix) {
2360                 /*
2361                  * If the user did not redefine the ARFLAGS macro in the
2362                  * default makefile (make.rules), then we'd like to
2363                  * change the macro value of ARFLAGS to be in accordance
2364                  * with "POSIX" requirements.
2365                  */
2366                 MBSTOWCS(wcs_buffer, NOCATGETS("ARFLAGS"));
2367                 name = GETNAME(wcs_buffer, wslen(wcs_buffer));
2368                 macro = get_prop(name->prop, macro_prop);
2369                 if ((macro != NULL) && /* Maybe (macro == NULL) || ? */
2370                     (IS_EQUAL(macro->body.macro.value->string_mb,
2371                               NOCATGETS("rv")))) {
2372                         MBSTOWCS(wcs_buffer, NOCATGETS("-rv"));
2373                         value = GETNAME(wcs_buffer, wslen(wcs_buffer));
2374                         (void) SETVAR(name,
2375                                       value,
2376                                       false);
2377                 }
2378         }
2379 
2380         if (!posix && !svr4) {
2381                 set_sgs_support();
2382         }
2383 
2384 
2385 /*
2386  *      Make sure KEEP_STATE is in the environment if KEEP_STATE is on.
2387  */
2388         macro = get_prop(keep_state_name->prop, macro_prop);
2389         if ((macro != NULL) &&
2390             macro->body.macro.exported) {
2391                 keep_state = true;
2392         }
2393         if (keep_state) {
2394                 if (macro == NULL) {
2395                         macro = maybe_append_prop(keep_state_name,
2396                                                   macro_prop);
2397                 }
2398                 macro->body.macro.exported = true;
2399                 (void) SETVAR(keep_state_name,
2400                               empty_name,
2401                               false);
2402 
2403                 /*
2404                  *      Read state file
2405                  */
2406 
2407                 /* Before we read state, let's make sure we have
2408                 ** right state file.
2409                 */
2410                 /* just in case macro references are used in make_state file
2411                 ** name, we better expand them at this stage using expand_value.
2412                 */
2413                 INIT_STRING_FROM_STACK(dest, destbuffer);
2414                 expand_value(make_state, &dest, false);
2415 
2416                 make_state = GETNAME(dest.buffer.start, FIND_LENGTH);
2417 
2418                 if(!stat(make_state->string_mb, &make_state_stat)) {
2419                    if(!(make_state_stat.st_mode & S_IFREG) ) {
2420                         /* copy the make_state structure to the other
2421                         ** and then let make_state point to the new
2422                         ** one.
2423                         */
2424                       memcpy(&state_filename, make_state,sizeof(state_filename));
2425                       state_filename.string_mb = state_file_str_mb;
2426                 /* Just a kludge to avoid two slashes back to back */                   
2427                       if((make_state->hash.length == 1)&&
2428                                 (make_state->string_mb[0] == '/')) {
2429                          make_state->hash.length = 0;
2430                          make_state->string_mb[0] = '\0';
2431                       }
2432                       sprintf(state_file_str_mb,NOCATGETS("%s%s"),
2433                        make_state->string_mb,NOCATGETS("/.make.state"));
2434                       make_state = &state_filename;
2435                         /* adjust the length to reflect the appended string */
2436                       make_state->hash.length += 12;
2437                    }
2438                 } else { /* the file doesn't exist or no permission */
2439                    char tmp_path[MAXPATHLEN];
2440                    char *slashp;
2441 
2442                    if (slashp = strrchr(make_state->string_mb, '/')) {
2443                       strncpy(tmp_path, make_state->string_mb, 
2444                                 (slashp - make_state->string_mb));
2445                         tmp_path[slashp - make_state->string_mb]=0;
2446                       if(strlen(tmp_path)) {
2447                         if(stat(tmp_path, &make_state_stat)) {
2448                           warning(catgets(catd, 1, 192, "directory %s for .KEEP_STATE_FILE does not exist"),tmp_path);
2449                         }
2450                         if (access(tmp_path, F_OK) != 0) {
2451                           warning(catgets(catd, 1, 193, "can't access dir %s"),tmp_path);
2452                         }
2453                       }
2454                    }
2455                 }
2456                 if (report_dependencies_level != 1) {
2457                         Makefile_type   makefile_type_temp = makefile_type;
2458                         makefile_type = reading_statefile;
2459                         if (read_trace_level > 1) {
2460                                 trace_reader = true;
2461                         }
2462                         (void) read_simple_file(make_state,
2463                                                 false,
2464                                                 false,
2465                                                 false,
2466                                                 false,
2467                                                 false,
2468                                                 true);
2469                         trace_reader = false;
2470                         makefile_type = makefile_type_temp;
2471                 }
2472         }
2473 }
2474 
2475 /*
2476  * Scan the argv for options and "=" type args and make them readonly.
2477  */
2478 static void
2479 enter_argv_values(int argc, char *argv[], ASCII_Dyn_Array *makeflags_and_macro)
2480 {
2481         register char           *cp;
2482         register int            i;
2483         int                     length;
2484         register Name           name;
2485         int                     opt_separator = argc; 
2486         char                    tmp_char;
2487         wchar_t                 *tmp_wcs_buffer;
2488         register Name           value;
2489         Boolean                 append = false;
2490         Property                macro;
2491         struct stat             statbuf;
2492 
2493 
2494         /* Read argv options and "=" type args and make them readonly. */
2495         makefile_type = reading_nothing;
2496         for (i = 1; i < argc; ++i) {
2497                 append = false;
2498                 if (argv[i] == NULL) {
2499                         continue;
2500                 } else if (((argv[i][0] == '-') && (argv[i][1] == '-')) ||
2501                            ((argv[i][0] == (int) ' ') &&
2502                             (argv[i][1] == (int) '-') &&
2503                             (argv[i][2] == (int) ' ') &&
2504                             (argv[i][3] == (int) '-'))) {
2505                         argv[i] = NULL;
2506                         opt_separator = i;
2507                         continue;
2508                 } else if ((i < opt_separator) && (argv[i][0] == (int) hyphen_char)) {
2509                         switch (parse_command_option(argv[i][1])) {
2510                         case 1: /* -f seen */
2511                                 ++i;
2512                                 continue;
2513                         case 2: /* -c seen */
2514                                 if (argv[i+1] == NULL) {
2515                                         fatal(catgets(catd, 1, 194, "No dmake rcfile argument after -c flag"));
2516                                 }
2517                                 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_RCFILE"));
2518                                 name = GETNAME(wcs_buffer, FIND_LENGTH);
2519                                 break;
2520                         case 4: /* -g seen */
2521                                 if (argv[i+1] == NULL) {
2522                                         fatal(catgets(catd, 1, 195, "No dmake group argument after -g flag"));
2523                                 }
2524                                 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_GROUP"));
2525                                 name = GETNAME(wcs_buffer, FIND_LENGTH);
2526                                 break;
2527                         case 8: /* -j seen */
2528                                 if (argv[i+1] == NULL) {
2529                                         fatal(catgets(catd, 1, 196, "No dmake max jobs argument after -j flag"));
2530                                 }
2531                                 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MAX_JOBS"));
2532                                 name = GETNAME(wcs_buffer, FIND_LENGTH);
2533                                 break;
2534                         case 16: /* -M seen */
2535                                 if (argv[i+1] == NULL) {
2536                                         fatal(catgets(catd, 1, 323, "No pmake machinesfile argument after -M flag"));
2537                                 }
2538                                 MBSTOWCS(wcs_buffer, NOCATGETS("PMAKE_MACHINESFILE"));
2539                                 name = GETNAME(wcs_buffer, FIND_LENGTH);
2540                                 break;
2541                         case 32: /* -m seen */
2542                                 if (argv[i+1] == NULL) {
2543                                         fatal(catgets(catd, 1, 197, "No dmake mode argument after -m flag"));
2544                                 }
2545                                 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE"));
2546                                 name = GETNAME(wcs_buffer, FIND_LENGTH);
2547                                 break;
2548                         case 128: /* -O seen */
2549                                 if (argv[i+1] == NULL) {
2550                                         fatal(catgets(catd, 1, 287, "No file descriptor argument after -O flag"));
2551                                 }
2552                                 mtool_msgs_fd = atoi(argv[i+1]);
2553                                 /* find out if mtool_msgs_fd is a valid file descriptor */
2554                                 if (fstat(mtool_msgs_fd, &statbuf) < 0) {
2555                                         fatal(catgets(catd, 1, 355, "Invalid file descriptor %d after -O flag"), mtool_msgs_fd);
2556                                 }
2557                                 argv[i] = NULL;
2558                                 argv[i+1] = NULL;
2559                                 continue;
2560                         case 256: /* -K seen */
2561                                 if (argv[i+1] == NULL) {
2562                                         fatal(catgets(catd, 1, 288, "No makestate filename argument after -K flag"));
2563                                 }
2564                                 MBSTOWCS(wcs_buffer, argv[i+1]);
2565                                 make_state = GETNAME(wcs_buffer, FIND_LENGTH);
2566                                 keep_state = true;
2567                                 argv[i] = NULL;
2568                                 argv[i+1] = NULL;
2569                                 continue;
2570                         case 512:       /* -o seen */
2571                                 if (argv[i+1] == NULL) {
2572                                         fatal(catgets(catd, 1, 312, "No dmake output dir argument after -o flag"));
2573                                 }
2574                                 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_ODIR"));
2575                                 name = GETNAME(wcs_buffer, FIND_LENGTH);
2576                                 break;
2577                         case 1024: /* -x seen */
2578                                 if (argv[i+1] == NULL) {
2579                                         fatal(catgets(catd, 1, 351, "No argument after -x flag"));
2580                                 }
2581                                 length = strlen( NOCATGETS("SUN_MAKE_COMPAT_MODE="));
2582                                 if (strncmp(argv[i+1], NOCATGETS("SUN_MAKE_COMPAT_MODE="), length) == 0) {
2583                                         argv[i+1] = &argv[i+1][length];
2584                                         MBSTOWCS(wcs_buffer, NOCATGETS("SUN_MAKE_COMPAT_MODE"));
2585                                         name = GETNAME(wcs_buffer, FIND_LENGTH);
2586                                         dmake_compat_mode_specified = dmake_add_mode_specified;
2587                                         break;
2588                                 }
2589                                 length = strlen( NOCATGETS("DMAKE_OUTPUT_MODE="));
2590                                 if (strncmp(argv[i+1], NOCATGETS("DMAKE_OUTPUT_MODE="), length) == 0) {
2591                                         argv[i+1] = &argv[i+1][length];
2592                                         MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_OUTPUT_MODE"));
2593                                         name = GETNAME(wcs_buffer, FIND_LENGTH);
2594                                         dmake_output_mode_specified = dmake_add_mode_specified;
2595                                 } else {
2596                                         warning(catgets(catd, 1, 354, "Unknown argument `%s' after -x flag (ignored)"),
2597                                               argv[i+1]);
2598                                         argv[i] = argv[i + 1] = NULL;
2599                                         continue;
2600                                 }
2601                                 break;
2602                         default: /* Shouldn't reach here */
2603                                 argv[i] = NULL;
2604                                 continue;
2605                         }
2606                         argv[i] = NULL;
2607                         if (i == (argc - 1)) {
2608                                 break;
2609                         }
2610                         if ((length = strlen(argv[i+1])) >= MAXPATHLEN) {
2611                                 tmp_wcs_buffer = ALLOC_WC(length + 1);
2612                                 (void) mbstowcs(tmp_wcs_buffer, argv[i+1], length + 1);
2613                                 value = GETNAME(tmp_wcs_buffer, FIND_LENGTH);
2614                                 retmem(tmp_wcs_buffer);
2615                         } else {
2616                                 MBSTOWCS(wcs_buffer, argv[i+1]);
2617                                 value = GETNAME(wcs_buffer, FIND_LENGTH);
2618                         }
2619                         argv[i+1] = NULL;
2620                 } else if ((cp = strchr(argv[i], (int) equal_char)) != NULL) {
2621 /* 
2622  * Combine all macro in dynamic array
2623  */
2624                         if(*(cp-1) == (int) plus_char)
2625                         {
2626                                 if(isspace(*(cp-2))) {
2627                                         append = true;
2628                                         cp--;
2629                                 }
2630                         }
2631                         if(!append)
2632                                 append_or_replace_macro_in_dyn_array(makeflags_and_macro, argv[i]);
2633 
2634                         while (isspace(*(cp-1))) {
2635                                 cp--;
2636                         }
2637                         tmp_char = *cp;
2638                         *cp = (int) nul_char;
2639                         MBSTOWCS(wcs_buffer, argv[i]);
2640                         *cp = tmp_char;
2641                         name = GETNAME(wcs_buffer, wslen(wcs_buffer));
2642                         while (*cp != (int) equal_char) {
2643                                 cp++;
2644                         }
2645                         cp++;
2646                         while (isspace(*cp) && (*cp != (int) nul_char)) {
2647                                 cp++;
2648                         }
2649                         if ((length = strlen(cp)) >= MAXPATHLEN) {
2650                                 tmp_wcs_buffer = ALLOC_WC(length + 1);
2651                                 (void) mbstowcs(tmp_wcs_buffer, cp, length + 1);
2652                                 value = GETNAME(tmp_wcs_buffer, FIND_LENGTH);
2653                                 retmem(tmp_wcs_buffer);
2654                         } else {
2655                                 MBSTOWCS(wcs_buffer, cp);
2656                                 value = GETNAME(wcs_buffer, FIND_LENGTH);
2657                         }
2658                         argv[i] = NULL;
2659                 } else {
2660                         /* Illegal MAKEFLAGS argument */
2661                         continue;
2662                 }
2663                 if(append) {
2664                         setvar_append(name, value);
2665                         append = false;
2666                 } else {
2667                         macro = maybe_append_prop(name, macro_prop);
2668                         macro->body.macro.exported = true;
2669                         SETVAR(name, value, false)->body.macro.read_only = true;
2670                 }
2671         }
2672 }
2673 
2674 /*
2675  * Append the DMake option and value to the MAKEFLAGS string.
2676  */
2677 static void
2678 append_makeflags_string(Name name, register String makeflags_string)
2679 {
2680         const char      *option;
2681 
2682         if (strcmp(name->string_mb, NOCATGETS("DMAKE_GROUP")) == 0) {
2683                 option = NOCATGETS(" -g ");
2684         } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_MAX_JOBS")) == 0) {
2685                 option = NOCATGETS(" -j ");
2686         } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_MODE")) == 0) {
2687                 option = NOCATGETS(" -m ");
2688         } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_ODIR")) == 0) {
2689                 option = NOCATGETS(" -o ");
2690         } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_RCFILE")) == 0) {
2691                 option = NOCATGETS(" -c ");
2692         } else if (strcmp(name->string_mb, NOCATGETS("PMAKE_MACHINESFILE")) == 0) {
2693                 option = NOCATGETS(" -M ");
2694         } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_OUTPUT_MODE")) == 0) {
2695                 option = NOCATGETS(" -x DMAKE_OUTPUT_MODE=");
2696         } else if (strcmp(name->string_mb, NOCATGETS("SUN_MAKE_COMPAT_MODE")) == 0) {
2697                 option = NOCATGETS(" -x SUN_MAKE_COMPAT_MODE=");
2698         } else {
2699                 fatal(catgets(catd, 1, 289, "Internal error: name not recognized in append_makeflags_string()"));
2700         }
2701         Property prop = maybe_append_prop(name, macro_prop);
2702         if( prop == 0 || prop->body.macro.value == 0 ||
2703             prop->body.macro.value->string_mb == 0 ) {
2704                 return;
2705         }
2706         char mbs_value[MAXPATHLEN + 100];
2707         strcpy(mbs_value, option);
2708         strcat(mbs_value, prop->body.macro.value->string_mb);
2709         MBSTOWCS(wcs_buffer, mbs_value);
2710         append_string(wcs_buffer, makeflags_string, FIND_LENGTH);
2711 }
2712 
2713 /*
2714  *      read_environment(read_only)
2715  *
2716  *      This routine reads the process environment when make starts and enters
2717  *      it as make macros. The environment variable SHELL is ignored.
2718  *
2719  *      Parameters:
2720  *              read_only       Should we make env vars read only?
2721  *
2722  *      Global variables used:
2723  *              report_pwd      Set if this make was started by other make
2724  */
2725 static void
2726 read_environment(Boolean read_only)
2727 {
2728         register char           **environment;
2729         int                     length;
2730         wchar_t                 *tmp_wcs_buffer;
2731         Boolean                 alloced_tmp_wcs_buffer = false;
2732         register wchar_t        *name;
2733         register wchar_t        *value;
2734         register Name           macro;
2735         Property                val;
2736         Boolean                 read_only_saved;
2737 
2738         reading_environment = true;
2739         environment = environ;
2740         for (; *environment; environment++) {
2741                 read_only_saved = read_only;
2742                 if ((length = strlen(*environment)) >= MAXPATHLEN) {
2743                         tmp_wcs_buffer = ALLOC_WC(length + 1);
2744                         alloced_tmp_wcs_buffer = true;
2745                         (void) mbstowcs(tmp_wcs_buffer, *environment, length + 1);
2746                         name = tmp_wcs_buffer;
2747                 } else {
2748                         MBSTOWCS(wcs_buffer, *environment);
2749                         name = wcs_buffer;
2750                 }
2751                 value = (wchar_t *) wschr(name, (int) equal_char);
2752 
2753                 /*
2754                  * Looks like there's a bug in the system, but sometimes
2755                  * you can get blank lines in *environment.
2756                  */
2757                 if (!value) {
2758                         continue;
2759                 }
2760                 MBSTOWCS(wcs_buffer2, NOCATGETS("SHELL="));
2761                 if (IS_WEQUALN(name, wcs_buffer2, wslen(wcs_buffer2))) {
2762                         continue;
2763                 }
2764                 MBSTOWCS(wcs_buffer2, NOCATGETS("MAKEFLAGS="));
2765                 if (IS_WEQUALN(name, wcs_buffer2, wslen(wcs_buffer2))) {
2766                         report_pwd = true;
2767                         /*
2768                          * In POSIX mode we do not want MAKEFLAGS to be readonly.
2769                          * If the MAKEFLAGS macro is subsequently set by the makefile,
2770                          * it replaces the MAKEFLAGS variable currently found in the
2771                          * environment.
2772                          * See Assertion 50 in section 6.2.5.3 of standard P1003.3.2/D8.
2773                          */
2774                         if(posix) {
2775                                 read_only_saved = false;
2776                         }
2777                 }
2778 
2779                 /*
2780                  * We ignore SUNPRO_DEPENDENCIES. This environment variable is
2781                  * set by make and read by cpp which then writes info to
2782                  * .make.dependency.xxx.  When make is invoked by another make
2783                  * (recursive make), we don't want to read this because then
2784                  * the child make will end up writing to the parent
2785                  * directory's .make.state and clobbering them.
2786                  */
2787                 MBSTOWCS(wcs_buffer2, NOCATGETS("SUNPRO_DEPENDENCIES"));
2788                 if (IS_WEQUALN(name, wcs_buffer2, wslen(wcs_buffer2))) {
2789                         continue;
2790                 }
2791 
2792                 macro = GETNAME(name, value - name);
2793                 maybe_append_prop(macro, macro_prop)->body.macro.exported =
2794                   true;
2795                 if ((value == NULL) || ((value + 1)[0] == (int) nul_char)) {
2796                         val = setvar_daemon(macro,
2797                                             (Name) NULL,
2798                                             false, no_daemon, false, debug_level);
2799                 } else {
2800                         val = setvar_daemon(macro,
2801                                             GETNAME(value + 1, FIND_LENGTH),
2802                                             false, no_daemon, false, debug_level);
2803                 }
2804                 val->body.macro.read_only = read_only_saved;
2805                 if (alloced_tmp_wcs_buffer) {
2806                         retmem(tmp_wcs_buffer);
2807                         alloced_tmp_wcs_buffer = false;
2808                 }
2809         }
2810         reading_environment = false;
2811 }
2812 
2813 /*
2814  *      read_makefile(makefile, complain, must_exist, report_file)
2815  *
2816  *      Read one makefile and check the result
2817  *
2818  *      Return value:
2819  *                              false is the read failed
2820  *
2821  *      Parameters:
2822  *              makefile        The file to read
2823  *              complain        Passed thru to read_simple_file()
2824  *              must_exist      Passed thru to read_simple_file()
2825  *              report_file     Passed thru to read_simple_file()
2826  *
2827  *      Global variables used:
2828  *              makefile_type   Set to indicate we are reading main file
2829  *              recursion_level Initialized
2830  */
2831 static Boolean
2832 read_makefile(register Name makefile, Boolean complain, Boolean must_exist, Boolean report_file)
2833 {
2834         Boolean                 b;
2835         
2836         makefile_type = reading_makefile;
2837         recursion_level = 0;
2838         reading_dependencies = true;
2839         b = read_simple_file(makefile, true, true, complain,
2840                              must_exist, report_file, false);
2841         reading_dependencies = false;
2842         return b;
2843 }
2844 
2845 /*
2846  *      make_targets(argc, argv, parallel_flag)
2847  *
2848  *      Call doname on the specified targets
2849  *
2850  *      Parameters:
2851  *              argc            You know what this is
2852  *              argv            You know what this is
2853  *              parallel_flag   True if building in parallel
2854  *
2855  *      Global variables used:
2856  *              build_failed_seen Used to generated message after failed -k
2857  *              commands_done   Used to generate message "Up to date"
2858  *              default_target_to_build First proper target in makefile
2859  *              init            The Name ".INIT", use to run command
2860  *              parallel        Global parallel building flag
2861  *              quest           make -q, suppresses messages
2862  *              recursion_level Initialized, used for tracing
2863  *              report_dependencies make -P, regroves whole process
2864  */
2865 static void
2866 make_targets(int argc, char **argv, Boolean parallel_flag)
2867 {
2868         int                     i;
2869         char                    *cp;
2870         Doname                  result;
2871         register Boolean        target_to_make_found = false;
2872 
2873         (void) doname(init, true, true);
2874         recursion_level = 1;
2875         parallel = parallel_flag;
2876 /*
2877  *      make remaining args
2878  */
2879 #ifdef TEAMWARE_MAKE_CMN
2880 /*
2881         if ((report_dependencies_level == 0) && parallel) {
2882  */
2883         if (parallel) {
2884                 /*
2885                  * If building targets in parallel, start all of the
2886                  * remaining args to build in parallel.
2887                  */
2888                 for (i = 1; i < argc; i++) {
2889                         if ((cp = argv[i]) != NULL) {
2890                                 commands_done = false;
2891                                 if ((cp[0] == (int) period_char) &&
2892                                     (cp[1] == (int) slash_char)) {
2893                                         cp += 2;
2894                                 }
2895                                  if((cp[0] == (int) ' ') &&
2896                                     (cp[1] == (int) '-') &&
2897                                     (cp[2] == (int) ' ') &&
2898                                     (cp[3] == (int) '-')) {
2899                                     argv[i] = NULL;
2900                                         continue;
2901                                 }
2902                                 MBSTOWCS(wcs_buffer, cp);
2903                                 //default_target_to_build = GETNAME(wcs_buffer,
2904                                 //                                FIND_LENGTH);
2905                                 default_target_to_build = normalize_name(wcs_buffer,
2906                                                                   wslen(wcs_buffer));
2907                                 if (default_target_to_build == wait_name) {
2908                                         if (parallel_process_cnt > 0) {
2909                                                 finish_running();
2910                                         }
2911                                         continue;
2912                                 }
2913                                 top_level_target = get_wstring(default_target_to_build->string_mb);
2914                                 /*
2915                                  * If we can't execute the current target in
2916                                  * parallel, hold off the target processing
2917                                  * to preserve the order of the targets as they appeared
2918                                  * in command line.
2919                                  */
2920                                 if (!parallel_ok(default_target_to_build, false)
2921                                                 && parallel_process_cnt > 0) {
2922                                         finish_running();
2923                                 }
2924                                 result = doname_check(default_target_to_build,
2925                                                       true,
2926                                                       false,
2927                                                       false);
2928                                 gather_recursive_deps();
2929                                 if (/* !commands_done && */
2930                                     (result == build_ok) &&
2931                                     !quest &&
2932                                     (report_dependencies_level == 0) /*  &&
2933                                     (exists(default_target_to_build) > file_doesnt_exist)  */) {
2934                                         if (posix) {
2935                                                 if (!commands_done) {
2936                                                         (void) printf(catgets(catd, 1, 293, "`%s' is updated.\n"),
2937                                                                       default_target_to_build->string_mb);
2938                                                 } else {
2939                                                         if (no_action_was_taken) {
2940                                                                 (void) printf(catgets(catd, 1, 294, "`%s': no action was taken.\n"),
2941                                                                               default_target_to_build->string_mb);
2942                                                         }
2943                                                 }
2944                                         } else {
2945                                                 default_target_to_build->stat.time = file_no_time;
2946                                                 if (!commands_done &&
2947                                                     (exists(default_target_to_build) > file_doesnt_exist)) {
2948                                                         (void) printf(catgets(catd, 1, 295, "`%s' is up to date.\n"),
2949                                                                       default_target_to_build->string_mb);
2950                                                 }
2951                                         }
2952                                 }
2953                         }
2954                 }
2955                 /* Now wait for all of the targets to finish running */
2956                 finish_running();
2957                 //              setjmp(jmpbuffer);
2958                 
2959         }
2960 #endif
2961         for (i = 1; i < argc; i++) {
2962                 if ((cp = argv[i]) != NULL) {
2963                         target_to_make_found = true;
2964                         if ((cp[0] == (int) period_char) &&
2965                             (cp[1] == (int) slash_char)) {
2966                                 cp += 2;
2967                         }
2968                                  if((cp[0] == (int) ' ') &&
2969                                     (cp[1] == (int) '-') &&
2970                                     (cp[2] == (int) ' ') &&
2971                                     (cp[3] == (int) '-')) {
2972                                     argv[i] = NULL;
2973                                         continue;
2974                                 }
2975                         MBSTOWCS(wcs_buffer, cp);
2976                         default_target_to_build = normalize_name(wcs_buffer, wslen(wcs_buffer));
2977                         top_level_target = get_wstring(default_target_to_build->string_mb);
2978                         report_recursion(default_target_to_build);
2979                         commands_done = false;
2980                         if (parallel) {
2981                                 result = (Doname) default_target_to_build->state;
2982                         } else {
2983                                 result = doname_check(default_target_to_build,
2984                                                       true,
2985                                                       false,
2986                                                       false);
2987                         }
2988                         gather_recursive_deps();
2989                         if (build_failed_seen) {
2990                                 build_failed_ever_seen = true;
2991                                 warning(catgets(catd, 1, 200, "Target `%s' not remade because of errors"),
2992                                         default_target_to_build->string_mb);
2993                         }
2994                         build_failed_seen = false;
2995                         if (report_dependencies_level > 0) {
2996                                 print_dependencies(default_target_to_build,
2997                                                    get_prop(default_target_to_build->prop,
2998                                                             line_prop));
2999                         }
3000                         default_target_to_build->stat.time =
3001                           file_no_time;
3002                         if (default_target_to_build->colon_splits > 0) {
3003                                 default_target_to_build->state =
3004                                   build_dont_know;
3005                         }
3006                         if (!parallel &&
3007                             /* !commands_done && */
3008                             (result == build_ok) &&
3009                             !quest &&
3010                             (report_dependencies_level == 0) /*  &&
3011                             (exists(default_target_to_build) > file_doesnt_exist)  */) {
3012                                 if (posix) {
3013                                         if (!commands_done) {
3014                                                 (void) printf(catgets(catd, 1, 296, "`%s' is updated.\n"),
3015                                                               default_target_to_build->string_mb);
3016                                         } else {
3017                                                 if (no_action_was_taken) {
3018                                                         (void) printf(catgets(catd, 1, 297, "`%s': no action was taken.\n"),
3019                                                                       default_target_to_build->string_mb);
3020                                                 }
3021                                         }
3022                                 } else {
3023                                         if (!commands_done &&
3024                                             (exists(default_target_to_build) > file_doesnt_exist)) {
3025                                                 (void) printf(catgets(catd, 1, 298, "`%s' is up to date.\n"),
3026                                                               default_target_to_build->string_mb);
3027                                         }
3028                                 }
3029                         }
3030                 }
3031         }
3032 
3033 /*
3034  *      If no file arguments have been encountered,
3035  *      make the first name encountered that doesnt start with a dot
3036  */
3037         if (!target_to_make_found) {
3038                 if (default_target_to_build == NULL) {
3039                         fatal(catgets(catd, 1, 202, "No arguments to build"));
3040                 }
3041                 commands_done = false;
3042                 top_level_target = get_wstring(default_target_to_build->string_mb);
3043                 report_recursion(default_target_to_build);
3044 
3045 
3046                 if (getenv(NOCATGETS("SPRO_EXPAND_ERRORS"))){
3047                         (void) printf(NOCATGETS("::(%s)\n"),
3048                                       default_target_to_build->string_mb);
3049                 }
3050 
3051 
3052 #ifdef TEAMWARE_MAKE_CMN
3053                 result = doname_parallel(default_target_to_build, true, false);
3054 #else
3055                 result = doname_check(default_target_to_build, true,
3056                                       false, false);
3057 #endif
3058                 gather_recursive_deps();
3059                 if (build_failed_seen) {
3060                         build_failed_ever_seen = true;
3061                         warning(catgets(catd, 1, 203, "Target `%s' not remade because of errors"),
3062                                 default_target_to_build->string_mb);
3063                 }
3064                 build_failed_seen = false;
3065                 if (report_dependencies_level > 0) {
3066                         print_dependencies(default_target_to_build,
3067                                            get_prop(default_target_to_build->
3068                                                     prop,
3069                                                     line_prop));
3070                 }
3071                 default_target_to_build->stat.time = file_no_time;
3072                 if (default_target_to_build->colon_splits > 0) {
3073                         default_target_to_build->state = build_dont_know;
3074                 }
3075                 if (/* !commands_done && */
3076                     (result == build_ok) &&
3077                     !quest &&
3078                     (report_dependencies_level == 0) /*  &&
3079                     (exists(default_target_to_build) > file_doesnt_exist)  */) {
3080                         if (posix) {
3081                                 if (!commands_done) {
3082                                         (void) printf(catgets(catd, 1, 299, "`%s' is updated.\n"),
3083                                                       default_target_to_build->string_mb);
3084                                 } else {
3085                                         if (no_action_was_taken) {
3086                                                 (void) printf(catgets(catd, 1, 300, "`%s': no action was taken.\n"),
3087                                                               default_target_to_build->string_mb);
3088                                         }
3089                                 }
3090                         } else {
3091                                 if (!commands_done &&
3092                                     (exists(default_target_to_build) > file_doesnt_exist)) {
3093                                         (void) printf(catgets(catd, 1, 301, "`%s' is up to date.\n"),
3094                                                       default_target_to_build->string_mb);
3095                                 }
3096                         }
3097                 }
3098         }
3099 }
3100 
3101 /*
3102  *      report_recursion(target)
3103  *
3104  *      If this is a recursive make and the parent make has KEEP_STATE on
3105  *      this routine reports the dependency to the parent make
3106  *
3107  *      Parameters:
3108  *              target          Target to report
3109  *
3110  *      Global variables used:
3111  *              makefiles_used          List of makefiles read
3112  *              recursive_name          The Name ".RECURSIVE", printed
3113  *              report_dependency       dwight
3114  */
3115 static void
3116 report_recursion(register Name target)
3117 {
3118         register FILE           *report_file = get_report_file();
3119 
3120         if ((report_file == NULL) || (report_file == (FILE*)-1)) {
3121                 return;
3122         }
3123         if (primary_makefile == NULL) {
3124                 /*
3125                  * This can happen when there is no makefile and
3126                  * only implicit rules are being used.
3127                  */
3128                 return;
3129         }
3130         (void) fprintf(report_file,
3131                        "%s: %s ",
3132                        get_target_being_reported_for(),
3133                        recursive_name->string_mb);
3134         report_dependency(get_current_path());
3135         report_dependency(target->string_mb);
3136         report_dependency(primary_makefile->string_mb);
3137         (void) fprintf(report_file, "\n");
3138 }
3139 
3140 /* Next function "append_or_replace_macro_in_dyn_array" must be in "misc.cc". */
3141 /* NIKMOL */
3142 extern void
3143 append_or_replace_macro_in_dyn_array(ASCII_Dyn_Array *Ar, char *macro)
3144 {
3145         register char   *cp0;   /* work pointer in macro */
3146         register char   *cp1;   /* work pointer in array */
3147         register char   *cp2;   /* work pointer in array */
3148         register char   *cp3;   /* work pointer in array */
3149         register char   *name;  /* macro name */
3150         register char   *value; /* macro value */
3151         register int    len_array;
3152         register int    len_macro;
3153 
3154         char * esc_value = NULL;
3155         int esc_len;
3156 
3157         if (!(len_macro = strlen(macro))) return;
3158         name = macro;
3159         while (isspace(*(name))) {
3160                 name++;
3161         }
3162         if (!(value = strchr(name, (int) equal_char))) {
3163                 /* no '=' in macro */
3164                 goto ERROR_MACRO;
3165         }
3166         cp0 = value;
3167         value++;
3168         while (isspace(*(value))) {
3169                 value++;
3170         }
3171         while (isspace(*(cp0-1))) {
3172                 cp0--;
3173         }
3174         if (cp0 <= name) goto ERROR_MACRO; /* no name */
3175         if (!(Ar->size)) goto ALLOC_ARRAY;
3176         cp1 = Ar->start;
3177 
3178 LOOK_FOR_NAME:
3179         if (!(cp1 = strchr(cp1, name[0]))) goto APPEND_MACRO;
3180         if (!(cp2 = strchr(cp1, (int) equal_char))) goto APPEND_MACRO;
3181         if (strncmp(cp1, name, (size_t)(cp0-name))) {
3182                 /* another name */
3183                 cp1++;
3184                 goto LOOK_FOR_NAME;
3185         }
3186         if (cp1 != Ar->start) {
3187                 if (!isspace(*(cp1-1))) {
3188                         /* another name */
3189                         cp1++;
3190                         goto LOOK_FOR_NAME;
3191                 }
3192         }
3193         for (cp3 = cp1 + (cp0-name); cp3 < cp2; cp3++) {
3194                 if (isspace(*cp3)) continue;
3195                 /* else: another name */
3196                 cp1++;
3197                 goto LOOK_FOR_NAME;
3198         }
3199         /* Look for the next macro name in array */
3200         cp3 = cp2+1;
3201         if (*cp3 != (int) doublequote_char) {
3202                 /* internal error */
3203                 goto ERROR_MACRO;
3204         }
3205         if (!(cp3 = strchr(cp3+1, (int) doublequote_char))) {
3206                 /* internal error */
3207                 goto ERROR_MACRO;
3208         }
3209         cp3++;
3210         while (isspace(*cp3)) {
3211                 cp3++;
3212         }
3213         
3214         cp2 = cp1;  /* remove old macro */
3215         if ((*cp3) && (cp3 < Ar->start + Ar->size)) {
3216                 for (; cp3 < Ar->start + Ar->size; cp3++) {
3217                         *cp2++ = *cp3;
3218                 }
3219         } 
3220         for (; cp2 < Ar->start + Ar->size; cp2++) {
3221                 *cp2 = 0;
3222         }
3223         if (*cp1) {
3224                 /* check next name */
3225                 goto LOOK_FOR_NAME;
3226         }
3227         goto APPEND_MACRO;
3228 
3229 ALLOC_ARRAY:
3230         if (Ar->size) {
3231                 cp1 = Ar->start;
3232         } else {
3233                 cp1 = 0;
3234         }
3235         Ar->size += 128;
3236         Ar->start = getmem(Ar->size);
3237         for (len_array=0; len_array < Ar->size; len_array++) {
3238                 Ar->start[len_array] = 0;
3239         }
3240         if (cp1) {
3241                 strcpy(Ar->start, cp1);
3242                 retmem((wchar_t *) cp1);
3243         }
3244 
3245 APPEND_MACRO:
3246         len_array = strlen(Ar->start);
3247         esc_value = (char*)malloc(strlen(value)*2 + 1);
3248         quote_str(value, esc_value);
3249         esc_len = strlen(esc_value) - strlen(value);
3250         if (len_array + len_macro + esc_len + 5 >= Ar->size) goto  ALLOC_ARRAY;
3251         strcat(Ar->start, " ");
3252         strncat(Ar->start, name, cp0-name);
3253         strcat(Ar->start, "=");
3254         strncat(Ar->start, esc_value, strlen(esc_value));
3255         free(esc_value);
3256         return;
3257 ERROR_MACRO:    
3258         /* Macro without '=' or with invalid left/right part */
3259         return;
3260 }
3261 
3262 #ifdef TEAMWARE_MAKE_CMN
3263 /*
3264  * This function, if registered w/ avo_cli_get_license(), will be called
3265  * if the application is about to exit because:
3266  *   1) there has been certain unrecoverable error(s) that cause the
3267  *      application to exit immediately.
3268  *   2) the user has lost a license while the application is running.
3269  */
3270 extern "C" void
3271 dmake_exit_callback(void)
3272 {
3273         fatal(catgets(catd, 1, 306, "can not get a license, exiting..."));
3274         exit(1);
3275 }
3276 
3277 /*
3278  * This function, if registered w/ avo_cli_get_license(), will be called
3279  * if the application can not get a license.
3280  */
3281 extern "C" void
3282 dmake_message_callback(char *err_msg)
3283 {
3284         static Boolean  first = true;
3285 
3286         if (!first) {
3287                 return;
3288         }
3289         first = false;
3290         if ((!list_all_targets) &&
3291             (report_dependencies_level == 0) &&
3292             (dmake_mode_type != serial_mode)) {
3293                 warning(catgets(catd, 1, 313, "can not get a TeamWare license, defaulting to serial mode..."));
3294         }
3295 }
3296 #endif
3297 
3298 
3299 static void
3300 report_dir_enter_leave(Boolean entering)
3301 {
3302         char    rcwd[MAXPATHLEN];
3303 static  char *  mlev = NULL;
3304         char *  make_level_str = NULL;
3305         int     make_level_val = 0;
3306 
3307         make_level_str = getenv(NOCATGETS("MAKELEVEL"));
3308         if(make_level_str) {
3309                 make_level_val = atoi(make_level_str);
3310         }
3311         if(mlev == NULL) {
3312                 mlev = (char*) malloc(MAXPATHLEN);
3313         }
3314         if(entering) {
3315                 sprintf(mlev, NOCATGETS("MAKELEVEL=%d"), make_level_val + 1);
3316         } else {
3317                 make_level_val--;
3318                 sprintf(mlev, NOCATGETS("MAKELEVEL=%d"), make_level_val);
3319         }
3320         putenv(mlev);
3321 
3322         if(report_cwd) {
3323                 if(make_level_val <= 0) {
3324                         if(entering) {
3325 #ifdef TEAMWARE_MAKE_CMN
3326                                 sprintf( rcwd
3327                                        , catgets(catd, 1, 329, "dmake: Entering directory `%s'\n")
3328                                        , get_current_path());
3329 #else
3330                                 sprintf( rcwd
3331                                        , catgets(catd, 1, 330, "make: Entering directory `%s'\n")
3332                                        , get_current_path());
3333 #endif
3334                         } else {
3335 #ifdef TEAMWARE_MAKE_CMN
3336                                 sprintf( rcwd
3337                                        , catgets(catd, 1, 331, "dmake: Leaving directory `%s'\n")
3338                                        , get_current_path());
3339 #else
3340                                 sprintf( rcwd
3341                                        , catgets(catd, 1, 332, "make: Leaving directory `%s'\n")
3342                                        , get_current_path());
3343 #endif
3344                         }
3345                 } else {
3346                         if(entering) {
3347 #ifdef TEAMWARE_MAKE_CMN
3348                                 sprintf( rcwd
3349                                        , catgets(catd, 1, 333, "dmake[%d]: Entering directory `%s'\n")
3350                                        , make_level_val, get_current_path());
3351 #else
3352                                 sprintf( rcwd
3353                                        , catgets(catd, 1, 334, "make[%d]: Entering directory `%s'\n")
3354                                        , make_level_val, get_current_path());
3355 #endif
3356                         } else {
3357 #ifdef TEAMWARE_MAKE_CMN
3358                                 sprintf( rcwd
3359                                        , catgets(catd, 1, 335, "dmake[%d]: Leaving directory `%s'\n")
3360                                        , make_level_val, get_current_path());
3361 #else
3362                                 sprintf( rcwd
3363                                        , catgets(catd, 1, 336, "make[%d]: Leaving directory `%s'\n")
3364                                        , make_level_val, get_current_path());
3365 #endif
3366                         }
3367                 }
3368                 printf(NOCATGETS("%s"), rcwd);
3369         }
3370 }