5e280cda19
The same treatement will happens on all sub-projects. The .h files have to be C++ compatibles and all symbols with an external visibility have to get the {PROJECT}_DECLSPEC in front of the prototype. This commit was SVN r11340.
321 строка
8.2 KiB
C
321 строка
8.2 KiB
C
/*
|
|
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
|
* University Research and Technology
|
|
* Corporation. All rights reserved.
|
|
* Copyright (c) 2004-2006 The University of Tennessee and The University
|
|
* of Tennessee Research Foundation. All rights
|
|
* reserved.
|
|
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
|
* University of Stuttgart. All rights reserved.
|
|
* Copyright (c) 2004-2005 The Regents of the University of California.
|
|
* All rights reserved.
|
|
* $COPYRIGHT$
|
|
*
|
|
* Additional copyrights may follow
|
|
*
|
|
* $HEADER$
|
|
*/
|
|
|
|
#include "opal_config.h"
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <locale.h>
|
|
|
|
#include "opal/install_dirs.h"
|
|
#include "opal/util/show_help.h"
|
|
#include "opal/util/show_help_lex.h"
|
|
#include "opal/util/printf.h"
|
|
#include "opal/util/argv.h"
|
|
#include "opal/util/os_path.h"
|
|
#include "opal/constants.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(char ***lines);
|
|
static int output(bool want_error_header, char **lines,
|
|
const char *base, const char *topic,
|
|
va_list arglist);
|
|
static int destroy_message(char **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 *dash_line = "--------------------------------------------------------------------------\n";
|
|
|
|
|
|
int opal_show_help(const char *filename, const char *topic,
|
|
bool want_error_header, ...)
|
|
{
|
|
int ret;
|
|
va_list arglist;
|
|
char **array = NULL;
|
|
|
|
if (OPAL_SUCCESS != (ret = open_file(filename, topic))) {
|
|
return ret;
|
|
}
|
|
if (OPAL_SUCCESS != (ret = find_topic(filename, topic))) {
|
|
fclose(opal_show_help_yyin);
|
|
return ret;
|
|
}
|
|
|
|
ret = read_message(&array);
|
|
opal_show_help_finish_parsing();
|
|
fclose(opal_show_help_yyin);
|
|
if (OPAL_SUCCESS != ret) {
|
|
destroy_message(array);
|
|
return ret;
|
|
}
|
|
|
|
va_start(arglist, want_error_header);
|
|
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. */
|
|
|
|
filename = opal_os_path( false, OPAL_PKGDATADIR, base, NULL );
|
|
opal_show_help_yyin = fopen(filename, "r");
|
|
free(filename);
|
|
if (NULL == opal_show_help_yyin) {
|
|
asprintf(&filename, "%s/%s.txt", OPAL_PKGDATADIR, base);
|
|
opal_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", OPAL_PKGDATADIR, base, lang);
|
|
opal_show_help_yyin = fopen(filename, "r");
|
|
free(filename);
|
|
if (NULL == opal_show_help_yyin) {
|
|
asprintf(&filename, "%s/%s.%s", OPAL_PKGDATADIR,
|
|
base, default_language);
|
|
opal_show_help_yyin = fopen(filename, "r");
|
|
free(filename);
|
|
}
|
|
|
|
/* If we still couldn't find it, try with no extension */
|
|
|
|
if (NULL == opal_show_help_yyin) {
|
|
filename = opal_os_path( false, OPAL_PKGDATADIR, base, NULL );
|
|
opal_show_help_yyin = fopen(filename, "r");
|
|
free(filename);
|
|
}
|
|
#endif
|
|
|
|
/* If we still couldn't open it, then something is wrong */
|
|
|
|
if (NULL == opal_show_help_yyin) {
|
|
fprintf(stderr, dash_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, dash_line);
|
|
return OPAL_ERR_NOT_FOUND;
|
|
}
|
|
|
|
/* Set the buffer */
|
|
|
|
opal_show_help_init_buffer(opal_show_help_yyin);
|
|
|
|
/* Happiness */
|
|
|
|
return OPAL_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 = opal_show_help_yylex();
|
|
switch (token) {
|
|
case OPAL_SHOW_HELP_PARSE_TOPIC:
|
|
tmp = strdup(opal_show_help_yytext);
|
|
if (NULL == tmp) {
|
|
return OPAL_ERR_OUT_OF_RESOURCE;
|
|
}
|
|
tmp[strlen(tmp) - 1] = '\0';
|
|
ret = strcmp(tmp + 1, topic);
|
|
free(tmp);
|
|
if (0 == ret) {
|
|
return OPAL_SUCCESS;
|
|
}
|
|
break;
|
|
|
|
case OPAL_SHOW_HELP_PARSE_MESSAGE:
|
|
break;
|
|
|
|
case OPAL_SHOW_HELP_PARSE_DONE:
|
|
fprintf(stderr, dash_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, dash_line);
|
|
return OPAL_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(char ***array)
|
|
{
|
|
char *tmp;
|
|
int token;
|
|
|
|
while (1) {
|
|
token = opal_show_help_yylex();
|
|
switch (token) {
|
|
case OPAL_SHOW_HELP_PARSE_MESSAGE:
|
|
tmp = strdup(opal_show_help_yytext);
|
|
if (NULL == tmp) {
|
|
return OPAL_ERR_OUT_OF_RESOURCE;
|
|
}
|
|
opal_argv_append_nosize(array, tmp);
|
|
break;
|
|
|
|
default:
|
|
return OPAL_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, char **lines,
|
|
const char *base, const char *topic,
|
|
va_list arglist)
|
|
{
|
|
int i, count;
|
|
size_t len;
|
|
char *concat;
|
|
|
|
/* See how much space we need */
|
|
|
|
len = want_error_header ? 2 * strlen(dash_line) : 0;
|
|
count = opal_argv_count(lines);
|
|
for (i = 0; i < count; ++i) {
|
|
if (NULL == lines[i]) {
|
|
break;
|
|
}
|
|
len += strlen(lines[i]) + 1;
|
|
}
|
|
|
|
/* Malloc it out */
|
|
|
|
concat = (char*) malloc(len + 1);
|
|
if (NULL == concat) {
|
|
fprintf(stderr, dash_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, dash_line);
|
|
return OPAL_ERR_OUT_OF_RESOURCE;
|
|
}
|
|
|
|
/* Fill the big string */
|
|
|
|
*concat = '\0';
|
|
if (want_error_header) {
|
|
strcat(concat, dash_line);
|
|
}
|
|
for (i = 0; i < count; ++i) {
|
|
if (NULL == lines[i]) {
|
|
break;
|
|
}
|
|
strcat(concat, lines[i]);
|
|
strcat(concat, "\n");
|
|
}
|
|
if (want_error_header) {
|
|
strcat(concat, dash_line);
|
|
}
|
|
|
|
/* Apply formatting */
|
|
vfprintf( stderr, concat, arglist );
|
|
|
|
/* All done */
|
|
|
|
free(concat);
|
|
return OPAL_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
* Free all the strings in the array and destruct the array
|
|
*/
|
|
static int destroy_message(char **lines)
|
|
{
|
|
int i, count;
|
|
|
|
count = opal_argv_count(lines);
|
|
for (i = 0; i < count; ++i) {
|
|
if (NULL == lines[i]) {
|
|
break;
|
|
}
|
|
free(lines[i]);
|
|
}
|
|
|
|
return OPAL_SUCCESS;
|
|
}
|