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