21 /*
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26
27 /*
28 * macro.cc
29 *
30 * Handle expansion of make macros
31 */
32
33 /*
34 * Included files
35 */
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 <mksdmsi18n/mksdmsi18n.h> /* libmksdmsi18n_init() */
42
43 #include <widec.h>
44
45 /*
46 * File table of contents
47 */
48 static void add_macro_to_global_list(Name macro_to_add);
49 static void expand_value_with_daemon(Name, register Property macro, register String destination, Boolean cmd);
50
51 static void init_arch_macros(void);
52 static void init_mach_macros(void);
53 static Boolean init_arch_done = false;
54 static Boolean init_mach_done = false;
55
56
57 long env_alloc_num = 0;
58 long env_alloc_bytes = 0;
59
60 /*
61 * getvar(name)
62 *
63 * Return expanded value of macro.
132 */
133 MBSTOWCS(wcs_buffer, "");
134 append_string(wcs_buffer, destination, FIND_LENGTH);
135 destination->text.end = destination->text.p;
136 return;
137 }
138 if (!value->dollar) {
139 /*
140 * If the value we are expanding does not contain
141 * any $, we don't have to parse it.
142 */
143 APPEND_NAME(value,
144 destination,
145 (int) value->hash.length
146 );
147 destination->text.end = destination->text.p;
148 return;
149 }
150
151 if (value->being_expanded) {
152 fatal_reader_mksh(catgets(libmksdmsi18n_catd, 1, 113, "Loop detected when expanding macro value `%s'"),
153 value->string_mb);
154 }
155 value->being_expanded = true;
156 /* Setup the structure we read from */
157 Wstring vals(value);
158 sourceb.string.text.p = sourceb.string.buffer.start = wsdup(vals.get_string());
159 sourceb.string.free_after_use = true;
160 sourceb.string.text.end =
161 sourceb.string.buffer.end =
162 sourceb.string.text.p + value->hash.length;
163 sourceb.previous = NULL;
164 sourceb.fd = -1;
165 sourceb.inp_buf =
166 sourceb.inp_buf_ptr =
167 sourceb.inp_buf_end = NULL;
168 sourceb.error_converting = false;
169 /* Lift some pointers from the struct to local register variables */
170 CACHE_SOURCE(0);
171 /* We parse the string in segments */
172 /* We read chars until we find a $, then we append what we have read so far */
197 source_p - block_start);
198 source->string.text.p = ++source_p;
199 UNCACHE_SOURCE();
200 /* Go expand the macro reference */
201 expand_macro(source, destination, sourceb.string.buffer.start, cmd);
202 CACHE_SOURCE(1);
203 block_start = source_p + 1;
204 break;
205 case nul_char:
206 /* The string ran out. Get some more */
207 append_string(block_start,
208 destination,
209 source_p - block_start);
210 GET_NEXT_BLOCK_NOCHK(source);
211 if (source == NULL) {
212 destination->text.end = destination->text.p;
213 value->being_expanded = false;
214 return;
215 }
216 if (source->error_converting) {
217 fatal_reader_mksh(NOCATGETS("Internal error: Invalid byte sequence in expand_value()"));
218 }
219 block_start = source_p;
220 source_p--;
221 continue;
222 }
223 quote_seen = 0;
224 }
225 retmem(sourceb.string.buffer.start);
226 }
227
228 /*
229 * expand_macro(source, destination, current_string, cmd)
230 *
231 * Should be called with source->string.text.p pointing to
232 * the first char after the $ that starts a macro reference.
233 * source->string.text.p is returned pointing to the first char after
234 * the macro name.
235 * It will read the macro name, expanding any macros in it,
236 * and get the value. The value is then expanded.
237 * destination is a String that is filled in with the expanded macro.
282 wchar_t *left_tail = NULL;
283 wchar_t *right_tail = NULL;
284 int left_head_len = 0;
285 int left_tail_len = 0;
286 int tmp_len = 0;
287 wchar_t *right_hand[128];
288 int i = 0;
289 enum {
290 no_extract,
291 dir_extract,
292 file_extract
293 } extraction = no_extract;
294 enum {
295 no_replace,
296 suffix_replace,
297 pattern_replace,
298 sh_replace
299 } replacement = no_replace;
300
301 if (make == NULL) {
302 MBSTOWCS(wcs_buffer, NOCATGETS("MAKE"));
303 make = GETNAME(wcs_buffer, FIND_LENGTH);
304
305 MBSTOWCS(colon_sh, NOCATGETS(":sh"));
306 MBSTOWCS(colon_shell, NOCATGETS(":shell"));
307 }
308
309 right_hand[0] = NULL;
310
311 /* First copy the (macro-expanded) macro name into string. */
312 INIT_STRING_FROM_STACK(string, buffer);
313 recheck_first_char:
314 /* Check the first char of the macro name to figure out what to do. */
315 switch (GET_CHAR()) {
316 case nul_char:
317 GET_NEXT_BLOCK_NOCHK(source);
318 if (source == NULL) {
319 WCSTOMBS(mbs_buffer, current_string);
320 fatal_reader_mksh(catgets(libmksdmsi18n_catd, 1, 114, "'$' at end of string `%s'"),
321 mbs_buffer);
322 }
323 if (source->error_converting) {
324 fatal_reader_mksh(NOCATGETS("Internal error: Invalid byte sequence in expand_macro()"));
325 }
326 goto recheck_first_char;
327 case parenleft_char:
328 /* Multi char name. */
329 closer = (int) parenright_char;
330 break;
331 case braceleft_char:
332 /* Multi char name. */
333 closer = (int) braceright_char;
334 break;
335 case newline_char:
336 fatal_reader_mksh(catgets(libmksdmsi18n_catd, 1, 115, "'$' at end of line"));
337 default:
338 /* Single char macro name. Just suck it up */
339 append_char(*source_p, &string);
340 source->string.text.p = source_p + 1;
341 goto get_macro_value;
342 }
343
344 /* Handle multi-char macro names */
345 block_start = ++source_p;
346 quote_seen = 0;
347 for (; 1; source_p++) {
348 switch (GET_CHAR()) {
349 case nul_char:
350 append_string(block_start,
351 &string,
352 source_p - block_start);
353 GET_NEXT_BLOCK_NOCHK(source);
354 if (source == NULL) {
355 if (current_string != NULL) {
356 WCSTOMBS(mbs_buffer, current_string);
357 fatal_reader_mksh(catgets(libmksdmsi18n_catd, 1, 116, "Unmatched `%c' in string `%s'"),
358 closer ==
359 (int) braceright_char ?
360 (int) braceleft_char :
361 (int) parenleft_char,
362 mbs_buffer);
363 } else {
364 fatal_reader_mksh(catgets(libmksdmsi18n_catd, 1, 117, "Premature EOF"));
365 }
366 }
367 if (source->error_converting) {
368 fatal_reader_mksh(NOCATGETS("Internal error: Invalid byte sequence in expand_macro()"));
369 }
370 block_start = source_p;
371 source_p--;
372 continue;
373 case newline_char:
374 fatal_reader_mksh(catgets(libmksdmsi18n_catd, 1, 118, "Unmatched `%c' on line"),
375 closer == (int) braceright_char ?
376 (int) braceleft_char :
377 (int) parenleft_char);
378 case backslash_char:
379 /* Quote dollar in macro value. */
380 if (!cmd) {
381 quote_seen = ~quote_seen;
382 }
383 continue;
384 case dollar_char:
385 /*
386 * Macro names may reference macros.
387 * This expands the value of such macros into the
388 * macro name string.
389 */
390 if (quote_seen) {
391 append_string(block_start,
392 &string,
393 source_p - block_start - 1);
394 block_start = source_p;
437 * We got the macro name. We now inspect it to see if it
438 * specifies any translations of the value.
439 */
440 get_macro_value:
441 name = NULL;
442 /* First check if we have a $(@D) type translation. */
443 if ((get_char_semantics_value(string.buffer.start[0]) &
444 (int) special_macro_sem) &&
445 (string.text.p - string.buffer.start >= 2) &&
446 ((string.buffer.start[1] == 'D') ||
447 (string.buffer.start[1] == 'F'))) {
448 switch (string.buffer.start[1]) {
449 case 'D':
450 extraction = dir_extract;
451 break;
452 case 'F':
453 extraction = file_extract;
454 break;
455 default:
456 WCSTOMBS(mbs_buffer, string.buffer.start);
457 fatal_reader_mksh(catgets(libmksdmsi18n_catd, 1, 119, "Illegal macro reference `%s'"),
458 mbs_buffer);
459 }
460 /* Internalize the macro name using the first char only. */
461 name = GETNAME(string.buffer.start, 1);
462 (void) wscpy(string.buffer.start, string.buffer.start + 2);
463 }
464 /* Check for other kinds of translations. */
465 if ((colon = (wchar_t *) wschr(string.buffer.start,
466 (int) colon_char)) != NULL) {
467 /*
468 * We have a $(FOO:.c=.o) type translation.
469 * Get the name of the macro proper.
470 */
471 if (name == NULL) {
472 name = GETNAME(string.buffer.start,
473 colon - string.buffer.start);
474 }
475 /* Pickup all the translations. */
476 if (IS_WEQUAL(colon, colon_sh) || IS_WEQUAL(colon, colon_shell)) {
477 replacement = sh_replace;
478 } else if ((svr4) ||
479 ((percent = (wchar_t *) wschr(colon + 1,
480 (int) percent_char)) == NULL)) {
481 while (colon != NULL) {
482 if ((eq = (wchar_t *) wschr(colon + 1,
483 (int) equal_char)) == NULL) {
484 fatal_reader_mksh(catgets(libmksdmsi18n_catd, 1, 120, "= missing from replacement macro reference"));
485 }
486 left_tail_len = eq - colon - 1;
487 if(left_tail) {
488 retmem(left_tail);
489 }
490 left_tail = ALLOC_WC(left_tail_len + 1);
491 (void) wsncpy(left_tail,
492 colon + 1,
493 eq - colon - 1);
494 left_tail[eq - colon - 1] = (int) nul_char;
495 replacement = suffix_replace;
496 if ((colon = (wchar_t *) wschr(eq + 1,
497 (int) colon_char)) != NULL) {
498 tmp_len = colon - eq;
499 if(right_tail) {
500 retmem(right_tail);
501 }
502 right_tail = ALLOC_WC(tmp_len);
503 (void) wsncpy(right_tail,
504 eq + 1,
505 colon - eq - 1);
506 right_tail[colon - eq - 1] =
507 (int) nul_char;
508 } else {
509 if(right_tail) {
510 retmem(right_tail);
511 }
512 right_tail = ALLOC_WC(wslen(eq) + 1);
513 (void) wscpy(right_tail, eq + 1);
514 }
515 }
516 } else {
517 if ((eq = (wchar_t *) wschr(colon + 1,
518 (int) equal_char)) == NULL) {
519 fatal_reader_mksh(catgets(libmksdmsi18n_catd, 1, 121, "= missing from replacement macro reference"));
520 }
521 if ((percent = (wchar_t *) wschr(colon + 1,
522 (int) percent_char)) == NULL) {
523 fatal_reader_mksh(catgets(libmksdmsi18n_catd, 1, 122, "%% missing from replacement macro reference"));
524 }
525 if (eq < percent) {
526 fatal_reader_mksh(catgets(libmksdmsi18n_catd, 1, 123, "%% missing from replacement macro reference"));
527 }
528
529 if (percent > (colon + 1)) {
530 tmp_len = percent - colon;
531 if(left_head) {
532 retmem(left_head);
533 }
534 left_head = ALLOC_WC(tmp_len);
535 (void) wsncpy(left_head,
536 colon + 1,
537 percent - colon - 1);
538 left_head[percent-colon-1] = (int) nul_char;
539 left_head_len = percent-colon-1;
540 } else {
541 left_head = NULL;
542 left_head_len = 0;
543 }
544
545 if (eq > percent+1) {
546 tmp_len = eq - percent;
557 left_tail = NULL;
558 left_tail_len = 0;
559 }
560
561 if ((percent = (wchar_t *) wschr(++eq,
562 (int) percent_char)) == NULL) {
563
564 right_hand[0] = ALLOC_WC(wslen(eq) + 1);
565 right_hand[1] = NULL;
566 (void) wscpy(right_hand[0], eq);
567 } else {
568 i = 0;
569 do {
570 right_hand[i] = ALLOC_WC(percent-eq+1);
571 (void) wsncpy(right_hand[i],
572 eq,
573 percent - eq);
574 right_hand[i][percent-eq] =
575 (int) nul_char;
576 if (i++ >= VSIZEOF(right_hand)) {
577 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 124, "Too many %% in pattern"));
578 }
579 eq = percent + 1;
580 if (eq[0] == (int) nul_char) {
581 MBSTOWCS(wcs_buffer, "");
582 right_hand[i] = (wchar_t *) wsdup(wcs_buffer);
583 i++;
584 break;
585 }
586 } while ((percent = (wchar_t *) wschr(eq, (int) percent_char)) != NULL);
587 if (eq[0] != (int) nul_char) {
588 right_hand[i] = ALLOC_WC(wslen(eq) + 1);
589 (void) wscpy(right_hand[i], eq);
590 i++;
591 }
592 right_hand[i] = NULL;
593 }
594 replacement = pattern_replace;
595 }
596 }
597 if (name == NULL) {
616 init_arch_done = true;
617 init_arch_macros();
618 }
619 }
620 if ((name == host_mach) || (name == target_mach)) {
621 if (!init_mach_done) {
622 init_mach_done = true;
623 init_mach_macros();
624 }
625 }
626 /* Get the macro value. */
627 macro = get_prop(name->prop, macro_prop);
628 if ((macro != NULL) && macro->body.macro.is_conditional) {
629 conditional_macro_used = true;
630 /*
631 * Add this conditional macro to the beginning of the
632 * global list.
633 */
634 add_macro_to_global_list(name);
635 if (makefile_type == reading_makefile) {
636 warning_mksh(catgets(libmksdmsi18n_catd, 1, 164, "Conditional macro `%s' referenced in file `%ws', line %d"),
637 name->string_mb, file_being_read, line_number);
638 }
639 }
640 /* Macro name read and parsed. Expand the value. */
641 if ((macro == NULL) || (macro->body.macro.value == NULL)) {
642 /* If the value is empty, we just get out of here. */
643 goto exit;
644 }
645 if (replacement == sh_replace) {
646 /* If we should do a :sh transform, we expand the command
647 * and process it.
648 */
649 INIT_STRING_FROM_STACK(string, buffer);
650 /* Expand the value into a local string buffer and run cmd. */
651 expand_value_with_daemon(name, macro, &string, cmd);
652 sh_command2string(&string, destination);
653 } else if ((replacement != no_replace) || (extraction != no_extract)) {
654 /*
655 * If there were any transforms specified in the macro
656 * name, we deal with them here.
795 FIND_LENGTH);
796 }
797 break;
798 case no_replace:
799 append_string(extracted.buffer.start,
800 destination,
801 FIND_LENGTH);
802 break;
803 case sh_replace:
804 break;
805 }
806 }
807 if (string.free_after_use) {
808 retmem(string.buffer.start);
809 }
810 } else {
811 /*
812 * This is for the case when the macro name did not
813 * specify transforms.
814 */
815 if (!strncmp(name->string_mb, NOCATGETS("GET"), 3)) {
816 dollarget_seen = true;
817 }
818 dollarless_flag = false;
819 if (!strncmp(name->string_mb, "<", 1) &&
820 dollarget_seen) {
821 dollarless_flag = true;
822 dollarget_seen = false;
823 }
824 expand_value_with_daemon(name, macro, destination, cmd);
825 }
826 exit:
827 if(left_tail) {
828 retmem(left_tail);
829 }
830 if(right_tail) {
831 retmem(right_tail);
832 }
833 if(left_head) {
834 retmem(left_head);
835 }
888 *
889 * Parameters:
890 *
891 * Global variables used:
892 * host_arch Property for magic macro HOST_ARCH
893 * target_arch Property for magic macro TARGET_ARCH
894 *
895 * Return value:
896 * The function does not return a value, but can
897 * call fatal() in case of error.
898 */
899 static void
900 init_arch_macros(void)
901 {
902 String_rec result_string;
903 wchar_t wc_buf[STRING_BUFFER_LENGTH];
904 char mb_buf[STRING_BUFFER_LENGTH];
905 FILE *pipe;
906 Name value;
907 int set_host, set_target;
908 const char *mach_command = NOCATGETS("/bin/mach");
909
910 set_host = (get_prop(host_arch->prop, macro_prop) == NULL);
911 set_target = (get_prop(target_arch->prop, macro_prop) == NULL);
912
913 if (set_host || set_target) {
914 INIT_STRING_FROM_STACK(result_string, wc_buf);
915 append_char((int) hyphen_char, &result_string);
916
917 if ((pipe = popen(mach_command, "r")) == NULL) {
918 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 185, "Execute of %s failed"), mach_command);
919 }
920 while (fgets(mb_buf, sizeof(mb_buf), pipe) != NULL) {
921 MBSTOWCS(wcs_buffer, mb_buf);
922 append_string(wcs_buffer, &result_string, wslen(wcs_buffer));
923 }
924 if (pclose(pipe) != 0) {
925 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 186, "Execute of %s failed"), mach_command);
926 }
927
928 value = GETNAME(result_string.buffer.start, wslen(result_string.buffer.start));
929
930 if (set_host) {
931 (void) setvar_daemon(host_arch, value, false, no_daemon, true, 0);
932 }
933 if (set_target) {
934 (void) setvar_daemon(target_arch, value, false, no_daemon, true, 0);
935 }
936 }
937 }
938
939 /*
940 * init_mach_macros(void)
941 *
942 * Set the magic macros TARGET_MACH, HOST_MACH,
943 *
944 * Parameters:
945 *
946 * Global variables used:
947 * host_mach Property for magic macro HOST_MACH
948 * target_mach Property for magic macro TARGET_MACH
949 *
950 * Return value:
951 * The function does not return a value, but can
952 * call fatal() in case of error.
953 */
954 static void
955 init_mach_macros(void)
956 {
957 String_rec result_string;
958 wchar_t wc_buf[STRING_BUFFER_LENGTH];
959 char mb_buf[STRING_BUFFER_LENGTH];
960 FILE *pipe;
961 Name value;
962 int set_host, set_target;
963 const char *arch_command = NOCATGETS("/bin/arch");
964
965 set_host = (get_prop(host_mach->prop, macro_prop) == NULL);
966 set_target = (get_prop(target_mach->prop, macro_prop) == NULL);
967
968 if (set_host || set_target) {
969 INIT_STRING_FROM_STACK(result_string, wc_buf);
970 append_char((int) hyphen_char, &result_string);
971
972 if ((pipe = popen(arch_command, "r")) == NULL) {
973 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 183, "Execute of %s failed"), arch_command);
974 }
975 while (fgets(mb_buf, sizeof(mb_buf), pipe) != NULL) {
976 MBSTOWCS(wcs_buffer, mb_buf);
977 append_string(wcs_buffer, &result_string, wslen(wcs_buffer));
978 }
979 if (pclose(pipe) != 0) {
980 fatal_mksh(catgets(libmksdmsi18n_catd, 1, 184, "Execute of %s failed"), arch_command);
981 }
982
983 value = GETNAME(result_string.buffer.start, wslen(result_string.buffer.start));
984
985 if (set_host) {
986 (void) setvar_daemon(host_mach, value, false, no_daemon, true, 0);
987 }
988 if (set_target) {
989 (void) setvar_daemon(target_mach, value, false, no_daemon, true, 0);
990 }
991 }
992 }
993
994 /*
995 * expand_value_with_daemon(name, macro, destination, cmd)
996 *
997 * Checks for daemons and then maybe calls expand_value().
998 *
999 * Parameters:
1000 * name Name of the macro (Added by the NSE)
1234 goto found_it;
1235 }
1236 }
1237 p = ALLOC(Envvar);
1238 p->name = name;
1239 p->value = value;
1240 p->next = envvar;
1241 p->env_string = NULL;
1242 p->already_put = false;
1243 envvar = p;
1244 found_it:;
1245 } if (reading_environment || (value == NULL) || !value->dollar) {
1246 length = 2 + strlen(name->string_mb);
1247 if (value != NULL) {
1248 length += strlen(value->string_mb);
1249 }
1250 Property env_prop = maybe_append_prop(name, env_mem_prop);
1251 /*
1252 * We use a permanent buffer to reset SUNPRO_DEPENDENCIES value.
1253 */
1254 if (!strncmp(name->string_mb, NOCATGETS("SUNPRO_DEPENDENCIES"), 19)) {
1255 if (length >= sunpro_dependencies_buf_size) {
1256 sunpro_dependencies_buf_size=length*2;
1257 if (sunpro_dependencies_buf_size < 4096)
1258 sunpro_dependencies_buf_size = 4096; // Default minimum size
1259 if (sunpro_dependencies_buf)
1260 sunpro_dependencies_oldbuf = sunpro_dependencies_buf;
1261 sunpro_dependencies_buf=getmem(sunpro_dependencies_buf_size);
1262 }
1263 env = sunpro_dependencies_buf;
1264 } else {
1265 env = getmem(length);
1266 }
1267 env_alloc_num++;
1268 env_alloc_bytes += length;
1269 (void) sprintf(env,
1270 "%s=%s",
1271 name->string_mb,
1272 value == NULL ?
1273 "" : value->string_mb);
1274 (void) putenv(env);
1285 Name ta = getvar(target_arch);
1286 Name vr = getvar(virtual_root);
1287 int length;
1288 wchar_t *new_value;
1289 wchar_t *old_vr;
1290 Boolean new_value_allocated = false;
1291
1292 Wstring ha_str(ha);
1293 Wstring ta_str(ta);
1294 Wstring vr_str(vr);
1295
1296 wchar_t * wcb_ha = ha_str.get_string();
1297 wchar_t * wcb_ta = ta_str.get_string();
1298 wchar_t * wcb_vr = vr_str.get_string();
1299
1300 length = 32 +
1301 wslen(wcb_ha) +
1302 wslen(wcb_ta) +
1303 wslen(wcb_vr);
1304 old_vr = wcb_vr;
1305 MBSTOWCS(wcs_buffer, NOCATGETS("/usr/arch/"));
1306 if (IS_WEQUALN(old_vr,
1307 wcs_buffer,
1308 wslen(wcs_buffer))) {
1309 old_vr = (wchar_t *) wschr(old_vr, (int) colon_char) + 1;
1310 }
1311 if ( (ha == ta) || (wslen(wcb_ta) == 0) ) {
1312 new_value = old_vr;
1313 } else {
1314 new_value = ALLOC_WC(length);
1315 new_value_allocated = true;
1316 WCSTOMBS(mbs_buffer, old_vr);
1317 (void) wsprintf(new_value,
1318 NOCATGETS("/usr/arch/%s/%s:%s"),
1319 ha->string_mb + 1,
1320 ta->string_mb + 1,
1321 mbs_buffer);
1322 }
1323 if (new_value[0] != 0) {
1324 (void) setvar_daemon(virtual_root,
1325 GETNAME(new_value, FIND_LENGTH),
1326 false,
1327 no_daemon,
1328 true,
1329 debug_level);
1330 }
1331 if (new_value_allocated) {
1332 retmem(new_value);
1333 }
1334 }
1335 return macro;
1336 }
|
21 /*
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26
27 /*
28 * macro.cc
29 *
30 * Handle expansion of make macros
31 */
32
33 /*
34 * Included files
35 */
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
42 #include <widec.h>
43 #include <libintl.h>
44
45 /*
46 * File table of contents
47 */
48 static void add_macro_to_global_list(Name macro_to_add);
49 static void expand_value_with_daemon(Name, register Property macro, register String destination, Boolean cmd);
50
51 static void init_arch_macros(void);
52 static void init_mach_macros(void);
53 static Boolean init_arch_done = false;
54 static Boolean init_mach_done = false;
55
56
57 long env_alloc_num = 0;
58 long env_alloc_bytes = 0;
59
60 /*
61 * getvar(name)
62 *
63 * Return expanded value of macro.
132 */
133 MBSTOWCS(wcs_buffer, "");
134 append_string(wcs_buffer, destination, FIND_LENGTH);
135 destination->text.end = destination->text.p;
136 return;
137 }
138 if (!value->dollar) {
139 /*
140 * If the value we are expanding does not contain
141 * any $, we don't have to parse it.
142 */
143 APPEND_NAME(value,
144 destination,
145 (int) value->hash.length
146 );
147 destination->text.end = destination->text.p;
148 return;
149 }
150
151 if (value->being_expanded) {
152 fatal_reader_mksh(gettext("Loop detected when expanding macro value `%s'"),
153 value->string_mb);
154 }
155 value->being_expanded = true;
156 /* Setup the structure we read from */
157 Wstring vals(value);
158 sourceb.string.text.p = sourceb.string.buffer.start = wsdup(vals.get_string());
159 sourceb.string.free_after_use = true;
160 sourceb.string.text.end =
161 sourceb.string.buffer.end =
162 sourceb.string.text.p + value->hash.length;
163 sourceb.previous = NULL;
164 sourceb.fd = -1;
165 sourceb.inp_buf =
166 sourceb.inp_buf_ptr =
167 sourceb.inp_buf_end = NULL;
168 sourceb.error_converting = false;
169 /* Lift some pointers from the struct to local register variables */
170 CACHE_SOURCE(0);
171 /* We parse the string in segments */
172 /* We read chars until we find a $, then we append what we have read so far */
197 source_p - block_start);
198 source->string.text.p = ++source_p;
199 UNCACHE_SOURCE();
200 /* Go expand the macro reference */
201 expand_macro(source, destination, sourceb.string.buffer.start, cmd);
202 CACHE_SOURCE(1);
203 block_start = source_p + 1;
204 break;
205 case nul_char:
206 /* The string ran out. Get some more */
207 append_string(block_start,
208 destination,
209 source_p - block_start);
210 GET_NEXT_BLOCK_NOCHK(source);
211 if (source == NULL) {
212 destination->text.end = destination->text.p;
213 value->being_expanded = false;
214 return;
215 }
216 if (source->error_converting) {
217 fatal_reader_mksh("Internal error: Invalid byte sequence in expand_value()");
218 }
219 block_start = source_p;
220 source_p--;
221 continue;
222 }
223 quote_seen = 0;
224 }
225 retmem(sourceb.string.buffer.start);
226 }
227
228 /*
229 * expand_macro(source, destination, current_string, cmd)
230 *
231 * Should be called with source->string.text.p pointing to
232 * the first char after the $ that starts a macro reference.
233 * source->string.text.p is returned pointing to the first char after
234 * the macro name.
235 * It will read the macro name, expanding any macros in it,
236 * and get the value. The value is then expanded.
237 * destination is a String that is filled in with the expanded macro.
282 wchar_t *left_tail = NULL;
283 wchar_t *right_tail = NULL;
284 int left_head_len = 0;
285 int left_tail_len = 0;
286 int tmp_len = 0;
287 wchar_t *right_hand[128];
288 int i = 0;
289 enum {
290 no_extract,
291 dir_extract,
292 file_extract
293 } extraction = no_extract;
294 enum {
295 no_replace,
296 suffix_replace,
297 pattern_replace,
298 sh_replace
299 } replacement = no_replace;
300
301 if (make == NULL) {
302 MBSTOWCS(wcs_buffer, "MAKE");
303 make = GETNAME(wcs_buffer, FIND_LENGTH);
304
305 MBSTOWCS(colon_sh, ":sh");
306 MBSTOWCS(colon_shell, ":shell");
307 }
308
309 right_hand[0] = NULL;
310
311 /* First copy the (macro-expanded) macro name into string. */
312 INIT_STRING_FROM_STACK(string, buffer);
313 recheck_first_char:
314 /* Check the first char of the macro name to figure out what to do. */
315 switch (GET_CHAR()) {
316 case nul_char:
317 GET_NEXT_BLOCK_NOCHK(source);
318 if (source == NULL) {
319 WCSTOMBS(mbs_buffer, current_string);
320 fatal_reader_mksh(gettext("'$' at end of string `%s'"),
321 mbs_buffer);
322 }
323 if (source->error_converting) {
324 fatal_reader_mksh("Internal error: Invalid byte sequence in expand_macro()");
325 }
326 goto recheck_first_char;
327 case parenleft_char:
328 /* Multi char name. */
329 closer = (int) parenright_char;
330 break;
331 case braceleft_char:
332 /* Multi char name. */
333 closer = (int) braceright_char;
334 break;
335 case newline_char:
336 fatal_reader_mksh(gettext("'$' at end of line"));
337 default:
338 /* Single char macro name. Just suck it up */
339 append_char(*source_p, &string);
340 source->string.text.p = source_p + 1;
341 goto get_macro_value;
342 }
343
344 /* Handle multi-char macro names */
345 block_start = ++source_p;
346 quote_seen = 0;
347 for (; 1; source_p++) {
348 switch (GET_CHAR()) {
349 case nul_char:
350 append_string(block_start,
351 &string,
352 source_p - block_start);
353 GET_NEXT_BLOCK_NOCHK(source);
354 if (source == NULL) {
355 if (current_string != NULL) {
356 WCSTOMBS(mbs_buffer, current_string);
357 fatal_reader_mksh(gettext("Unmatched `%c' in string `%s'"),
358 closer ==
359 (int) braceright_char ?
360 (int) braceleft_char :
361 (int) parenleft_char,
362 mbs_buffer);
363 } else {
364 fatal_reader_mksh(gettext("Premature EOF"));
365 }
366 }
367 if (source->error_converting) {
368 fatal_reader_mksh("Internal error: Invalid byte sequence in expand_macro()");
369 }
370 block_start = source_p;
371 source_p--;
372 continue;
373 case newline_char:
374 fatal_reader_mksh(gettext("Unmatched `%c' on line"),
375 closer == (int) braceright_char ?
376 (int) braceleft_char :
377 (int) parenleft_char);
378 case backslash_char:
379 /* Quote dollar in macro value. */
380 if (!cmd) {
381 quote_seen = ~quote_seen;
382 }
383 continue;
384 case dollar_char:
385 /*
386 * Macro names may reference macros.
387 * This expands the value of such macros into the
388 * macro name string.
389 */
390 if (quote_seen) {
391 append_string(block_start,
392 &string,
393 source_p - block_start - 1);
394 block_start = source_p;
437 * We got the macro name. We now inspect it to see if it
438 * specifies any translations of the value.
439 */
440 get_macro_value:
441 name = NULL;
442 /* First check if we have a $(@D) type translation. */
443 if ((get_char_semantics_value(string.buffer.start[0]) &
444 (int) special_macro_sem) &&
445 (string.text.p - string.buffer.start >= 2) &&
446 ((string.buffer.start[1] == 'D') ||
447 (string.buffer.start[1] == 'F'))) {
448 switch (string.buffer.start[1]) {
449 case 'D':
450 extraction = dir_extract;
451 break;
452 case 'F':
453 extraction = file_extract;
454 break;
455 default:
456 WCSTOMBS(mbs_buffer, string.buffer.start);
457 fatal_reader_mksh(gettext("Illegal macro reference `%s'"),
458 mbs_buffer);
459 }
460 /* Internalize the macro name using the first char only. */
461 name = GETNAME(string.buffer.start, 1);
462 (void) wscpy(string.buffer.start, string.buffer.start + 2);
463 }
464 /* Check for other kinds of translations. */
465 if ((colon = (wchar_t *) wschr(string.buffer.start,
466 (int) colon_char)) != NULL) {
467 /*
468 * We have a $(FOO:.c=.o) type translation.
469 * Get the name of the macro proper.
470 */
471 if (name == NULL) {
472 name = GETNAME(string.buffer.start,
473 colon - string.buffer.start);
474 }
475 /* Pickup all the translations. */
476 if (IS_WEQUAL(colon, colon_sh) || IS_WEQUAL(colon, colon_shell)) {
477 replacement = sh_replace;
478 } else if ((svr4) ||
479 ((percent = (wchar_t *) wschr(colon + 1,
480 (int) percent_char)) == NULL)) {
481 while (colon != NULL) {
482 if ((eq = (wchar_t *) wschr(colon + 1,
483 (int) equal_char)) == NULL) {
484 fatal_reader_mksh(gettext("= missing from replacement macro reference"));
485 }
486 left_tail_len = eq - colon - 1;
487 if(left_tail) {
488 retmem(left_tail);
489 }
490 left_tail = ALLOC_WC(left_tail_len + 1);
491 (void) wsncpy(left_tail,
492 colon + 1,
493 eq - colon - 1);
494 left_tail[eq - colon - 1] = (int) nul_char;
495 replacement = suffix_replace;
496 if ((colon = (wchar_t *) wschr(eq + 1,
497 (int) colon_char)) != NULL) {
498 tmp_len = colon - eq;
499 if(right_tail) {
500 retmem(right_tail);
501 }
502 right_tail = ALLOC_WC(tmp_len);
503 (void) wsncpy(right_tail,
504 eq + 1,
505 colon - eq - 1);
506 right_tail[colon - eq - 1] =
507 (int) nul_char;
508 } else {
509 if(right_tail) {
510 retmem(right_tail);
511 }
512 right_tail = ALLOC_WC(wslen(eq) + 1);
513 (void) wscpy(right_tail, eq + 1);
514 }
515 }
516 } else {
517 if ((eq = (wchar_t *) wschr(colon + 1,
518 (int) equal_char)) == NULL) {
519 fatal_reader_mksh(gettext("= missing from replacement macro reference"));
520 }
521 if ((percent = (wchar_t *) wschr(colon + 1,
522 (int) percent_char)) == NULL) {
523 fatal_reader_mksh(gettext("%% missing from replacement macro reference"));
524 }
525 if (eq < percent) {
526 fatal_reader_mksh(gettext("%% missing from replacement macro reference"));
527 }
528
529 if (percent > (colon + 1)) {
530 tmp_len = percent - colon;
531 if(left_head) {
532 retmem(left_head);
533 }
534 left_head = ALLOC_WC(tmp_len);
535 (void) wsncpy(left_head,
536 colon + 1,
537 percent - colon - 1);
538 left_head[percent-colon-1] = (int) nul_char;
539 left_head_len = percent-colon-1;
540 } else {
541 left_head = NULL;
542 left_head_len = 0;
543 }
544
545 if (eq > percent+1) {
546 tmp_len = eq - percent;
557 left_tail = NULL;
558 left_tail_len = 0;
559 }
560
561 if ((percent = (wchar_t *) wschr(++eq,
562 (int) percent_char)) == NULL) {
563
564 right_hand[0] = ALLOC_WC(wslen(eq) + 1);
565 right_hand[1] = NULL;
566 (void) wscpy(right_hand[0], eq);
567 } else {
568 i = 0;
569 do {
570 right_hand[i] = ALLOC_WC(percent-eq+1);
571 (void) wsncpy(right_hand[i],
572 eq,
573 percent - eq);
574 right_hand[i][percent-eq] =
575 (int) nul_char;
576 if (i++ >= VSIZEOF(right_hand)) {
577 fatal_mksh(gettext("Too many %% in pattern"));
578 }
579 eq = percent + 1;
580 if (eq[0] == (int) nul_char) {
581 MBSTOWCS(wcs_buffer, "");
582 right_hand[i] = (wchar_t *) wsdup(wcs_buffer);
583 i++;
584 break;
585 }
586 } while ((percent = (wchar_t *) wschr(eq, (int) percent_char)) != NULL);
587 if (eq[0] != (int) nul_char) {
588 right_hand[i] = ALLOC_WC(wslen(eq) + 1);
589 (void) wscpy(right_hand[i], eq);
590 i++;
591 }
592 right_hand[i] = NULL;
593 }
594 replacement = pattern_replace;
595 }
596 }
597 if (name == NULL) {
616 init_arch_done = true;
617 init_arch_macros();
618 }
619 }
620 if ((name == host_mach) || (name == target_mach)) {
621 if (!init_mach_done) {
622 init_mach_done = true;
623 init_mach_macros();
624 }
625 }
626 /* Get the macro value. */
627 macro = get_prop(name->prop, macro_prop);
628 if ((macro != NULL) && macro->body.macro.is_conditional) {
629 conditional_macro_used = true;
630 /*
631 * Add this conditional macro to the beginning of the
632 * global list.
633 */
634 add_macro_to_global_list(name);
635 if (makefile_type == reading_makefile) {
636 warning_mksh(gettext("Conditional macro `%s' referenced in file `%ws', line %d"),
637 name->string_mb, file_being_read, line_number);
638 }
639 }
640 /* Macro name read and parsed. Expand the value. */
641 if ((macro == NULL) || (macro->body.macro.value == NULL)) {
642 /* If the value is empty, we just get out of here. */
643 goto exit;
644 }
645 if (replacement == sh_replace) {
646 /* If we should do a :sh transform, we expand the command
647 * and process it.
648 */
649 INIT_STRING_FROM_STACK(string, buffer);
650 /* Expand the value into a local string buffer and run cmd. */
651 expand_value_with_daemon(name, macro, &string, cmd);
652 sh_command2string(&string, destination);
653 } else if ((replacement != no_replace) || (extraction != no_extract)) {
654 /*
655 * If there were any transforms specified in the macro
656 * name, we deal with them here.
795 FIND_LENGTH);
796 }
797 break;
798 case no_replace:
799 append_string(extracted.buffer.start,
800 destination,
801 FIND_LENGTH);
802 break;
803 case sh_replace:
804 break;
805 }
806 }
807 if (string.free_after_use) {
808 retmem(string.buffer.start);
809 }
810 } else {
811 /*
812 * This is for the case when the macro name did not
813 * specify transforms.
814 */
815 if (!strncmp(name->string_mb, "GET", 3)) {
816 dollarget_seen = true;
817 }
818 dollarless_flag = false;
819 if (!strncmp(name->string_mb, "<", 1) &&
820 dollarget_seen) {
821 dollarless_flag = true;
822 dollarget_seen = false;
823 }
824 expand_value_with_daemon(name, macro, destination, cmd);
825 }
826 exit:
827 if(left_tail) {
828 retmem(left_tail);
829 }
830 if(right_tail) {
831 retmem(right_tail);
832 }
833 if(left_head) {
834 retmem(left_head);
835 }
888 *
889 * Parameters:
890 *
891 * Global variables used:
892 * host_arch Property for magic macro HOST_ARCH
893 * target_arch Property for magic macro TARGET_ARCH
894 *
895 * Return value:
896 * The function does not return a value, but can
897 * call fatal() in case of error.
898 */
899 static void
900 init_arch_macros(void)
901 {
902 String_rec result_string;
903 wchar_t wc_buf[STRING_BUFFER_LENGTH];
904 char mb_buf[STRING_BUFFER_LENGTH];
905 FILE *pipe;
906 Name value;
907 int set_host, set_target;
908 const char *mach_command = "/bin/mach";
909
910 set_host = (get_prop(host_arch->prop, macro_prop) == NULL);
911 set_target = (get_prop(target_arch->prop, macro_prop) == NULL);
912
913 if (set_host || set_target) {
914 INIT_STRING_FROM_STACK(result_string, wc_buf);
915 append_char((int) hyphen_char, &result_string);
916
917 if ((pipe = popen(mach_command, "r")) == NULL) {
918 fatal_mksh(gettext("Execute of %s failed"), mach_command);
919 }
920 while (fgets(mb_buf, sizeof(mb_buf), pipe) != NULL) {
921 MBSTOWCS(wcs_buffer, mb_buf);
922 append_string(wcs_buffer, &result_string, wslen(wcs_buffer));
923 }
924 if (pclose(pipe) != 0) {
925 fatal_mksh(gettext("Execute of %s failed"), mach_command);
926 }
927
928 value = GETNAME(result_string.buffer.start, wslen(result_string.buffer.start));
929
930 if (set_host) {
931 (void) setvar_daemon(host_arch, value, false, no_daemon, true, 0);
932 }
933 if (set_target) {
934 (void) setvar_daemon(target_arch, value, false, no_daemon, true, 0);
935 }
936 }
937 }
938
939 /*
940 * init_mach_macros(void)
941 *
942 * Set the magic macros TARGET_MACH, HOST_MACH,
943 *
944 * Parameters:
945 *
946 * Global variables used:
947 * host_mach Property for magic macro HOST_MACH
948 * target_mach Property for magic macro TARGET_MACH
949 *
950 * Return value:
951 * The function does not return a value, but can
952 * call fatal() in case of error.
953 */
954 static void
955 init_mach_macros(void)
956 {
957 String_rec result_string;
958 wchar_t wc_buf[STRING_BUFFER_LENGTH];
959 char mb_buf[STRING_BUFFER_LENGTH];
960 FILE *pipe;
961 Name value;
962 int set_host, set_target;
963 const char *arch_command = "/bin/arch";
964
965 set_host = (get_prop(host_mach->prop, macro_prop) == NULL);
966 set_target = (get_prop(target_mach->prop, macro_prop) == NULL);
967
968 if (set_host || set_target) {
969 INIT_STRING_FROM_STACK(result_string, wc_buf);
970 append_char((int) hyphen_char, &result_string);
971
972 if ((pipe = popen(arch_command, "r")) == NULL) {
973 fatal_mksh(gettext("Execute of %s failed"), arch_command);
974 }
975 while (fgets(mb_buf, sizeof(mb_buf), pipe) != NULL) {
976 MBSTOWCS(wcs_buffer, mb_buf);
977 append_string(wcs_buffer, &result_string, wslen(wcs_buffer));
978 }
979 if (pclose(pipe) != 0) {
980 fatal_mksh(gettext("Execute of %s failed"), arch_command);
981 }
982
983 value = GETNAME(result_string.buffer.start, wslen(result_string.buffer.start));
984
985 if (set_host) {
986 (void) setvar_daemon(host_mach, value, false, no_daemon, true, 0);
987 }
988 if (set_target) {
989 (void) setvar_daemon(target_mach, value, false, no_daemon, true, 0);
990 }
991 }
992 }
993
994 /*
995 * expand_value_with_daemon(name, macro, destination, cmd)
996 *
997 * Checks for daemons and then maybe calls expand_value().
998 *
999 * Parameters:
1000 * name Name of the macro (Added by the NSE)
1234 goto found_it;
1235 }
1236 }
1237 p = ALLOC(Envvar);
1238 p->name = name;
1239 p->value = value;
1240 p->next = envvar;
1241 p->env_string = NULL;
1242 p->already_put = false;
1243 envvar = p;
1244 found_it:;
1245 } if (reading_environment || (value == NULL) || !value->dollar) {
1246 length = 2 + strlen(name->string_mb);
1247 if (value != NULL) {
1248 length += strlen(value->string_mb);
1249 }
1250 Property env_prop = maybe_append_prop(name, env_mem_prop);
1251 /*
1252 * We use a permanent buffer to reset SUNPRO_DEPENDENCIES value.
1253 */
1254 if (!strncmp(name->string_mb, "SUNPRO_DEPENDENCIES", 19)) {
1255 if (length >= sunpro_dependencies_buf_size) {
1256 sunpro_dependencies_buf_size=length*2;
1257 if (sunpro_dependencies_buf_size < 4096)
1258 sunpro_dependencies_buf_size = 4096; // Default minimum size
1259 if (sunpro_dependencies_buf)
1260 sunpro_dependencies_oldbuf = sunpro_dependencies_buf;
1261 sunpro_dependencies_buf=getmem(sunpro_dependencies_buf_size);
1262 }
1263 env = sunpro_dependencies_buf;
1264 } else {
1265 env = getmem(length);
1266 }
1267 env_alloc_num++;
1268 env_alloc_bytes += length;
1269 (void) sprintf(env,
1270 "%s=%s",
1271 name->string_mb,
1272 value == NULL ?
1273 "" : value->string_mb);
1274 (void) putenv(env);
1285 Name ta = getvar(target_arch);
1286 Name vr = getvar(virtual_root);
1287 int length;
1288 wchar_t *new_value;
1289 wchar_t *old_vr;
1290 Boolean new_value_allocated = false;
1291
1292 Wstring ha_str(ha);
1293 Wstring ta_str(ta);
1294 Wstring vr_str(vr);
1295
1296 wchar_t * wcb_ha = ha_str.get_string();
1297 wchar_t * wcb_ta = ta_str.get_string();
1298 wchar_t * wcb_vr = vr_str.get_string();
1299
1300 length = 32 +
1301 wslen(wcb_ha) +
1302 wslen(wcb_ta) +
1303 wslen(wcb_vr);
1304 old_vr = wcb_vr;
1305 MBSTOWCS(wcs_buffer, "/usr/arch/");
1306 if (IS_WEQUALN(old_vr,
1307 wcs_buffer,
1308 wslen(wcs_buffer))) {
1309 old_vr = (wchar_t *) wschr(old_vr, (int) colon_char) + 1;
1310 }
1311 if ( (ha == ta) || (wslen(wcb_ta) == 0) ) {
1312 new_value = old_vr;
1313 } else {
1314 new_value = ALLOC_WC(length);
1315 new_value_allocated = true;
1316 WCSTOMBS(mbs_buffer, old_vr);
1317 (void) wsprintf(new_value,
1318 "/usr/arch/%s/%s:%s",
1319 ha->string_mb + 1,
1320 ta->string_mb + 1,
1321 mbs_buffer);
1322 }
1323 if (new_value[0] != 0) {
1324 (void) setvar_daemon(virtual_root,
1325 GETNAME(new_value, FIND_LENGTH),
1326 false,
1327 no_daemon,
1328 true,
1329 debug_level);
1330 }
1331 if (new_value_allocated) {
1332 retmem(new_value);
1333 }
1334 }
1335 return macro;
1336 }
|