xref: /illumos-gate/usr/src/cmd/make/bin/misc.cc (revision 10d63b7db37a83b39c7f511cf9426c9d03ea0760)
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 2005 Sun Microsystems, Inc. All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  *	misc.cc
28  *
29  *	This file contains various unclassified routines. Some main groups:
30  *		getname
31  *		Memory allocation
32  *		String handling
33  *		Property handling
34  *		Error message handling
35  *		Make internal state dumping
36  *		main routine support
37  */
38 
39 /*
40  * Included files
41  */
42 #include <errno.h>
43 #include <mk/defs.h>
44 #include <mksh/macro.h>		/* SETVAR() */
45 #include <mksh/misc.h>		/* enable_interrupt() */
46 #include <stdarg.h>		/* va_list, va_start(), va_end() */
47 #include <vroot/report.h>	/* SUNPRO_DEPENDENCIES */
48 #include <libintl.h>
49 
50 extern void job_adjust_fini();
51 
52 /*
53  * Defined macros
54  */
55 
56 /*
57  * typedefs & structs
58  */
59 
60 /*
61  * Static variables
62  */
63 
64 /*
65  * File table of contents
66  */
67 static	void		print_rule(register Name target);
68 static	void		print_target_n_deps(register Name target);
69 
70 /*****************************************
71  *
72  *	getname
73  */
74 
75 /*****************************************
76  *
77  *	Memory allocation
78  */
79 
80 /*
81  *	free_chain()
82  *
83  *	frees a chain of Name_vector's
84  *
85  *	Parameters:
86  *		ptr		Pointer to the first element in the chain
87  *				to be freed.
88  *
89  *	Global variables used:
90  */
91 void
92 free_chain(Name_vector ptr)
93 {
94 	if (ptr != NULL) {
95 		if (ptr->next != NULL) {
96 			free_chain(ptr->next);
97 		}
98 		free((char *) ptr);
99 	}
100 }
101 
102 /*****************************************
103  *
104  *	String manipulation
105  */
106 
107 /*****************************************
108  *
109  *	Nameblock property handling
110  */
111 
112 /*****************************************
113  *
114  *	Error message handling
115  */
116 
117 /*
118  *	fatal(format, args...)
119  *
120  *	Print a message and die
121  *
122  *	Parameters:
123  *		format		printf type format string
124  *		args		Arguments to match the format
125  *
126  *	Global variables used:
127  *		fatal_in_progress Indicates if this is a recursive call
128  *		parallel_process_cnt Do we need to wait for anything?
129  *		report_pwd	Should we report the current path?
130  */
131 /*VARARGS*/
132 void
133 fatal(const char *message, ...)
134 {
135 	va_list args;
136 
137 	va_start(args, message);
138 	(void) fflush(stdout);
139 	(void) fprintf(stderr, gettext("%s: Fatal error: "), getprogname());
140 	(void) vfprintf(stderr, message, args);
141 	(void) fprintf(stderr, "\n");
142 	va_end(args);
143 	if (report_pwd) {
144 		(void) fprintf(stderr,
145 			       gettext("Current working directory %s\n"),
146 			       get_current_path());
147 	}
148 	(void) fflush(stderr);
149 	if (fatal_in_progress) {
150 		exit_status = 1;
151 		exit(1);
152 	}
153 	fatal_in_progress = true;
154 	/* Let all parallel children finish */
155 	if ((dmake_mode_type == parallel_mode) &&
156 	    (parallel_process_cnt > 0)) {
157 		(void) fprintf(stderr,
158 			       gettext("Waiting for %d %s to finish\n"),
159 			       parallel_process_cnt,
160 			       parallel_process_cnt == 1 ?
161 			       gettext("job") : gettext("jobs"));
162 		(void) fflush(stderr);
163 	}
164 
165 	while (parallel_process_cnt > 0) {
166 		await_parallel(true);
167 		finish_children(false);
168 	}
169 
170 	job_adjust_fini();
171 
172 	exit_status = 1;
173 	exit(1);
174 }
175 
176 /*
177  *	warning(format, args...)
178  *
179  *	Print a message and continue.
180  *
181  *	Parameters:
182  *		format		printf type format string
183  *		args		Arguments to match the format
184  *
185  *	Global variables used:
186  *		report_pwd	Should we report the current path?
187  */
188 /*VARARGS*/
189 void
190 warning(char * message, ...)
191 {
192 	va_list args;
193 
194 	va_start(args, message);
195 	(void) fflush(stdout);
196 	(void) fprintf(stderr, gettext("%s: Warning: "), getprogname());
197 	(void) vfprintf(stderr, message, args);
198 	(void) fprintf(stderr, "\n");
199 	va_end(args);
200 	if (report_pwd) {
201 		(void) fprintf(stderr,
202 			       gettext("Current working directory %s\n"),
203 			       get_current_path());
204 	}
205 	(void) fflush(stderr);
206 }
207 
208 /*
209  *	time_to_string(time)
210  *
211  *	Take a numeric time value and produce
212  *	a proper string representation.
213  *
214  *	Return value:
215  *				The string representation of the time
216  *
217  *	Parameters:
218  *		time		The time we need to translate
219  *
220  *	Global variables used:
221  */
222 char *
223 time_to_string(const timestruc_t &time)
224 {
225 	struct tm		*tm;
226 	char			buf[128];
227 
228         if (time == file_doesnt_exist) {
229                 return gettext("File does not exist");
230         }
231         if (time == file_max_time) {
232                 return gettext("Younger than any file");
233         }
234 	tm = localtime(&time.tv_sec);
235 	strftime(buf, sizeof (buf), "%c %Z", tm);
236         buf[127] = (int) nul_char;
237         return strdup(buf);
238 }
239 
240 /*
241  *	get_current_path()
242  *
243  *	Stuff current_path with the current path if it isnt there already.
244  *
245  *	Parameters:
246  *
247  *	Global variables used:
248  */
249 char *
250 get_current_path(void)
251 {
252 	char			pwd[(MAXPATHLEN * MB_LEN_MAX)];
253 	static char		*current_path;
254 
255 	if (current_path == NULL) {
256 		getcwd(pwd, sizeof(pwd));
257 		if (pwd[0] == (int) nul_char) {
258 			pwd[0] = (int) slash_char;
259 			pwd[1] = (int) nul_char;
260 		}
261 		current_path = strdup(pwd);
262 	}
263 	return current_path;
264 }
265 
266 /*****************************************
267  *
268  *	Make internal state dumping
269  *
270  *	This is a set  of routines for dumping the internal make state
271  *	Used for the -p option
272  */
273 
274 /*
275  *	dump_make_state()
276  *
277  *	Dump make's internal state to stdout
278  *
279  *	Parameters:
280  *
281  *	Global variables used:
282  *		svr4 			Was ".SVR4" seen in makefile?
283  *		svr4_name		The Name ".SVR4", printed
284  *		posix			Was ".POSIX" seen in makefile?
285  *		posix_name		The Name ".POSIX", printed
286  *		default_rule		Points to the .DEFAULT rule
287  *		default_rule_name	The Name ".DEFAULT", printed
288  *		default_target_to_build	The first target to print
289  *		dot_keep_state		The Name ".KEEP_STATE", printed
290  *		dot_keep_state_file	The Name ".KEEP_STATE_FILE", printed
291  *		hashtab			The make hash table for Name blocks
292  *		ignore_errors		Was ".IGNORE" seen in makefile?
293  *		ignore_name		The Name ".IGNORE", printed
294  *		keep_state		Was ".KEEP_STATE" seen in makefile?
295  *		percent_list		The list of % rules
296  *		precious		The Name ".PRECIOUS", printed
297  *		sccs_get_name		The Name ".SCCS_GET", printed
298  *		sccs_get_posix_name	The Name ".SCCS_GET_POSIX", printed
299  *		get_name		The Name ".GET", printed
300  *		get_posix_name		The Name ".GET_POSIX", printed
301  *		sccs_get_rule		Points to the ".SCCS_GET" rule
302  *		silent			Was ".SILENT" seen in makefile?
303  *		silent_name		The Name ".SILENT", printed
304  *		suffixes		The suffix list from ".SUFFIXES"
305  *		suffixes_name		The Name ".SUFFIX", printed
306  */
307 void
308 dump_make_state(void)
309 {
310 	Name_set::iterator	p, e;
311 	register Property	prop;
312 	register Dependency	dep;
313 	register Cmd_line	rule;
314 	Percent			percent, percent_depe;
315 
316 	/* Default target */
317 	if (default_target_to_build != NULL) {
318 		print_rule(default_target_to_build);
319 	}
320 	(void) printf("\n");
321 
322 	/* .POSIX */
323 	if (posix) {
324 		(void) printf("%s:\n", posix_name->string_mb);
325 	}
326 
327 	/* .DEFAULT */
328 	if (default_rule != NULL) {
329 		(void) printf("%s:\n", default_rule_name->string_mb);
330 		for (rule = default_rule; rule != NULL; rule = rule->next) {
331 			(void) printf("\t%s\n", rule->command_line->string_mb);
332 		}
333 	}
334 
335 	/* .IGNORE */
336 	if (ignore_errors) {
337 		(void) printf("%s:\n", ignore_name->string_mb);
338 	}
339 
340 	/* .KEEP_STATE: */
341 	if (keep_state) {
342 		(void) printf("%s:\n\n", dot_keep_state->string_mb);
343 	}
344 
345 	/* .PRECIOUS */
346 	(void) printf("%s:", precious->string_mb);
347 	for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) {
348 			if ((p->stat.is_precious) || (all_precious)) {
349 				(void) printf(" %s", p->string_mb);
350 			}
351 	}
352 	(void) printf("\n");
353 
354 	/* .SCCS_GET */
355 	if (sccs_get_rule != NULL) {
356 		(void) printf("%s:\n", sccs_get_name->string_mb);
357 		for (rule = sccs_get_rule; rule != NULL; rule = rule->next) {
358 			(void) printf("\t%s\n", rule->command_line->string_mb);
359 		}
360 	}
361 
362 	/* .SILENT */
363 	if (silent) {
364 		(void) printf("%s:\n", silent_name->string_mb);
365 	}
366 
367 	/* .SUFFIXES: */
368 	(void) printf("%s:", suffixes_name->string_mb);
369 	for (dep = suffixes; dep != NULL; dep = dep->next) {
370 		(void) printf(" %s", dep->name->string_mb);
371 		build_suffix_list(dep->name);
372 	}
373 	(void) printf("\n\n");
374 
375 	/* % rules */
376 	for (percent = percent_list;
377 	     percent != NULL;
378 	     percent = percent->next) {
379 		(void) printf("%s:",
380 			      percent->name->string_mb);
381 
382 		for (percent_depe = percent->dependencies;
383 		     percent_depe != NULL;
384 		     percent_depe = percent_depe->next) {
385 			(void) printf(" %s", percent_depe->name->string_mb);
386 		}
387 
388 		(void) printf("\n");
389 
390 		for (rule = percent->command_template;
391 		     rule != NULL;
392 		     rule = rule->next) {
393 			(void) printf("\t%s\n", rule->command_line->string_mb);
394 		}
395 	}
396 
397 	/* Suffix rules */
398 	for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) {
399 			Wstring wcb(p);
400 			if (wcb.get_string()[0] == (int) period_char) {
401 				print_rule(p);
402 			}
403 	}
404 
405 	/* Macro assignments */
406 	for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) {
407 			if (((prop = get_prop(p->prop, macro_prop)) != NULL) &&
408 			    (prop->body.macro.value != NULL)) {
409 				(void) printf("%s", p->string_mb);
410 				print_value(prop->body.macro.value,
411 					    (Daemon) prop->body.macro.daemon);
412 			}
413 	}
414 	(void) printf("\n");
415 
416 	/* Conditional macro assignments */
417 	for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) {
418 			for (prop = get_prop(p->prop, conditional_prop);
419 			     prop != NULL;
420 			     prop = get_prop(prop->next, conditional_prop)) {
421 				(void) printf("%s := %s",
422 					      p->string_mb,
423 					      prop->body.conditional.name->
424 					      string_mb);
425 				if (prop->body.conditional.append) {
426 					printf(" +");
427 				}
428 				else {
429 					printf(" ");
430 				}
431 				print_value(prop->body.conditional.value,
432 					    no_daemon);
433 			}
434 	}
435 	(void) printf("\n");
436 
437 	/* All other dependencies */
438 	for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) {
439 			if (p->colons != no_colon) {
440 				print_rule(p);
441 			}
442 	}
443 	(void) printf("\n");
444 }
445 
446 /*
447  *	print_rule(target)
448  *
449  *	Print the rule for one target
450  *
451  *	Parameters:
452  *		target		Target we print rule for
453  *
454  *	Global variables used:
455  */
456 static void
457 print_rule(register Name target)
458 {
459 	register Cmd_line	rule;
460 	register Property	line;
461 	register Dependency	dependency;
462 
463 	if (target->dependency_printed ||
464 	    ((line = get_prop(target->prop, line_prop)) == NULL) ||
465 	    ((line->body.line.command_template == NULL) &&
466 	     (line->body.line.dependencies == NULL))) {
467 		return;
468 	}
469 	target->dependency_printed = true;
470 
471 	(void) printf("%s:", target->string_mb);
472 
473 	for (dependency = line->body.line.dependencies;
474 	     dependency != NULL;
475 	     dependency = dependency->next) {
476 		(void) printf(" %s", dependency->name->string_mb);
477 	}
478 
479 	(void) printf("\n");
480 
481 	for (rule = line->body.line.command_template;
482 	     rule != NULL;
483 	     rule = rule->next) {
484 		(void) printf("\t%s\n", rule->command_line->string_mb);
485 	}
486 }
487 
488 void
489 dump_target_list(void)
490 {
491 	Name_set::iterator	p, e;
492 	Wstring	str;
493 
494 	for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) {
495 			str.init(p);
496 			wchar_t * wcb = str.get_string();
497 			if ((p->colons != no_colon) &&
498 			    ((wcb[0] != (int) period_char) ||
499 			     ((wcb[0] == (int) period_char) &&
500 			      (wcschr(wcb, (int) slash_char))))) {
501 				print_target_n_deps(p);
502 			}
503 	}
504 }
505 
506 static void
507 print_target_n_deps(register Name target)
508 {
509 	register Cmd_line	rule;
510 	register Property	line;
511 	register Dependency	dependency;
512 
513 	if (target->dependency_printed) {
514 		return;
515 	}
516 	target->dependency_printed = true;
517 
518 	(void) printf("%s\n", target->string_mb);
519 
520 	if ((line = get_prop(target->prop, line_prop)) == NULL) {
521 		return;
522 	}
523 	for (dependency = line->body.line.dependencies;
524 	     dependency != NULL;
525 	     dependency = dependency->next) {
526 		if (!dependency->automatic) {
527 			print_target_n_deps(dependency->name);
528 		}
529 	}
530 }
531 
532 /*****************************************
533  *
534  *	main() support
535  */
536 
537 /*
538  *	load_cached_names()
539  *
540  *	Load the vector of cached names
541  *
542  *	Parameters:
543  *
544  *	Global variables used:
545  *		Many many pointers to Name blocks.
546  */
547 void
548 load_cached_names(void)
549 {
550 	char		*cp;
551 	Name		dollar;
552 
553 	/* Load the cached_names struct */
554 	MBSTOWCS(wcs_buffer, ".BUILT_LAST_MAKE_RUN");
555 	built_last_make_run = GETNAME(wcs_buffer, FIND_LENGTH);
556 	MBSTOWCS(wcs_buffer, "@");
557 	c_at = GETNAME(wcs_buffer, FIND_LENGTH);
558 	MBSTOWCS(wcs_buffer, " *conditionals* ");
559 	conditionals = GETNAME(wcs_buffer, FIND_LENGTH);
560 	/*
561 	 * A version of make was released with NSE 1.0 that used
562 	 * VERSION-1.1 but this version is identical to VERSION-1.0.
563 	 * The version mismatch code makes a special case for this
564 	 * situation.  If the version number is changed from 1.0
565 	 * it should go to 1.2.
566 	 */
567 	MBSTOWCS(wcs_buffer, "VERSION-1.0");
568 	current_make_version = GETNAME(wcs_buffer, FIND_LENGTH);
569 	MBSTOWCS(wcs_buffer, ".SVR4");
570 	svr4_name = GETNAME(wcs_buffer, FIND_LENGTH);
571 	MBSTOWCS(wcs_buffer, ".POSIX");
572 	posix_name = GETNAME(wcs_buffer, FIND_LENGTH);
573 	MBSTOWCS(wcs_buffer, ".DEFAULT");
574 	default_rule_name = GETNAME(wcs_buffer, FIND_LENGTH);
575 	MBSTOWCS(wcs_buffer, "$");
576 	dollar = GETNAME(wcs_buffer, FIND_LENGTH);
577 	MBSTOWCS(wcs_buffer, ".DONE");
578 	done = GETNAME(wcs_buffer, FIND_LENGTH);
579 	MBSTOWCS(wcs_buffer, ".");
580 	dot = GETNAME(wcs_buffer, FIND_LENGTH);
581 	MBSTOWCS(wcs_buffer, ".KEEP_STATE");
582 	dot_keep_state = GETNAME(wcs_buffer, FIND_LENGTH);
583 	MBSTOWCS(wcs_buffer, ".KEEP_STATE_FILE");
584 	dot_keep_state_file = GETNAME(wcs_buffer, FIND_LENGTH);
585 	MBSTOWCS(wcs_buffer, "");
586 	empty_name = GETNAME(wcs_buffer, FIND_LENGTH);
587 	MBSTOWCS(wcs_buffer, " FORCE");
588 	force = GETNAME(wcs_buffer, FIND_LENGTH);
589 	MBSTOWCS(wcs_buffer, "HOST_ARCH");
590 	host_arch = GETNAME(wcs_buffer, FIND_LENGTH);
591 	MBSTOWCS(wcs_buffer, "HOST_MACH");
592 	host_mach = GETNAME(wcs_buffer, FIND_LENGTH);
593 	MBSTOWCS(wcs_buffer, ".IGNORE");
594 	ignore_name = GETNAME(wcs_buffer, FIND_LENGTH);
595 	MBSTOWCS(wcs_buffer, ".INIT");
596 	init = GETNAME(wcs_buffer, FIND_LENGTH);
597 	MBSTOWCS(wcs_buffer, ".LOCAL");
598 	localhost_name = GETNAME(wcs_buffer, FIND_LENGTH);
599 	MBSTOWCS(wcs_buffer, ".make.state");
600 	make_state = GETNAME(wcs_buffer, FIND_LENGTH);
601 	MBSTOWCS(wcs_buffer, "MAKEFLAGS");
602 	makeflags = GETNAME(wcs_buffer, FIND_LENGTH);
603 	MBSTOWCS(wcs_buffer, ".MAKE_VERSION");
604 	make_version = GETNAME(wcs_buffer, FIND_LENGTH);
605 	MBSTOWCS(wcs_buffer, ".NO_PARALLEL");
606 	no_parallel_name = GETNAME(wcs_buffer, FIND_LENGTH);
607 	MBSTOWCS(wcs_buffer, ".NOT_AUTO");
608 	not_auto = GETNAME(wcs_buffer, FIND_LENGTH);
609 	MBSTOWCS(wcs_buffer, ".PARALLEL");
610 	parallel_name = GETNAME(wcs_buffer, FIND_LENGTH);
611 	MBSTOWCS(wcs_buffer, "PATH");
612 	path_name = GETNAME(wcs_buffer, FIND_LENGTH);
613 	MBSTOWCS(wcs_buffer, "+");
614 	plus = GETNAME(wcs_buffer, FIND_LENGTH);
615 	MBSTOWCS(wcs_buffer, ".PRECIOUS");
616 	precious = GETNAME(wcs_buffer, FIND_LENGTH);
617 	MBSTOWCS(wcs_buffer, "?");
618 	query = GETNAME(wcs_buffer, FIND_LENGTH);
619 	MBSTOWCS(wcs_buffer, "^");
620 	hat = GETNAME(wcs_buffer, FIND_LENGTH);
621 	MBSTOWCS(wcs_buffer, ".RECURSIVE");
622 	recursive_name = GETNAME(wcs_buffer, FIND_LENGTH);
623 	MBSTOWCS(wcs_buffer, ".SCCS_GET");
624 	sccs_get_name = GETNAME(wcs_buffer, FIND_LENGTH);
625 	MBSTOWCS(wcs_buffer, ".SCCS_GET_POSIX");
626 	sccs_get_posix_name = GETNAME(wcs_buffer, FIND_LENGTH);
627 	MBSTOWCS(wcs_buffer, ".GET");
628 	get_name = GETNAME(wcs_buffer, FIND_LENGTH);
629 	MBSTOWCS(wcs_buffer, ".GET_POSIX");
630 	get_posix_name = GETNAME(wcs_buffer, FIND_LENGTH);
631 	MBSTOWCS(wcs_buffer, "SHELL");
632 	shell_name = GETNAME(wcs_buffer, FIND_LENGTH);
633 	MBSTOWCS(wcs_buffer, ".SILENT");
634 	silent_name = GETNAME(wcs_buffer, FIND_LENGTH);
635 	MBSTOWCS(wcs_buffer, ".SUFFIXES");
636 	suffixes_name = GETNAME(wcs_buffer, FIND_LENGTH);
637 	MBSTOWCS(wcs_buffer, SUNPRO_DEPENDENCIES);
638 	sunpro_dependencies = GETNAME(wcs_buffer, FIND_LENGTH);
639 	MBSTOWCS(wcs_buffer, "TARGET_ARCH");
640 	target_arch = GETNAME(wcs_buffer, FIND_LENGTH);
641 	MBSTOWCS(wcs_buffer, "TARGET_MACH");
642 	target_mach = GETNAME(wcs_buffer, FIND_LENGTH);
643 	MBSTOWCS(wcs_buffer, "VIRTUAL_ROOT");
644 	virtual_root = GETNAME(wcs_buffer, FIND_LENGTH);
645 	MBSTOWCS(wcs_buffer, "VPATH");
646 	vpath_name = GETNAME(wcs_buffer, FIND_LENGTH);
647 	MBSTOWCS(wcs_buffer, ".WAIT");
648 	wait_name = GETNAME(wcs_buffer, FIND_LENGTH);
649 
650 	wait_name->state = build_ok;
651 
652 	/* Mark special targets so that the reader treats them properly */
653 	svr4_name->special_reader = svr4_special;
654 	posix_name->special_reader = posix_special;
655 	built_last_make_run->special_reader = built_last_make_run_special;
656 	default_rule_name->special_reader = default_special;
657 	dot_keep_state->special_reader = keep_state_special;
658 	dot_keep_state_file->special_reader = keep_state_file_special;
659 	ignore_name->special_reader = ignore_special;
660 	make_version->special_reader = make_version_special;
661 	no_parallel_name->special_reader = no_parallel_special;
662 	parallel_name->special_reader = parallel_special;
663 	localhost_name->special_reader = localhost_special;
664 	precious->special_reader = precious_special;
665 	sccs_get_name->special_reader = sccs_get_special;
666 	sccs_get_posix_name->special_reader = sccs_get_posix_special;
667 	get_name->special_reader = get_special;
668 	get_posix_name->special_reader = get_posix_special;
669 	silent_name->special_reader = silent_special;
670 	suffixes_name->special_reader = suffixes_special;
671 
672 	/* The value of $$ is $ */
673 	(void) SETVAR(dollar, dollar, false);
674 	dollar->dollar = false;
675 
676 	/* Set the value of $(SHELL) */
677 	if (posix) {
678 	  MBSTOWCS(wcs_buffer, "/usr/xpg4/bin/sh");
679 	} else {
680 	  MBSTOWCS(wcs_buffer, "/bin/sh");
681 	}
682 	(void) SETVAR(shell_name, GETNAME(wcs_buffer, FIND_LENGTH), false);
683 
684 	/*
685 	 * Use " FORCE" to simulate a FRC dependency for :: type
686 	 * targets with no dependencies.
687 	 */
688 	(void) append_prop(force, line_prop);
689 	force->stat.time = file_max_time;
690 
691 	/* Make sure VPATH is defined before current dir is read */
692 	if ((cp = getenv(vpath_name->string_mb)) != NULL) {
693 		MBSTOWCS(wcs_buffer, cp);
694 		(void) SETVAR(vpath_name,
695 			      GETNAME(wcs_buffer, FIND_LENGTH),
696 			      false);
697 	}
698 
699 	/* Check if there is NO PATH variable. If not we construct one. */
700 	if (getenv(path_name->string_mb) == NULL) {
701 		vroot_path = NULL;
702 		add_dir_to_path(".", &vroot_path, -1);
703 		add_dir_to_path("/bin", &vroot_path, -1);
704 		add_dir_to_path("/usr/bin", &vroot_path, -1);
705 	}
706 }
707 
708 /*
709  * iterate on list of conditional macros in np, and place them in
710  * a String_rec starting with, and separated by the '$' character.
711  */
712 void
713 cond_macros_into_string(Name np, String_rec *buffer)
714 {
715 	Macro_list	macro_list;
716 
717 	/*
718 	 * Put the version number at the start of the string
719 	 */
720 	MBSTOWCS(wcs_buffer, DEPINFO_FMT_VERSION);
721 	append_string(wcs_buffer, buffer, FIND_LENGTH);
722 	/*
723 	 * Add the rest of the conditional macros to the buffer
724 	 */
725 	if (np->depends_on_conditional){
726 		for (macro_list = np->conditional_macro_list;
727 		     macro_list != NULL; macro_list = macro_list->next){
728 			append_string(macro_list->macro_name, buffer,
729 				FIND_LENGTH);
730 			append_char((int) equal_char, buffer);
731 			append_string(macro_list->value, buffer, FIND_LENGTH);
732 			append_char((int) dollar_char, buffer);
733 		}
734 	}
735 }
736 
737