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.
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.
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]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
30 * Handle expansion of make macros
36 #include <mksh/dosys.h> /* sh_command2string() */
37 #include <mksh/i18n.h> /* get_char_semantics_value() */
38 #include <mksh/macro.h>
39 #include <mksh/misc.h> /* retmem() */
40 #include <mksh/read.h> /* get_next_block_fn() */
41 #include <sys/utsname.h>
42 #include <sys/systeminfo.h>
47 * File table of contents
49 static void add_macro_to_global_list(Name macro_to_add
);
50 static void expand_value_with_daemon(Name
, register Property macro
, register String destination
, Boolean cmd
);
52 static void init_arch_macros(void);
53 static void init_mach_macros(void);
54 static Boolean init_arch_done
= false;
55 static Boolean init_mach_done
= false;
58 long env_alloc_num
= 0;
59 long env_alloc_bytes
= 0;
64 * Return expanded value of macro.
67 * The expanded value of the macro
70 * name The name of the macro we want the value for
72 * Global variables used:
75 getvar(register Name name
)
77 String_rec destination
;
78 wchar_t buffer
[STRING_BUFFER_LENGTH
];
81 if ((name
== host_arch
) || (name
== target_arch
)) {
82 if (!init_arch_done
) {
83 init_arch_done
= true;
87 if ((name
== host_mach
) || (name
== target_mach
)) {
88 if (!init_mach_done
) {
89 init_mach_done
= true;
94 INIT_STRING_FROM_STACK(destination
, buffer
);
95 expand_value(maybe_append_prop(name
, macro_prop
)->body
.macro
.value
,
98 result
= GETNAME(destination
.buffer
.start
, FIND_LENGTH
);
99 if (destination
.free_after_use
) {
100 retmem(destination
.buffer
.start
);
106 * expand_value(value, destination, cmd)
108 * Recursively expands all macros in the string value.
109 * destination is where the expanded value should be appended.
112 * value The value we are expanding
113 * destination Where to deposit the expansion
114 * cmd If we are evaluating a command line we
117 * Global variables used:
120 expand_value(Name value
, register String destination
, Boolean cmd
)
123 register Source source
= &sourceb
;
124 register wchar_t *source_p
= NULL
;
125 register wchar_t *source_end
= NULL
;
126 wchar_t *block_start
= NULL
;
131 * Make sure to get a string allocated even if it
134 MBSTOWCS(wcs_buffer
, "");
135 append_string(wcs_buffer
, destination
, FIND_LENGTH
);
136 destination
->text
.end
= destination
->text
.p
;
139 if (!value
->dollar
) {
141 * If the value we are expanding does not contain
142 * any $, we don't have to parse it.
146 (int) value
->hash
.length
148 destination
->text
.end
= destination
->text
.p
;
152 if (value
->being_expanded
) {
153 fatal_reader_mksh(gettext("Loop detected when expanding macro value `%s'"),
156 value
->being_expanded
= true;
157 /* Setup the structure we read from */
159 sourceb
.string
.text
.p
= sourceb
.string
.buffer
.start
= wcsdup(vals
.get_string());
160 sourceb
.string
.free_after_use
= true;
161 sourceb
.string
.text
.end
=
162 sourceb
.string
.buffer
.end
=
163 sourceb
.string
.text
.p
+ value
->hash
.length
;
164 sourceb
.previous
= NULL
;
167 sourceb
.inp_buf_ptr
=
168 sourceb
.inp_buf_end
= NULL
;
169 sourceb
.error_converting
= false;
170 /* Lift some pointers from the struct to local register variables */
172 /* We parse the string in segments */
173 /* We read chars until we find a $, then we append what we have read so far */
174 /* (since last $ processing) to the destination. When we find a $ we call */
175 /* expand_macro() and let it expand that particular $ reference into dest */
176 block_start
= source_p
;
178 for (; 1; source_p
++) {
179 switch (GET_CHAR()) {
181 /* Quote $ in macro value */
183 quote_seen
= ~quote_seen
;
187 /* Save the plain string we found since */
188 /* start of string or previous $ */
190 append_string(block_start
,
192 source_p
- block_start
- 1);
193 block_start
= source_p
;
196 append_string(block_start
,
198 source_p
- block_start
);
199 source
->string
.text
.p
= ++source_p
;
201 /* Go expand the macro reference */
202 expand_macro(source
, destination
, sourceb
.string
.buffer
.start
, cmd
);
204 block_start
= source_p
+ 1;
207 /* The string ran out. Get some more */
208 append_string(block_start
,
210 source_p
- block_start
);
211 GET_NEXT_BLOCK_NOCHK(source
);
212 if (source
== NULL
) {
213 destination
->text
.end
= destination
->text
.p
;
214 value
->being_expanded
= false;
217 if (source
->error_converting
) {
218 fatal_reader_mksh("Internal error: Invalid byte sequence in expand_value()");
220 block_start
= source_p
;
226 retmem(sourceb
.string
.buffer
.start
);
230 * expand_macro(source, destination, current_string, cmd)
232 * Should be called with source->string.text.p pointing to
233 * the first char after the $ that starts a macro reference.
234 * source->string.text.p is returned pointing to the first char after
236 * It will read the macro name, expanding any macros in it,
237 * and get the value. The value is then expanded.
238 * destination is a String that is filled in with the expanded macro.
239 * It may be passed in referencing a buffer to expand the macro into.
240 * Note that most expansions are done on demand, e.g. right
241 * before the command is executed and not while the file is
245 * source The source block that references the string
247 * destination Where to put the result
248 * current_string The string we are expanding, for error msg
249 * cmd If we are evaluating a command line we
252 * Global variables used:
253 * funny Vector of semantic tags for characters
254 * is_conditional Set if a conditional macro is refd
255 * make_word_mentioned Set if the word "MAKE" is mentioned
256 * makefile_type We deliver extra msg when reading makefiles
257 * query The Name "?", compared against
258 * query_mentioned Set if the word "?" is mentioned
261 expand_macro(register Source source
, register String destination
, wchar_t *current_string
, Boolean cmd
)
263 static Name make
= (Name
)NULL
;
264 static wchar_t colon_sh
[4];
265 static wchar_t colon_shell
[7];
267 wchar_t buffer
[STRING_BUFFER_LENGTH
];
268 register wchar_t *source_p
= source
->string
.text
.p
;
269 register wchar_t *source_end
= source
->string
.text
.end
;
270 register int closer
= 0;
271 wchar_t *block_start
= (wchar_t *)NULL
;
273 register int closer_level
= 1;
274 Name name
= (Name
)NULL
;
275 wchar_t *colon
= (wchar_t *)NULL
;
276 wchar_t *percent
= (wchar_t *)NULL
;
277 wchar_t *eq
= (wchar_t *) NULL
;
278 Property macro
= NULL
;
279 wchar_t *p
= (wchar_t*)NULL
;
280 String_rec extracted
;
281 wchar_t extracted_string
[MAXPATHLEN
];
282 wchar_t *left_head
= NULL
;
283 wchar_t *left_tail
= NULL
;
284 wchar_t *right_tail
= NULL
;
285 int left_head_len
= 0;
286 int left_tail_len
= 0;
288 wchar_t *right_hand
[128];
294 } extraction
= no_extract
;
300 } replacement
= no_replace
;
303 MBSTOWCS(wcs_buffer
, "MAKE");
304 make
= GETNAME(wcs_buffer
, FIND_LENGTH
);
306 MBSTOWCS(colon_sh
, ":sh");
307 MBSTOWCS(colon_shell
, ":shell");
310 right_hand
[0] = NULL
;
312 /* First copy the (macro-expanded) macro name into string. */
313 INIT_STRING_FROM_STACK(string
, buffer
);
315 /* Check the first char of the macro name to figure out what to do. */
316 switch (GET_CHAR()) {
318 GET_NEXT_BLOCK_NOCHK(source
);
319 if (source
== NULL
) {
320 WCSTOMBS(mbs_buffer
, current_string
);
321 fatal_reader_mksh(gettext("'$' at end of string `%s'"),
324 if (source
->error_converting
) {
325 fatal_reader_mksh("Internal error: Invalid byte sequence in expand_macro()");
327 goto recheck_first_char
;
329 /* Multi char name. */
330 closer
= (int) parenright_char
;
333 /* Multi char name. */
334 closer
= (int) braceright_char
;
337 fatal_reader_mksh(gettext("'$' at end of line"));
339 /* Single char macro name. Just suck it up */
340 append_char(*source_p
, &string
);
341 source
->string
.text
.p
= source_p
+ 1;
342 goto get_macro_value
;
345 /* Handle multi-char macro names */
346 block_start
= ++source_p
;
348 for (; 1; source_p
++) {
349 switch (GET_CHAR()) {
351 append_string(block_start
,
353 source_p
- block_start
);
354 GET_NEXT_BLOCK_NOCHK(source
);
355 if (source
== NULL
) {
356 if (current_string
!= NULL
) {
357 WCSTOMBS(mbs_buffer
, current_string
);
358 fatal_reader_mksh(gettext("Unmatched `%c' in string `%s'"),
360 (int) braceright_char
?
361 (int) braceleft_char
:
362 (int) parenleft_char
,
365 fatal_reader_mksh(gettext("Premature EOF"));
368 if (source
->error_converting
) {
369 fatal_reader_mksh("Internal error: Invalid byte sequence in expand_macro()");
371 block_start
= source_p
;
375 fatal_reader_mksh(gettext("Unmatched `%c' on line"),
376 closer
== (int) braceright_char
?
377 (int) braceleft_char
:
378 (int) parenleft_char
);
380 /* Quote dollar in macro value. */
382 quote_seen
= ~quote_seen
;
387 * Macro names may reference macros.
388 * This expands the value of such macros into the
392 append_string(block_start
,
394 source_p
- block_start
- 1);
395 block_start
= source_p
;
398 append_string(block_start
,
400 source_p
- block_start
);
401 source
->string
.text
.p
= ++source_p
;
403 expand_macro(source
, &string
, current_string
, cmd
);
405 block_start
= source_p
;
409 /* Allow nested pairs of () in the macro name. */
410 if (closer
== (int) parenright_char
) {
415 /* Allow nested pairs of {} in the macro name. */
416 if (closer
== (int) braceright_char
) {
420 case parenright_char
:
421 case braceright_char
:
423 * End of the name. Save the string in the macro
426 if ((*source_p
== closer
) && (--closer_level
<= 0)) {
427 source
->string
.text
.p
= source_p
+ 1;
428 append_string(block_start
,
430 source_p
- block_start
);
431 goto get_macro_value
;
438 * We got the macro name. We now inspect it to see if it
439 * specifies any translations of the value.
443 /* First check if we have a $(@D) type translation. */
444 if ((get_char_semantics_value(string
.buffer
.start
[0]) &
445 (int) special_macro_sem
) &&
446 (string
.text
.p
- string
.buffer
.start
>= 2) &&
447 ((string
.buffer
.start
[1] == 'D') ||
448 (string
.buffer
.start
[1] == 'F'))) {
449 switch (string
.buffer
.start
[1]) {
451 extraction
= dir_extract
;
454 extraction
= file_extract
;
457 WCSTOMBS(mbs_buffer
, string
.buffer
.start
);
458 fatal_reader_mksh(gettext("Illegal macro reference `%s'"),
461 /* Internalize the macro name using the first char only. */
462 name
= GETNAME(string
.buffer
.start
, 1);
463 (void) wcscpy(string
.buffer
.start
, string
.buffer
.start
+ 2);
465 /* Check for other kinds of translations. */
466 if ((colon
= (wchar_t *) wcschr(string
.buffer
.start
,
467 (int) colon_char
)) != NULL
) {
469 * We have a $(FOO:.c=.o) type translation.
470 * Get the name of the macro proper.
473 name
= GETNAME(string
.buffer
.start
,
474 colon
- string
.buffer
.start
);
476 /* Pickup all the translations. */
477 if (IS_WEQUAL(colon
, colon_sh
) || IS_WEQUAL(colon
, colon_shell
)) {
478 replacement
= sh_replace
;
480 ((percent
= (wchar_t *) wcschr(colon
+ 1,
481 (int) percent_char
)) == NULL
)) {
482 while (colon
!= NULL
) {
483 if ((eq
= (wchar_t *) wcschr(colon
+ 1,
484 (int) equal_char
)) == NULL
) {
485 fatal_reader_mksh(gettext("= missing from replacement macro reference"));
487 left_tail_len
= eq
- colon
- 1;
491 left_tail
= ALLOC_WC(left_tail_len
+ 1);
492 (void) wcsncpy(left_tail
,
495 left_tail
[eq
- colon
- 1] = (int) nul_char
;
496 replacement
= suffix_replace
;
497 if ((colon
= (wchar_t *) wcschr(eq
+ 1,
498 (int) colon_char
)) != NULL
) {
499 tmp_len
= colon
- eq
;
503 right_tail
= ALLOC_WC(tmp_len
);
504 (void) wcsncpy(right_tail
,
507 right_tail
[colon
- eq
- 1] =
513 right_tail
= ALLOC_WC(wcslen(eq
) + 1);
514 (void) wcscpy(right_tail
, eq
+ 1);
518 if ((eq
= (wchar_t *) wcschr(colon
+ 1,
519 (int) equal_char
)) == NULL
) {
520 fatal_reader_mksh(gettext("= missing from replacement macro reference"));
522 if ((percent
= (wchar_t *) wcschr(colon
+ 1,
523 (int) percent_char
)) == NULL
) {
524 fatal_reader_mksh(gettext("%% missing from replacement macro reference"));
527 fatal_reader_mksh(gettext("%% missing from replacement macro reference"));
530 if (percent
> (colon
+ 1)) {
531 tmp_len
= percent
- colon
;
535 left_head
= ALLOC_WC(tmp_len
);
536 (void) wcsncpy(left_head
,
538 percent
- colon
- 1);
539 left_head
[percent
-colon
-1] = (int) nul_char
;
540 left_head_len
= percent
-colon
-1;
546 if (eq
> percent
+1) {
547 tmp_len
= eq
- percent
;
551 left_tail
= ALLOC_WC(tmp_len
);
552 (void) wcsncpy(left_tail
,
555 left_tail
[eq
-percent
-1] = (int) nul_char
;
556 left_tail_len
= eq
-percent
-1;
562 if ((percent
= (wchar_t *) wcschr(++eq
,
563 (int) percent_char
)) == NULL
) {
565 right_hand
[0] = ALLOC_WC(wcslen(eq
) + 1);
566 right_hand
[1] = NULL
;
567 (void) wcscpy(right_hand
[0], eq
);
571 right_hand
[i
] = ALLOC_WC(percent
-eq
+1);
572 (void) wcsncpy(right_hand
[i
],
575 right_hand
[i
][percent
-eq
] =
577 if (i
++ >= VSIZEOF(right_hand
)) {
578 fatal_mksh(gettext("Too many %% in pattern"));
581 if (eq
[0] == (int) nul_char
) {
582 MBSTOWCS(wcs_buffer
, "");
583 right_hand
[i
] = (wchar_t *) wcsdup(wcs_buffer
);
587 } while ((percent
= (wchar_t *) wcschr(eq
, (int) percent_char
)) != NULL
);
588 if (eq
[0] != (int) nul_char
) {
589 right_hand
[i
] = ALLOC_WC(wcslen(eq
) + 1);
590 (void) wcscpy(right_hand
[i
], eq
);
593 right_hand
[i
] = NULL
;
595 replacement
= pattern_replace
;
600 * No translations found.
601 * Use the whole string as the macro name.
603 name
= GETNAME(string
.buffer
.start
,
604 string
.text
.p
- string
.buffer
.start
);
606 if (string
.free_after_use
) {
607 retmem(string
.buffer
.start
);
610 make_word_mentioned
= true;
613 query_mentioned
= true;
615 if ((name
== host_arch
) || (name
== target_arch
)) {
616 if (!init_arch_done
) {
617 init_arch_done
= true;
621 if ((name
== host_mach
) || (name
== target_mach
)) {
622 if (!init_mach_done
) {
623 init_mach_done
= true;
627 /* Get the macro value. */
628 macro
= get_prop(name
->prop
, macro_prop
);
629 if ((macro
!= NULL
) && macro
->body
.macro
.is_conditional
) {
630 conditional_macro_used
= true;
632 * Add this conditional macro to the beginning of the
635 add_macro_to_global_list(name
);
636 if (makefile_type
== reading_makefile
) {
637 warning_mksh(gettext("Conditional macro `%s' referenced in file `%ws', line %d"),
638 name
->string_mb
, file_being_read
, line_number
);
641 /* Macro name read and parsed. Expand the value. */
642 if ((macro
== NULL
) || (macro
->body
.macro
.value
== NULL
)) {
643 /* If the value is empty, we just get out of here. */
646 if (replacement
== sh_replace
) {
647 /* If we should do a :sh transform, we expand the command
650 INIT_STRING_FROM_STACK(string
, buffer
);
651 /* Expand the value into a local string buffer and run cmd. */
652 expand_value_with_daemon(name
, macro
, &string
, cmd
);
653 sh_command2string(&string
, destination
);
654 } else if ((replacement
!= no_replace
) || (extraction
!= no_extract
)) {
656 * If there were any transforms specified in the macro
657 * name, we deal with them here.
659 INIT_STRING_FROM_STACK(string
, buffer
);
660 /* Expand the value into a local string buffer. */
661 expand_value_with_daemon(name
, macro
, &string
, cmd
);
662 /* Scan the expanded string. */
663 p
= string
.buffer
.start
;
664 while (*p
!= (int) nul_char
) {
668 * First skip over any white space and append
669 * that to the destination string.
672 while ((*p
!= (int) nul_char
) && iswspace(*p
)) {
675 append_string(block_start
,
678 /* Then find the end of the next word. */
680 while ((*p
!= (int) nul_char
) && !iswspace(*p
)) {
683 /* If we cant find another word we are done */
684 if (block_start
== p
) {
687 /* Then apply the transforms to the word */
688 INIT_STRING_FROM_STACK(extracted
, extracted_string
);
689 switch (extraction
) {
692 * $(@D) type transform. Extract the
693 * path from the word. Deliver "." if
700 eq
= (wchar_t *) wcsrchr(block_start
, (int) slash_char
);
704 if ((eq
== NULL
) || (eq
> p
)) {
705 MBSTOWCS(wcs_buffer
, ".");
706 append_string(wcs_buffer
, &extracted
, 1);
708 append_string(block_start
,
715 * $(@F) type transform. Remove the path
716 * from the word if any.
722 eq
= (wchar_t *) wcsrchr(block_start
, (int) slash_char
);
726 if ((eq
== NULL
) || (eq
> p
)) {
727 append_string(block_start
,
731 append_string(eq
+ 1,
737 append_string(block_start
,
742 switch (replacement
) {
745 * $(FOO:.o=.c) type transform.
746 * Maybe replace the tail of the word.
748 if (((extracted
.text
.p
-
749 extracted
.buffer
.start
) >=
751 IS_WEQUALN(extracted
.text
.p
- left_tail_len
,
754 append_string(extracted
.buffer
.start
,
757 extracted
.buffer
.start
)
759 append_string(right_tail
,
763 append_string(extracted
.buffer
.start
,
768 case pattern_replace
:
769 /* $(X:a%b=c%d) type transform. */
770 if (((extracted
.text
.p
-
771 extracted
.buffer
.start
) >=
772 left_head_len
+left_tail_len
) &&
773 IS_WEQUALN(left_head
,
774 extracted
.buffer
.start
,
776 IS_WEQUALN(left_tail
,
777 extracted
.text
.p
- left_tail_len
,
780 while (right_hand
[i
] != NULL
) {
781 append_string(right_hand
[i
],
785 if (right_hand
[i
] != NULL
) {
786 append_string(extracted
.buffer
.
790 (extracted
.text
.p
- extracted
.buffer
.start
)-left_head_len
-left_tail_len
);
794 append_string(extracted
.buffer
.start
,
800 append_string(extracted
.buffer
.start
,
808 if (string
.free_after_use
) {
809 retmem(string
.buffer
.start
);
813 * This is for the case when the macro name did not
814 * specify transforms.
816 if (!strncmp(name
->string_mb
, "GET", 3)) {
817 dollarget_seen
= true;
819 dollarless_flag
= false;
820 if (!strncmp(name
->string_mb
, "<", 1) &&
822 dollarless_flag
= true;
823 dollarget_seen
= false;
825 expand_value_with_daemon(name
, macro
, destination
, cmd
);
838 while (right_hand
[i
] != NULL
) {
839 retmem(right_hand
[i
]);
842 *destination
->text
.p
= (int) nul_char
;
843 destination
->text
.end
= destination
->text
.p
;
847 add_macro_to_global_list(Name macro_to_add
)
849 Macro_list new_macro
;
850 Macro_list macro_on_list
;
851 char *name_on_list
= NULL
;
852 char *name_to_add
= macro_to_add
->string_mb
;
853 char *value_on_list
= NULL
;
854 const char *value_to_add
= NULL
;
856 if (macro_to_add
->prop
->body
.macro
.value
!= NULL
) {
857 value_to_add
= macro_to_add
->prop
->body
.macro
.value
->string_mb
;
863 * Check if this macro is already on list, if so, do nothing
865 for (macro_on_list
= cond_macro_list
;
866 macro_on_list
!= NULL
;
867 macro_on_list
= macro_on_list
->next
) {
869 name_on_list
= macro_on_list
->macro_name
;
870 value_on_list
= macro_on_list
->value
;
872 if (IS_EQUAL(name_on_list
, name_to_add
)) {
873 if (IS_EQUAL(value_on_list
, value_to_add
)) {
878 new_macro
= (Macro_list
) malloc(sizeof(Macro_list_rec
));
879 new_macro
->macro_name
= strdup(name_to_add
);
880 new_macro
->value
= strdup(value_to_add
);
881 new_macro
->next
= cond_macro_list
;
882 cond_macro_list
= new_macro
;
886 * init_arch_macros(void)
888 * Set the magic macros TARGET_ARCH, HOST_ARCH,
892 * Global variables used:
893 * host_arch Property for magic macro HOST_ARCH
894 * target_arch Property for magic macro TARGET_ARCH
897 * The function does not return a value, but can
898 * call fatal() in case of error.
901 init_arch_macros(void)
903 String_rec result_string
;
904 wchar_t wc_buf
[STRING_BUFFER_LENGTH
];
905 char mb_buf
[STRING_BUFFER_LENGTH
];
908 int set_host
, set_target
;
910 set_host
= (get_prop(host_arch
->prop
, macro_prop
) == NULL
);
911 set_target
= (get_prop(target_arch
->prop
, macro_prop
) == NULL
);
913 if (set_host
|| set_target
) {
914 INIT_STRING_FROM_STACK(result_string
, wc_buf
);
915 append_char((int) hyphen_char
, &result_string
);
916 if (sysinfo(SI_PLATFORM
, mb_buf
, sizeof (mb_buf
)) < 0)
917 fatal_mksh(gettext("sysinfo() failed"));
918 MBSTOWCS(wcs_buffer
, mb_buf
);
919 append_string(wcs_buffer
, &result_string
, wcslen(wcs_buffer
));
921 value
= GETNAME(result_string
.buffer
.start
, wcslen(result_string
.buffer
.start
));
924 (void) setvar_daemon(host_arch
, value
, false, no_daemon
, true, 0);
927 (void) setvar_daemon(target_arch
, value
, false, no_daemon
, true, 0);
933 * init_mach_macros(void)
935 * Set the magic macros TARGET_MACH, HOST_MACH,
939 * Global variables used:
940 * host_mach Property for magic macro HOST_MACH
941 * target_mach Property for magic macro TARGET_MACH
944 * The function does not return a value, but can
945 * call fatal() in case of error.
948 init_mach_macros(void)
950 String_rec result_string
;
951 wchar_t wc_buf
[STRING_BUFFER_LENGTH
];
954 int set_host
, set_target
;
957 set_host
= (get_prop(host_mach
->prop
, macro_prop
) == NULL
);
958 set_target
= (get_prop(target_mach
->prop
, macro_prop
) == NULL
);
960 if (set_host
|| set_target
) {
961 INIT_STRING_FROM_STACK(result_string
, wc_buf
);
962 append_char((int) hyphen_char
, &result_string
);
964 fatal_mksh(gettext("uname() failed"));
965 MBSTOWCS(wcs_buffer
, uts
.machine
);
966 append_string(wcs_buffer
, &result_string
, wcslen(wcs_buffer
));
968 value
= GETNAME(result_string
.buffer
.start
, wcslen(result_string
.buffer
.start
));
971 (void) setvar_daemon(host_mach
, value
, false, no_daemon
, true, 0);
974 (void) setvar_daemon(target_mach
, value
, false, no_daemon
, true, 0);
980 * expand_value_with_daemon(name, macro, destination, cmd)
982 * Checks for daemons and then maybe calls expand_value().
985 * name Name of the macro (Added by the NSE)
986 * macro The property block with the value to expand
987 * destination Where the result should be deposited
988 * cmd If we are evaluating a command line we
991 * Global variables used:
994 expand_value_with_daemon(Name
, register Property macro
, register String destination
, Boolean cmd
)
996 register Chain chain
;
999 switch (macro
->body
.macro
.daemon
) {
1001 if (!svr4
&& !posix
) {
1002 expand_value(macro
->body
.macro
.value
, destination
, cmd
);
1004 if (dollarless_flag
&& tilde_rule
) {
1005 expand_value(dollarless_value
, destination
, cmd
);
1006 dollarless_flag
= false;
1009 expand_value(macro
->body
.macro
.value
, destination
, cmd
);
1014 /* If this is a $? value we call the daemon to translate the */
1015 /* list of names to a string */
1016 for (chain
= (Chain
) macro
->body
.macro
.value
;
1018 chain
= chain
->next
) {
1019 APPEND_NAME(chain
->name
,
1021 (int) chain
->name
->hash
.length
);
1022 if (chain
->next
!= NULL
) {
1023 append_char((int) space_char
, destination
);
1031 * We use a permanent buffer to reset SUNPRO_DEPENDENCIES value.
1033 char *sunpro_dependencies_buf
= NULL
;
1034 char *sunpro_dependencies_oldbuf
= NULL
;
1035 int sunpro_dependencies_buf_size
= 0;
1038 * setvar_daemon(name, value, append, daemon, strip_trailing_spaces)
1040 * Set a macro value, possibly supplying a daemon to be used
1041 * when referencing the value.
1044 * The property block with the new value
1047 * name Name of the macro to set
1048 * value The value to set
1049 * append Should we reset or append to the current value?
1050 * daemon Special treatment when reading the value
1051 * strip_trailing_spaces from the end of value->string
1052 * debug_level Indicates how much tracing we should do
1054 * Global variables used:
1055 * makefile_type Used to check if we should enforce read only
1056 * path_name The Name "PATH", compared against
1057 * virtual_root The Name "VIRTUAL_ROOT", compared against
1058 * vpath_defined Set if the macro VPATH is set
1059 * vpath_name The Name "VPATH", compared against
1060 * envvar A list of environment vars with $ in value
1063 setvar_daemon(register Name name
, register Name value
, Boolean append
, Daemon daemon
, Boolean strip_trailing_spaces
, short debug_level
)
1065 register Property macro
= maybe_append_prop(name
, macro_prop
);
1066 register Property macro_apx
= get_prop(name
->prop
, macro_append_prop
);
1068 String_rec destination
;
1069 wchar_t buffer
[STRING_BUFFER_LENGTH
];
1070 register Chain chain
;
1072 wchar_t *val_string
= (wchar_t*)NULL
;
1076 if ((makefile_type
!= reading_nothing
) &&
1077 macro
->body
.macro
.read_only
) {
1080 /* Strip spaces from the end of the value */
1081 if (daemon
== no_daemon
) {
1084 length
= wcb
.length();
1085 val_string
= wcb
.get_string();
1087 if ((length
> 0) && iswspace(val_string
[length
-1])) {
1088 INIT_STRING_FROM_STACK(destination
, buffer
);
1090 append_string(val_string
, &destination
, length
);
1091 if (strip_trailing_spaces
) {
1092 while ((length
> 0) &&
1093 iswspace(destination
.buffer
.start
[length
-1])) {
1094 destination
.buffer
.start
[--length
] = 0;
1097 value
= GETNAME(destination
.buffer
.start
, FIND_LENGTH
);
1101 if(macro_apx
!= NULL
) {
1102 val
= macro_apx
->body
.macro_appendix
.value
;
1104 val
= macro
->body
.macro
.value
;
1109 * If we are appending, we just tack the new value after
1110 * the old one with a space in between.
1112 INIT_STRING_FROM_STACK(destination
, buffer
);
1114 if ((macro
!= NULL
) && (val
!= NULL
)) {
1117 (int) val
->hash
.length
);
1118 if (value
!= NULL
) {
1120 if(wcb
.length() > 0) {
1121 MBTOWC(wcs_buffer
, " ");
1122 append_char(wcs_buffer
[0], &destination
);
1126 if (value
!= NULL
) {
1129 (int) value
->hash
.length
);
1131 value
= GETNAME(destination
.buffer
.start
, FIND_LENGTH
);
1133 if (destination
.free_after_use
) {
1134 retmem(destination
.buffer
.start
);
1138 /* Debugging trace */
1139 if (debug_level
> 1) {
1140 if (value
!= NULL
) {
1143 (void) printf("%s =", name
->string_mb
);
1144 for (chain
= (Chain
) value
;
1146 chain
= chain
->next
) {
1147 (void) printf(" %s", chain
->name
->string_mb
);
1149 (void) printf("\n");
1152 (void) printf("%s= %s\n",
1158 (void) printf("%s =\n", name
->string_mb
);
1161 /* Set the new values in the macro property block */
1163 if(macro_apx
!= NULL
) {
1164 macro_apx
->body
.macro_appendix
.value
= value
;
1165 INIT_STRING_FROM_STACK(destination
, buffer
);
1167 if (value
!= NULL
) {
1170 (int) value
->hash
.length
);
1171 if (macro_apx
->body
.macro_appendix
.value_to_append
!= NULL
) {
1172 MBTOWC(wcs_buffer
, " ");
1173 append_char(wcs_buffer
[0], &destination
);
1176 if (macro_apx
->body
.macro_appendix
.value_to_append
!= NULL
) {
1177 APPEND_NAME(macro_apx
->body
.macro_appendix
.value_to_append
,
1179 (int) macro_apx
->body
.macro_appendix
.value_to_append
->hash
.length
);
1181 value
= GETNAME(destination
.buffer
.start
, FIND_LENGTH
);
1182 if (destination
.free_after_use
) {
1183 retmem(destination
.buffer
.start
);
1187 macro
->body
.macro
.value
= value
;
1188 macro
->body
.macro
.daemon
= daemon
;
1190 * If the user changes the VIRTUAL_ROOT, we need to flush
1191 * the vroot package cache.
1193 if (name
== path_name
) {
1196 if (name
== virtual_root
) {
1197 flush_vroot_cache();
1199 /* If this sets the VPATH we remember that */
1200 if ((name
== vpath_name
) &&
1202 (value
->hash
.length
> 0)) {
1203 vpath_defined
= true;
1206 * For environment variables we also set the
1207 * environment value each time.
1209 if (macro
->body
.macro
.exported
) {
1212 if (!reading_environment
&& (value
!= NULL
)) {
1215 for (p
= envvar
; p
!= NULL
; p
= p
->next
) {
1216 if (p
->name
== name
) {
1218 p
->already_put
= false;
1226 p
->env_string
= NULL
;
1227 p
->already_put
= false;
1230 } if (reading_environment
|| (value
== NULL
) || !value
->dollar
) {
1231 length
= 2 + strlen(name
->string_mb
);
1232 if (value
!= NULL
) {
1233 length
+= strlen(value
->string_mb
);
1235 Property env_prop
= maybe_append_prop(name
, env_mem_prop
);
1237 * We use a permanent buffer to reset SUNPRO_DEPENDENCIES value.
1239 if (!strncmp(name
->string_mb
, "SUNPRO_DEPENDENCIES", 19)) {
1240 if (length
>= sunpro_dependencies_buf_size
) {
1241 sunpro_dependencies_buf_size
=length
*2;
1242 if (sunpro_dependencies_buf_size
< 4096)
1243 sunpro_dependencies_buf_size
= 4096; // Default minimum size
1244 if (sunpro_dependencies_buf
)
1245 sunpro_dependencies_oldbuf
= sunpro_dependencies_buf
;
1246 sunpro_dependencies_buf
=getmem(sunpro_dependencies_buf_size
);
1248 env
= sunpro_dependencies_buf
;
1250 env
= getmem(length
);
1253 env_alloc_bytes
+= length
;
1258 "" : value
->string_mb
);
1260 env_prop
->body
.env_mem
.value
= env
;
1261 if (sunpro_dependencies_oldbuf
) {
1262 /* Return old buffer */
1263 retmem_mb(sunpro_dependencies_oldbuf
);
1264 sunpro_dependencies_oldbuf
= NULL
;
1268 if (name
== target_arch
) {
1269 Name ha
= getvar(host_arch
);
1270 Name ta
= getvar(target_arch
);
1271 Name vr
= getvar(virtual_root
);
1275 Boolean new_value_allocated
= false;
1281 wchar_t * wcb_ha
= ha_str
.get_string();
1282 wchar_t * wcb_ta
= ta_str
.get_string();
1283 wchar_t * wcb_vr
= vr_str
.get_string();
1290 MBSTOWCS(wcs_buffer
, "/usr/arch/");
1291 if (IS_WEQUALN(old_vr
,
1293 wcslen(wcs_buffer
))) {
1294 old_vr
= (wchar_t *) wcschr(old_vr
, (int) colon_char
) + 1;
1296 if ( (ha
== ta
) || (wcslen(wcb_ta
) == 0) ) {
1299 new_value
= ALLOC_WC(length
);
1300 new_value_allocated
= true;
1301 WCSTOMBS(mbs_buffer
, old_vr
);
1302 (void) swprintf(new_value
, length
* SIZEOFWCHAR_T
,
1303 L
"/usr/arch/%s/%s:%s",
1308 if (new_value
[0] != 0) {
1309 (void) setvar_daemon(virtual_root
,
1310 GETNAME(new_value
, FIND_LENGTH
),
1316 if (new_value_allocated
) {