LAL  7.5.0.1-b72065a
UserInput.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2016 Karl Wette
3  * Copyright (C) 2015 Reinhard Prix
4  * Copyright (C) 2010 Reinhard Prix (xlalified)
5  * Copyright (C) 2004, 2005 Reinhard Prix
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with with program; see the file COPYING. If not, write to the
19  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20  * MA 02110-1301 USA
21  */
22 
23 #ifndef _USERINPUT_H /* Double-include protection. */
24 #define _USERINPUT_H
25 
26 #ifdef __cplusplus /* C++ protection. */
27 extern "C" {
28 #endif
29 
30 #include <lal/ConfigFile.h>
31 #include <lal/UserInputParse.h>
32 #include <lal/LALVCSInfoType.h>
33 
34 /**
35  * \defgroup UserInput_h Header UserInput.h
36  * \ingroup lal_support
37  * \author Reinhard Prix
38  * \brief Module for simple unified handling of user-input from config-file and/or command-line.
39  *
40  *
41  * ### Description ###
42  *
43  * This module provides functions and macros to 'register' a set off C-variables as 'User Variables',
44  * which can then be read in from the commandline and/or an input config file, as parsed by \ref ConfigFile_h.
45  *
46  * The module also handles generating and outputting a help-string on the available input options when requested, and
47  * can deal with enforcing input of required options and using default values.
48  *
49  * ### Usage ###
50  *
51  * The general approach consists of the following steps:
52  * <ol>
53  * <li> set default-values for optional user-variables as appropriate</li>
54  * <li> \c register all user-variables using calls to \c XLALRegisterUvarMember(), which assumes a
55  * pointer named 'uvar' to a struct containing all user-variables in the form 'uvar->UserVariable'.</li>
56  * <li> parse user-input using XLALUserVarReadAllInput()</li>
57  * </ol>
58  *
59  * One can use XLALUserVarWasSet() to determine whether a given user-input option has been set by the user.
60  *
61  * The function XLALUserVarGetLog() can be used to obtain a log-string containing the full user-input, either in \c commandline- or \c ConfigFile format.
62  *
63  * Here is a worked simple example of its recommended use:
64  * \code
65  * #include <stdio.h>
66  * #include <lal/XLALError.h>
67  * #include <lal/LALDatatypes.h>
68  *
69  * #include <lal/UserInput.h>
70  *
71  * // these are the C-variables we want to read in from user-input
72  * typedef struct {
73  * BOOLEAN help; // did user request help-output?
74  * INT4 anInteger;
75  * REAL8 aDoubleVar;
76  * CHAR *andAString;
77  * REAL8 specialGeekSwitch;
78  * LIGOTimeGPS someEpoch;
79  * REAL8 RA;
80  * REAL8 DEC;
81  * } UserInput_t;
82  *
83  *
84  * int main(int argc,char *argv[])
85  * {
86  * UserInput_t XLAL_INIT_DECL(UserVariables); // initializes this struct to {0}
87  * UserInput_t *uvar = &UserVariables; // struct-pointer allows us to use the XLALreg<TYPE>UserStruct() macros...
88  *
89  * // 1. step: set default-values for optional user-input variables
90  * uvar->anInteger = 0;
91  * uvar->andAString = NULL; // Note: need to assign allocated strings here as default!!
92  *
93  * // 2. step: Register all user-variables using the shortcut macros:
94  * XLALRegisterUvarMember( help, BOOLEAN, 'h', HELP, "Output this help-message");
95  * XLALRegisterUvarMember( anInteger, INT4, 'i', OPTIONAL, "An example user-variable of an optional integer");
96  * XLALRegisterUvarMember( aDoubleVar, REAL8, 'r', REQUIRED, "This REAL8 user-variable is required");
97  * XLALRegisterUvarMember( andAString, STRING, 0, OPTIONAL, "Optional string-input, has no short-option");
98  * XLALRegisterUvarMember( someEpoch, EPOCH, 0, OPTIONAL, "Reference epoch (format 'xx.yy[GPS|MJD]')");
99  * XLALRegisterUvarMember( RAJ, RAJ, 0, OPTIONAL, "Sky location: equatorial right ascension in [0,2pi] (in radians or hours:minutes:seconds)");
100  * XLALRegisterUvarMember( DEC, DECJ, 0, OPTIONAL, "Sky location: equatorial declination [-pi/2,pi/2] (in radians or degrees:minutes:seconds)");
101  * XLALRegisterUvarMember( specialGeekSwitch, REAL8, 'g', DEVELOPER, "This REAL8 user-variable may not be relevant for standard usage");
102  *
103  * // 3. step: parse all user-input, from either config-file if given, or commandline (overloads config-file values)
104  * XLAL_CHECK ( XLALUserVarReadAllInput ( argc, argv, lalAppsVCSInfoList ) == XLAL_SUCCESS, XLAL_EFUNC);
105  *
106  * if (uvar->help){ // if user had requested help, then we're already done here
107  * return 0;
108  * }
109  *
110  * printf ("User-input was: anInteger = %d, aDoubleVar = %f, andAString = %s\n", uvar->anInteger, uvar->aDoubleVar, uvar->andAString );
111  * printf ("someEpoch = {%d s, %d ns}, RA = %f rad, DEC = %f rad\n", uvar->someEpoch.gpsSeconds, uvar->someEpoch.gpsNanoSeconds, uvar->RA, uvar->DEC );
112  *
113  * // 4. step: free user-input module memory
114  * XLALDestroyUserVars();
115  *
116  * LALCheckMemoryLeaks();
117  * return 0;
118  * } // main()
119  * \endcode
120  *
121  * \note This code can be compiled <b>as is</b> within lalapps, and yields
122  *
123  * \verbatim
124 $ LAL_DEBUG_LEVEL=1 ./tmp --help
125 
126 Usage: ./tmp [@ConfigFile] [options], where options are:
127 
128 -h, --help BOOLEAN Output this help-message []
129 -i, --anInteger INT4 An example user-variable of an optional integer [0]
130 -r, --aDoubleVar REAL8 This REAL8 user-variable is required [REQUIRED]
131  --andAString STRING Optional string-input, has no short-option [NULL]
132  --someEpoch EPOCH Reference epoch (format 'xx.yy[GPS|MJD]') [0.000000000GPS]
133  --RA RAJ Sky location: right ascension in [0,2pi] (in radians or hours:minutes:seconds) [0.0]
134  --DEC DECJ Sky location: declination [-pi/2,pi/2] (in radians or degrees:minutes:seconds) [0.0]
135 
136 ---------- The following are 'Developer'-options not useful for most users:----------
137 
138 -g, --specialGeekSwitch REAL8 This REAL8 user-variable may not be relevant for standard usage [0.0]
139 
140 \endverbatim
141  *
142  * And if called
143  * \verbatim
144 $ ./tmp -r 3.1415 --andAString="stupid example" --someEpoch=5555MJD --RA=10:25:10.123 --DEC=-30:0:0
145 User-input was: anInteger = 0, aDoubleVar = 3.141500, andAString = stupid example
146 someEpoch = {2147483596 s, 816000000 ns}, RA = 2.727813 rad, DEC = -0.523599 rad
147 \endverbatim
148  *
149  * \note For a real-world example of usage, see various codes under lalapps/src/pulsar/{Injections,Fstatistic}
150  *
151  */
152 /** @{ */
153 
154 /**
155  * Shortcut macro for registering new user variables, which are accessed via the \e struct-pointer '*uvar'
156  */
157 #define XLALRegisterUvarMember(name,type,option,category,...) \
158  XLALRegister ##type## UserVar( &(uvar-> name), NULL, #name, option, UVAR_CATEGORY_ ## category, __VA_ARGS__)
159 
160 /**
161  * Shortcut macro for registering new user variables, which are accessed via the \e struct-pointer '*uvar',
162  * and which acquire some auxilliary data in order to be parsed
163  */
164 #define XLALRegisterUvarAuxDataMember(name,type,cdata,option,category,...) \
165  XLALRegister ##type## UserVar( &(uvar-> name), cdata, #name, option, UVAR_CATEGORY_ ## category, __VA_ARGS__)
166 
167 /**
168  * Shortcut macro for registering new user variables, named 'name' and accessed via the \e variable-pointer '*cvar'
169  * \note This style of user variable is deprecated; XLALRegisterUvarMember() is preferred
170  */
171 #define XLALRegisterNamedUvar(cvar,name,type,option,category,...) \
172  XLALRegister ##type## UserVar( cvar, NULL, name, option, UVAR_CATEGORY_ ## category, __VA_ARGS__)
173 
174 /**
175  * Shortcut macro for registering new user variables, named 'name' and accessed via the \e variable-pointer '*cvar',
176  * and which acquire some auxilliary data in order to be parsed
177  * \note This style of user variable is deprecated; XLALRegisterUvarAuxDataMember() is preferred
178  */
179 #define XLALRegisterNamedUvarAuxData(cvar,name,type,cdata,option,category,...) \
180  XLALRegister ##type## UserVar( cvar, cdata, name, option, UVAR_CATEGORY_ ## category, __VA_ARGS__)
181 
182 /**
183  * Mutually-exclusive user variable categories: optional, required, help, developer, ...
184  */
185 typedef enum tagUserVarCategory {
186  UVAR_CATEGORY_START = 0, ///< internal start marker for range checking
187 
188  UVAR_CATEGORY_OPTIONAL, ///< optional
189  UVAR_CATEGORY_REQUIRED, ///< required
190  UVAR_CATEGORY_DEVELOPER, ///< optional and hidden in help-output until lalDebugLevel>=warning
191  UVAR_CATEGORY_DEPRECATED, ///< optional and hidden until lalDebugLevel>=info; still supported but output warning if used
192  UVAR_CATEGORY_DEFUNCT, ///< hidden completely from help output; not supported, will output error + help-string if used
193  UVAR_CATEGORY_NODEFAULT, ///< optional and supresses printing the default value in the help, where it doesn't make sense
194  UVAR_CATEGORY_END ///< internal end marker for range checking
196 
197 /**
198  * Format for logging User-input: configFile- or cmdLine-style.
199  * This determines the format of the string returned from XLALUserVarGetLog().
200  */
201 typedef enum tagUserVarLogFormat {
202  UVAR_LOGFMT_RAWFORM, /**< return UserVars in a raw format suitable for further parsing */
203  UVAR_LOGFMT_CFGFILE, /**< return UserVars as a config-file */
204  UVAR_LOGFMT_CMDLINE, /**< return UserVars as a command-line */
205  UVAR_LOGFMT_PROCPARAMS, /**< return UserVars suitable for filling in process-params struct */
208 
209 /* Global variables */
210 #ifndef SWIG /* exclude from SWIG interface */
211 extern const char *lalUserVarHelpBrief;
212 extern const char *lalUserVarHelpDescription;
213 extern const char *lalUserVarHelpOptionSubsection;
214 #endif /* SWIG */
215 
216 /* Function prototypes */
217 void XLALDestroyUserVars( void );
218 int XLALUserVarReadCmdline( BOOLEAN *should_exit, int argc, char *argv[], const LALVCSInfoList vcs_list );
219 int XLALUserVarReadCfgfile( BOOLEAN *should_exit, const CHAR *cfgfile );
220 int XLALUserVarReadAllInput( BOOLEAN *should_exit, int argc, char *argv[], const LALVCSInfoList vcs_list );
221 int XLALUserVarWasSet( const void *cvar );
222 void XLALUserVarCheck( BOOLEAN *should_exit, const int assertion, const CHAR *fmt, ... ) _LAL_GCC_PRINTF_FORMAT_(3,4);
224 CHAR * XLALUserVarGetLogEx ( UserVarLogFormat format, const BOOLEAN skip_unset );
225 
226 /**
227  * \name Convenience macros for checking how many of a set of user input variables were set
228  */
229 /** @{ */
230 #define UVAR_SET(n) (XLALUserVarWasSet(&(uvar-> n)) ? 1 : 0)
231 #define UVAR_SET2(n1,n2) (UVAR_SET(n1) + UVAR_SET(n2))
232 #define UVAR_SET3(n1,n2,n3) (UVAR_SET2(n1,n2) + UVAR_SET(n3))
233 #define UVAR_SET4(n1,n2,n3,n4) (UVAR_SET3(n1,n2,n3) + UVAR_SET(n4))
234 #define UVAR_SET5(n1,n2,n3,n4,n5) (UVAR_SET4(n1,n2,n3,n4) + UVAR_SET(n5))
235 #define UVAR_SET6(n1,n2,n3,n4,n5,n6) (UVAR_SET5(n1,n2,n3,n4,n5) + UVAR_SET(n6))
236 /** @} */
237 
238 /**
239  * \name Convenience macros for checking whether all of a set of user input variables were set
240  */
241 /** @{ */
242 #define UVAR_ALLSET2(n1,n2) (UVAR_SET2(n1,n2) == 2)
243 #define UVAR_ALLSET3(n1,n2,n3) (UVAR_SET3(n1,n2,n3) == 3)
244 #define UVAR_ALLSET4(n1,n2,n3,n4) (UVAR_SET4(n1,n2,n3,n4) == 4)
245 #define UVAR_ALLSET5(n1,n2,n3,n4,n5) (UVAR_SET5(n1,n2,n3,n4,n5) == 5)
246 #define UVAR_ALLSET6(n1,n2,n3,n4,n5,n6) (UVAR_SET6(n1,n2,n3,n4,n5,n6) == 6)
247 /** @} */
248 
249 /**
250  * \name Convenience macros for checking whether any of a set of user input variables were set
251  */
252 /** @{ */
253 #define UVAR_ANYSET2(n1,n2) (UVAR_SET2(n1,n2) > 0)
254 #define UVAR_ANYSET3(n1,n2,n3) (UVAR_SET3(n1,n2,n3) > 0)
255 #define UVAR_ANYSET4(n1,n2,n3,n4) (UVAR_SET4(n1,n2,n3,n4) > 0)
256 #define UVAR_ANYSET5(n1,n2,n3,n4,n5) (UVAR_SET5(n1,n2,n3,n4,n5) > 0)
257 #define UVAR_ANYSET6(n1,n2,n3,n4,n5,n6) (UVAR_SET6(n1,n2,n3,n4,n5,n6) > 0)
258 /** @} */
259 
260 /**
261  * \name Convenience macros for printing user input variables in error messages
262  */
263 /** @{ */
264 #define UVAR_FMT "`--%s'"
265 #define UVAR_STR(n) "`--"#n"'"
266 #define UVAR_STR2AND(n1,n2) "`--"#n1"' and `--"#n2"'"
267 #define UVAR_STR2OR(n1,n2) "`--"#n1"' or `--"#n2"'"
268 #define UVAR_STR3AND(n1,n2,n3) "`--"#n1"', `--"#n2"', and `--"#n3"'"
269 #define UVAR_STR3OR(n1,n2,n3) "`--"#n1"', `--"#n2"', or `--"#n3"'"
270 #define UVAR_STR4AND(n1,n2,n3,n4) "`--"#n1"', `--"#n2"', `--"#n3"', and `--"#n4"'"
271 #define UVAR_STR4OR(n1,n2,n3,n4) "`--"#n1"', `--"#n2"', `--"#n3"', or `--"#n4"'"
272 #define UVAR_STR5AND(n1,n2,n3,n4,n5) "`--"#n1"', `--"#n2"', `--"#n3"', `--"#n4"', and `--"#n5"'"
273 #define UVAR_STR5OR(n1,n2,n3,n4,n5) "`--"#n1"', `--"#n2"', `--"#n3"', `--"#n4"', or `--"#n5"'"
274 #define UVAR_STR6AND(n1,n2,n3,n4,n5,n6) "`--"#n1"', `--"#n2"', `--"#n3"', `--"#n4"', `--"#n5"', and `--"#n6"'"
275 #define UVAR_STR6OR(n1,n2,n3,n4,n5,n6) "`--"#n1"', `--"#n2"', `--"#n3"', `--"#n4"', `--"#n5"', or `--"#n6"'"
276 /** @} */
277 
278 // declare type-specific wrappers to XLALRegisterUserVar() to allow for strict C type-checking!
279 #define DECL_REGISTER_UVAR(UTYPE,CTYPE) \
280  DECL_REGISTER_UVAR_AUX_DATA(UTYPE,CTYPE,void)
281 #define DECL_REGISTER_UVAR_AUX_DATA(UTYPE,CTYPE,DTYPE) \
282  int XLALRegister ##UTYPE## UserVar ( CTYPE *cvar, const DTYPE *cdata, const CHAR *name, CHAR optchar, UserVarCategory category, const CHAR *fmt, ... ) _LAL_GCC_PRINTF_FORMAT_(6,7)
283 
284 // ------ declare registration functions
295 
301 
304 
309 
310 /** @} */
311 
312 #ifdef __cplusplus
313 }
314 #endif /* C++ protection. */
315 
316 #endif /* Double-include protection. */
#define _LAL_GCC_PRINTF_FORMAT_(NFMT, NARG)
Definition: LALStddef.h:47
#define STRING(a)
Definition: PrintVector.c:12
unsigned char BOOLEAN
Boolean logical type, see Headers LAL(Atomic)Datatypes.h for more details.
uint64_t UINT8
Eight-byte unsigned integer; on some platforms this is equivalent to unsigned long int instead.
double REAL8
Double precision real floating-point number (8 bytes).
int64_t INT8
Eight-byte signed integer; on some platforms this is equivalent to long int instead.
char CHAR
One-byte signed integer, see Headers LAL(Atomic)Datatypes.h for more details.
uint32_t UINT4
Four-byte unsigned integer.
int32_t INT4
Four-byte signed integer.
const LALVCSInfo *const LALVCSInfoList[16]
NULL-terminated list of VCS and build information structures
const char * lalUserVarHelpOptionSubsection
An optional subsection heading under OPTIONS, under which all subsequently-defined user variables are...
Definition: UserInput.c:258
const char * lalUserVarHelpBrief
An optional brief description of the program, printed after its name as part of the help page.
Definition: UserInput.c:248
UserVarLogFormat
Format for logging User-input: configFile- or cmdLine-style.
Definition: UserInput.h:201
void CHAR * XLALUserVarGetLog(UserVarLogFormat format)
Return a log-string representing the complete user-input.
Definition: UserInput.c:1228
int XLALUserVarReadAllInput(BOOLEAN *should_exit, int argc, char *argv[], const LALVCSInfoList vcs_list)
Put all the pieces together, and basically does everything: print help (if requested),...
Definition: UserInput.c:1064
CHAR * XLALUserVarGetLogEx(UserVarLogFormat format, const BOOLEAN skip_unset)
Return a log-string representing the complete user-input.
Definition: UserInput.c:1238
void XLALDestroyUserVars(void)
Free all memory associated with user-variable linked list.
Definition: UserInput.c:349
#define DECL_REGISTER_UVAR_AUX_DATA(UTYPE, CTYPE, DTYPE)
Definition: UserInput.h:281
#define DECL_REGISTER_UVAR(UTYPE, CTYPE)
Definition: UserInput.h:279
void XLALUserVarCheck(BOOLEAN *should_exit, const int assertion, const CHAR *fmt,...) _LAL_GCC_PRINTF_FORMAT_(3
UserVarCategory
Mutually-exclusive user variable categories: optional, required, help, developer, ....
Definition: UserInput.h:185
int XLALUserVarReadCmdline(BOOLEAN *should_exit, int argc, char *argv[], const LALVCSInfoList vcs_list)
Parse command-line into UserVariable array.
Definition: UserInput.c:394
const char * lalUserVarHelpDescription
An optional longer description of the program, printed in its own section as part of the help page.
Definition: UserInput.c:253
int XLALUserVarWasSet(const void *cvar)
Has this user-variable been set by the user? returns 1 (=TRUE) or 0 (=FALSE) on success,...
Definition: UserInput.c:1175
int XLALUserVarReadCfgfile(BOOLEAN *should_exit, const CHAR *cfgfile)
Read config-variables from cfgfile and parse into input-structure.
Definition: UserInput.c:647
@ UVAR_LOGFMT_RAWFORM
return UserVars in a raw format suitable for further parsing
Definition: UserInput.h:202
@ UVAR_LOGFMT_CMDLINE
return UserVars as a command-line
Definition: UserInput.h:204
@ UVAR_LOGFMT_LAST
Definition: UserInput.h:206
@ UVAR_LOGFMT_PROCPARAMS
return UserVars suitable for filling in process-params struct
Definition: UserInput.h:205
@ UVAR_LOGFMT_CFGFILE
return UserVars as a config-file
Definition: UserInput.h:203
@ UVAR_CATEGORY_START
internal start marker for range checking
Definition: UserInput.h:186
@ UVAR_CATEGORY_REQUIRED
required
Definition: UserInput.h:189
@ UVAR_CATEGORY_DEFUNCT
hidden completely from help output; not supported, will output error + help-string if used
Definition: UserInput.h:192
@ UVAR_CATEGORY_OPTIONAL
optional
Definition: UserInput.h:188
@ UVAR_CATEGORY_NODEFAULT
optional and supresses printing the default value in the help, where it doesn't make sense
Definition: UserInput.h:193
@ UVAR_CATEGORY_DEVELOPER
optional and hidden in help-output until lalDebugLevel>=warning
Definition: UserInput.h:190
@ UVAR_CATEGORY_DEPRECATED
optional and hidden until lalDebugLevel>=info; still supported but output warning if used
Definition: UserInput.h:191
@ UVAR_CATEGORY_END
internal end marker for range checking
Definition: UserInput.h:194
LIGOTimeGPS LIGOTimeGPSRange[2]
A range of GPS times; first element is minimum, second element is maximum of range.
REAL8 REAL8Range[2]
A range of REAL8 values; first element is minimum, second element is maximum of range.
INT4 INT4Range[2]
A range of INT4 values; first element is minimum, second element is maximum of range.
Vector of type INT4, see DATATYPE-Vector types for more details.
Definition: LALDatatypes.h:109
Vector of type CHAR*, ie 'strings', see DATATYPE-Vector types for more details.
Definition: LALDatatypes.h:82
Epoch relative to GPS epoch, see LIGOTimeGPS type for more details.
Definition: LALDatatypes.h:458
Vector of type REAL8, see DATATYPE-Vector types for more details.
Definition: LALDatatypes.h:154
Vector of type UINT4, see DATATYPE-Vector types for more details.
Definition: LALDatatypes.h:118
Possible choices the user may select for an enumeration or bitflag.