This source file includes following definitions.
- pmix_show_help_init
- pmix_show_help_finalize
- array2string
- open_file
- find_topic
- read_topic
- load_array
- pmix_show_help_vstring
- pmix_show_help_string
- pmix_show_vhelp_internal
- pmix_show_help_internal
- pmix_show_help_add_dir
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
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
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
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
89
90
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
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
110
111 (*outstring) = (char*) malloc(len + 1);
112 if (NULL == *outstring) {
113 return PMIX_ERR_OUT_OF_RESOURCE;
114 }
115
116
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
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
148
149 if (NULL == base) {
150 base = default_filename;
151 }
152
153
154
155
156 if (NULL != search_dirs) {
157
158
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
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
195
196 pmix_show_help_init_buffer(pmix_show_help_yyin);
197
198
199
200 return PMIX_SUCCESS;
201 }
202
203
204
205
206
207
208 static int find_topic(const char *base, const char *topic)
209 {
210 int token, ret;
211 char *tmp;
212
213
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
245 }
246
247
248
249
250
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
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
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
307 if (PMIX_SUCCESS != (rc = load_array(&array, filename, topic))) {
308 return NULL;
309 }
310
311
312 rc = array2string(&single_string, want_error_header, array);
313
314 if (PMIX_SUCCESS == rc) {
315
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
346 output = pmix_show_help_vstring(filename, topic, want_error_header,
347 arglist);
348
349
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
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 }