1
1

First cut of the Show Help Subsystem (SHS)

- see src/util/show_help.h for details (doxygen); main function call
  is ompi_show_help()

- text message files are expected to be located in $pkgdatadir
  (usually $prefix/share/openmpi).  Anyone can install a text file in
  $pkgdatadir with their message(s) in it and then have them displayed
  via ompi_show_help().  "pkgdata_DATA" is the keyword to use in
  Makefile.am's, for example (from src/mca/base/Makefile.am):

    pkgdata_DATA = help-mca-base.txt

- added a few examples in the code base using ompi_show_help(), but
  not too many -- can convert more "show_help" comments in the code
  over time; no huge rush.  :-)
- no i18n-like support yet; waiting for advice and consensus from
  other developers

This commit was SVN r2519.
Этот коммит содержится в:
Jeff Squyres 2004-09-05 16:05:37 +00:00
родитель f00b228e73
Коммит 3498f7a283
17 изменённых файлов: 792 добавлений и 161 удалений

Просмотреть файл

@ -15,6 +15,8 @@ LEX_OUTPUT_ROOT = lex.mca_base_yy
noinst_LTLIBRARIES = libmca_base.la
pkgdata_DATA = help-mca-base.txt
# Source code files
headers = \

17
src/mca/base/help-mca-base.txt Обычный файл
Просмотреть файл

@ -0,0 +1,17 @@
# -*- text -*-
#
# $HEADER$
#
# This is the US/English help file for Open MPI MCA error messages.
#
[find-available:none-found]
No available %s components were found!
This means that there are no components of this type installed on your
system or all the components reported that they could not be used.
This is a fatal error; your MPI process is likely to abort. Check the
output of the "ompi_info" command and ensure that components of this
type are available on your system. You may also wish to check the
value of the "component_path" MCA parameter and ensure that it has at
least one directory that contains valid MCA components.

Просмотреть файл

@ -8,7 +8,7 @@
/*
* local functions
*/
static int mca_base_yyerror(void);
static int finish_parsing(void) ;
static int mca_base_yywrap(void);
/*
@ -18,6 +18,9 @@ int mca_base_yynewlines = 1;
bool mca_base_parse_done = false;
char *mca_base_string = NULL;
#define yyterminate() \
return finish_parsing()
%}
WHITE [\f\t\v ]
@ -42,13 +45,19 @@ CHAR [A-Za-z0-9_\-\.]
%%
static int mca_base_yyerror(void)
/*
* This cleans up at the end of the parse (since, in this case, we
* always parse the entire file) and prevents a memory leak.
*/
static int finish_parsing(void)
{
printf("%d: Invalid input (%s)\n", mca_base_yynewlines, mca_base_yytext);
return MCA_BASE_PARSE_ERROR;
if (NULL != YY_CURRENT_BUFFER) {
yy_delete_buffer(YY_CURRENT_BUFFER);
YY_CURRENT_BUFFER = NULL;
}
return YY_NULL;
}
static int mca_base_yywrap(void)
{
mca_base_parse_done = true;

Просмотреть файл

@ -6,6 +6,8 @@ include $(top_srcdir)/config/Makefile.options
noinst_LTLIBRARIES = libmca_coll_base.la
pkgdata_DATA = help-mca-coll-base.txt
headers = \
base.h \
coll_tags.h

Просмотреть файл

@ -11,6 +11,7 @@
#include "mpi.h"
#include "communicator/communicator.h"
#include "util/argv.h"
#include "util/show_help.h"
#include "class/ompi_list.h"
#include "class/ompi_object.h"
#include "mca/mca.h"
@ -207,7 +208,8 @@ int mca_coll_base_comm_select(ompi_communicator_t *comm,
if (!found) {
/* There's no modules available -- including basic. Doh! */
/* show_help */
ompi_show_help("help-mca-coll-base",
"comm-select:none-available", true);
return OMPI_ERROR;
}
}

Просмотреть файл

@ -9,11 +9,12 @@
#include <stdlib.h>
#include "mpi.h"
#include "communicator/communicator.h"
#include "util/show_help.h"
#include "mca/mca.h"
#include "mca/base/base.h"
#include "mca/coll/coll.h"
#include "mca/coll/base/base.h"
#include "communicator/communicator.h"
extern ompi_list_t mca_coll_base_available;
@ -36,7 +37,8 @@ int mca_coll_base_comm_unselect(ompi_communicator_t *comm)
NULL != comm->c_coll_selected_module->coll_module_finalize) {
err = comm->c_coll_selected_module->coll_module_finalize(comm);
if (OMPI_SUCCESS != err) {
/* JMS show_help */
ompi_show_help("help-mca-coll-base",
"comm-unselect:failed-finalize", true);
return err;
}
}
@ -50,7 +52,8 @@ int mca_coll_base_comm_unselect(ompi_communicator_t *comm)
NULL != comm->c_coll_basic_module->coll_module_finalize) {
err = comm->c_coll_basic_module->coll_module_finalize(comm);
if (OMPI_SUCCESS != err) {
/* JMS show_help */
ompi_show_help("help-mca-coll-base",
"comm-unselect:basic-failed-finalize", true);
return err;
}
}

Просмотреть файл

@ -11,6 +11,7 @@
#include "include/constants.h"
#include "class/ompi_list.h"
#include "util/output.h"
#include "util/show_help.h"
#include "mca/mca.h"
#include "mca/base/base.h"
#include "mca/coll/coll.h"
@ -130,7 +131,8 @@ int mca_coll_base_find_available(bool *allow_multi_user_threads,
mca_coll_base_components_available_valid = false;
ompi_output_verbose(10, mca_coll_base_output,
"coll:find_available: no coll components available!");
/* JMS show_help */
ompi_show_help("help-mca-base", "find-available:none-found", true,
"coll");
return OMPI_ERROR;
}
@ -164,11 +166,10 @@ static int init_query(const mca_base_component_t *m,
/* Unrecognized coll API version */
ompi_output_verbose(10, mca_coll_base_output,
"coll:find_available: unrecognized coll API version (%d.%d.%d)",
"coll:find_available: unrecognized coll API version (%d.%d.%d, ignored)",
m->mca_type_major_version,
m->mca_type_minor_version,
m->mca_type_release_version);
/* JMS show_help */
return OMPI_ERROR;
}

32
src/mca/coll/base/help-mca-coll-base.txt Обычный файл
Просмотреть файл

@ -0,0 +1,32 @@
# -*- text -*-
#
# $HEADER$
#
# This is the US/English help file for Open MPI MCA coll-specific
# error messages.
#
[comm-select:none-available]
Although some coll components are available on your system, none of
them said that they could be used for a new communicator.
This is extremely unusual -- in a worse case scenario, the "basic"
component should be able to be chosen for any communicator. As such,
this likely means that something else is wrong (although you should
double check that the "basic" coll component is available on your
system -- look at the output of the "ompi_info" command).
#
[comm-unselect:failed-finalize]
A coll module failed to finalize properly when a communicator that was
using it was destroyed.
This is somewhat unusual: the module itself may be at fault, or this
may be a symptom of another issue (e.g., a memory problem).
#
[comm-unselect:basic-failed-finalize]
The basic coll module failed to finalize properly when a communicator
that was using it was destroyed. This happened on the communicator
named "%s".
This is extremely unusual and typically indicates some other kind of
problem (e.g., a memory problem)

Просмотреть файл

@ -9,6 +9,8 @@ AM_CPPFLAGS = -I$(top_builddir)/src/event
noinst_LTLIBRARIES = libmpiruntime.la
pkgdata_DATA = help-mpi-runtime.txt
# Source code files
headers = \

16
src/mpi/runtime/help-mpi-runtime.txt Обычный файл
Просмотреть файл

@ -0,0 +1,16 @@
# -*- text -*-
#
# $HEADER$
#
# This is the US/English general help file for Open MPI.
#
[mpi_init:startup:internal-failure]
It looks like %s failed for some reason; your parallel process is
likely to abort. There are many reasons that a parallel process can
fail during %s; some of which are due to configuration or environment
problems. This failure appears to be an internal failure; here's some
additional information (which may only be relevant to an Open MPI
developer):
%s
--> Returned value %d instead of OMPI_SUCCESS

Просмотреть файл

@ -15,6 +15,7 @@
#include "group/group.h"
#include "info/info.h"
#include "util/common_cmd_line.h"
#include "util/show_help.h"
#include "errhandler/errhandler.h"
#include "errhandler/errcode.h"
#include "errhandler/errclass.h"
@ -59,29 +60,27 @@ int ompi_mpi_init(int argc, char **argv, int requested, int *provided)
bool have_hidden_threads;
ompi_proc_t** procs;
size_t nprocs;
char *error;
/* Save command line parameters */
if (OMPI_SUCCESS != (ret = ompi_common_cmd_line_init(argc, argv))) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in ompi_common_cmd_line_init\n");
return ret;
error = "ompi_common_cmd_line_init() failed";
goto error;
}
/* Become a OMPI process */
if (OMPI_SUCCESS != (ret = ompi_init(argc, argv))) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in ompi_init\n");
return ret;
error = "ompi_init() failed";
goto error;
}
/* Open up the MCA */
if (OMPI_SUCCESS != (ret = mca_base_open())) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in mca_base_open\n");
return ret;
error = "mca_base_open() failed";
goto error;
}
/* Join the run-time environment */
@ -91,63 +90,53 @@ int ompi_mpi_init(int argc, char **argv, int requested, int *provided)
&have_hidden_threads))) ||
(OMPI_SUCCESS != (ret = ompi_rte_init_stage2(&allow_multi_user_threads,
&have_hidden_threads)))) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in mca_rte_init\n");
return ret;
error = "mca_rte_init() failed";
goto error;
}
/* Once we've joined the RTE, see if any MCA parameters were
passed to the MPI level */
if (OMPI_SUCCESS != (ret = ompi_mpi_register_params())) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in mca_mpi_register_params\n");
return ret;
error = "mca_mpi_register_params() failed";
goto error;
}
/* initialize ompi procs */
if (OMPI_SUCCESS != (ret = ompi_proc_init())) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in mca_proc_init\n");
return ret;
error = "mca_proc_init() failed";
goto error;
}
/* Open up relevant MCA modules. */
if (OMPI_SUCCESS != (ret = mca_allocator_base_open())) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in mca_allocator_base_open\n");
return ret;
error = "mca_allocator_base_open() failed";
goto error;
}
if (OMPI_SUCCESS != (ret = mca_mpool_base_open())) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in mca_mpool_base_open\n");
return ret;
error = "mca_mpool_base_open() failed";
goto error;
}
if (OMPI_SUCCESS != (ret = mca_pml_base_open())) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in mca_pml_base_open\n");
return ret;
error = "mca_pml_base_open() failed";
goto error;
}
if (OMPI_SUCCESS != (ret = mca_ptl_base_open())) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in mca_ptl_base_open\n");
return ret;
error = "mca_ptl_base_open() failed";
goto error;
}
if (OMPI_SUCCESS != (ret = mca_coll_base_open())) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in mca_coll_base_open\n");
return ret;
error = "mca_coll_base_open() failed";
goto error;
}
if (OMPI_SUCCESS != (ret = mca_topo_base_open())) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in mca_topo_base_open\n");
return ret;
error = "mca_topo_base_open() failed";
goto error;
}
if (OMPI_SUCCESS != (ret = mca_io_base_open())) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in mca_io_base_open\n");
return ret;
error = "mca_io_base_open() failed";
goto error;
}
/* Select which pml, ptl, and coll modules to use, and determine the
@ -158,118 +147,102 @@ int ompi_mpi_init(int argc, char **argv, int requested, int *provided)
allow_multi_user_threads,
have_hidden_threads,
provided))) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in mca_base_init_select_modules\n");
return ret;
error = "mca_base_init_select_components() failed";
goto error;
}
/* initialize info */
if (OMPI_SUCCESS != (ret = ompi_info_init())) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in ompi_info_init\n");
return ret;
}
/* initialize error handlers */
if (OMPI_SUCCESS != (ret = ompi_errhandler_init())) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in ompi_errhandler_init\n");
return ret;
}
/* initialize info */
if (OMPI_SUCCESS != (ret = ompi_info_init())) {
error = "ompi_info_init() failed";
goto error;
}
/* initialize error handlers */
if (OMPI_SUCCESS != (ret = ompi_errhandler_init())) {
error = "ompi_errhandler_init() failed";
goto error;
}
/* initialize error codes */
if (OMPI_SUCCESS != (ret = ompi_mpi_errcode_init())) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in ompi_errcode_init\n");
return ret;
}
/* initialize error codes */
if (OMPI_SUCCESS != (ret = ompi_mpi_errcode_init())) {
error = "ompi_mpi_errcode_init() failed";
goto error;
}
/* initialize error classes */
if (OMPI_SUCCESS != (ret = ompi_errclass_init())) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in ompi_errclass_init\n");
return ret;
}
/* initialize internal error codes */
if (OMPI_SUCCESS != (ret = ompi_errcode_intern_init())) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in ompi_errcode_internal_init\n");
return ret;
}
/* initialize error classes */
if (OMPI_SUCCESS != (ret = ompi_errclass_init())) {
error = "ompi_errclass_init() failed";
goto error;
}
/* initialize internal error codes */
if (OMPI_SUCCESS != (ret = ompi_errcode_intern_init())) {
error = "ompi_errcode_intern_init() failed";
goto error;
}
/* initialize groups */
if (OMPI_SUCCESS != (ret = ompi_group_init())) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in ompi_group_init\n");
return ret;
}
/* initialize groups */
if (OMPI_SUCCESS != (ret = ompi_group_init())) {
error = "ompi_group_init() failed";
goto error;
}
/* initialize attribute meta-data structure for comm/win/dtype */
if (OMPI_SUCCESS != (ret = ompi_attr_init())) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in ompi_attr_init\n");
return ret;
}
/* initialize attribute meta-data structure for comm/win/dtype */
if (OMPI_SUCCESS != (ret = ompi_attr_init())) {
error = "ompi_attr_init() failed";
goto error;
}
/* initialize communicators */
if (OMPI_SUCCESS != (ret = ompi_comm_init())) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in ompi_comm_init\n");
return ret;
}
/* initialize communicators */
if (OMPI_SUCCESS != (ret = ompi_comm_init())) {
error = "ompi_comm_init() failed";
goto error;
}
/* initialize datatypes */
if (OMPI_SUCCESS != (ret = ompi_ddt_init())) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in ompi_ddt_init\n");
return ret;
}
/* initialize datatypes */
if (OMPI_SUCCESS != (ret = ompi_ddt_init())) {
error = "ompi_ddt_init() failed";
goto error;
}
/* initialize ops */
if (OMPI_SUCCESS != (ret = ompi_op_init())) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in ompi_op_init\n");
return ret;
}
/* initialize ops */
if (OMPI_SUCCESS != (ret = ompi_op_init())) {
error = "ompi_op_init() failed";
goto error;
}
/* initialize file handles */
if (OMPI_SUCCESS != (ret = ompi_file_init())) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in ompi_file_init\n");
return ret;
}
/* initialize file handles */
if (OMPI_SUCCESS != (ret = ompi_file_init())) {
error = "ompi_file_init() failed";
goto error;
}
/* do module exchange */
if (OMPI_SUCCESS != (ret = mca_base_modex_exchange())) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in mca_base_modex_exchange\n");
return ret;
}
/* do module exchange */
if (OMPI_SUCCESS != (ret = mca_base_modex_exchange())) {
error = "ompi_base_modex_exchange() failed";
goto error;
}
/* add all ompi_proc_t's to PML */
if (NULL == (procs = ompi_proc_world(&nprocs))) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in NULL proc world!\n");
return OMPI_ERROR;
}
if (OMPI_SUCCESS != (ret = mca_pml.pml_add_procs(procs, nprocs))) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in pml_add_procs!\n");
free(procs);
return ret;
}
free(procs);
/* add all ompi_proc_t's to PML */
if (NULL == (procs = ompi_proc_world(&nprocs))) {
error = "ompi_proc_world() failed";
goto error;
}
if (OMPI_SUCCESS != (ret = mca_pml.pml_add_procs(procs, nprocs))) {
free(procs);
error = "PML add procs failed";
goto error;
}
free(procs);
/* start PTL's */
param = 1;
if (OMPI_SUCCESS !=
(ret = mca_pml.pml_control(MCA_PTL_ENABLE, &param, sizeof(param)))) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in pml_control!\n");
return ret;
}
/* start PTL's */
param = 1;
if (OMPI_SUCCESS !=
(ret = mca_pml.pml_control(MCA_PTL_ENABLE, &param, sizeof(param)))) {
error = "PML control failed";
goto error;
}
/* save the resulting thread levels */
/* save the resulting thread levels */
ompi_mpi_thread_requested = requested;
*provided = ompi_mpi_thread_provided;
@ -278,25 +251,32 @@ int ompi_mpi_init(int argc, char **argv, int requested, int *provided)
/* Init coll for the comms */
if (OMPI_ERROR == mca_coll_base_comm_select(MPI_COMM_SELF, NULL)) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in mca_coll_base_comm_select SELF!\n");
return OMPI_ERROR;
if (OMPI_SUCCESS !=
(ret = mca_coll_base_comm_select(MPI_COMM_SELF, NULL))) {
error = "mca_coll_base_comm_select(MPI_COMM_SELF) failed";
goto error;
}
if (OMPI_ERROR == mca_coll_base_comm_select(MPI_COMM_WORLD, NULL)) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in mca_coll_base_comm_select WORLD!\n");
return OMPI_ERROR;
if (OMPI_SUCCESS !=
(ret = mca_coll_base_comm_select(MPI_COMM_WORLD, NULL))) {
error = "mca_coll_base_comm_select(MPI_COMM_WORLD) failed";
goto error;
}
/* Wait for everyone to initialize */
if (MPI_SUCCESS != (ret =
MPI_COMM_WORLD->c_coll.coll_barrier(MPI_COMM_WORLD))) {
/* JMS show_help */
printf("show_help: ompi_mpi_init failed in WORLD barrier!\n");
return ret;
error = "Barrier over MPI_COMM_WORLD failed";
goto error;
}
error:
if (ret != OMPI_SUCCESS) {
ompi_show_help("help-mpi-runtime",
"mpi_init:startup:internal-failure", true,
"MPI_INIT", "MPI_INIT", error, ret);
return ret;
}
/* All done */

Просмотреть файл

@ -40,6 +40,7 @@ const string ompi_info::type_ompi = "ompi";
const string ompi_info::type_base = "base";
ompi_info::type_vector_t ompi_info::mca_types;
int main(int argc, char *argv[])
{
int ret = 0;

Просмотреть файл

@ -1,10 +1,13 @@
# -*- makefile -*-
#
# $HEADER$
#
include $(top_srcdir)/config/Makefile.options
AM_CPPFLAGS = -DOMPI_PKGDATADIR=\"$(pkgdatadir)\"
AM_LFLAGS = -Pompi_show_help_yy
LEX_OUTPUT_ROOT = lex.ompi_show_help_yy
libutil_la_CCASFLAGS = $(CPPFLAGS)
noinst_LTLIBRARIES = libutil.la
@ -30,6 +33,8 @@ headers = \
os_create_dirpath.h \
pow2.h \
session_dir.h \
show_help.h \
show_help_lex.h \
daemon_init.h \
universe_setup_file_io.h \
strncpy.h
@ -54,6 +59,8 @@ libutil_la_SOURCES = \
os_create_dirpath.c \
pow2.c \
session_dir.c \
show_help.c \
show_help_lex.l \
daemon_init.c \
universe_setup_file_io.c \
strncpy.c

313
src/util/show_help.c Обычный файл
Просмотреть файл

@ -0,0 +1,313 @@
/*
* $HEADER$
*/
#include "ompi_config.h"
#include <stdio.h>
#include <string.h>
#include <locale.h>
#include "include/constants.h"
#include "util/show_help.h"
#include "util/show_help_lex.h"
#include "util/printf.h"
#include "class/ompi_pointer_array.h"
static int open_file(const char *base, const char *topic);
static int find_topic(const char *base, const char *topic);
static int read_message(ompi_pointer_array_t *lines);
static int output(bool want_error_header, ompi_pointer_array_t *lines,
const char *base, const char *topic,
va_list arglist);
static int destroy_message(ompi_pointer_array_t *lines);
/*
* Private variables
*/
#if 0
/* not attempting i18n-like support right now */
static const char *default_language = "C";
#endif
static const char *default_filename = "help-messages";
static const char *star_line = "**************************************************************************\n";
int ompi_show_help(const char *filename, const char *topic,
bool want_error_header, ...)
{
int ret;
va_list arglist;
ompi_pointer_array_t array;
if (OMPI_SUCCESS != (ret = open_file(filename, topic))) {
return ret;
}
if (OMPI_SUCCESS != (ret = find_topic(filename, topic))) {
fclose(ompi_show_help_yyin);
return ret;
}
OBJ_CONSTRUCT(&array, ompi_pointer_array_t);
ret = read_message(&array);
ompi_show_help_finish_parsing();
fclose(ompi_show_help_yyin);
if (OMPI_SUCCESS != ret) {
destroy_message(&array);
return ret;
}
#if __STDC__
va_start(arglist, want_error_header);
#else
va_start(arglist);
#endif
output(want_error_header, &array, filename, topic, arglist);
va_end(arglist);
destroy_message(&array);
return ret;
}
/*
* Find the right file to open
*/
static int open_file(const char *base, const char *topic)
{
#if 0
/* not attempting i18n-like support right now */
const char *lang;
#endif
char *filename;
/* If no filename was supplied, use the default */
if (NULL == base) {
base = default_filename;
}
/* Don't try any i18n-like support right now */
#if 1
/* Try to open the file. If we can't find it, try it with a .txt
extension. */
asprintf(&filename, "%s/%s", OMPI_PKGDATADIR, base);
ompi_show_help_yyin = fopen(filename, "r");
free(filename);
if (NULL == ompi_show_help_yyin) {
asprintf(&filename, "%s/%s.txt", OMPI_PKGDATADIR, base);
ompi_show_help_yyin = fopen(filename, "r");
free(filename);
}
#else
/* What's our locale? */
lang = setlocale(LC_MESSAGES, "");
if (NULL == lang) {
lang = default_language;
}
/* Do we have a file matching that locale? If not, open the
default language (because we know that we have that one) */
asprintf(&filename, "%s/%s.%s", OMPI_PKGDATADIR, base, lang);
ompi_show_help_yyin = fopen(filename, "r");
free(filename);
if (NULL == ompi_show_help_yyin) {
asprintf(&filename, "%s/%s.%s", OMPI_PKGDATADIR,
base, default_language);
ompi_show_help_yyin = fopen(filename, "r");
free(filename);
}
/* If we still couldn't find it, try with no extension */
if (NULL == ompi_show_help_yyin) {
asprintf(&filename, "%s/%s", OMPI_PKGDATADIR, base);
ompi_show_help_yyin = fopen(filename, "r");
free(filename);
}
#endif
/* If we still couldn't open it, then something is wrong */
if (NULL == ompi_show_help_yyin) {
fprintf(stderr, star_line);
fprintf(stderr, "Sorry! You were supposed to get help about:\n %s\nfrom the file:\n %s\n", topic, base);
fprintf(stderr, "But I couldn't find any file matching that name. Sorry!\n");
fprintf(stderr, star_line);
return OMPI_ERR_NOT_FOUND;
}
/* Happiness */
return OMPI_SUCCESS;
}
/*
* In the file that has already been opened, find the topic that we're
* supposed to output
*/
static int find_topic(const char *base, const char *topic)
{
int token, ret;
char *tmp;
/* Examine every topic */
while (1) {
token = ompi_show_help_yylex();
switch (token) {
case OMPI_SHOW_HELP_PARSE_TOPIC:
tmp = strdup(ompi_show_help_yytext);
if (NULL == tmp) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
tmp[strlen(tmp) - 1] = '\0';
ret = strcmp(tmp + 1, topic);
free(tmp);
if (0 == ret) {
return OMPI_SUCCESS;
}
break;
case OMPI_SHOW_HELP_PARSE_MESSAGE:
break;
case OMPI_SHOW_HELP_PARSE_DONE:
fprintf(stderr, star_line);
fprintf(stderr, "Sorry! You were supposed to get help about:\n %s\nfrom the file:\n %s\n", topic, base);
fprintf(stderr, "But I couldn't find that topic in the file. Sorry!\n");
fprintf(stderr, star_line);
return OMPI_ERR_NOT_FOUND;
break;
default:
break;
}
}
/* Never get here */
}
/*
* We have an open file, and we're pointed at the right topic. So
* read in all the lines in the topic and make a list of them.
*/
static int read_message(ompi_pointer_array_t *array)
{
char *tmp;
int token;
while (1) {
token = ompi_show_help_yylex();
switch (token) {
case OMPI_SHOW_HELP_PARSE_MESSAGE:
tmp = strdup(ompi_show_help_yytext);
if (NULL == tmp) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
ompi_pointer_array_add(array, tmp);
break;
default:
return OMPI_SUCCESS;
break;
}
}
/* Never get here */
}
/*
* Make one big string with all the lines. This isn't the most
* efficient method in the world, but we're going for clarity here --
* not optimization. :-)
*/
static int output(bool want_error_header, ompi_pointer_array_t *lines,
const char *base, const char *topic,
va_list arglist)
{
size_t i, len;
char *tmp, *concat, *formatted;
/* See how much space we need */
len = want_error_header ? 2 * strlen(star_line) : 0;
for (i = 0; i < ompi_pointer_array_get_size(lines); ++i) {
tmp = ompi_pointer_array_get_item(lines, i);
if (NULL == tmp) {
break;
}
len += strlen(tmp) + 1;
}
/* Malloc it out */
concat = malloc(len + 1);
if (NULL == concat) {
fprintf(stderr, star_line);
fprintf(stderr, "Sorry! You were supposed to get help about:\n %s\nfrom the file:\n %s\n", topic, base);
fprintf(stderr, "But memory seems to be exhausted. Sorry!\n");
fprintf(stderr, star_line);
return OMPI_ERR_OUT_OF_RESOURCE;
}
/* Fill the big string */
*concat = '\0';
if (want_error_header) {
strcat(concat, star_line);
}
for (i = 0; i < ompi_pointer_array_get_size(lines); ++i) {
tmp = ompi_pointer_array_get_item(lines, i);
if (NULL == tmp) {
break;
}
strcat(concat, tmp);
strcat(concat, "\n");
}
if (want_error_header) {
strcat(concat, star_line);
}
/* Apply formatting */
vasprintf(&formatted, concat, arglist);
/* Print it out */
fprintf(stderr, formatted);
/* All done */
free(formatted);
free(concat);
return OMPI_SUCCESS;
}
/*
* Free all the strings in the array and destruct the array
*/
static int destroy_message(ompi_pointer_array_t *lines)
{
size_t i;
char *tmp;
for (i = 0; i < ompi_pointer_array_get_size(lines); ++i) {
tmp = ompi_pointer_array_get_item(lines, i);
if (NULL == tmp) {
break;
}
free(tmp);
}
OBJ_DESTRUCT(lines);
return OMPI_SUCCESS;
}

128
src/util/show_help.h Обычный файл
Просмотреть файл

@ -0,0 +1,128 @@
/*
* $HEADER$
*/
/**
* @file
*
* The "show help" subsystem (SHS) in Open MPI is intended to help the
* developer convey meaningful information to the user (read longer
* than is convenient in a single printf), particularly when errors
* occur. The SHS allows the storage of arbitrary-length help
* messages in text files which can be parameterized by text filename,
* message name, POSIX locale, and printf()-style parameters (e.g.,
* "%s", "%d", etc.). Note that the primary purpose of the SHS is to
* display help messages, but it can actually be used to display any
* arbitrary text messages.
*
* The function ompi_show_help() is used to find a help message and
* display it. Its important parameters are a filename, message name,
* and printf()-style varargs parameters used to substitute into the
* message.
*
* There's work pending about i18n-like support (nothing near as
* complex as GNU gettext -- just a simple mechanism that may be
* used). But I won't describe it here until/if it's actually used.
* So right now, the file lookup is quite straightforward -- the
* caller passes in the filename to find the help message, and the SHS
* looks for that file in $pkgdatadir (typically
* $prefix/share/openmpi).
*
* Once the file is successfully opened, the SHS looks for the
* appropriate help message to display. It looks for the message name
* in the file, reads in the message, and displays it. printf()-like
* substitutions are performed (e.g., %d, %s, etc.) --
* ompi_show_help() takes a variable legnth argument list that are
* used for these substitutions.
*
* The format of the help file is simplistic:
*
* - Comments begin with #. Any characters after a # on a line are
* ignored. It is not possible to escape a #.
* - Message names are on a line by themselves and marked with [].
* Names can be any ASCII string within the [] (excluding the
* characters newline, linefeed, [, ], and #).
* - Messages are any characters between message names and/or the end
* of the file.
*
* Here's a sample helpfile:
*
* \verbatimbegin
* # This is a comment.
* [topic 1]
* Here's the first message. Let's substitute in an integer: %d.
* The quick brown fox jumped over the lazy %s.
* # This is another comment -- it's not displayed in the first message.
* [another:topic:foo:foo:foo]
* This is the second message. Let's just keep rolling along to get
* to the second line in the message for this example.
* \verbatimend
*
* It is expected that help messages will be grouped by filename;
* similar messages should be in a single file. For example, an MCA
* component may install its own helpfile in Open MPI's $pkgdatadir,
* and therefore the component can invoke ompi_show_help() to display
* its own help messages.
*
* Message files in $pkgdatadir have a naming convention: they
* generally start with the prefix "help-" and are followed by a name
* descriptive of what kind of messages they contain. MCA components
* should generally abide by the MCA prefix rule, with the exception
* that they should start the filename with "help-", as mentioned
* previously.
*/
#ifndef OMPI_SHOW_HELP_H
#define OMPI_SHOW_HELP_H
#include "ompi_config.h"
#if __STDC__
#include <stdarg.h>
#else
#ifdef __cplusplus
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#endif /* __STDC__ */
#ifdef __cplusplus
extern "C" {
#endif
/**
* Look up a text message in a text file and display it to the
* stderr using printf()-like substitutions (%d, %s, etc.).
*
* @param filename File where the text messages are contained.
* @param topic String index of which message to display from the
* text file.
* @param want_error_header Display error-bar line header and
* footer with the message.
* @param varargs Any additional parameters are substituted,
* printf()-style into the help message that is displayed.
*
* This function looks for the filename in the $pkgdatadir
* (typically $prefix/share/openmpi), and looks up the message
* based on the topic, and displays it. If want_error_header is
* true, a header and footer of asterisks are also displayed.
*/
int ompi_show_help(const char *filename, const char *topic,
bool want_error_header, ...);
/**
* \internal
*
* Internal function to help clean up the flex parser.
*
* This function is called internally by the SHS to shut down the
* flex parser since we may not hit the <<EOF>> rule and call this
* function automatically.
*/
int ompi_show_help_finish_parsing(void);
#ifdef __cplusplus
}
#endif
#endif

48
src/util/show_help_lex.h Обычный файл
Просмотреть файл

@ -0,0 +1,48 @@
/*
* $HEADER$
*/
#ifndef OMPI_SHOW_HELP_LEX_H
#define OMPI_SHOW_HELP_LEX_H
#include "ompi_config.h"
#ifdef malloc
#undef malloc
#endif
#ifdef realloc
#undef realloc
#endif
#ifdef free
#undef free
#endif
#include <stdio.h>
extern int ompi_show_help_yylex(void);
extern FILE *ompi_show_help_yyin;
extern bool ompi_show_help_parse_done;
extern char *ompi_show_help_yytext;
extern int ompi_show_help_yynewlines;
/*
* Make lex-generated files not issue compiler warnings
*/
#define YY_STACK_USED 0
#define YY_ALWAYS_INTERACTIVE 0
#define YY_NEVER_INTERACTIVE 0
#define YY_MAIN 0
#define YY_NO_UNPUT 1
enum {
OMPI_SHOW_HELP_PARSE_DONE,
OMPI_SHOW_HELP_PARSE_ERROR,
OMPI_SHOW_HELP_PARSE_TOPIC,
OMPI_SHOW_HELP_PARSE_MESSAGE,
OMPI_SHOW_HELP_PARSE_MAX
};
#endif

68
src/util/show_help_lex.l Обычный файл
Просмотреть файл

@ -0,0 +1,68 @@
%{ /* -*- C -*- */
#include "ompi_config.h"
#include <stdio.h>
#include <unistd.h>
#include "util/show_help_lex.h"
/*
* public functions
*/
int ompi_show_help_finish_parsing(void);
/*
* local functions
*/
static int ompi_show_help_yywrap(void);
/*
* global variables
*/
int ompi_show_help_yynewlines = 1;
bool ompi_show_help_parse_done = false;
char *ompi_show_help_string = NULL;
#define yyterminate() \
return ompi_show_help_finish_parsing()
%}
WHITE [\f\t\v ]
CHAR [A-Za-z0-9_\-\.]
%x CHOMP
%%
#.*\n ; /* comment line */
^\[.+\]/.*\n { BEGIN(CHOMP); return OMPI_SHOW_HELP_PARSE_TOPIC; }
<CHOMP>.*\n { BEGIN(INITIAL); }
.*/\n { BEGIN(CHOMP); return OMPI_SHOW_HELP_PARSE_MESSAGE; }
%%
/*
* This cleans up at the end of the parse (since, in this case, we
* always parse the entire file) and prevents a memory leak.
*/
int ompi_show_help_finish_parsing(void)
{
if (NULL != YY_CURRENT_BUFFER) {
yy_delete_buffer(YY_CURRENT_BUFFER);
YY_CURRENT_BUFFER = NULL;
}
return YY_NULL;
}
static int ompi_show_help_yywrap(void)
{
ompi_show_help_parse_done = true;
return 1;
}