Print this page
make: translate using gettext, rather than the unmaintainable catgets


  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 }