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