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