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