root/opal/mca/pmix/pmix4x/pmix/src/util/show_help.c

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

DEFINITIONS

This source file includes following definitions.
  1. pmix_show_help_init
  2. pmix_show_help_finalize
  3. array2string
  4. open_file
  5. find_topic
  6. read_topic
  7. load_array
  8. pmix_show_help_vstring
  9. pmix_show_help_string
  10. pmix_show_vhelp_internal
  11. pmix_show_help_internal
  12. pmix_show_help_add_dir

   1 /*
   2  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
   3  *                         University Research and Technology
   4  *                         Corporation.  All rights reserved.
   5  * Copyright (c) 2004-2006 The University of Tennessee and The University
   6  *                         of Tennessee Research Foundation.  All rights
   7  *                         reserved.
   8  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
   9  *                         University of Stuttgart.  All rights reserved.
  10  * Copyright (c) 2004-2005 The Regents of the University of California.
  11  *                         All rights reserved.
  12  * Copyright (c) 2008      Cisco Systems, Inc.  All rights reserved.
  13  * Copyright (c) 2015      Research Organization for Information Science
  14  *                         and Technology (RIST). All rights reserved.
  15  * Copyright (c) 2016-2018 Intel, Inc.  All rights reserved.
  16  * $COPYRIGHT$
  17  *
  18  * Additional copyrights may follow
  19  *
  20  * $HEADER$
  21  */
  22 
  23 #include <src/include/pmix_config.h>
  24 
  25 #include <stdio.h>
  26 #include <string.h>
  27 #include <locale.h>
  28 #include <errno.h>
  29 
  30 #include "src/mca/pinstalldirs/pinstalldirs.h"
  31 #include "src/util/show_help.h"
  32 #include "src/util/show_help_lex.h"
  33 #include "src/util/printf.h"
  34 #include "src/util/argv.h"
  35 #include "src/util/os_path.h"
  36 #include "src/util/output.h"
  37 #include "pmix_common.h"
  38 
  39 
  40 /*
  41  * Private variables
  42  */
  43 static const char *default_filename = "help-messages";
  44 static const char *dash_line = "--------------------------------------------------------------------------\n";
  45 static int output_stream = -1;
  46 static char **search_dirs = NULL;
  47 
  48 /*
  49  * Local functions
  50  */
  51 static int pmix_show_vhelp_internal(const char *filename, const char *topic,
  52                                     int want_error_header, va_list arglist);
  53 static int pmix_show_help_internal(const char *filename, const char *topic,
  54                                    int want_error_header, ...);
  55 
  56 pmix_show_help_fn_t pmix_show_help = pmix_show_help_internal;
  57 pmix_show_vhelp_fn_t pmix_show_vhelp = pmix_show_vhelp_internal;
  58 
  59 
  60 int pmix_show_help_init(void)
  61 {
  62     pmix_output_stream_t lds;
  63 
  64     PMIX_CONSTRUCT(&lds, pmix_output_stream_t);
  65     lds.lds_want_stderr = true;
  66     output_stream = pmix_output_open(&lds);
  67 
  68     pmix_argv_append_nosize(&search_dirs, pmix_pinstall_dirs.pmixdatadir);
  69 
  70     return PMIX_SUCCESS;
  71 }
  72 
  73 int pmix_show_help_finalize(void)
  74 {
  75     pmix_output_close(output_stream);
  76     output_stream = -1;
  77 
  78     /* destruct the search list */
  79     if (NULL != search_dirs) {
  80         pmix_argv_free(search_dirs);
  81         search_dirs = NULL;
  82     };
  83 
  84     return PMIX_SUCCESS;
  85 }
  86 
  87 /*
  88  * Make one big string with all the lines.  This isn't the most
  89  * efficient method in the world, but we're going for clarity here --
  90  * not optimization.  :-)
  91  */
  92 static int array2string(char **outstring,
  93                         int want_error_header, char **lines)
  94 {
  95     int i, count;
  96     size_t len;
  97 
  98     /* See how much space we need */
  99 
 100     len = want_error_header ? 2 * strlen(dash_line) : 0;
 101     count = pmix_argv_count(lines);
 102     for (i = 0; i < count; ++i) {
 103         if (NULL == lines[i]) {
 104             break;
 105         }
 106         len += strlen(lines[i]) + 1;
 107     }
 108 
 109     /* Malloc it out */
 110 
 111     (*outstring) = (char*) malloc(len + 1);
 112     if (NULL == *outstring) {
 113         return PMIX_ERR_OUT_OF_RESOURCE;
 114     }
 115 
 116     /* Fill the big string */
 117 
 118     *(*outstring) = '\0';
 119     if (want_error_header) {
 120         strcat(*outstring, dash_line);
 121     }
 122     for (i = 0; i < count; ++i) {
 123         if (NULL == lines[i]) {
 124             break;
 125         }
 126         strcat(*outstring, lines[i]);
 127         strcat(*outstring, "\n");
 128     }
 129     if (want_error_header) {
 130         strcat(*outstring, dash_line);
 131     }
 132 
 133     return PMIX_SUCCESS;
 134 }
 135 
 136 
 137 /*
 138  * Find the right file to open
 139  */
 140 static int open_file(const char *base, const char *topic)
 141 {
 142     char *filename;
 143     char *err_msg = NULL;
 144     size_t base_len;
 145     int i;
 146 
 147     /* If no filename was supplied, use the default */
 148 
 149     if (NULL == base) {
 150         base = default_filename;
 151     }
 152 
 153     /* if this is called prior to someone initializing the system,
 154      * then don't try to look
 155      */
 156     if (NULL != search_dirs) {
 157         /* Try to open the file.  If we can't find it, try it with a .txt
 158          * extension.
 159          */
 160         for (i=0; NULL != search_dirs[i]; i++) {
 161             filename = pmix_os_path( false, search_dirs[i], base, NULL );
 162             pmix_show_help_yyin = fopen(filename, "r");
 163             if (NULL == pmix_show_help_yyin) {
 164                 if (0 > asprintf(&err_msg, "%s: %s", filename, strerror(errno))) {
 165                     return PMIX_ERR_OUT_OF_RESOURCE;
 166                 }
 167                 base_len = strlen(base);
 168                 if (4 > base_len || 0 != strcmp(base + base_len - 4, ".txt")) {
 169                     free(filename);
 170                     if (0 > asprintf(&filename, "%s%s%s.txt", search_dirs[i], PMIX_PATH_SEP, base)) {
 171                         return PMIX_ERR_OUT_OF_RESOURCE;
 172                     }
 173                     pmix_show_help_yyin = fopen(filename, "r");
 174                 }
 175             }
 176             free(filename);
 177             if (NULL != pmix_show_help_yyin) {
 178                 break;
 179             }
 180         }
 181     }
 182 
 183     /* If we still couldn't open it, then something is wrong */
 184     if (NULL == pmix_show_help_yyin) {
 185         pmix_output(output_stream, "%sSorry!  You were supposed to get help about:\n    %s\nBut I couldn't open the help file:\n    %s.  Sorry!\n%s", dash_line, topic, err_msg, dash_line);
 186         free(err_msg);
 187         return PMIX_ERR_NOT_FOUND;
 188     }
 189 
 190     if (NULL != err_msg) {
 191         free(err_msg);
 192     }
 193 
 194     /* Set the buffer */
 195 
 196     pmix_show_help_init_buffer(pmix_show_help_yyin);
 197 
 198     /* Happiness */
 199 
 200     return PMIX_SUCCESS;
 201 }
 202 
 203 
 204 /*
 205  * In the file that has already been opened, find the topic that we're
 206  * supposed to output
 207  */
 208 static int find_topic(const char *base, const char *topic)
 209 {
 210     int token, ret;
 211     char *tmp;
 212 
 213     /* Examine every topic */
 214 
 215     while (1) {
 216         token = pmix_show_help_yylex();
 217         switch (token) {
 218         case PMIX_SHOW_HELP_PARSE_TOPIC:
 219             tmp = strdup(pmix_show_help_yytext);
 220             if (NULL == tmp) {
 221                 return PMIX_ERR_OUT_OF_RESOURCE;
 222             }
 223             tmp[strlen(tmp) - 1] = '\0';
 224             ret = strcmp(tmp + 1, topic);
 225             free(tmp);
 226             if (0 == ret) {
 227                 return PMIX_SUCCESS;
 228             }
 229             break;
 230 
 231         case PMIX_SHOW_HELP_PARSE_MESSAGE:
 232             break;
 233 
 234         case PMIX_SHOW_HELP_PARSE_DONE:
 235             pmix_output(output_stream, "%sSorry!  You were supposed to get help about:\n    %s\nfrom the file:\n    %s\nBut I couldn't find that topic in the file.  Sorry!\n%s", dash_line, topic, base, dash_line);
 236             return PMIX_ERR_NOT_FOUND;
 237             break;
 238 
 239         default:
 240             break;
 241         }
 242     }
 243 
 244     /* Never get here */
 245 }
 246 
 247 
 248 /*
 249  * We have an open file, and we're pointed at the right topic.  So
 250  * read in all the lines in the topic and make a list of them.
 251  */
 252 static int read_topic(char ***array)
 253 {
 254     int token, rc;
 255 
 256     while (1) {
 257         token = pmix_show_help_yylex();
 258         switch (token) {
 259         case PMIX_SHOW_HELP_PARSE_MESSAGE:
 260             /* pmix_argv_append_nosize does strdup(pmix_show_help_yytext) */
 261             rc = pmix_argv_append_nosize(array, pmix_show_help_yytext);
 262             if (rc != PMIX_SUCCESS) {
 263                 return rc;
 264             }
 265             break;
 266 
 267         default:
 268             return PMIX_SUCCESS;
 269             break;
 270         }
 271     }
 272 
 273     /* Never get here */
 274 }
 275 
 276 
 277 static int load_array(char ***array, const char *filename, const char *topic)
 278 {
 279     int ret;
 280 
 281     if (PMIX_SUCCESS != (ret = open_file(filename, topic))) {
 282         return ret;
 283     }
 284 
 285     ret = find_topic(filename, topic);
 286     if (PMIX_SUCCESS == ret) {
 287         ret = read_topic(array);
 288     }
 289 
 290     fclose(pmix_show_help_yyin);
 291     pmix_show_help_yylex_destroy ();
 292 
 293     if (PMIX_SUCCESS != ret) {
 294         pmix_argv_free(*array);
 295     }
 296 
 297     return ret;
 298 }
 299 
 300 char *pmix_show_help_vstring(const char *filename, const char *topic,
 301                              int want_error_header, va_list arglist)
 302 {
 303     int rc;
 304     char *single_string, *output, **array = NULL;
 305 
 306     /* Load the message */
 307     if (PMIX_SUCCESS != (rc = load_array(&array, filename, topic))) {
 308         return NULL;
 309     }
 310 
 311     /* Convert it to a single raw string */
 312     rc = array2string(&single_string, want_error_header, array);
 313 
 314     if (PMIX_SUCCESS == rc) {
 315         /* Apply the formatting to make the final output string */
 316         if (0 > vasprintf(&output, single_string, arglist)) {
 317             output = NULL;
 318         }
 319         free(single_string);
 320     }
 321 
 322     pmix_argv_free(array);
 323     return (PMIX_SUCCESS == rc) ? output : NULL;
 324 }
 325 
 326 char *pmix_show_help_string(const char *filename, const char *topic,
 327                             int want_error_handler, ...)
 328 {
 329     char *output;
 330     va_list arglist;
 331 
 332     va_start(arglist, want_error_handler);
 333     output = pmix_show_help_vstring(filename, topic, want_error_handler,
 334                                     arglist);
 335     va_end(arglist);
 336 
 337     return output;
 338 }
 339 
 340 static int pmix_show_vhelp_internal(const char *filename, const char *topic,
 341                                     int want_error_header, va_list arglist)
 342 {
 343     char *output;
 344 
 345     /* Convert it to a single string */
 346     output = pmix_show_help_vstring(filename, topic, want_error_header,
 347                                     arglist);
 348 
 349     /* If we got a single string, output it with formatting */
 350     if (NULL != output) {
 351         pmix_output(output_stream, "%s", output);
 352         free(output);
 353     }
 354 
 355     return (NULL == output) ? PMIX_ERROR : PMIX_SUCCESS;
 356 }
 357 
 358 static int pmix_show_help_internal(const char *filename, const char *topic,
 359                                    int want_error_header, ...)
 360 {
 361     va_list arglist;
 362     int rc;
 363 
 364     /* Convert it to a single string */
 365     va_start(arglist, want_error_header);
 366     rc = pmix_show_vhelp(filename, topic, want_error_header, arglist);
 367     va_end(arglist);
 368 
 369     return rc;
 370 }
 371 
 372 int pmix_show_help_add_dir(const char *directory)
 373 {
 374     pmix_argv_append_nosize(&search_dirs, directory);
 375     return PMIX_SUCCESS;
 376 }

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