root/opal/mca/base/mca_base_var.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mca_base_var_source_file
  2. mca_base_var_generate_full_name4
  3. compare_strings
  4. append_filename_to_list
  5. mca_base_var_init
  6. process_env_list
  7. mca_base_var_process_env_list
  8. mca_base_var_process_env_list_from_file
  9. resolve_relative_paths
  10. mca_base_var_cache_files
  11. mca_base_var_get_value
  12. var_set_string
  13. int_from_string
  14. var_set_from_string
  15. mca_base_var_set_value
  16. mca_base_var_deregister
  17. var_get
  18. mca_base_var_env_name
  19. var_find_by_name
  20. var_find
  21. mca_base_var_find
  22. mca_base_var_find_by_name
  23. mca_base_var_set_flag
  24. mca_base_var_get
  25. mca_base_var_build_env
  26. mca_base_var_finalize
  27. fixup_files
  28. read_files
  29. register_variable
  30. mca_base_var_register
  31. mca_base_component_var_register
  32. mca_base_framework_var_register
  33. mca_base_var_register_synonym
  34. var_get_env
  35. var_set_from_env
  36. var_set_from_file
  37. var_set_initial
  38. var_constructor
  39. var_destructor
  40. fv_constructor
  41. fv_destructor
  42. source_name
  43. var_value_string
  44. mca_base_var_check_exclusive
  45. mca_base_var_get_count
  46. mca_base_var_dump

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   2 /*
   3  * Copyright (c) 2004-2008 The Trustees of Indiana University and Indiana
   4  *                         University Research and Technology
   5  *                         Corporation.  All rights reserved.
   6  * Copyright (c) 2004-2012 The University of Tennessee and The University
   7  *                         of Tennessee Research Foundation.  All rights
   8  *                         reserved.
   9  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
  10  *                         University of Stuttgart.  All rights reserved.
  11  * Copyright (c) 2004-2005 The Regents of the University of California.
  12  *                         All rights reserved.
  13  * Copyright (c) 2008-2018 Cisco Systems, Inc.  All rights reserved
  14  * Copyright (c) 2012-2018 Los Alamos National Security, LLC. All rights
  15  *                         reserved.
  16  * Copyright (c) 2014-2016 Intel, Inc. All rights reserved.
  17  * Copyright (c) 2015      Research Organization for Information Science
  18  *                         and Technology (RIST). All rights reserved.
  19  * Copyright (c) 2017      IBM Corporation. All rights reserved.
  20  * Copyright (c) 2018      Amazon.com, Inc. or its affiliates.  All Rights reserved.
  21  * Copyright (c) 2018      Triad National Security, LLC. All rights
  22  *                         reserved.
  23  * $COPYRIGHT$
  24  *
  25  * Additional copyrights may follow
  26  *
  27  * $HEADER$
  28  */
  29 
  30 #include "opal_config.h"
  31 
  32 #include <stdio.h>
  33 #include <string.h>
  34 #include <stdlib.h>
  35 #ifdef HAVE_UNISTD_H
  36 #include <unistd.h>
  37 #endif
  38 #ifdef HAVE_SYS_PARAM_H
  39 #include <sys/param.h>
  40 #endif
  41 #include <errno.h>
  42 
  43 #include "opal/include/opal_stdint.h"
  44 #include "opal/mca/installdirs/installdirs.h"
  45 #include "opal/util/os_path.h"
  46 #include "opal/util/path.h"
  47 #include "opal/util/show_help.h"
  48 #include "opal/util/printf.h"
  49 #include "opal/util/argv.h"
  50 #include "opal/mca/mca.h"
  51 #include "opal/mca/base/mca_base_vari.h"
  52 #include "opal/constants.h"
  53 #include "opal/util/output.h"
  54 #include "opal/util/opal_environ.h"
  55 #include "opal/runtime/opal.h"
  56 
  57 /*
  58  * local variables
  59  */
  60 static opal_pointer_array_t mca_base_vars;
  61 static const char *mca_prefix = OPAL_MCA_PREFIX;
  62 static char *home = NULL;
  63 static char *cwd  = NULL;
  64 bool mca_base_var_initialized = false;
  65 static char * force_agg_path = NULL;
  66 static char *mca_base_var_files = NULL;
  67 static char *mca_base_envar_files = NULL;
  68 static char **mca_base_var_file_list = NULL;
  69 static char *mca_base_var_override_file = NULL;
  70 static char *mca_base_var_file_prefix = NULL;
  71 static char *mca_base_envar_file_prefix = NULL;
  72 static char *mca_base_param_file_path = NULL;
  73 char *mca_base_env_list = NULL;
  74 char *mca_base_env_list_sep = MCA_BASE_ENV_LIST_SEP_DEFAULT;
  75 char *mca_base_env_list_internal = NULL;
  76 static bool mca_base_var_suppress_override_warning = false;
  77 static opal_list_t mca_base_var_file_values;
  78 static opal_list_t mca_base_envar_file_values;
  79 static opal_list_t mca_base_var_override_values;
  80 
  81 static int mca_base_var_count = 0;
  82 
  83 static opal_hash_table_t mca_base_var_index_hash;
  84 
  85 const char *ompi_var_type_names[] = {
  86     "int",
  87     "unsigned_int",
  88     "unsigned_long",
  89     "unsigned_long_long",
  90     "size_t",
  91     "string",
  92     "version_string",
  93     "bool",
  94     "double",
  95     "long",
  96     "int32_t",
  97     "uint32_t",
  98     "int64_t",
  99     "uint64_t",
 100 };
 101 
 102 const size_t ompi_var_type_sizes[] = {
 103     sizeof (int),
 104     sizeof (unsigned),
 105     sizeof (unsigned long),
 106     sizeof (unsigned long long),
 107     sizeof (size_t),
 108     sizeof (char),
 109     sizeof (char),
 110     sizeof (bool),
 111     sizeof (double),
 112     sizeof (long),
 113     sizeof (int32_t),
 114     sizeof (uint32_t),
 115     sizeof (int64_t),
 116     sizeof (uint64_t),
 117 };
 118 
 119 static const char *var_source_names[] = {
 120     "default",
 121     "command line",
 122     "environment",
 123     "file",
 124     "set",
 125     "override"
 126 };
 127 
 128 
 129 static const char *info_lvl_strings[] = {
 130     "user/basic",
 131     "user/detail",
 132     "user/all",
 133     "tuner/basic",
 134     "tuner/detail",
 135     "tuner/all",
 136     "dev/basic",
 137     "dev/detail",
 138     "dev/all"
 139 };
 140 
 141 /*
 142  * local functions
 143  */
 144 static int fixup_files(char **file_list, char * path, bool rel_path_search, char sep);
 145 static int read_files (char *file_list, opal_list_t *file_values, char sep);
 146 static int var_set_initial (mca_base_var_t *var, mca_base_var_t *original);
 147 static int var_get (int vari, mca_base_var_t **var_out, bool original);
 148 static int var_value_string (mca_base_var_t *var, char **value_string);
 149 static void mca_base_var_finalize (void);
 150 
 151 /*
 152  * classes
 153  */
 154 static void var_constructor (mca_base_var_t *p);
 155 static void var_destructor (mca_base_var_t *p);
 156 OBJ_CLASS_INSTANCE(mca_base_var_t, opal_object_t,
 157                    var_constructor, var_destructor);
 158 
 159 static void fv_constructor (mca_base_var_file_value_t *p);
 160 static void fv_destructor (mca_base_var_file_value_t *p);
 161 OBJ_CLASS_INSTANCE(mca_base_var_file_value_t, opal_list_item_t,
 162                    fv_constructor, fv_destructor);
 163 
 164 static const char *mca_base_var_source_file (const mca_base_var_t *var)
 165 {
 166     mca_base_var_file_value_t *fv = (mca_base_var_file_value_t *) var->mbv_file_value;
 167 
 168     if (NULL != var->mbv_source_file) {
 169         return var->mbv_source_file;
 170     }
 171 
 172     if (fv) {
 173         return fv->mbvfv_file;
 174     }
 175 
 176     return NULL;
 177 }
 178 
 179 /*
 180  * Generate a full name from three names
 181  */
 182 int mca_base_var_generate_full_name4 (const char *project, const char *framework, const char *component,
 183                                       const char *variable, char **full_name)
 184 {
 185     const char * const names[] = {project, framework, component, variable};
 186     char *name, *tmp;
 187     size_t i, len;
 188 
 189     *full_name = NULL;
 190 
 191     for (i = 0, len = 0 ; i < 4 ; ++i) {
 192         if (NULL != names[i]) {
 193             /* Add space for the string + _ or \0 */
 194             len += strlen (names[i]) + 1;
 195         }
 196     }
 197 
 198     name = calloc (1, len);
 199     if (NULL == name) {
 200         return OPAL_ERR_OUT_OF_RESOURCE;
 201     }
 202 
 203     for (i = 0, tmp = name ; i < 4 ; ++i) {
 204         if (NULL != names[i]) {
 205             if (name != tmp) {
 206                 *tmp++ = '_';
 207             }
 208             strncat (name, names[i], len - (size_t)(uintptr_t)(tmp - name));
 209             tmp += strlen (names[i]);
 210         }
 211     }
 212 
 213     *full_name = name;
 214     return OPAL_SUCCESS;
 215 }
 216 
 217 static int compare_strings (const char *str1, const char *str2) {
 218     if ((NULL != str1 && 0 == strcmp (str1, "*")) ||
 219         (NULL == str1 && NULL == str2)) {
 220         return 0;
 221     }
 222 
 223     if (NULL != str1 && NULL != str2) {
 224         return strcmp (str1, str2);
 225     }
 226 
 227     return 1;
 228 }
 229 
 230 /*
 231  * Append a filename to the file list if it does not exist and return a
 232  * pointer to the filename in the list.
 233  */
 234 static char *append_filename_to_list(const char *filename)
 235 {
 236     int i, count;
 237 
 238     (void) opal_argv_append_unique_nosize(&mca_base_var_file_list, filename, false);
 239 
 240     count = opal_argv_count(mca_base_var_file_list);
 241 
 242     for (i = count - 1; i >= 0; --i) {
 243         if (0 == strcmp (mca_base_var_file_list[i], filename)) {
 244             return mca_base_var_file_list[i];
 245         }
 246     }
 247 
 248     /* *#@*? */
 249     return NULL;
 250 }
 251 
 252 /*
 253  * Set it up
 254  */
 255 int mca_base_var_init(void)
 256 {
 257     int ret;
 258 
 259     if (!mca_base_var_initialized) {
 260         /* Init the value array for the param storage */
 261 
 262         OBJ_CONSTRUCT(&mca_base_vars, opal_pointer_array_t);
 263         /* These values are arbitrary */
 264         ret = opal_pointer_array_init (&mca_base_vars, 128, 16384, 128);
 265         if (OPAL_SUCCESS != ret) {
 266             return ret;
 267         }
 268 
 269         mca_base_var_count = 0;
 270 
 271         /* Init the file param value list */
 272 
 273         OBJ_CONSTRUCT(&mca_base_var_file_values, opal_list_t);
 274         OBJ_CONSTRUCT(&mca_base_envar_file_values, opal_list_t);
 275         OBJ_CONSTRUCT(&mca_base_var_override_values, opal_list_t);
 276         OBJ_CONSTRUCT(&mca_base_var_index_hash, opal_hash_table_t);
 277 
 278         ret = opal_hash_table_init (&mca_base_var_index_hash, 1024);
 279         if (OPAL_SUCCESS != ret) {
 280             return ret;
 281         }
 282 
 283         ret = mca_base_var_group_init ();
 284         if  (OPAL_SUCCESS != ret) {
 285             return ret;
 286         }
 287 
 288         ret = mca_base_pvar_init ();
 289         if (OPAL_SUCCESS != ret) {
 290             return ret;
 291         }
 292 
 293         /* Set this before we register the parameter, below */
 294 
 295         mca_base_var_initialized = true;
 296 
 297     }
 298 
 299     opal_finalize_register_cleanup (mca_base_var_finalize);
 300 
 301     return OPAL_SUCCESS;
 302 }
 303 
 304 static void process_env_list(char *env_list, char ***argv, char sep)
 305 {
 306     char** tokens;
 307     char *ptr, *value;
 308 
 309     tokens = opal_argv_split(env_list, (int)sep);
 310     if (NULL == tokens) {
 311         return;
 312     }
 313 
 314     for (int i = 0 ; NULL != tokens[i] ; ++i) {
 315         if (NULL == (ptr = strchr(tokens[i], '='))) {
 316             value = getenv(tokens[i]);
 317             if (NULL == value) {
 318                 opal_show_help("help-mca-var.txt", "incorrect-env-list-param",
 319                                true, tokens[i], env_list);
 320                 break;
 321             }
 322 
 323             /* duplicate the value to silence tainted string coverity issue */
 324             value = strdup (value);
 325             if (NULL == value) {
 326                 /* out of memory */
 327                 break;
 328             }
 329 
 330             if (NULL != (ptr = strchr(value, '='))) {
 331                 *ptr = '\0';
 332                 opal_setenv(value, ptr + 1, true, argv);
 333             } else {
 334                 opal_setenv(tokens[i], value, true, argv);
 335             }
 336 
 337             free (value);
 338         } else {
 339             *ptr = '\0';
 340             opal_setenv(tokens[i], ptr + 1, true, argv);
 341             /* NTH: don't bother resetting ptr to = since the string will not be used again */
 342         }
 343     }
 344 
 345     opal_argv_free(tokens);
 346 }
 347 
 348 int mca_base_var_process_env_list(char *list, char ***argv)
 349 {
 350     char sep;
 351     sep = ';';
 352     if (NULL != mca_base_env_list_sep) {
 353         if (1 == strlen(mca_base_env_list_sep)) {
 354             sep = mca_base_env_list_sep[0];
 355         } else {
 356             opal_show_help("help-mca-var.txt", "incorrect-env-list-sep",
 357                     true, mca_base_env_list_sep);
 358             return OPAL_SUCCESS;
 359         }
 360     }
 361     if (NULL != list) {
 362         process_env_list(list, argv, sep);
 363     } else if (NULL != mca_base_env_list) {
 364         process_env_list(mca_base_env_list, argv, sep);
 365     }
 366 
 367     return OPAL_SUCCESS;
 368 }
 369 
 370 int mca_base_var_process_env_list_from_file(char ***argv)
 371 {
 372     if (NULL != mca_base_env_list_internal) {
 373         process_env_list(mca_base_env_list_internal, argv, ';');
 374     }
 375     return OPAL_SUCCESS;
 376 }
 377 
 378 static void resolve_relative_paths(char **file_prefix, char *file_path, bool rel_path_search, char **files, char sep)
 379 {
 380     char *tmp_str;
 381     /*
 382      * Resolve all relative paths.
 383      * the file list returned will contain only absolute paths
 384      */
 385     if( OPAL_SUCCESS != fixup_files(file_prefix, file_path, rel_path_search, sep) ) {
 386 #if 0
 387         /* JJH We need to die! */
 388         abort();
 389 #else
 390         ;
 391 #endif
 392     }
 393     else {
 394         /* Prepend the files to the search list */
 395         opal_asprintf(&tmp_str, "%s%c%s", *file_prefix, sep, *files);
 396         free (*files);
 397         *files = tmp_str;
 398     }
 399 }
 400 
 401 int mca_base_var_cache_files(bool rel_path_search)
 402 {
 403     char *tmp;
 404     int ret;
 405 
 406     /* We may need this later */
 407     home = (char*)opal_home_directory();
 408 
 409     if (NULL == cwd) {
 410         cwd = (char *) malloc(sizeof(char) * MAXPATHLEN);
 411         if( NULL == (cwd = getcwd(cwd, MAXPATHLEN) )) {
 412             opal_output(0, "Error: Unable to get the current working directory\n");
 413             cwd = strdup(".");
 414         }
 415     }
 416 
 417 #if OPAL_WANT_HOME_CONFIG_FILES
 418     opal_asprintf(&mca_base_var_files, "%s"OPAL_PATH_SEP".openmpi" OPAL_PATH_SEP
 419              "mca-params.conf%c%s" OPAL_PATH_SEP "openmpi-mca-params.conf",
 420              home, ',', opal_install_dirs.sysconfdir);
 421 #else
 422     opal_asprintf(&mca_base_var_files, "%s" OPAL_PATH_SEP "openmpi-mca-params.conf",
 423              opal_install_dirs.sysconfdir);
 424 #endif
 425 
 426     /* Initialize a parameter that says where MCA param files can be found.
 427        We may change this value so set the scope to MCA_BASE_VAR_SCOPE_READONLY */
 428     tmp = mca_base_var_files;
 429     ret = mca_base_var_register ("opal", "mca", "base", "param_files", "Path for MCA "
 430                                  "configuration files containing variable values",
 431                                  MCA_BASE_VAR_TYPE_STRING, NULL, 0, 0, OPAL_INFO_LVL_2,
 432                                  MCA_BASE_VAR_SCOPE_READONLY, &mca_base_var_files);
 433     free (tmp);
 434     if (0 > ret) {
 435         return ret;
 436     }
 437 
 438     mca_base_envar_files = strdup(mca_base_var_files);
 439 
 440     (void) mca_base_var_register_synonym (ret, "opal", "mca", NULL, "param_files",
 441                                           MCA_BASE_VAR_SYN_FLAG_DEPRECATED);
 442 
 443     ret = opal_asprintf(&mca_base_var_override_file, "%s" OPAL_PATH_SEP "openmpi-mca-params-override.conf",
 444                    opal_install_dirs.sysconfdir);
 445     if (0 > ret) {
 446         return OPAL_ERR_OUT_OF_RESOURCE;
 447     }
 448 
 449     tmp = mca_base_var_override_file;
 450     ret = mca_base_var_register ("opal", "mca", "base", "override_param_file",
 451                                  "Variables set in this file will override any value set in"
 452                                  "the environment or another configuration file",
 453                                  MCA_BASE_VAR_TYPE_STRING, NULL, 0, MCA_BASE_VAR_FLAG_DEFAULT_ONLY,
 454                                  OPAL_INFO_LVL_2, MCA_BASE_VAR_SCOPE_CONSTANT,
 455                                  &mca_base_var_override_file);
 456     free (tmp);
 457     if (0 > ret) {
 458         return ret;
 459     }
 460 
 461     /* Disable reading MCA parameter files. */
 462     if (0 == strcmp (mca_base_var_files, "none")) {
 463         return OPAL_SUCCESS;
 464     }
 465 
 466     mca_base_var_suppress_override_warning = false;
 467     ret = mca_base_var_register ("opal", "mca", "base", "suppress_override_warning",
 468                                  "Suppress warnings when attempting to set an overridden value (default: false)",
 469                                  MCA_BASE_VAR_TYPE_BOOL, NULL, 0, 0, OPAL_INFO_LVL_2,
 470                                  MCA_BASE_VAR_SCOPE_LOCAL, &mca_base_var_suppress_override_warning);
 471     if (0 > ret) {
 472         return ret;
 473     }
 474 
 475     /* Aggregate MCA parameter files
 476      * A prefix search path to look up aggregate MCA parameter file
 477      * requests that do not specify an absolute path
 478      */
 479     mca_base_var_file_prefix = NULL;
 480     ret = mca_base_var_register ("opal", "mca", "base", "param_file_prefix",
 481                                  "Aggregate MCA parameter file sets",
 482                                  MCA_BASE_VAR_TYPE_STRING, NULL, 0, 0, OPAL_INFO_LVL_3,
 483                                  MCA_BASE_VAR_SCOPE_READONLY, &mca_base_var_file_prefix);
 484     if (0 > ret) {
 485         return ret;
 486     }
 487 
 488     mca_base_envar_file_prefix = NULL;
 489     ret = mca_base_var_register ("opal", "mca", "base", "envar_file_prefix",
 490                                  "Aggregate MCA parameter file set for env variables",
 491                                  MCA_BASE_VAR_TYPE_STRING, NULL, 0, 0, OPAL_INFO_LVL_3,
 492                                  MCA_BASE_VAR_SCOPE_READONLY, &mca_base_envar_file_prefix);
 493     if (0 > ret) {
 494         return ret;
 495     }
 496 
 497     ret = opal_asprintf(&mca_base_param_file_path, "%s" OPAL_PATH_SEP "amca-param-sets%c%s",
 498                    opal_install_dirs.opaldatadir, OPAL_ENV_SEP, cwd);
 499     if (0 > ret) {
 500         return OPAL_ERR_OUT_OF_RESOURCE;
 501     }
 502 
 503     tmp = mca_base_param_file_path;
 504     ret = mca_base_var_register ("opal", "mca", "base", "param_file_path",
 505                                  "Aggregate MCA parameter Search path",
 506                                  MCA_BASE_VAR_TYPE_STRING, NULL, 0, 0, OPAL_INFO_LVL_3,
 507                                  MCA_BASE_VAR_SCOPE_READONLY, &mca_base_param_file_path);
 508     free (tmp);
 509     if (0 > ret) {
 510         return ret;
 511     }
 512 
 513     force_agg_path = NULL;
 514     ret = mca_base_var_register ("opal", "mca", "base", "param_file_path_force",
 515                                  "Forced Aggregate MCA parameter Search path",
 516                                  MCA_BASE_VAR_TYPE_STRING, NULL, 0, 0, OPAL_INFO_LVL_3,
 517                                  MCA_BASE_VAR_SCOPE_READONLY, &force_agg_path);
 518     if (0 > ret) {
 519         return ret;
 520     }
 521 
 522     if (NULL != force_agg_path) {
 523         if (NULL != mca_base_param_file_path) {
 524             char *tmp_str = mca_base_param_file_path;
 525 
 526             opal_asprintf(&mca_base_param_file_path, "%s%c%s", force_agg_path, OPAL_ENV_SEP, tmp_str);
 527             free(tmp_str);
 528         } else {
 529             mca_base_param_file_path = strdup(force_agg_path);
 530         }
 531     }
 532 
 533     if (NULL != mca_base_var_file_prefix) {
 534        resolve_relative_paths(&mca_base_var_file_prefix, mca_base_param_file_path, rel_path_search, &mca_base_var_files, OPAL_ENV_SEP);
 535     }
 536     read_files (mca_base_var_files, &mca_base_var_file_values, ',');
 537 
 538     if (NULL != mca_base_envar_file_prefix) {
 539        resolve_relative_paths(&mca_base_envar_file_prefix, mca_base_param_file_path, rel_path_search, &mca_base_envar_files, ',');
 540     }
 541     read_files (mca_base_envar_files, &mca_base_envar_file_values, ',');
 542 
 543     if (0 == access(mca_base_var_override_file, F_OK)) {
 544         read_files (mca_base_var_override_file, &mca_base_var_override_values, OPAL_ENV_SEP);
 545     }
 546 
 547     return OPAL_SUCCESS;
 548 }
 549 
 550 /*
 551  * Look up an integer MCA parameter.
 552  */
 553 int mca_base_var_get_value (int vari, const void *value,
 554                             mca_base_var_source_t *source,
 555                             const char **source_file)
 556 {
 557     mca_base_var_t *var;
 558     void **tmp = (void **) value;
 559     int ret;
 560 
 561     ret = var_get (vari, &var, true);
 562     if (OPAL_SUCCESS != ret) {
 563         return ret;
 564     }
 565 
 566     if (!VAR_IS_VALID(var[0])) {
 567         return OPAL_ERR_NOT_FOUND;
 568     }
 569 
 570     if (NULL != value) {
 571         /* Return a poiner to our backing store (either a char **, int *,
 572            or bool *) */
 573         *tmp = var->mbv_storage;
 574     }
 575 
 576     if (NULL != source) {
 577         *source = var->mbv_source;
 578     }
 579 
 580     if (NULL != source_file) {
 581         *source_file = mca_base_var_source_file (var);
 582     }
 583 
 584     return OPAL_SUCCESS;
 585 }
 586 
 587 static int var_set_string (mca_base_var_t *var, char *value)
 588 {
 589     char *tmp;
 590     int ret;
 591 
 592     if (NULL != var->mbv_storage->stringval) {
 593         free (var->mbv_storage->stringval);
 594     }
 595 
 596     var->mbv_storage->stringval = NULL;
 597 
 598     if (NULL == value || 0 == strlen (value)) {
 599         return OPAL_SUCCESS;
 600     }
 601 
 602     /* Replace all instances of ~/ in a path-style string with the
 603        user's home directory. This may be handled by the enumerator
 604        in the future. */
 605     if (0 == strncmp (value, "~/", 2)) {
 606         if (NULL != home) {
 607             ret = opal_asprintf (&value, "%s/%s", home, value + 2);
 608             if (0 > ret) {
 609                 return OPAL_ERROR;
 610             }
 611         } else {
 612             value = strdup (value + 2);
 613         }
 614     } else {
 615         value = strdup (value);
 616     }
 617 
 618     if (NULL == value) {
 619         return OPAL_ERR_OUT_OF_RESOURCE;
 620     }
 621 
 622     while (NULL != (tmp = strstr (value, ":~/"))) {
 623         tmp[0] = '\0';
 624         tmp += 3;
 625 
 626         ret = opal_asprintf (&tmp, "%s:%s%s%s", value,
 627                         home ? home : "", home ? "/" : "", tmp);
 628 
 629         free (value);
 630 
 631         if (0 > ret) {
 632             return OPAL_ERR_OUT_OF_RESOURCE;
 633         }
 634 
 635         value = tmp;
 636     }
 637 
 638     var->mbv_storage->stringval = value;
 639 
 640     return OPAL_SUCCESS;
 641 }
 642 
 643 static int int_from_string(const char *src, mca_base_var_enum_t *enumerator, uint64_t *value_out)
 644 {
 645     uint64_t value;
 646     bool is_int;
 647     char *tmp;
 648 
 649     if (NULL == src || 0 == strlen (src)) {
 650         if (NULL == enumerator) {
 651             *value_out = 0;
 652         }
 653 
 654         return OPAL_SUCCESS;
 655     }
 656 
 657     if (enumerator) {
 658         int int_val, ret;
 659         ret = enumerator->value_from_string(enumerator, src, &int_val);
 660         if (OPAL_SUCCESS != ret) {
 661             return ret;
 662         }
 663         *value_out = (uint64_t) int_val;
 664 
 665         return OPAL_SUCCESS;
 666     }
 667 
 668     /* Check for an integer value */
 669     value = strtoull (src, &tmp, 0);
 670     is_int = tmp[0] == '\0';
 671 
 672     if (!is_int && tmp != src) {
 673         switch (tmp[0]) {
 674         case 'G':
 675         case 'g':
 676             value <<= 10;
 677         case 'M':
 678         case 'm':
 679             value <<= 10;
 680         case 'K':
 681         case 'k':
 682             value <<= 10;
 683             break;
 684         default:
 685             break;
 686         }
 687     }
 688 
 689     *value_out = value;
 690 
 691     return OPAL_SUCCESS;
 692 }
 693 
 694 static int var_set_from_string (mca_base_var_t *var, char *src)
 695 {
 696     mca_base_var_storage_t *dst = var->mbv_storage;
 697     uint64_t int_value = 0;
 698     int ret;
 699 
 700     switch (var->mbv_type) {
 701     case MCA_BASE_VAR_TYPE_INT:
 702     case MCA_BASE_VAR_TYPE_INT32_T:
 703     case MCA_BASE_VAR_TYPE_UINT32_T:
 704     case MCA_BASE_VAR_TYPE_LONG:
 705     case MCA_BASE_VAR_TYPE_UNSIGNED_INT:
 706     case MCA_BASE_VAR_TYPE_UNSIGNED_LONG:
 707     case MCA_BASE_VAR_TYPE_INT64_T:
 708     case MCA_BASE_VAR_TYPE_UINT64_T:
 709     case MCA_BASE_VAR_TYPE_UNSIGNED_LONG_LONG:
 710     case MCA_BASE_VAR_TYPE_BOOL:
 711     case MCA_BASE_VAR_TYPE_SIZE_T:
 712         ret = int_from_string(src, var->mbv_enumerator, &int_value);
 713         if (OPAL_SUCCESS != ret ||
 714             (MCA_BASE_VAR_TYPE_INT == var->mbv_type && ((int) int_value != (int64_t) int_value)) ||
 715             (MCA_BASE_VAR_TYPE_UNSIGNED_INT == var->mbv_type && ((unsigned int) int_value != int_value))) {
 716             if (var->mbv_enumerator) {
 717                 char *valid_values;
 718                 (void) var->mbv_enumerator->dump(var->mbv_enumerator, &valid_values);
 719                 opal_show_help("help-mca-var.txt", "invalid-value-enum",
 720                                true, var->mbv_full_name, src, valid_values);
 721                 free(valid_values);
 722             } else {
 723                 opal_show_help("help-mca-var.txt", "invalid-value",
 724                                true, var->mbv_full_name, src);
 725             }
 726 
 727             return OPAL_ERR_VALUE_OUT_OF_BOUNDS;
 728         }
 729 
 730         if (MCA_BASE_VAR_TYPE_INT == var->mbv_type ||
 731             MCA_BASE_VAR_TYPE_UNSIGNED_INT == var->mbv_type) {
 732             int *castme = (int*) var->mbv_storage;
 733             *castme = int_value;
 734         } else if (MCA_BASE_VAR_TYPE_INT32_T == var->mbv_type ||
 735             MCA_BASE_VAR_TYPE_UINT32_T == var->mbv_type) {
 736             int32_t *castme = (int32_t *) var->mbv_storage;
 737             *castme = int_value;
 738         } else if (MCA_BASE_VAR_TYPE_INT64_T == var->mbv_type ||
 739             MCA_BASE_VAR_TYPE_UINT64_T == var->mbv_type) {
 740             int64_t *castme = (int64_t *) var->mbv_storage;
 741             *castme = int_value;
 742         } else if (MCA_BASE_VAR_TYPE_LONG == var->mbv_type) {
 743             long *castme = (long*) var->mbv_storage;
 744             *castme = (long) int_value;
 745         } else if (MCA_BASE_VAR_TYPE_UNSIGNED_LONG == var->mbv_type) {
 746             unsigned long *castme = (unsigned long*) var->mbv_storage;
 747             *castme = (unsigned long) int_value;
 748         } else if (MCA_BASE_VAR_TYPE_UNSIGNED_LONG_LONG == var->mbv_type) {
 749             unsigned long long *castme = (unsigned long long*) var->mbv_storage;
 750             *castme = (unsigned long long) int_value;
 751         } else if (MCA_BASE_VAR_TYPE_SIZE_T == var->mbv_type) {
 752             size_t *castme = (size_t*) var->mbv_storage;
 753             *castme = (size_t) int_value;
 754         } else if (MCA_BASE_VAR_TYPE_BOOL == var->mbv_type) {
 755             bool *castme = (bool*) var->mbv_storage;
 756             *castme = !!int_value;
 757         }
 758 
 759         return ret;
 760     case MCA_BASE_VAR_TYPE_DOUBLE:
 761         dst->lfval = strtod (src, NULL);
 762         break;
 763     case MCA_BASE_VAR_TYPE_STRING:
 764     case MCA_BASE_VAR_TYPE_VERSION_STRING:
 765         var_set_string (var, src);
 766         break;
 767     case MCA_BASE_VAR_TYPE_MAX:
 768         return OPAL_ERROR;
 769     }
 770 
 771     return OPAL_SUCCESS;
 772 }
 773 
 774 /*
 775  * Set a variable
 776  */
 777 int mca_base_var_set_value (int vari, const void *value, size_t size, mca_base_var_source_t source,
 778                             const char *source_file)
 779 {
 780     mca_base_var_t *var;
 781     int ret;
 782 
 783     ret = var_get (vari, &var, true);
 784     if (OPAL_SUCCESS != ret) {
 785         return ret;
 786     }
 787 
 788     if (!VAR_IS_VALID(var[0])) {
 789         return OPAL_ERR_BAD_PARAM;
 790     }
 791 
 792     if (!VAR_IS_SETTABLE(var[0])) {
 793         return OPAL_ERR_PERM;
 794     }
 795 
 796     if (NULL != var->mbv_enumerator) {
 797         /* Validate */
 798         ret = var->mbv_enumerator->string_from_value(var->mbv_enumerator,
 799                                                      ((int *) value)[0], NULL);
 800         if (OPAL_SUCCESS != ret) {
 801             return ret;
 802         }
 803     }
 804 
 805     if (MCA_BASE_VAR_TYPE_STRING != var->mbv_type && MCA_BASE_VAR_TYPE_VERSION_STRING != var->mbv_type) {
 806         memmove (var->mbv_storage, value, ompi_var_type_sizes[var->mbv_type]);
 807     } else {
 808         var_set_string (var, (char *) value);
 809     }
 810 
 811     var->mbv_source = source;
 812 
 813     if (MCA_BASE_VAR_SOURCE_FILE == source && NULL != source_file) {
 814         var->mbv_file_value = NULL;
 815         var->mbv_source_file = append_filename_to_list(source_file);
 816     }
 817 
 818     return OPAL_SUCCESS;
 819 }
 820 
 821 /*
 822  * Deregister a parameter
 823  */
 824 int mca_base_var_deregister(int vari)
 825 {
 826     mca_base_var_t *var;
 827     int ret;
 828 
 829     ret = var_get (vari, &var, false);
 830     if (OPAL_SUCCESS != ret) {
 831         return ret;
 832     }
 833 
 834     if (!VAR_IS_VALID(var[0])) {
 835         return OPAL_ERR_BAD_PARAM;
 836     }
 837 
 838     /* Mark this parameter as invalid but keep its info in case this
 839        parameter is reregistered later */
 840     var->mbv_flags &= ~MCA_BASE_VAR_FLAG_VALID;
 841 
 842     /* Done deregistering synonym */
 843     if (MCA_BASE_VAR_FLAG_SYNONYM & var->mbv_flags) {
 844         return OPAL_SUCCESS;
 845     }
 846 
 847     /* Release the current value if it is a string. */
 848     if ((MCA_BASE_VAR_TYPE_STRING == var->mbv_type || MCA_BASE_VAR_TYPE_VERSION_STRING == var->mbv_type) &&
 849         var->mbv_storage->stringval) {
 850         free (var->mbv_storage->stringval);
 851         var->mbv_storage->stringval = NULL;
 852     } else if (var->mbv_enumerator && !var->mbv_enumerator->enum_is_static) {
 853         OBJ_RELEASE(var->mbv_enumerator);
 854     }
 855 
 856     var->mbv_enumerator = NULL;
 857 
 858     var->mbv_storage = NULL;
 859 
 860     return OPAL_SUCCESS;
 861 }
 862 
 863 static int var_get (int vari, mca_base_var_t **var_out, bool original)
 864 {
 865     mca_base_var_t *var;
 866 
 867     if (var_out) {
 868         *var_out = NULL;
 869     }
 870 
 871     /* Check for bozo cases */
 872     if (!mca_base_var_initialized) {
 873         return OPAL_ERROR;
 874     }
 875 
 876     if (vari < 0) {
 877         return OPAL_ERR_BAD_PARAM;
 878     }
 879 
 880     var = opal_pointer_array_get_item (&mca_base_vars, vari);
 881     if (NULL == var) {
 882         return OPAL_ERR_BAD_PARAM;
 883     }
 884 
 885     if (VAR_IS_SYNONYM(var[0]) && original) {
 886         return var_get(var->mbv_synonym_for, var_out, false);
 887     }
 888 
 889     if (var_out) {
 890         *var_out = var;
 891     }
 892 
 893     return OPAL_SUCCESS;
 894 }
 895 
 896 int mca_base_var_env_name(const char *param_name,
 897                           char **env_name)
 898 {
 899     int ret;
 900 
 901     assert (NULL != env_name);
 902 
 903     ret = opal_asprintf(env_name, "%s%s", mca_prefix, param_name);
 904     if (0 > ret) {
 905         return OPAL_ERR_OUT_OF_RESOURCE;
 906     }
 907 
 908     return OPAL_SUCCESS;
 909 }
 910 
 911 /*
 912  * Find the index for an MCA parameter based on its names.
 913  */
 914 static int var_find_by_name (const char *full_name, int *vari, bool invalidok)
 915 {
 916     mca_base_var_t *var = NULL;
 917     void *tmp;
 918     int rc;
 919 
 920     rc = opal_hash_table_get_value_ptr (&mca_base_var_index_hash, full_name, strlen (full_name),
 921                                         &tmp);
 922     if (OPAL_SUCCESS != rc) {
 923         return rc;
 924     }
 925 
 926     (void) var_get ((int)(uintptr_t) tmp, &var, false);
 927 
 928     if (invalidok || (var && VAR_IS_VALID(var[0]))) {
 929         *vari = (int)(uintptr_t) tmp;
 930         return OPAL_SUCCESS;
 931     }
 932 
 933     return OPAL_ERR_NOT_FOUND;
 934 }
 935 
 936 static int var_find (const char *project_name, const char *framework_name,
 937                      const char *component_name, const char *variable_name,
 938                      bool invalidok)
 939 {
 940     char *full_name;
 941     int ret, vari;
 942 
 943     ret = mca_base_var_generate_full_name4 (NULL, framework_name, component_name,
 944                                             variable_name, &full_name);
 945     if (OPAL_SUCCESS != ret) {
 946         return OPAL_ERROR;
 947     }
 948 
 949     ret = var_find_by_name(full_name, &vari, invalidok);
 950 
 951     /* NTH: should we verify the name components match? */
 952 
 953     free (full_name);
 954 
 955     if (OPAL_SUCCESS != ret) {
 956         return ret;
 957     }
 958 
 959     return vari;
 960 }
 961 
 962 /*
 963  * Find the index for an MCA parameter based on its name components.
 964  */
 965 int mca_base_var_find (const char *project_name, const char *framework_name,
 966                        const char *component_name, const char *variable_name)
 967 {
 968     return var_find (project_name, framework_name, component_name, variable_name, false);
 969 }
 970 
 971 /*
 972  * Find the index for an MCA parameter based on full name.
 973  */
 974 int mca_base_var_find_by_name (const char *full_name, int *vari)
 975 {
 976     return var_find_by_name (full_name, vari, false);
 977 }
 978 
 979 int mca_base_var_set_flag (int vari, mca_base_var_flag_t flag, bool set)
 980 {
 981     mca_base_var_t *var;
 982     int ret;
 983 
 984     ret = var_get (vari, &var, true);
 985     if (OPAL_SUCCESS != ret || VAR_IS_SYNONYM(var[0])) {
 986         return OPAL_ERR_BAD_PARAM;
 987     }
 988 
 989     var->mbv_flags = (var->mbv_flags & ~flag) | (set ? flag : 0);
 990 
 991     /* All done */
 992     return OPAL_SUCCESS;
 993 }
 994 
 995 /*
 996  * Return info on a parameter at an index
 997  */
 998 int mca_base_var_get (int vari, const mca_base_var_t **var)
 999 {
1000     int ret;
1001     ret = var_get (vari, (mca_base_var_t **) var, false);
1002 
1003     if (OPAL_SUCCESS != ret) {
1004         return ret;
1005     }
1006 
1007     if (!VAR_IS_VALID(*(var[0]))) {
1008         return OPAL_ERR_NOT_FOUND;
1009     }
1010 
1011     return OPAL_SUCCESS;
1012 }
1013 
1014 /*
1015  * Make an argv-style list of strings suitable for an environment
1016  */
1017 int mca_base_var_build_env(char ***env, int *num_env, bool internal)
1018 {
1019     mca_base_var_t *var;
1020     size_t i, len;
1021     int ret;
1022 
1023     /* Check for bozo cases */
1024 
1025     if (!mca_base_var_initialized) {
1026         return OPAL_ERROR;
1027     }
1028 
1029     /* Iterate through all the registered parameters */
1030 
1031     len = opal_pointer_array_get_size(&mca_base_vars);
1032     for (i = 0; i < len; ++i) {
1033         char *value_string;
1034         char *str = NULL;
1035 
1036         var = opal_pointer_array_get_item (&mca_base_vars, i);
1037         if (NULL == var) {
1038             continue;
1039         }
1040 
1041         /* Don't output default values or internal variables (unless
1042            requested) */
1043         if (MCA_BASE_VAR_SOURCE_DEFAULT == var->mbv_source ||
1044             (!internal && VAR_IS_INTERNAL(var[0]))) {
1045             continue;
1046         }
1047 
1048         if ((MCA_BASE_VAR_TYPE_STRING == var->mbv_type || MCA_BASE_VAR_TYPE_VERSION_STRING == var->mbv_type) &&
1049             NULL == var->mbv_storage->stringval) {
1050             continue;
1051         }
1052 
1053         ret = var_value_string (var, &value_string);
1054         if (OPAL_SUCCESS != ret) {
1055             goto cleanup;
1056         }
1057 
1058         ret = opal_asprintf (&str, "%s%s=%s", mca_prefix, var->mbv_full_name,
1059                         value_string);
1060         free (value_string);
1061         if (0 > ret) {
1062             goto cleanup;
1063         }
1064 
1065         opal_argv_append(num_env, env, str);
1066         free(str);
1067 
1068         switch (var->mbv_source) {
1069         case MCA_BASE_VAR_SOURCE_FILE:
1070         case MCA_BASE_VAR_SOURCE_OVERRIDE:
1071             opal_asprintf (&str, "%sSOURCE_%s=FILE:%s", mca_prefix, var->mbv_full_name,
1072                       mca_base_var_source_file (var));
1073             break;
1074         case MCA_BASE_VAR_SOURCE_COMMAND_LINE:
1075             opal_asprintf (&str, "%sSOURCE_%s=COMMAND_LINE", mca_prefix, var->mbv_full_name);
1076             break;
1077         case MCA_BASE_VAR_SOURCE_ENV:
1078         case MCA_BASE_VAR_SOURCE_SET:
1079         case MCA_BASE_VAR_SOURCE_DEFAULT:
1080             str = NULL;
1081             break;
1082         case MCA_BASE_VAR_SOURCE_MAX:
1083             goto cleanup;
1084         }
1085 
1086         if (NULL != str) {
1087             opal_argv_append(num_env, env, str);
1088             free(str);
1089         }
1090     }
1091 
1092     /* All done */
1093 
1094     return OPAL_SUCCESS;
1095 
1096     /* Error condition */
1097 
1098  cleanup:
1099     if (*num_env > 0) {
1100         opal_argv_free(*env);
1101         *num_env = 0;
1102         *env = NULL;
1103     }
1104     return OPAL_ERR_NOT_FOUND;
1105 }
1106 
1107 /*
1108  * Shut down the MCA parameter system (normally only invoked by the
1109  * MCA framework itself).
1110  */
1111 static void mca_base_var_finalize (void)
1112 {
1113     opal_object_t *object;
1114     opal_list_item_t *item;
1115     int size, i;
1116 
1117     if (mca_base_var_initialized) {
1118         size = opal_pointer_array_get_size(&mca_base_vars);
1119         for (i = 0 ; i < size ; ++i) {
1120             object = opal_pointer_array_get_item (&mca_base_vars, i);
1121             if (NULL != object) {
1122                 OBJ_RELEASE(object);
1123             }
1124         }
1125         OBJ_DESTRUCT(&mca_base_vars);
1126 
1127         while (NULL !=
1128                (item = opal_list_remove_first(&mca_base_var_file_values))) {
1129             OBJ_RELEASE(item);
1130         }
1131         OBJ_DESTRUCT(&mca_base_var_file_values);
1132 
1133         while (NULL !=
1134                (item = opal_list_remove_first(&mca_base_envar_file_values))) {
1135             OBJ_RELEASE(item);
1136         }
1137         OBJ_DESTRUCT(&mca_base_envar_file_values);
1138 
1139         while (NULL !=
1140                (item = opal_list_remove_first(&mca_base_var_override_values))) {
1141             OBJ_RELEASE(item);
1142         }
1143         OBJ_DESTRUCT(&mca_base_var_override_values);
1144 
1145         if( NULL != cwd ) {
1146             free(cwd);
1147             cwd = NULL;
1148         }
1149 
1150         mca_base_var_initialized = false;
1151         mca_base_var_count = 0;
1152 
1153         if (NULL != mca_base_var_file_list) {
1154             opal_argv_free(mca_base_var_file_list);
1155         }
1156         mca_base_var_file_list = NULL;
1157 
1158         (void) mca_base_var_group_finalize ();
1159         (void) mca_base_pvar_finalize ();
1160 
1161         OBJ_DESTRUCT(&mca_base_var_index_hash);
1162 
1163         free (mca_base_envar_files);
1164         mca_base_envar_files = NULL;
1165     }
1166 }
1167 
1168 
1169 /*************************************************************************/
1170 static int fixup_files(char **file_list, char * path, bool rel_path_search, char sep) {
1171     int exit_status = OPAL_SUCCESS;
1172     char **files = NULL;
1173     char **search_path = NULL;
1174     char * tmp_file = NULL;
1175     char **argv = NULL;
1176     char *rel_path;
1177     int mode = R_OK; /* The file exists, and we can read it */
1178     int count, i, argc = 0;
1179 
1180     search_path = opal_argv_split(path, OPAL_ENV_SEP);
1181     files = opal_argv_split(*file_list, sep);
1182     count = opal_argv_count(files);
1183 
1184     rel_path = force_agg_path ? force_agg_path : cwd;
1185 
1186     /* Read in reverse order, so we can preserve the original ordering */
1187     for (i = 0 ; i < count; ++i) {
1188         char *msg_path = path;
1189         if (opal_path_is_absolute(files[i])) {
1190             /* Absolute paths preserved */
1191             tmp_file = opal_path_access(files[i], NULL, mode);
1192         } else if (!rel_path_search && NULL != strchr(files[i], OPAL_PATH_SEP[0])) {
1193             /* Resolve all relative paths:
1194              *  - If filename contains a "/" (e.g., "./foo" or "foo/bar")
1195              *    - look for it relative to cwd
1196              *    - if exists, use it
1197              *    - ow warn/error
1198              */
1199             msg_path = rel_path;
1200             tmp_file = opal_path_access(files[i], rel_path, mode);
1201         } else {
1202             /* Resolve all relative paths:
1203              * - Use path resolution
1204              *    - if found and readable, use it
1205              *    - otherwise, warn/error
1206              */
1207             tmp_file = opal_path_find (files[i], search_path, mode, NULL);
1208         }
1209 
1210         if (NULL == tmp_file) {
1211             opal_show_help("help-mca-var.txt", "missing-param-file",
1212                            true, getpid(), files[i], msg_path);
1213             exit_status = OPAL_ERROR;
1214             break;
1215         }
1216 
1217         opal_argv_append(&argc, &argv, tmp_file);
1218 
1219         free(tmp_file);
1220         tmp_file = NULL;
1221     }
1222 
1223     if (OPAL_SUCCESS == exit_status) {
1224         free(*file_list);
1225         *file_list = opal_argv_join(argv, sep);
1226     }
1227 
1228     if( NULL != files ) {
1229         opal_argv_free(files);
1230         files = NULL;
1231     }
1232 
1233     if( NULL != argv ) {
1234         opal_argv_free(argv);
1235         argv = NULL;
1236     }
1237 
1238     if( NULL != search_path ) {
1239         opal_argv_free(search_path);
1240         search_path = NULL;
1241     }
1242 
1243     return exit_status;
1244 }
1245 
1246 static int read_files(char *file_list, opal_list_t *file_values, char sep)
1247 {
1248     char **tmp = opal_argv_split(file_list, sep);
1249     int i, count;
1250 
1251     if (!tmp) {
1252         return OPAL_ERR_OUT_OF_RESOURCE;
1253     }
1254 
1255     count = opal_argv_count(tmp);
1256 
1257     /* Iterate through all the files passed in -- read them in reverse
1258        order so that we preserve unix/shell path-like semantics (i.e.,
1259        the entries farthest to the left get precedence) */
1260 
1261     for (i = count - 1; i >= 0; --i) {
1262         char *file_name = append_filename_to_list (tmp[i]);
1263         mca_base_parse_paramfile(file_name, file_values);
1264     }
1265 
1266     opal_argv_free (tmp);
1267 
1268     mca_base_internal_env_store();
1269 
1270     return OPAL_SUCCESS;
1271 }
1272 
1273 /******************************************************************************/
1274 static int register_variable (const char *project_name, const char *framework_name,
1275                               const char *component_name, const char *variable_name,
1276                               const char *description, mca_base_var_type_t type,
1277                               mca_base_var_enum_t *enumerator, int bind,
1278                               mca_base_var_flag_t flags, mca_base_var_info_lvl_t info_lvl,
1279                               mca_base_var_scope_t scope, int synonym_for,
1280                               void *storage)
1281 {
1282     int ret, var_index, group_index, tmp;
1283     mca_base_var_group_t *group;
1284     mca_base_var_t *var, *original = NULL;
1285 
1286     /* Developer error. Storage can not be NULL and type must exist */
1287     assert (((flags & MCA_BASE_VAR_FLAG_SYNONYM) || NULL != storage) && type >= 0 && type < MCA_BASE_VAR_TYPE_MAX);
1288 
1289     /* Developer error: check max length of strings */
1290     if (NULL != project_name &&
1291         strlen(project_name) > MCA_BASE_MAX_PROJECT_NAME_LEN) {
1292         return OPAL_ERR_BAD_PARAM;
1293     }
1294     if (NULL != framework_name &&
1295         strlen(framework_name) > MCA_BASE_MAX_TYPE_NAME_LEN) {
1296         return OPAL_ERR_BAD_PARAM;
1297     }
1298     if (NULL != component_name &&
1299         strlen(component_name) > MCA_BASE_MAX_COMPONENT_NAME_LEN) {
1300         return OPAL_ERR_BAD_PARAM;
1301     }
1302     if (NULL != variable_name &&
1303         strlen(variable_name) > MCA_BASE_MAX_VARIABLE_NAME_LEN) {
1304         return OPAL_ERR_BAD_PARAM;
1305     }
1306 
1307 #if OPAL_ENABLE_DEBUG
1308     /* Developer error: check for alignments */
1309     uintptr_t align = 0;
1310     switch (type) {
1311     case MCA_BASE_VAR_TYPE_INT:
1312     case MCA_BASE_VAR_TYPE_UNSIGNED_INT:
1313         align = OPAL_ALIGNMENT_INT;
1314         break;
1315     case MCA_BASE_VAR_TYPE_INT32_T:
1316     case MCA_BASE_VAR_TYPE_UINT32_T:
1317         align = OPAL_ALIGNMENT_INT32;
1318         break;
1319     case MCA_BASE_VAR_TYPE_INT64_T:
1320     case MCA_BASE_VAR_TYPE_UINT64_T:
1321         align = OPAL_ALIGNMENT_INT64;
1322         break;
1323     case MCA_BASE_VAR_TYPE_LONG:
1324     case MCA_BASE_VAR_TYPE_UNSIGNED_LONG:
1325         align = OPAL_ALIGNMENT_LONG;
1326         break;
1327     case MCA_BASE_VAR_TYPE_UNSIGNED_LONG_LONG:
1328         align = OPAL_ALIGNMENT_LONG_LONG;
1329         break;
1330     case MCA_BASE_VAR_TYPE_SIZE_T:
1331         align = OPAL_ALIGNMENT_SIZE_T;
1332         break;
1333     case MCA_BASE_VAR_TYPE_BOOL:
1334         align = OPAL_ALIGNMENT_BOOL;
1335         break;
1336     case MCA_BASE_VAR_TYPE_DOUBLE:
1337         align = OPAL_ALIGNMENT_DOUBLE;
1338         break;
1339     case MCA_BASE_VAR_TYPE_VERSION_STRING:
1340     case MCA_BASE_VAR_TYPE_STRING:
1341     default:
1342         align = 0;
1343         break;
1344     }
1345 
1346     if (0 != align) {
1347         assert(((uintptr_t) storage) % align == 0);
1348     }
1349 
1350     /* Also check to ensure that synonym_for>=0 when
1351        MCA_BCASE_VAR_FLAG_SYNONYM is specified */
1352     if (flags & MCA_BASE_VAR_FLAG_SYNONYM && synonym_for < 0) {
1353         assert((flags & MCA_BASE_VAR_FLAG_SYNONYM) && synonym_for >= 0);
1354     }
1355 #endif
1356 
1357     if (flags & MCA_BASE_VAR_FLAG_SYNONYM) {
1358         original = opal_pointer_array_get_item (&mca_base_vars, synonym_for);
1359         if (NULL == original) {
1360             /* Attempting to create a synonym for a non-existent variable. probably a
1361              * developer error. */
1362             assert (NULL != original);
1363             return OPAL_ERR_NOT_FOUND;
1364         }
1365     }
1366 
1367     /* There are data holes in the var struct */
1368     OPAL_DEBUG_ZERO(var);
1369 
1370     /* Initialize the array if it has never been initialized */
1371     if (!mca_base_var_initialized) {
1372         mca_base_var_init();
1373     }
1374 
1375     /* See if this entry is already in the array */
1376     var_index = var_find (project_name, framework_name, component_name, variable_name,
1377                           true);
1378 
1379     if (0 > var_index) {
1380         /* Create a new parameter entry */
1381         group_index = mca_base_var_group_register (project_name, framework_name, component_name,
1382                                                    NULL);
1383         if (-1 > group_index) {
1384             return group_index;
1385         }
1386 
1387         /* Read-only and constant variables can't be settable */
1388         if (scope < MCA_BASE_VAR_SCOPE_LOCAL || (flags & MCA_BASE_VAR_FLAG_DEFAULT_ONLY)) {
1389             if ((flags & MCA_BASE_VAR_FLAG_DEFAULT_ONLY) && (flags & MCA_BASE_VAR_FLAG_SETTABLE)) {
1390                 opal_show_help("help-mca-var.txt", "invalid-flag-combination",
1391                                true, "MCA_BASE_VAR_FLAG_DEFAULT_ONLY", "MCA_BASE_VAR_FLAG_SETTABLE");
1392                 return OPAL_ERROR;
1393             }
1394 
1395             /* Should we print a warning for other cases? */
1396             flags &= ~MCA_BASE_VAR_FLAG_SETTABLE;
1397         }
1398 
1399         var = OBJ_NEW(mca_base_var_t);
1400 
1401         var->mbv_type        = type;
1402         var->mbv_flags       = flags;
1403         var->mbv_group_index = group_index;
1404         var->mbv_info_lvl    = info_lvl;
1405         var->mbv_scope       = scope;
1406         var->mbv_synonym_for = synonym_for;
1407         var->mbv_bind        = bind;
1408 
1409         if (NULL != description) {
1410             var->mbv_description = strdup(description);
1411         }
1412 
1413         ret = mca_base_var_generate_full_name4 (project_name, framework_name, component_name,
1414                                                 variable_name, &var->mbv_long_name);
1415         if (OPAL_SUCCESS != ret) {
1416             OBJ_RELEASE(var);
1417             return OPAL_ERROR;
1418         }
1419         /* The mbv_full_name and the variable name are subset of the mbv_long_name
1420          * so instead of allocating them we can just point into the var mbv_long_name
1421          * at the right location.
1422          */
1423         var->mbv_full_name = var->mbv_long_name +
1424                              (NULL == project_name ? 0 : (strlen(project_name)+1)); /* 1 for _ */
1425         if( NULL != variable_name ) {
1426             var->mbv_variable_name = var->mbv_full_name +
1427                                      (NULL == framework_name ? 0 : (strlen(framework_name)+1)) +
1428                                      (NULL == component_name ? 0 : (strlen(component_name)+1));
1429         }
1430 
1431         /* Add it to the array.  Note that we copy the mca_var_t by value,
1432            so the entire contents of the struct is copied.  The synonym list
1433            will always be empty at this point, so there's no need for an
1434            extra RETAIN or RELEASE. */
1435         var_index = opal_pointer_array_add (&mca_base_vars, var);
1436         if (0 > var_index) {
1437             OBJ_RELEASE(var);
1438             return OPAL_ERROR;
1439         }
1440 
1441         var->mbv_index = var_index;
1442 
1443         if (0 <= group_index) {
1444             mca_base_var_group_add_var (group_index, var_index);
1445         }
1446 
1447         mca_base_var_count++;
1448         if (0 <= var_find_by_name (var->mbv_full_name, &tmp, 0)) {
1449             /* XXX --- FIXME: variable overshadows an existing variable. this is difficult to support */
1450             assert (0);
1451         }
1452 
1453         opal_hash_table_set_value_ptr (&mca_base_var_index_hash, var->mbv_full_name, strlen (var->mbv_full_name),
1454                                        (void *)(uintptr_t) var_index);
1455     } else {
1456         ret = var_get (var_index, &var, false);
1457         if (OPAL_SUCCESS != ret) {
1458             /* Shouldn't ever happen */
1459             return OPAL_ERROR;
1460         }
1461 
1462         ret = mca_base_var_group_get_internal (var->mbv_group_index, &group, true);
1463         if (OPAL_SUCCESS != ret) {
1464             /* Shouldn't ever happen */
1465             return OPAL_ERROR;
1466         }
1467 
1468         if (!group->group_isvalid) {
1469             group->group_isvalid = true;
1470         }
1471 
1472         /* Verify the name components match */
1473         if (0 != compare_strings(framework_name, group->group_framework) ||
1474             0 != compare_strings(component_name, group->group_component) ||
1475             0 != compare_strings(variable_name, var->mbv_variable_name)) {
1476             opal_show_help("help-mca-var.txt", "var-name-conflict",
1477                            true, var->mbv_full_name, framework_name,
1478                            component_name, variable_name,
1479                            group->group_framework, group->group_component,
1480                            var->mbv_variable_name);
1481             /* This is developer error. abort! */
1482             assert (0);
1483             return OPAL_ERROR;
1484         }
1485 
1486         if (var->mbv_type != type) {
1487 #if OPAL_ENABLE_DEBUG
1488             opal_show_help("help-mca-var.txt",
1489                            "re-register-with-different-type",
1490                            true, var->mbv_full_name);
1491 #endif
1492             return OPAL_ERR_VALUE_OUT_OF_BOUNDS;
1493         }
1494     }
1495 
1496     if (MCA_BASE_VAR_TYPE_BOOL == var->mbv_type) {
1497         enumerator = &mca_base_var_enum_bool;
1498     } else if (NULL != enumerator) {
1499         if (var->mbv_enumerator) {
1500             OBJ_RELEASE (var->mbv_enumerator);
1501         }
1502 
1503         if (!enumerator->enum_is_static) {
1504             OBJ_RETAIN(enumerator);
1505         }
1506     }
1507 
1508     var->mbv_enumerator = enumerator;
1509 
1510     if (!original) {
1511         var->mbv_storage = storage;
1512 
1513         /* make a copy of the default string value */
1514         if ((MCA_BASE_VAR_TYPE_STRING == type || MCA_BASE_VAR_TYPE_VERSION_STRING == type) && NULL != ((char **)storage)[0]) {
1515             ((char **)storage)[0] = strdup (((char **)storage)[0]);
1516         }
1517     } else {
1518         /* synonym variable */
1519         opal_value_array_append_item(&original->mbv_synonyms, &var_index);
1520     }
1521 
1522     /* go ahead and mark this variable as valid */
1523     var->mbv_flags |= MCA_BASE_VAR_FLAG_VALID;
1524 
1525     ret = var_set_initial (var, original);
1526     if (OPAL_SUCCESS != ret) {
1527         return ret;
1528     }
1529 
1530     /* All done */
1531     return var_index;
1532 }
1533 
1534 int mca_base_var_register (const char *project_name, const char *framework_name,
1535                            const char *component_name, const char *variable_name,
1536                            const char *description, mca_base_var_type_t type,
1537                            mca_base_var_enum_t *enumerator, int bind,
1538                            mca_base_var_flag_t flags,
1539                            mca_base_var_info_lvl_t info_lvl,
1540                            mca_base_var_scope_t scope, void *storage)
1541 {
1542     /* Only integer variables can have enumerator */
1543     assert (NULL == enumerator || (MCA_BASE_VAR_TYPE_INT == type || MCA_BASE_VAR_TYPE_UNSIGNED_INT == type));
1544 
1545     return register_variable (project_name, framework_name, component_name,
1546                               variable_name, description, type, enumerator,
1547                               bind, flags, info_lvl, scope, -1, storage);
1548 }
1549 
1550 int mca_base_component_var_register (const mca_base_component_t *component,
1551                                      const char *variable_name, const char *description,
1552                                      mca_base_var_type_t type, mca_base_var_enum_t *enumerator,
1553                                      int bind, mca_base_var_flag_t flags,
1554                                      mca_base_var_info_lvl_t info_lvl,
1555                                      mca_base_var_scope_t scope, void *storage)
1556 {
1557     return mca_base_var_register (component->mca_project_name, component->mca_type_name,
1558                                   component->mca_component_name,
1559                                   variable_name, description, type, enumerator,
1560                                   bind, flags | MCA_BASE_VAR_FLAG_DWG,
1561                                   info_lvl, scope, storage);
1562 }
1563 
1564 int mca_base_framework_var_register (const mca_base_framework_t *framework,
1565                                      const char *variable_name,
1566                                      const char *help_msg, mca_base_var_type_t type,
1567                                      mca_base_var_enum_t *enumerator, int bind,
1568                                      mca_base_var_flag_t flags,
1569                                      mca_base_var_info_lvl_t info_level,
1570                                      mca_base_var_scope_t scope, void *storage)
1571 {
1572     return mca_base_var_register (framework->framework_project, framework->framework_name,
1573                                   "base", variable_name, help_msg, type, enumerator, bind,
1574                                   flags | MCA_BASE_VAR_FLAG_DWG, info_level, scope, storage);
1575 }
1576 
1577 int mca_base_var_register_synonym (int synonym_for, const char *project_name,
1578                                    const char *framework_name,
1579                                    const char *component_name,
1580                                    const char *synonym_name,
1581                                    mca_base_var_syn_flag_t flags)
1582 {
1583     mca_base_var_flag_t var_flags = (mca_base_var_flag_t) MCA_BASE_VAR_FLAG_SYNONYM;
1584     mca_base_var_t *var;
1585     int ret;
1586 
1587     ret = var_get (synonym_for, &var, false);
1588     if (OPAL_SUCCESS != ret || VAR_IS_SYNONYM(var[0])) {
1589         return OPAL_ERR_BAD_PARAM;
1590     }
1591 
1592     if (flags & MCA_BASE_VAR_SYN_FLAG_DEPRECATED) {
1593         var_flags |= MCA_BASE_VAR_FLAG_DEPRECATED;
1594     }
1595     if (flags & MCA_BASE_VAR_SYN_FLAG_INTERNAL) {
1596         var_flags |= MCA_BASE_VAR_FLAG_INTERNAL;
1597     }
1598 
1599     return register_variable (project_name, framework_name, component_name,
1600                               synonym_name, var->mbv_description, var->mbv_type, var->mbv_enumerator,
1601                               var->mbv_bind, var_flags, var->mbv_info_lvl, var->mbv_scope,
1602                               synonym_for, NULL);
1603 }
1604 
1605 static int var_get_env (mca_base_var_t *var, const char *name, char **source, char **value)
1606 {
1607     const char source_prefix[] = "SOURCE_";
1608     const int max_len = strlen(mca_prefix) + strlen(source_prefix) +
1609         strlen(name) + 1;
1610     char *envvar = alloca(max_len);
1611     if (NULL == envvar) {
1612         return OPAL_ERR_OUT_OF_RESOURCE;
1613     }
1614 
1615     int ret;
1616     ret = snprintf(envvar, max_len, "%s%s", mca_prefix, name);
1617     if (0 > ret) {
1618         return OPAL_ERROR;
1619     }
1620     *value = getenv(envvar);
1621     if( NULL == *value ) {
1622         *source = NULL;
1623         return OPAL_ERR_NOT_FOUND;
1624     }
1625 
1626     ret = snprintf(envvar, max_len, "%s%s%s", mca_prefix,
1627                    source_prefix, name);
1628     if( 0 > ret ) {
1629         return OPAL_ERROR;
1630     }
1631     *source = getenv(envvar);
1632 
1633     return OPAL_SUCCESS;
1634 }
1635 
1636 /*
1637  * Lookup a param in the environment
1638  */
1639 static int var_set_from_env (mca_base_var_t *var, mca_base_var_t *original)
1640 {
1641     const char *var_full_name = var->mbv_full_name;
1642     const char *var_long_name = var->mbv_long_name;
1643     bool deprecated = VAR_IS_DEPRECATED(var[0]);
1644     bool is_synonym = VAR_IS_SYNONYM(var[0]);
1645     char *source_env, *value_env;
1646     int ret;
1647 
1648     ret = var_get_env (var, var_long_name, &source_env, &value_env);
1649     if (OPAL_SUCCESS != ret) {
1650         ret = var_get_env (var, var_full_name, &source_env, &value_env);
1651     }
1652 
1653     if (OPAL_SUCCESS != ret) {
1654         return ret;
1655     }
1656 
1657     /* we found an environment variable but this variable is default-only. print
1658        a warning. */
1659     if (VAR_IS_DEFAULT_ONLY(original[0])) {
1660         opal_show_help("help-mca-var.txt", "default-only-param-set",
1661                        true, var_full_name);
1662 
1663         return OPAL_ERR_NOT_FOUND;
1664     }
1665 
1666     if (MCA_BASE_VAR_SOURCE_OVERRIDE == original->mbv_source) {
1667         if (!mca_base_var_suppress_override_warning) {
1668             opal_show_help("help-mca-var.txt", "overridden-param-set",
1669                            true, var_full_name);
1670         }
1671 
1672         return OPAL_ERR_NOT_FOUND;
1673     }
1674 
1675     original->mbv_source = MCA_BASE_VAR_SOURCE_ENV;
1676 
1677     if (NULL != source_env) {
1678         if (0 == strncasecmp (source_env, "file:", 5)) {
1679             original->mbv_source_file = append_filename_to_list(source_env + 5);
1680             if (0 == strcmp (var->mbv_source_file, mca_base_var_override_file)) {
1681                 original->mbv_source = MCA_BASE_VAR_SOURCE_OVERRIDE;
1682             } else {
1683                 original->mbv_source = MCA_BASE_VAR_SOURCE_FILE;
1684             }
1685         } else if (0 == strcasecmp (source_env, "command")) {
1686             var->mbv_source = MCA_BASE_VAR_SOURCE_COMMAND_LINE;
1687         }
1688     }
1689 
1690     if (deprecated) {
1691         const char *new_variable = "None (going away)";
1692 
1693         if (is_synonym) {
1694             new_variable = original->mbv_full_name;
1695         }
1696 
1697         switch (var->mbv_source) {
1698         case MCA_BASE_VAR_SOURCE_ENV:
1699             opal_show_help("help-mca-var.txt", "deprecated-mca-env",
1700                            true, var_full_name, new_variable);
1701             break;
1702         case MCA_BASE_VAR_SOURCE_COMMAND_LINE:
1703             opal_show_help("help-mca-var.txt", "deprecated-mca-cli",
1704                            true, var_full_name, new_variable);
1705             break;
1706         case MCA_BASE_VAR_SOURCE_FILE:
1707         case MCA_BASE_VAR_SOURCE_OVERRIDE:
1708             opal_show_help("help-mca-var.txt", "deprecated-mca-file",
1709                            true, var_full_name, mca_base_var_source_file (var),
1710                            new_variable);
1711             break;
1712 
1713         case MCA_BASE_VAR_SOURCE_DEFAULT:
1714         case MCA_BASE_VAR_SOURCE_MAX:
1715         case MCA_BASE_VAR_SOURCE_SET:
1716             /* silence compiler warnings about unhandled enumerations */
1717             break;
1718         }
1719     }
1720 
1721     return var_set_from_string (original, value_env);
1722 }
1723 
1724 /*
1725  * Lookup a param in the files
1726  */
1727 static int var_set_from_file (mca_base_var_t *var, mca_base_var_t *original, opal_list_t *file_values)
1728 {
1729     const char *var_full_name = var->mbv_full_name;
1730     const char *var_long_name = var->mbv_long_name;
1731     bool deprecated = VAR_IS_DEPRECATED(var[0]);
1732     bool is_synonym = VAR_IS_SYNONYM(var[0]);
1733     mca_base_var_file_value_t *fv;
1734 
1735     /* Scan through the list of values read in from files and try to
1736        find a match.  If we do, cache it on the param (for future
1737        lookups) and save it in the storage. */
1738 
1739     OPAL_LIST_FOREACH(fv, file_values, mca_base_var_file_value_t) {
1740         if (0 != strcmp(fv->mbvfv_var, var_full_name) &&
1741             0 != strcmp(fv->mbvfv_var, var_long_name)) {
1742             continue;
1743         }
1744 
1745         /* found it */
1746         if (VAR_IS_DEFAULT_ONLY(var[0])) {
1747             opal_show_help("help-mca-var.txt", "default-only-param-set",
1748                            true, var_full_name);
1749 
1750             return OPAL_ERR_NOT_FOUND;
1751         }
1752 
1753         if (MCA_BASE_VAR_FLAG_ENVIRONMENT_ONLY & original->mbv_flags) {
1754             opal_show_help("help-mca-var.txt", "environment-only-param",
1755                            true, var_full_name, fv->mbvfv_value,
1756                            fv->mbvfv_file);
1757 
1758             return OPAL_ERR_NOT_FOUND;
1759         }
1760 
1761         if (MCA_BASE_VAR_SOURCE_OVERRIDE == original->mbv_source) {
1762             if (!mca_base_var_suppress_override_warning) {
1763                 opal_show_help("help-mca-var.txt", "overridden-param-set",
1764                                true, var_full_name);
1765             }
1766 
1767             return OPAL_ERR_NOT_FOUND;
1768         }
1769 
1770         if (deprecated) {
1771             const char *new_variable = "None (going away)";
1772 
1773             if (is_synonym) {
1774                 new_variable = original->mbv_full_name;
1775             }
1776 
1777             opal_show_help("help-mca-var.txt", "deprecated-mca-file",
1778                            true, var_full_name, fv->mbvfv_file,
1779                            new_variable);
1780         }
1781 
1782         original->mbv_file_value = (void *) fv;
1783         original->mbv_source = MCA_BASE_VAR_SOURCE_FILE;
1784         if (is_synonym) {
1785             var->mbv_file_value = (void *) fv;
1786             var->mbv_source = MCA_BASE_VAR_SOURCE_FILE;
1787         }
1788 
1789         return var_set_from_string (original, fv->mbvfv_value);
1790     }
1791 
1792     return OPAL_ERR_NOT_FOUND;
1793 }
1794 
1795 /*
1796  * Lookup the initial value for a parameter
1797  */
1798 static int var_set_initial (mca_base_var_t *var, mca_base_var_t *original)
1799 {
1800     int ret;
1801 
1802     if (original) {
1803         /* synonym */
1804         var->mbv_source = original->mbv_source;
1805         var->mbv_file_value = original->mbv_file_value;
1806         var->mbv_source_file = original->mbv_source_file;
1807     } else {
1808         var->mbv_source = MCA_BASE_VAR_SOURCE_DEFAULT;
1809         original = var;
1810     }
1811 
1812     /* Check all the places that the param may be hiding, in priority
1813        order. If the default only flag is set the user will get a
1814        warning if they try to set a value from the environment or a
1815        file. */
1816     ret = var_set_from_file (var, original, &mca_base_var_override_values);
1817     if (OPAL_SUCCESS == ret) {
1818         var->mbv_flags = ~MCA_BASE_VAR_FLAG_SETTABLE & (var->mbv_flags | MCA_BASE_VAR_FLAG_OVERRIDE);
1819         var->mbv_source = MCA_BASE_VAR_SOURCE_OVERRIDE;
1820     }
1821 
1822     ret = var_set_from_env (var, original);
1823     if (OPAL_ERR_NOT_FOUND != ret) {
1824         return ret;
1825     }
1826 
1827     ret = var_set_from_file (var, original, &mca_base_envar_file_values);
1828     if (OPAL_ERR_NOT_FOUND != ret) {
1829         return ret;
1830     }
1831 
1832     ret = var_set_from_file (var, original, &mca_base_var_file_values);
1833     if (OPAL_ERR_NOT_FOUND != ret) {
1834         return ret;
1835     }
1836 
1837     return OPAL_SUCCESS;
1838 }
1839 
1840 /*
1841  * Create an empty param container
1842  */
1843 static void var_constructor(mca_base_var_t *var)
1844 {
1845     memset ((char *) var + sizeof (var->super), 0, sizeof (*var) - sizeof (var->super));
1846 
1847     var->mbv_type = MCA_BASE_VAR_TYPE_MAX;
1848     OBJ_CONSTRUCT(&var->mbv_synonyms, opal_value_array_t);
1849     opal_value_array_init (&var->mbv_synonyms, sizeof (int));
1850 }
1851 
1852 
1853 /*
1854  * Free all the contents of a param container
1855  */
1856 static void var_destructor(mca_base_var_t *var)
1857 {
1858     if ((MCA_BASE_VAR_TYPE_STRING == var->mbv_type ||
1859                 MCA_BASE_VAR_TYPE_VERSION_STRING == var->mbv_type) &&
1860         NULL != var->mbv_storage &&
1861         NULL != var->mbv_storage->stringval) {
1862         free (var->mbv_storage->stringval);
1863         var->mbv_storage->stringval = NULL;
1864     }
1865 
1866     /* don't release the boolean enumerator */
1867     if (var->mbv_enumerator && !var->mbv_enumerator->enum_is_static) {
1868         OBJ_RELEASE(var->mbv_enumerator);
1869     }
1870 
1871     if (NULL != var->mbv_long_name) {
1872         free(var->mbv_long_name);
1873     }
1874     var->mbv_full_name = NULL;
1875     var->mbv_variable_name = NULL;
1876 
1877     if (NULL != var->mbv_description) {
1878         free(var->mbv_description);
1879     }
1880 
1881     /* Destroy the synonym array */
1882     OBJ_DESTRUCT(&var->mbv_synonyms);
1883 
1884     /* mark this parameter as invalid */
1885     var->mbv_type = MCA_BASE_VAR_TYPE_MAX;
1886 
1887 #if OPAL_ENABLE_DEBUG
1888     /* Cheap trick to reset everything to NULL */
1889     memset ((char *) var + sizeof (var->super), 0, sizeof (*var) - sizeof (var->super));
1890 #endif
1891 }
1892 
1893 
1894 static void fv_constructor(mca_base_var_file_value_t *f)
1895 {
1896     memset ((char *) f + sizeof (f->super), 0, sizeof (*f) - sizeof (f->super));
1897 }
1898 
1899 
1900 static void fv_destructor(mca_base_var_file_value_t *f)
1901 {
1902     if (NULL != f->mbvfv_var) {
1903         free(f->mbvfv_var);
1904     }
1905     if (NULL != f->mbvfv_value) {
1906         free(f->mbvfv_value);
1907     }
1908     /* the file name is stored in mca_*/
1909     fv_constructor(f);
1910 }
1911 
1912 static char *source_name(mca_base_var_t *var)
1913 {
1914     char *ret;
1915 
1916     if (MCA_BASE_VAR_SOURCE_FILE == var->mbv_source || MCA_BASE_VAR_SOURCE_OVERRIDE == var->mbv_source) {
1917         struct mca_base_var_file_value_t *fv = var->mbv_file_value;
1918         int rc;
1919 
1920         if (fv) {
1921             rc = opal_asprintf(&ret, "file (%s:%d)", fv->mbvfv_file, fv->mbvfv_lineno);
1922         } else {
1923             rc = opal_asprintf(&ret, "file (%s)", var->mbv_source_file);
1924         }
1925 
1926         /* some compilers will warn if the return code of opal_asprintf is not checked (even if it is cast to void) */
1927         if (0 > rc) {
1928             return NULL;
1929         }
1930         return ret;
1931     } else if (MCA_BASE_VAR_SOURCE_MAX <= var->mbv_source) {
1932         return strdup ("unknown(!!)");
1933     }
1934 
1935     return strdup (var_source_names[var->mbv_source]);
1936 }
1937 
1938 static int var_value_string (mca_base_var_t *var, char **value_string)
1939 {
1940     const mca_base_var_storage_t *value=NULL;
1941     int ret;
1942 
1943     assert (MCA_BASE_VAR_TYPE_MAX > var->mbv_type);
1944 
1945     /** Parameters with MCA_BASE_VAR_FLAG_DEF_UNSET flag should be shown
1946      * as "unset" by default. */
1947     if ((var->mbv_flags & MCA_BASE_VAR_FLAG_DEF_UNSET) &&
1948         (MCA_BASE_VAR_SOURCE_DEFAULT == var->mbv_source)){
1949         opal_asprintf (value_string, "%s", "unset");
1950         return OPAL_SUCCESS;
1951     }
1952 
1953     ret = mca_base_var_get_value(var->mbv_index, &value, NULL, NULL);
1954     if (OPAL_SUCCESS != ret || NULL == value) {
1955         return ret;
1956     }
1957 
1958     if (NULL == var->mbv_enumerator) {
1959         switch (var->mbv_type) {
1960         case MCA_BASE_VAR_TYPE_INT:
1961             ret = opal_asprintf (value_string, "%d", value->intval);
1962             break;
1963         case MCA_BASE_VAR_TYPE_INT32_T:
1964             ret = opal_asprintf (value_string, "%" PRId32, value->int32tval);
1965             break;
1966         case MCA_BASE_VAR_TYPE_UINT32_T:
1967             ret = opal_asprintf (value_string, "%" PRIu32, value->uint32tval);
1968             break;
1969         case MCA_BASE_VAR_TYPE_INT64_T:
1970             ret = opal_asprintf (value_string, "%" PRId64, value->int64tval);
1971             break;
1972         case MCA_BASE_VAR_TYPE_UINT64_T:
1973             ret = opal_asprintf (value_string, "%" PRIu64, value->uint64tval);
1974             break;
1975         case MCA_BASE_VAR_TYPE_LONG:
1976             ret = opal_asprintf (value_string, "%ld", value->longval);
1977             break;
1978         case MCA_BASE_VAR_TYPE_UNSIGNED_INT:
1979             ret = opal_asprintf (value_string, "%u", value->uintval);
1980             break;
1981         case MCA_BASE_VAR_TYPE_UNSIGNED_LONG:
1982             ret = opal_asprintf (value_string, "%lu", value->ulval);
1983             break;
1984         case MCA_BASE_VAR_TYPE_UNSIGNED_LONG_LONG:
1985             ret = opal_asprintf (value_string, "%llu", value->ullval);
1986             break;
1987         case MCA_BASE_VAR_TYPE_SIZE_T:
1988             ret = opal_asprintf (value_string, "%" PRIsize_t, value->sizetval);
1989             break;
1990         case MCA_BASE_VAR_TYPE_STRING:
1991         case MCA_BASE_VAR_TYPE_VERSION_STRING:
1992             ret = opal_asprintf (value_string, "%s",
1993                             value->stringval ? value->stringval : "");
1994             break;
1995         case MCA_BASE_VAR_TYPE_BOOL:
1996             ret = opal_asprintf (value_string, "%d", value->boolval);
1997             break;
1998         case MCA_BASE_VAR_TYPE_DOUBLE:
1999             ret = opal_asprintf (value_string, "%lf", value->lfval);
2000             break;
2001         default:
2002             ret = -1;
2003             break;
2004         }
2005 
2006         ret = (0 > ret) ? OPAL_ERR_OUT_OF_RESOURCE : OPAL_SUCCESS;
2007     } else {
2008         /* we use an enumerator to handle string->bool and bool->string conversion */
2009         if (MCA_BASE_VAR_TYPE_BOOL == var->mbv_type) {
2010             ret = var->mbv_enumerator->string_from_value(var->mbv_enumerator, value->boolval, value_string);
2011         } else {
2012             ret = var->mbv_enumerator->string_from_value(var->mbv_enumerator, value->intval, value_string);
2013         }
2014     }
2015 
2016     return ret;
2017 }
2018 
2019 int mca_base_var_check_exclusive (const char *project,
2020                                   const char *type_a,
2021                                   const char *component_a,
2022                                   const char *param_a,
2023                                   const char *type_b,
2024                                   const char *component_b,
2025                                   const char *param_b)
2026 {
2027     mca_base_var_t *var_a = NULL, *var_b = NULL;
2028     int var_ai, var_bi;
2029 
2030     /* XXX -- Remove me once the project name is in the componennt */
2031     project = NULL;
2032 
2033     var_ai = mca_base_var_find (project, type_a, component_a, param_a);
2034     var_bi = mca_base_var_find (project, type_b, component_b, param_b);
2035     if (var_bi < 0 || var_ai < 0) {
2036         return OPAL_ERR_NOT_FOUND;
2037     }
2038 
2039     (void) var_get (var_ai, &var_a, true);
2040     (void) var_get (var_bi, &var_b, true);
2041     if (NULL == var_a || NULL == var_b) {
2042         return OPAL_ERR_NOT_FOUND;
2043     }
2044 
2045     if (MCA_BASE_VAR_SOURCE_DEFAULT != var_a->mbv_source &&
2046         MCA_BASE_VAR_SOURCE_DEFAULT != var_b->mbv_source) {
2047         char *str_a, *str_b;
2048 
2049         /* Form cosmetic string names for A */
2050         str_a = source_name(var_a);
2051 
2052         /* Form cosmetic string names for B */
2053         str_b = source_name(var_b);
2054 
2055         /* Print it all out */
2056         opal_show_help("help-mca-var.txt",
2057                        "mutually-exclusive-vars",
2058                        true, var_a->mbv_full_name,
2059                        str_a, var_b->mbv_full_name,
2060                        str_b);
2061 
2062         /* Free the temp strings */
2063         free(str_a);
2064         free(str_b);
2065 
2066         return OPAL_ERR_BAD_PARAM;
2067     }
2068 
2069     return OPAL_SUCCESS;
2070 }
2071 
2072 int mca_base_var_get_count (void)
2073 {
2074     return mca_base_var_count;
2075 }
2076 
2077 int mca_base_var_dump(int vari, char ***out, mca_base_var_dump_type_t output_type)
2078 {
2079     const char *framework, *component, *full_name;
2080     int i, line_count, line = 0, enum_count = 0;
2081     char *value_string, *source_string, *tmp;
2082     int synonym_count, ret, *synonyms = NULL;
2083     mca_base_var_t *var, *original=NULL;
2084     mca_base_var_group_t *group;
2085 
2086     ret = var_get(vari, &var, false);
2087     if (OPAL_SUCCESS != ret) {
2088         return ret;
2089     }
2090 
2091     ret = mca_base_var_group_get_internal(var->mbv_group_index, &group, false);
2092     if (OPAL_SUCCESS != ret) {
2093         return ret;
2094     }
2095 
2096     if (VAR_IS_SYNONYM(var[0])) {
2097         ret = var_get(var->mbv_synonym_for, &original, false);
2098         if (OPAL_SUCCESS != ret) {
2099             return ret;
2100         }
2101         /* just for protection... */
2102         if (NULL == original) {
2103             return OPAL_ERR_NOT_FOUND;
2104         }
2105     }
2106 
2107     framework = group->group_framework;
2108     component = group->group_component ? group->group_component : "base";
2109     full_name = var->mbv_full_name;
2110 
2111     synonym_count = opal_value_array_get_size(&var->mbv_synonyms);
2112     if (synonym_count) {
2113         synonyms = OPAL_VALUE_ARRAY_GET_BASE(&var->mbv_synonyms, int);
2114     }
2115 
2116     ret = var_value_string (var, &value_string);
2117     if (OPAL_SUCCESS != ret) {
2118         return ret;
2119     }
2120 
2121     source_string = source_name(var);
2122     if (NULL == source_string) {
2123         free (value_string);
2124         return OPAL_ERR_OUT_OF_RESOURCE;
2125     }
2126 
2127     if (MCA_BASE_VAR_DUMP_PARSABLE == output_type) {
2128         if (NULL != var->mbv_enumerator) {
2129             (void) var->mbv_enumerator->get_count(var->mbv_enumerator, &enum_count);
2130         }
2131 
2132         line_count = 8 + (var->mbv_description ? 1 : 0) + (VAR_IS_SYNONYM(var[0]) ? 1 : synonym_count) +
2133             enum_count;
2134 
2135         *out = (char **) calloc (line_count + 1, sizeof (char *));
2136         if (NULL == *out) {
2137             free (value_string);
2138             free (source_string);
2139             return OPAL_ERR_OUT_OF_RESOURCE;
2140         }
2141 
2142         /* build the message*/
2143         opal_asprintf(&tmp, "mca:%s:%s:param:%s:", framework, component,
2144                  full_name);
2145 
2146         /* Output the value */
2147         char *colon = strchr(value_string, ':');
2148         if (NULL != colon) {
2149             opal_asprintf(out[0] + line++, "%svalue:\"%s\"", tmp, value_string);
2150         } else {
2151             opal_asprintf(out[0] + line++, "%svalue:%s", tmp, value_string);
2152         }
2153 
2154         /* Output the source */
2155         opal_asprintf(out[0] + line++, "%ssource:%s", tmp, source_string);
2156 
2157         /* Output whether it's read only or writable */
2158         opal_asprintf(out[0] + line++, "%sstatus:%s", tmp,
2159                       VAR_IS_SETTABLE(var[0]) ? "writeable" : "read-only");
2160 
2161         /* Output the info level of this parametere */
2162         opal_asprintf(out[0] + line++, "%slevel:%d", tmp, var->mbv_info_lvl + 1);
2163 
2164         /* If it has a help message, output the help message */
2165         if (var->mbv_description) {
2166             opal_asprintf(out[0] + line++, "%shelp:%s", tmp, var->mbv_description);
2167         }
2168 
2169         if (NULL != var->mbv_enumerator) {
2170             for (i = 0 ; i < enum_count ; ++i) {
2171                 const char *enum_string = NULL;
2172                 int enum_value;
2173 
2174                 ret = var->mbv_enumerator->get_value(var->mbv_enumerator, i, &enum_value,
2175                                                      &enum_string);
2176                 if (OPAL_SUCCESS != ret) {
2177                     continue;
2178                 }
2179 
2180                 opal_asprintf(out[0] + line++, "%senumerator:value:%d:%s", tmp, enum_value, enum_string);
2181             }
2182         }
2183 
2184         /* Is this variable deprecated? */
2185         opal_asprintf(out[0] + line++, "%sdeprecated:%s", tmp, VAR_IS_DEPRECATED(var[0]) ? "yes" : "no");
2186 
2187         opal_asprintf(out[0] + line++, "%stype:%s", tmp, ompi_var_type_names[var->mbv_type]);
2188 
2189         /* Does this parameter have any synonyms or is it a synonym? */
2190         if (VAR_IS_SYNONYM(var[0])) {
2191             opal_asprintf(out[0] + line++, "%ssynonym_of:name:%s", tmp, original->mbv_full_name);
2192         } else if (opal_value_array_get_size(&var->mbv_synonyms)) {
2193             for (i = 0 ; i < synonym_count ; ++i) {
2194                 mca_base_var_t *synonym;
2195 
2196                 ret = var_get(synonyms[i], &synonym, false);
2197                 if (OPAL_SUCCESS != ret) {
2198                     continue;
2199                 }
2200 
2201                 opal_asprintf(out[0] + line++, "%ssynonym:name:%s", tmp, synonym->mbv_full_name);
2202             }
2203         }
2204 
2205         free (tmp);
2206     } else if (MCA_BASE_VAR_DUMP_READABLE == output_type) {
2207         /* There will be at most three lines in the pretty print case */
2208         *out = (char **) calloc (4, sizeof (char *));
2209         if (NULL == *out) {
2210             free (value_string);
2211             free (source_string);
2212             return OPAL_ERR_OUT_OF_RESOURCE;
2213         }
2214 
2215         opal_asprintf (out[0], "%s \"%s\" (current value: \"%s\", data source: %s, level: %d %s, type: %s",
2216                   VAR_IS_DEFAULT_ONLY(var[0]) ? "informational" : "parameter",
2217                   full_name, value_string, source_string, var->mbv_info_lvl + 1,
2218                   info_lvl_strings[var->mbv_info_lvl], ompi_var_type_names[var->mbv_type]);
2219 
2220         tmp = out[0][0];
2221         if (VAR_IS_DEPRECATED(var[0])) {
2222             opal_asprintf (out[0], "%s, deprecated", tmp);
2223             free (tmp);
2224             tmp = out[0][0];
2225         }
2226 
2227         /* Does this parameter have any synonyms or is it a synonym? */
2228         if (VAR_IS_SYNONYM(var[0])) {
2229             opal_asprintf(out[0], "%s, synonym of: %s)", tmp, original->mbv_full_name);
2230             free (tmp);
2231         } else if (synonym_count) {
2232             opal_asprintf(out[0], "%s, synonyms: ", tmp);
2233             free (tmp);
2234 
2235             for (i = 0 ; i < synonym_count ; ++i) {
2236                 mca_base_var_t *synonym;
2237 
2238                 ret = var_get(synonyms[i], &synonym, false);
2239                 if (OPAL_SUCCESS != ret) {
2240                     continue;
2241                 }
2242 
2243                 tmp = out[0][0];
2244                 if (synonym_count == i+1) {
2245                     opal_asprintf(out[0], "%s%s)", tmp, synonym->mbv_full_name);
2246                 } else {
2247                     opal_asprintf(out[0], "%s%s, ", tmp, synonym->mbv_full_name);
2248                 }
2249                 free(tmp);
2250             }
2251         } else {
2252             opal_asprintf(out[0], "%s)", tmp);
2253             free(tmp);
2254         }
2255 
2256         line++;
2257 
2258         if (var->mbv_description) {
2259             opal_asprintf(out[0] + line++, "%s", var->mbv_description);
2260         }
2261 
2262         if (NULL != var->mbv_enumerator) {
2263             char *values;
2264 
2265             ret = var->mbv_enumerator->dump(var->mbv_enumerator, &values);
2266             if (OPAL_SUCCESS == ret) {
2267                 opal_asprintf (out[0] + line++, "Valid values: %s", values);
2268                 free (values);
2269             }
2270         }
2271     } else if (MCA_BASE_VAR_DUMP_SIMPLE == output_type) {
2272         *out = (char **) calloc (2, sizeof (char *));
2273         if (NULL == *out) {
2274             free (value_string);
2275             free (source_string);
2276             return OPAL_ERR_OUT_OF_RESOURCE;
2277         }
2278 
2279         opal_asprintf(out[0], "%s=%s (%s)", var->mbv_full_name, value_string, source_string);
2280     }
2281 
2282     free (value_string);
2283     free (source_string);
2284 
2285     return OPAL_SUCCESS;
2286 }
2287 

/* [<][>][^][v][top][bottom][index][help] */