1 /*****************************************************************************
2  *  parse_config.h - parse any slurm.conf-like configuration file
3  *
4  *  NOTE: when you see the prefix "s_p_", think "slurm parser".
5  *****************************************************************************
6  *  Copyright (C) 2006 The Regents of the University of California.
7  *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
8  *  Written by Christopher J. Morrone <morrone2@llnl.gov>.
9  *  CODE-OCEC-09-009. All rights reserved.
10  *
11  *  This file is part of Slurm, a resource management program.
12  *  For details, see <https://slurm.schedmd.com/>.
13  *  Please also read the included file: DISCLAIMER.
14  *
15  *  Slurm is free software; you can redistribute it and/or modify it under
16  *  the terms of the GNU General Public License as published by the Free
17  *  Software Foundation; either version 2 of the License, or (at your option)
18  *  any later version.
19  *
20  *  In addition, as a special exception, the copyright holders give permission
21  *  to link the code of portions of this program with the OpenSSL library under
22  *  certain conditions as described in each individual source file, and
23  *  distribute linked combinations including the two. You must obey the GNU
24  *  General Public License in all respects for all of the code used other than
25  *  OpenSSL. If you modify file(s) with this exception, you may extend this
26  *  exception to your version of the file(s), but you are not obligated to do
27  *  so. If you do not wish to do so, delete this exception statement from your
28  *  version.  If you delete this exception statement from all source files in
29  *  the program, then also delete it here.
30  *
31  *  Slurm is distributed in the hope that it will be useful, but WITHOUT ANY
32  *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
33  *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
34  *  details.
35  *
36  *  You should have received a copy of the GNU General Public License along
37  *  with Slurm; if not, write to the Free Software Foundation, Inc.,
38  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
39 \*****************************************************************************/
40 
41 #ifndef _PARSE_CONFIG_H
42 #define _PARSE_CONFIG_H
43 
44 #include <stdint.h>
45 #include "slurm/slurm.h"
46 #include "src/common/pack.h"
47 
48 /*
49  * This slurm file parser provides a method for parsing a file
50  * for key-value pairs of the form "key = value".  This parser can be used
51  * for any slurm-like configuration file, not just slurm.conf.  If you are
52  * looking for code specific to slurm.conf, look in
53  * src/common/slurm_conf.[hc].
54  *
55  * In the parsed file, any amount of white-space is allowed between the
56  * key, equal-sign, and value.  The parser handles comments, line
57  * continuations, and escaped characters automatically.  Double-quotes can
58  * be used to surround an entire value if white-space is needed within
59  * a value string.
60  *
61  * A comment begins with a "#" and ends at the end of the line. A line
62  * continuation is a "\" character at the end of the line (only white-space
63  * may follow the "\").  A line continuation tells the parser to
64  * concatenate the following line with the current line.
65  *
66  * To include a literal "\" or "#" character in a file, it can be escaped
67  * by a preceding "\".
68  *
69  * Double-quotes CANNOT be escaped, and they must surround the entire value
70  * string, they cannot be used within some substring of a value string.
71  * An empty string can be specified with doubles quotes: Apple="".
72  *
73  * To use this parser, first construct an array of s_p_options_t structures.
74  * Only the "key" string needs to be non-zero.  Zero or NULL are valid
75  * defaults for type, handler, and destroy, which conventiently allows
76  * then to be left out in any static initializations of options arrays. For
77  * instance:
78  *
79  *	s_p_options_t options[] = {{"Apples", S_P_UINT16},
80  *	                           {"Oranges"},
81  *	                           {NULL}};
82  *
83  * In this example, the handler and destroy functions for the "Apples" key
84  * are NULL pointers, and for key "Oranges" even the type is zero.  A zero
85  * type is equivalent to specifying type S_P_IGNORE.
86  *
87  * Once an s_p_options_t array is defined, it is converted into a slurm
88  * parser hash table structure with the s_p_hashtbl_create() function.
89  * The s_p_hashtbl_t thus returned can be given to the s_p_parse_file()
90  * function to parse a file, and fill in the s_p_hashtbl_t structure with
91  * the values found in the file.  Values for keys can then be retrieved
92  * from the s_p_hashtbl_t with the functions with names beginning with
93  * "s_p_get_", e.g. s_p_get_boolean(), s_p_get_string(), s_p_get_uint16(),
94  * etc.
95  *
96  * Valid types
97  * -----------
98  *
99  * S_P_IGNORE - Any instance of specified key and associated value in a file
100  *	will be allowed, but the value will not be stored and will not
101  *	be retirevable from the s_p_hashtbl_t.
102  * S_P_STRING - The value for a given key will be saved in string form. no
103  *      conversions will be performed on the value, unless it is used as a
104  *      nested definition inside a S_P_EXPLINE definition. (see S_P_EXPLINE)
105  * S_P_PLAIN_STRING - The value for a given key will be saved in string form,
106  *      no conversions will be performed on the value.
107  * S_P_LONG - The value for a given key must be a valid
108  *	string representation of a long integer (as determined by strtol()),
109  *	otherwise an error will be raised.
110  * S_P_UINT16 - The value for a given key must be a valid
111  *	string representation of an unsigned 16-bit integer.
112  * S_P_UINT32 - The value for a given key must be be a valid
113  *	string representation of an unsigned 32-bit integer.
114  * S_P_UINT64 - The value for a given key must be be a valid
115  *	string representation of an unsigned 64-bit integer.
116  * S_P_POINTER - The parser makes no assumption about the type of the value.
117  *    	The s_p_get_pointer() function will return a pointer to the
118  *	s_p_hashtbl_t's internal copy of the value.  By default, the value
119  *	will simply be the string representation of the value found in the file.
120  *	This differs from S_P_STRING in that s_p_get_string() returns a COPY
121  *	of the value which must be xfree'ed by the user.  The pointer
122  *	returns by s_p_get_pointer() must NOT be freed by the user.
123  *  	It is intended that normally S_P_POINTER with be used in conjunction
124  *	with "handler" and "destroy" functions to implement a custom type.
125  * S_P_ARRAY - This (and S_P_IGNORE, which does not record the fact that it
126  *	has seen the key previously) is the only type which allows its key to
127  * 	appear multiple times in a file.  With any other type (except
128  *	S_P_IGNORE), an error will be raised when a key is seen more than
129  *	once in a file.
130  *	S_P_ARRAY works mostly the same as S_P_POINTER, except that it builds
131  *	an array of pointers to the found values.
132  * S_P_LINE - This type avoids to write custom handlers by directly providing
133  *      the capability to express nested s_p_options_t structs into an
134  *      s_p_options_t. As with S_P_ARRAY, it allows its key to appear multiple
135  *      times in a file.
136  *      It can be seen as an advanced version of the S_P_ARRAY type enabling
137  *      to return an array of s_p_hashtable_t containing the sub-elements as
138  *      described in the nested s_p_options_t.
139  *      No custom handlers are supported with S_P_LINE. An example of S_P_LINE
140  *      usage would be :
141  *      s_p_options_t entity_options[] = {
142  *         {"Entity", S_P_STRING}
143  *         {"CoordX", S_P_UINT32},
144  *         {"CoordY", S_P_UINT32},
145  *         {"CoordZ", S_P_UINT32},
146  *         {NULL}
147  *      };
148  *      s_p_options_t options[] = {
149  *         {"Entity", S_P_LINE, NULL, NULL, entity_options},
150  *         {NULL}
151  *      };
152  *      The s_p_get_line() function will return the array of hashtables
153  *      corresponding to the "Entity" entries found in the configuration file.
154  *      Note that "Entity=%key% ..." lines sharing the same master "key"
155  *      will be automatically merged into the same hashtable enabling to split
156  *      the definition over multiple lines without having to use the '\'
157  *      delimiter.
158  *      The following example shows the content the previously defined
159  *      s_p_options_t would handle :
160  *      -----
161  *      Entity=node[0-3] CoordX=0
162  *      Entity=node[0-3] CoordY=2
163  *      Entity=node[4-7] CoordX=1
164  *      Entity=node[4-7] CoordY=2
165  *      -----
166  *      This file would provide a hashtables array containing 2 elements with
167  *      the following master keys :
168  *      - node[0-3]
169  *      - node[4-7]
170  *      /!\ WARNING: do not specify the same struct as suboption or /!\
171  *      /!\ an infinite loop will occur.                            /!\
172  * * S_P_EXPLINE - This type is an extended version of the S_P_LINE type that
173  *      add the capability to expand the hostlist formated elements when
174  *      possible in order to reduce the number of lines required to parse some
175  *      complex configurations. The values associated to the key of the
176  *      S_P_EXPLINE will then be automatically expanded in order to return one
177  *      hashtable element per associated value.
178  *      Replacing the S_P_LINE with an S_P_EXPLINE in the previous example with :
179  *      s_p_options_t options[] = {
180  *         {"Entity", S_P_EXPLINE, NULL, NULL, entity_options},
181  *         {NULL}
182  *      };
183  *      would then enable to automatically manage conf files like :
184  *      -----
185  *      Entity=node[0-3] CoordX=0
186  *      Entity=node[0-3] CoordY=2 CoordZ=[10-13]
187  *      Entity=node[4-7] CoordX=1
188  *      Entity=node[4-7] CoordY=2 CoordZ=[10-13]
189  *      -----
190  *      The s_p_get_expline() function will in this example returns an array of
191  *      eight elements, having the master key set to the following values :
192  *      - node0
193  *      - node1
194  *      ...
195  *      Note that in case a particular option string must not be expanded but
196  *      still used within an S_P_EXPLINE definition, it will have to be
197  *      expressed as a S_P_PLAIN_STRING instead of a basic S_P_STRING. Indeed,
198  *      S_P_STRING are automatically expanded using hostlist related functions.
199  *      An example of such a situation would be something like :
200  *      s_p_options_t entity_options[] = {
201  *         {"Entity", S_P_STRING}
202  *         {"Enclosed", S_P_PLAIN_STRING},
203  *         {NULL}
204  *      };
205  *      s_p_options_t options[] = {
206  *         {"Entity", S_P_EXPLINE, NULL, NULL, entity_options},
207  *         {NULL}
208  *      };
209  *      -----
210  *      Entity=switch[0-1] Enclosed=flake[0-17]
211  *      Entity=switch[2-3] Enclosed=flake[18-35]
212  *      -----
213  *      /!\ WARNING: do not specify the same struct as suboption or /!\
214  *      /!\ an infinite loop will occur.                            /!\
215  *
216  * Handlers and destructors
217  * ------------------------
218  *
219  * Any key specified in an s_p_options_t array can have function callbacks for
220  * a "handler" function and a "destroy" function.  The prototypes for each
221  * are available below in the typedef of s_p_options_t.
222  *
223  * The "handler" function is given the "key" string, "value" string, and a
224  * pointer to the remainder of the "line" on which the key-value pair was found
225  * (this is the line after the parser has removed comments and concatenated
226  * continued lines).  The handler can transform the value any way it desires,
227  * and then return a pointer to the newly allocated value data in the "data"
228  * pointer.  The handler shall also return int the "leftover" parameter a
229  * pointer into the "line" buffer designating the start of any leftover,
230  * unparsed characters in the string.  The return code from "handler" must be
231  * -1 if the value is invalid, 0 if the value is valid but no value will be set
232  * for "data" (the parser will not flag this key as already seen, and the
233  * destroy() function will not be called during s_p_hashtbl_destroy()),
234  * and 1 if "data" is set.
235  *
236  * If the "destroy" function is set for a key, and the parser will mark the key
237  * as "seen" during parsing, then it will pass the pointer to the value data
238  * to the "destroy" function when s_p_hashtbl_destroy() is called.  If
239  * a key was "seen" during parsing, but the "destroy" function is NULL,
240  * s_p_hashtbl_destroy() will call xfree() on the data pointer.
241  */
242 
243 typedef struct s_p_values s_p_values_t;
244 typedef s_p_values_t * s_p_hashtbl_t;
245 
246 typedef enum slurm_parser_enum {
247 	S_P_IGNORE = 0,
248 	S_P_STRING,
249 	S_P_LONG,
250 	S_P_UINT16,
251 	S_P_UINT32,
252 	S_P_UINT64,
253 	S_P_POINTER,
254 	S_P_ARRAY,
255 	S_P_BOOLEAN,
256 	S_P_LINE,
257 	S_P_EXPLINE,
258 	S_P_PLAIN_STRING /* useful only within S_P_EXPLINE */,
259 	S_P_FLOAT,
260 	S_P_DOUBLE,
261 	S_P_LONG_DOUBLE
262 
263 } slurm_parser_enum_t;
264 
265 /*
266  * Standard Slurm conf files use key=value elements.
267  * slurm_parser_operator_t extends that concept to cover additionnal
268  * use cases like :
269  *        key+=value
270  *        key-=value
271  *        key*=value
272  *        key/=value
273  *
274  * this feature is for now dedicated to the layouts framework. It enables
275  * to have advanced modifications of entities reusing the traditional
276  * Slurm parser with the new operator information to manage updates.
277  *
278  */
279 typedef enum slurm_parser_operator {
280 	S_P_OPERATOR_SET = 0,
281 	S_P_OPERATOR_ADD,
282 	S_P_OPERATOR_SUB,
283 	S_P_OPERATOR_MUL,
284 	S_P_OPERATOR_DIV,
285 	S_P_OPERATOR_SET_IF_MIN,
286 	S_P_OPERATOR_SET_IF_MAX,
287 	S_P_OPERATOR_AVG
288 } slurm_parser_operator_t;
289 
290 typedef struct conf_file_options {
291 	char *key;
292 	slurm_parser_enum_t type;
293 	int (*handler)(void **data, slurm_parser_enum_t type,
294 		       const char *key, const char *value,
295 		       const char *line, char **leftover);
296 	void (*destroy)(void *data);
297 	struct conf_file_options* line_options;
298 } s_p_options_t;
299 
300 
301 s_p_hashtbl_t *s_p_hashtbl_create(const struct conf_file_options options[]);
302 void s_p_hashtbl_destroy(s_p_hashtbl_t *hashtbl);
303 
304 /* Returns SLURM_SUCCESS if file was opened and parse correctly
305  * OUT hash_val - cyclic redundancy check (CRC) character-wise value
306  *                of file.
307  * IN ignore_new - do not treat unrecognized keywords as a fatal error,
308  *                 print debug() message and continue
309  */
310 int s_p_parse_file(s_p_hashtbl_t *hashtbl, uint32_t *hash_val, char *filename,
311 		   bool ignore_new);
312 
313 /* Returns SLURM_SUCCESS if buffer was opened and parse correctly.
314  * buffer must be a valid Buf bufferonly containing strings.The parsing
315  * stops at the first non string content extracted.
316  * OUT hash_val - cyclic redundancy check (CRC) character-wise value
317  *                of file.
318  * IN ignore_new - do not treat unrecognized keywords as a fatal error,
319  *                 print debug() message and continue
320  */
321 int s_p_parse_buffer(s_p_hashtbl_t *hashtbl, uint32_t *hash_val,
322 		     Buf buffer, bool ignore_new);
323 
324 /*
325  * Returns 1 if the line is parsed cleanly, and 0 otherwise.
326  */
327 int s_p_parse_pair(s_p_hashtbl_t *hashtbl, const char *key, const char *value);
328 
329 /*
330  * Returns 1 if the line is parsed cleanly, and 0 otherwise.
331  * Set the operator of the updated s_p_values_t to the provided one.
332  */
333 int s_p_parse_pair_with_op(s_p_hashtbl_t *hashtbl, const char *key,
334 			   const char *value, slurm_parser_operator_t opt);
335 
336 /*
337  * Returns 1 if the line is parsed cleanly, and 0 otherwise.
338  */
339 int s_p_parse_line(s_p_hashtbl_t *hashtbl, const char *line, char **leftover);
340 
341 /*
342  * s_p_hashtbl_merge
343  *
344  * Merge the contents of two s_p_hashtbl_t data structures. Anything in
345  * from_hashtbl that does not also appear in to_hashtbl is transfered to it.
346  * This is intended primary to support multiple lines of DEFAULT configuration
347  * information and preserve the old default values while adding new defaults.
348  *
349  * IN from_hashtbl - Source of old data
350  * IN to_hashtbl - Destination for old data (if new value not already set)
351  */
352 void s_p_hashtbl_merge(s_p_hashtbl_t *to_hashtbl, s_p_hashtbl_t *from_hashtbl);
353 
354 /* Like s_p_hashtbl_merge, but if for a key, data exists in both tables, data
355  * is swapped.
356  */
357 void s_p_hashtbl_merge_override(s_p_hashtbl_t *to_hashtbl,
358 				s_p_hashtbl_t *from_hashtbl);
359 
360 /*
361  * Mainly to enable a generic set of option to be merged with a specific set
362  * of options.
363  */
364 void s_p_hashtbl_merge_keys(s_p_hashtbl_t *to_hashtbl,
365 			    s_p_hashtbl_t *from_hashtbl);
366 
367 int s_p_parse_line_complete(s_p_hashtbl_t *hashtbl,
368 		const char* key, const char* value,
369 		const char *line, char **leftover);
370 
371 /*
372  * s_p_parse_line_expanded
373  *
374  * Parse a whole line of data and generate an array of s_p_hashtable. This
375  * function is meant to be used inside a custom handler of a (left most) key.
376  *
377  * This function can be used in a custom handler, but in general, use of
378  * S_P_*LINE is prefered.
379  *
380  * IN hashtbl - hash table template of a final line after expansion,
381  *		types and custom handlers are used after line has been
382  *		expanded. They will parse values as if the line were not
383  *		expandable and were written only with one value by key.
384  *		This hash table must contains the master key definition
385  *		(left most key of the line).
386  * OUT data - resulting hashtables array
387  * OUT data_count - number of resulting hashtables in the array
388  * IN key - the master key (left most key of the line)
389  * IN value - the value attached to the master key (which will be converted
390  *	      with s_p_parse_pair thanks to hashtbl)
391  * IN line - only used for logging
392  * IN leftover - used by s_p_parse_line
393  */
394 int s_p_parse_line_expanded(const s_p_hashtbl_t *hashtbl,
395 		s_p_hashtbl_t*** data, int* data_count,
396 		const char* key, const char* value,
397 		const char *line, char **leftover);
398 
399 /*
400  * s_p_get_string
401  *
402  * Search for a key in a s_p_hashtbl_t with value of type
403  * string.  If the key is found and has a set value, the
404  * value is retuned in "str".
405  *
406  * OUT str - pointer to a copy of the string value
407  *           (caller is resonsible for freeing str with xfree())
408  * IN key - hash table key.
409  * IN hashtbl - hash table created by s_p_hashtbl_create()
410  *
411  * Returns 1 when a value was set for "key" during parsing and "str"
412  *   was successfully set, otherwise returns 0;
413  *
414  * NOTE: Caller is responsible for freeing the returned string with xfree!
415  */
416 int s_p_get_string(char **str, const char *key, const s_p_hashtbl_t *hashtbl);
417 
418 /*
419  * s_p_get_long
420  *
421  * Search for a key in a s_p_hashtbl_t with value of type
422  * long.  If the key is found and has a set value, the
423  * value is retuned in "num".
424  *
425  * OUT num - pointer to a long where the value is returned
426  * IN key - hash table key
427  * IN hashtbl - hash table created by s_p_hashtbl_create()
428  *
429  * Returns 1 when a value was set for "key" during parsing and "num"
430  *   was successfully set, otherwise returns 0;
431  */
432 int s_p_get_long(long *num, const char *key, const s_p_hashtbl_t *hashtbl);
433 
434 /*
435  * s_p_get_uint16
436  *
437  * Search for a key in a s_p_hashtbl_t with value of type
438  * uint16.  If the key is found and has a set value, the
439  * value is retuned in "num".
440  *
441  * OUT num - pointer to a uint16_t where the value is returned
442  * IN key - hash table key
443  * IN hashtbl - hash table created by s_p_hashtbl_create()
444  *
445  * Returns 1 when a value was set for "key" during parsing and "num"
446  *   was successfully set, otherwise returns 0;
447  */
448 int s_p_get_uint16(uint16_t *num, const char *key,
449 		   const s_p_hashtbl_t *hashtbl);
450 
451 /*
452  * s_p_get_uint32
453  *
454  * Search for a key in a s_p_hashtbl_t with value of type
455  * uint32.  If the key is found and has a set value, the
456  * value is retuned in "num".
457  *
458  * OUT num - pointer to a uint32_t where the value is returned
459  * IN key - hash table key
460  * IN hashtbl - hash table created by s_p_hashtbl_create()
461  *
462  * Returns 1 when a value was set for "key" during parsing and "num"
463  *   was successfully set, otherwise returns 0;
464  */
465 int s_p_get_uint32(uint32_t *num, const char *key,
466 		   const s_p_hashtbl_t *hashtbl);
467 
468 /*
469  * s_p_get_uint64
470  *
471  * Search for a key in a s_p_hashtbl_t with value of type
472  * uint64.  If the key is found and has a set value, the
473  * value is retuned in "num".
474  *
475  * OUT num - pointer to a uint64_t where the value is returned
476  * IN key - hash table key
477  * IN hashtbl - hash table created by s_p_hashtbl_create()
478  *
479  * Returns 1 when a value was set for "key" during parsing and "num"
480  *   was successfully set, otherwise returns 0;
481  */
482 int s_p_get_uint64(uint64_t *num, const char *key,
483 		   const s_p_hashtbl_t *hashtbl);
484 
485 /*
486  * s_p_get_float
487  *
488  * Search for a key in a s_p_hashtbl_t with value of type
489  * float.  If the key is found and has a set value, the
490  * value is retuned in "num".
491  *
492  * OUT num - pointer to a float where the value is returned
493  * IN key - hash table key
494  * IN hashtbl - hash table created by s_p_hashtbl_create()
495  *
496  * Returns 1 when a value was set for "key" during parsing and "num"
497  *   was successfully set, otherwise returns 0;
498  */
499 int s_p_get_float(float *num, const char *key,
500 		  const s_p_hashtbl_t *hashtbl);
501 
502 /*
503  * s_p_get_double
504  *
505  * Search for a key in a s_p_hashtbl_t with value of type
506  * double.  If the key is found and has a set value, the
507  * value is retuned in "num".
508  *
509  * OUT num - pointer to a double where the value is returned
510  * IN key - hash table key
511  * IN hashtbl - hash table created by s_p_hashtbl_create()
512  *
513  * Returns 1 when a value was set for "key" during parsing and "num"
514  *   was successfully set, otherwise returns 0;
515  */
516 int s_p_get_double(double *num, const char *key,
517 		   const s_p_hashtbl_t *hashtbl);
518 
519 /*
520  * s_p_get_long_double
521  *
522  * Search for a key in a s_p_hashtbl_t with value of type
523  * long double.  If the key is found and has a set value, the
524  * value is retuned in "num".
525  *
526  * OUT num - pointer to a long double where the value is returned
527  * IN key - hash table key
528  * IN hashtbl - hash table created by s_p_hashtbl_create()
529  *
530  * Returns 1 when a value was set for "key" during parsing and "num"
531  *   was successfully set, otherwise returns 0;
532  */
533 int s_p_get_long_double(long double *num, const char *key,
534 			const s_p_hashtbl_t *hashtbl);
535 
536 /*
537  * s_p_get_operator
538  *
539  * Search for a key in a s_p_hashtbl_t and return the operator
540  * associated with that key in the configuration file. The operator
541  * is one of the slurm_parser_operator_t enum possible values.
542  *
543  * OUT operator - pointer to a slurm_parser_operator_t where the
544  *     operator is returned
545  * IN key - hash table key
546  * IN hashtbl - hash table created by s_p_hashtbl_create()
547  *
548  * Returns 1 when a operator was set for "key" during parsing and
549  *     "operator" was successfully set, otherwise returns 0;
550  */
551 int s_p_get_operator(slurm_parser_operator_t *opt, const char *key,
552 		     const s_p_hashtbl_t *hashtbl);
553 
554 /*
555  * s_p_get_pointer
556  *
557  * Search for a key in a s_p_hashtbl_t with value of type
558  * pointer.  If the key is found and has a set value, the
559  * value is retuned in "ptr".
560  *
561  * OUT num - pointer to a void pointer where the value is returned
562  * IN key - hash table key
563  * IN hashtbl - hash table created by s_p_hashtbl_create()
564  *
565  * Returns 1 when a value was set for "key" during parsing and "ptr"
566  *   was successfully set, otherwise returns 0;
567  */
568 int s_p_get_pointer(void **ptr, const char *key, const s_p_hashtbl_t *hashtbl);
569 
570 /*
571  * s_p_get_array
572  *
573  * Most s_p_ data types allow a key to appear only once in a file
574  * (s_p_parse_file) or line (s_p_parse_line).  S_P_ARRAY is the exception.
575  *
576  * S_P_ARRAY allows a key to appear any number of times.  Each time
577  * a particular key is found the value array grows by one element, and
578  * that element contains a pointer to the newly parsed value.  You can
579  * think of this as being an array of S_P_POINTER types.
580  *
581  * OUT num - pointer to a void pointer-pointer where the value is returned
582  * IN key - hash table key
583  * IN hashtbl - hash table created by s_p_hashtbl_create()
584  *
585  * Returns 1 when a value was set for "key" during parsing and "ptr"
586  *   was successfully set, otherwise returns 0;
587  */
588 int s_p_get_array(void **ptr_array[], int *count,
589 		  const char *key, const s_p_hashtbl_t *hashtbl);
590 
591 /** works like s_p_get_array but each item of the array is a s_p_hashtbl_t */
592 int s_p_get_line(s_p_hashtbl_t **ptr_array[], int *count,
593 		  const char *key, const s_p_hashtbl_t *hashtbl);
594 
595 /** works like s_p_get_array but each item of the array is a s_p_hashtbl_t */
596 int s_p_get_expline(s_p_hashtbl_t **ptr_array[], int *count,
597 		  const char *key, const s_p_hashtbl_t *hashtbl);
598 
599 /*
600  * s_p_get_boolean
601  *
602  * Search for a key in a s_p_hashtbl_t with value of type
603  * boolean.  If the key is found and has a set value, the
604  * value is retuned in "flag".
605  *
606  * OUT flag - pointer to a bool where the value is returned
607  * IN key - hash table key
608  * IN hashtbl - hash table created by s_p_hashtbl_create()
609  *
610  * Returns 1 when a value was set for "key" during parsing and "num"
611  *   was successfully set, otherwise returns 0;
612  */
613 int s_p_get_boolean(bool *flag, const char *key, const s_p_hashtbl_t *hashtbl);
614 
615 /*
616  * Given an "options" array, print the current values of all
617  * options in supplied hash table "hashtbl".
618  *
619  * Primarily for debugging purposes.
620  */
621 void s_p_dump_values(const s_p_hashtbl_t *hashtbl,
622 		     const s_p_options_t options[]);
623 
624 
625 /*
626  * Given an "options" array, pack the key, type of options along with values and
627  * op of the hashtbl.
628  *
629  * Primarily for sending a table across the network so you don't have to read a
630  * file in.
631  */
632 extern Buf s_p_pack_hashtbl(const s_p_hashtbl_t *hashtbl,
633 			   const s_p_options_t options[],
634 			   const uint32_t cnt);
635 
636 /*
637  * Given a buffer, unpack key, type, op and value into a hashtbl.
638  */
639 extern s_p_hashtbl_t *s_p_unpack_hashtbl(Buf buffer);
640 
641 /*
642  * copy options onto the end of full_options
643  * IN/OUT full_options
644  * IN options
645  * IN/OUT full_options_cnt
646  *
647  * Used if the full set of options are not available from one location.
648  */
649 extern void transfer_s_p_options(s_p_options_t **full_options,
650 				 s_p_options_t *options,
651 				 int *full_options_cnt);
652 
653 #endif /* !_PARSE_CONFIG_H */
654