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