1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 /*
  26  * @(#)macro.cc 1.28 06/12/12
  27  */
  28 
  29 #pragma ident   "@(#)macro.cc   1.28    06/12/12"
  30 
  31 /*
  32  *      macro.cc
  33  *
  34  *      Handle expansion of make macros
  35  */
  36 
  37 /*
  38  * Included files
  39  */
  40 #ifdef DISTRIBUTED
  41 #include <avo/strings.h>  /* AVO_STRDUP() */
  42 #include <dm/Avo_DoJobMsg.h>
  43 #endif
  44 #include <mk/defs.h>
  45 #include <mksh/macro.h>           /* getvar(), expand_value() */
  46 #include <mksh/misc.h>            /* getmem() */
  47 
  48 /*
  49  * Defined macros
  50  */
  51 
  52 /*
  53  * typedefs & structs
  54  */
  55 
  56 /*
  57  * Static variables
  58  */
  59 
  60 /*
  61  * File table of contents
  62  */
  63 
  64 void
  65 setvar_append(register Name name, register Name value)
  66 {
  67         register Property       macro_apx = get_prop(name->prop, macro_append_prop);
  68         register Property       macro = get_prop(name->prop, macro_prop);
  69         int                     length;
  70         String_rec              destination;
  71         wchar_t                 buffer[STRING_BUFFER_LENGTH];
  72         register Chain          chain;
  73         Name                    val = NULL;
  74 
  75         if(macro_apx == NULL) {
  76                 macro_apx = append_prop(name, macro_append_prop);
  77                 if(macro != NULL) {
  78                         macro_apx->body.macro_appendix.value = macro->body.macro.value;
  79                 }
  80         }
  81 
  82         val = macro_apx->body.macro_appendix.value_to_append;
  83 
  84         INIT_STRING_FROM_STACK(destination, buffer);
  85         buffer[0] = 0;
  86         if (val != NULL) {
  87                 APPEND_NAME(val,
  88                               &destination,
  89                               (int) val->hash.length);
  90                 if (value != NULL) {
  91                         MBTOWC(wcs_buffer, " ");
  92                         append_char(wcs_buffer[0], &destination);
  93                 }
  94         }
  95         if (value != NULL) {
  96                 APPEND_NAME(value,
  97                               &destination,
  98                               (int) value->hash.length);
  99         }
 100         value = GETNAME(destination.buffer.start, FIND_LENGTH);
 101         if (destination.free_after_use) {
 102                 retmem(destination.buffer.start);
 103         }
 104         macro_apx->body.macro_appendix.value_to_append = value;
 105 
 106         SETVAR(name, empty_name, true);
 107 }
 108 
 109 /*
 110  *      setvar_envvar()
 111  *
 112  *      This function scans the list of environment variables that have
 113  *      dynamic values and sets them.
 114  *
 115  *      Parameters:
 116  *
 117  *      Global variables used:
 118  *              envvar          A list of environment vars with $ in value
 119  */
 120 void
 121 #ifdef DISTRIBUTED
 122 setvar_envvar(Avo_DoJobMsg *dmake_job_msg)
 123 #else
 124 setvar_envvar(void)
 125 #endif
 126 {
 127         wchar_t                 buffer[STRING_BUFFER_LENGTH];
 128         int                     length;
 129 #ifdef DISTRIBUTED
 130         Property                macro;
 131 #endif
 132         register        char    *mbs, *tmp_mbs_buffer = NULL;
 133         register        char    *env, *tmp_mbs_buffer2 = NULL;
 134         Envvar                  p;
 135         String_rec              value;
 136 
 137         for (p = envvar; p != NULL; p = p->next) {
 138                 if (p->already_put
 139 #ifdef DISTRIBUTED
 140                     && !dmake_job_msg
 141 #endif
 142                     ) {
 143                         continue;
 144                 }
 145                 INIT_STRING_FROM_STACK(value, buffer);          
 146                 expand_value(p->value, &value, false);
 147                 if ((length = wslen(value.buffer.start)) >= MAXPATHLEN) {
 148                         mbs = tmp_mbs_buffer = getmem((length + 1) * MB_LEN_MAX);
 149                         (void) wcstombs(mbs,
 150                                         value.buffer.start,
 151                                         (length + 1) * MB_LEN_MAX);
 152                 } else {
 153                         mbs = mbs_buffer;
 154                         WCSTOMBS(mbs, value.buffer.start);
 155                 }
 156                 length = 2 + strlen(p->name->string_mb) + strlen(mbs);
 157                 if (!p->already_put || length > (MAXPATHLEN * MB_LEN_MAX)) {
 158                         env = tmp_mbs_buffer2 = getmem(length);
 159                 } else {
 160                         env = mbs_buffer2;
 161                 }
 162                 (void) sprintf(env,
 163                                "%s=%s",
 164                                p->name->string_mb,
 165                                mbs);
 166                 if (!p->already_put) {
 167                         (void) putenv(env);
 168                         p->already_put = true;
 169                         if (p->env_string) {
 170                                 retmem_mb(p->env_string);
 171                         }
 172                         p->env_string = env;
 173                         tmp_mbs_buffer2 = NULL; // We should not return this memory now
 174                 }
 175 #ifdef DISTRIBUTED
 176                 if (dmake_job_msg) {
 177                         dmake_job_msg->appendVar(env);
 178                 }
 179 #endif
 180                 if (tmp_mbs_buffer2) {
 181                         retmem_mb(tmp_mbs_buffer2);
 182                         tmp_mbs_buffer2 = NULL;
 183                 }
 184                 if (tmp_mbs_buffer) {
 185                         retmem_mb(tmp_mbs_buffer);
 186                         tmp_mbs_buffer = NULL;
 187                 }
 188         }
 189 #ifdef DISTRIBUTED
 190         /* Append SUNPRO_DEPENDENCIES to the dmake_job_msg. */
 191         if (keep_state && dmake_job_msg) {
 192                 macro = get_prop(sunpro_dependencies->prop, macro_prop);
 193                 length = 2 +
 194                          strlen(sunpro_dependencies->string_mb) +
 195                          strlen(macro->body.macro.value->string_mb);
 196                 if (length > (MAXPATHLEN * MB_LEN_MAX)) {
 197                         env = tmp_mbs_buffer2 = getmem(length);
 198                 } else {
 199                         env = mbs_buffer2;
 200                 }
 201                 (void) sprintf(env,
 202                                "%s=%s",
 203                                sunpro_dependencies->string_mb,
 204                                macro->body.macro.value->string_mb);
 205                 dmake_job_msg->appendVar(env);
 206                 if (tmp_mbs_buffer2) {
 207                         retmem_mb(tmp_mbs_buffer2);
 208                         tmp_mbs_buffer2 = NULL;
 209                 }
 210         }
 211 #endif
 212 }
 213 
 214