root/opal/util/show_help.c

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

DEFINITIONS

This source file includes following definitions.
  1. opal_show_help_init
  2. opal_show_help_finalize
  3. array2string
  4. open_file
  5. find_topic
  6. read_topic
  7. load_array
  8. opal_show_help_vstring
  9. opal_show_help_string
  10. opal_show_vhelp_internal
  11. opal_show_help_internal
  12. opal_show_help_add_dir

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

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