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