1 /* 2 libcore: library for basic data structures and algorithms. 3 Copyright (C) 2005 IPD Goos, Universit"at Karlsruhe, Germany 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with this library; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 /* 21 Option management library. 22 This module can read (typed) options from a config file or 23 parse a command line. The options are managed in a tree structure. 24 */ 25 26 #ifndef _LC_OPTS_H 27 #define _LC_OPTS_H 28 29 #include <stdio.h> 30 31 #include "lc_printf.h" 32 33 /** 34 * The type of an option. 35 */ 36 typedef enum { 37 lc_opt_type_invalid, 38 lc_opt_type_enum, 39 lc_opt_type_bit, 40 lc_opt_type_negbit, 41 lc_opt_type_boolean, 42 lc_opt_type_negboolean, 43 lc_opt_type_string, 44 lc_opt_type_int, 45 lc_opt_type_double 46 } lc_opt_type_t; 47 48 /** 49 * Error codes. 50 */ 51 typedef enum { 52 lc_opt_err_none = 0, 53 lc_opt_err_no_callback, 54 lc_opt_err_illegal_option_type, 55 lc_opt_err_illegal_format, 56 lc_opt_err_grp_not_found, 57 lc_opt_err_opt_not_found, 58 lc_opt_err_grp_expected, 59 lc_opt_err_opt_already_there, 60 lc_opt_err_file_not_found, 61 lc_opt_err_unknown_value 62 } lc_opt_err_t; 63 64 typedef struct { 65 int error; 66 const char *msg; 67 const char *arg; 68 } lc_opt_err_info_t; 69 70 #define lc_opt_is_error(err) ((err)->error != lc_opt_err_none) 71 72 typedef struct lc_opt_entry_t lc_opt_entry_t; 73 74 typedef int (lc_opt_callback_t)(const char *name, lc_opt_type_t type, void *data, size_t length, ...); 75 76 typedef int (lc_opt_dump_t)(char *buf, size_t n, const char *name, lc_opt_type_t type, void *data, size_t length); 77 78 typedef int (lc_opt_dump_vals_t)(char *buf, size_t n, const char *name, lc_opt_type_t type, void *data, size_t length); 79 80 typedef int (lc_opt_error_handler_t)(const char *prefix, const lc_opt_err_info_t *err); 81 82 typedef struct { 83 const char *name; /**< The name of the option. */ 84 const char *desc; /**< A description for the option. */ 85 lc_opt_type_t type; /**< The type of the option (see enum). */ 86 void *value; /**< A pointer to the area, where the value 87 of the option shall be put to. May be 88 NULL. */ 89 90 size_t len; /**< The amount of bytes available at the 91 location value points to. */ 92 lc_opt_callback_t *cb; /**< A callback that is called, when the 93 option is set. This may never be NULL. */ 94 95 lc_opt_dump_t *dump; /**< A function which is able to format the 96 options value into a string. May be 97 NULL. */ 98 99 lc_opt_dump_vals_t *dump_vals; /**< A function which is able to format the possible values 100 for this option into a string. May be NULL. */ 101 102 103 } lc_opt_table_entry_t; 104 105 #define _LC_OPT_ENT(name, desc, type, val_type, value, len, cb, dump, dump_vals) \ 106 { name, desc, type, 1 ? (value) : (val_type*)0 /* Produces a warning, if var has wrong type. */, len, cb, dump, dump_vals } 107 108 #define LC_OPT_ENT_INT(name, desc, addr) \ 109 _LC_OPT_ENT(name, desc, lc_opt_type_int, int, addr, 0, lc_opt_std_cb, lc_opt_std_dump, NULL) 110 111 #define LC_OPT_ENT_DBL(name, desc, addr) \ 112 _LC_OPT_ENT(name, desc, lc_opt_type_double, double, addr, 0, lc_opt_std_cb, lc_opt_std_dump, NULL) 113 114 #define LC_OPT_ENT_BIT(name, desc, addr, mask) \ 115 _LC_OPT_ENT(name, desc, lc_opt_type_bit, unsigned, addr, mask, lc_opt_std_cb, lc_opt_std_dump, NULL) 116 117 #define LC_OPT_ENT_NEGBIT(name, desc, addr, mask) \ 118 _LC_OPT_ENT(name, desc, lc_opt_type_negbit, unsigned, addr, mask, lc_opt_std_cb, lc_opt_std_dump, NULL) 119 120 #define LC_OPT_ENT_BOOL(name, desc, addr) \ 121 _LC_OPT_ENT(name, desc, lc_opt_type_boolean, int, addr, 0, lc_opt_std_cb, lc_opt_std_dump, lc_opt_bool_dump_vals) 122 123 #define LC_OPT_ENT_NEGBOOL(name, desc, addr) \ 124 _LC_OPT_ENT(name, desc, lc_opt_type_negboolean, int, addr, 0, lc_opt_std_cb, lc_opt_std_dump, lc_opt_bool_dump_vals) 125 126 #define LC_OPT_ENT_STR(name, desc, buf) \ 127 _LC_OPT_ENT(name, desc, lc_opt_type_string, char, buf, sizeof(buf), lc_opt_std_cb, lc_opt_std_dump, NULL) 128 129 #define LC_OPT_LAST \ 130 _LC_OPT_ENT(NULL, NULL, lc_opt_type_invalid, void, NULL, 0, NULL, NULL, NULL) 131 132 /** 133 * Get the root option group. 134 * @return The root option group. 135 */ 136 lc_opt_entry_t *lc_opt_root_grp(void); 137 138 /** 139 * Check, if a group is the root group 140 * @param ent The entry to check for. 141 * @return 1, if the entry is the root group, 0 otherwise. 142 */ 143 int lc_opt_grp_is_root(const lc_opt_entry_t *ent); 144 145 /** 146 * Get an option group. 147 * If the group is not already present, it is created. 148 * @param parent The parent group to look in. 149 * @param name The name of the group to lookup 150 * @return The already present or created group. 151 */ 152 lc_opt_entry_t *lc_opt_get_grp(lc_opt_entry_t *parent, const char *name); 153 154 /** 155 * Add an option to a group. 156 * @param grp The group to add the option to. 157 * @param name The name of the option (must be unique inside the group). 158 * @param desc A description of the option. 159 * @param type The data type of the option (see lc_opt_type_*) 160 * @param value A pointer to the memory, where the value shall be stored. 161 * (May be NULL). 162 * @param length Amount of bytes available at the memory location 163 * indicated by @p value. 164 * @param cb A callback function to be called, as the option's value 165 * is set (may be NULL). 166 * @param err Error information to be set (may be NULL). 167 * @return The handle for the option. 168 */ 169 lc_opt_entry_t *lc_opt_add_opt(lc_opt_entry_t *grp, 170 const char *name, 171 const char *desc, 172 lc_opt_type_t type, 173 void *value, size_t length, 174 lc_opt_callback_t *cb, 175 lc_opt_dump_t *dump, 176 lc_opt_dump_vals_t *dump_vals, 177 lc_opt_err_info_t *err); 178 179 int lc_opt_std_cb(const char *name, lc_opt_type_t type, void *data, size_t length, ...); 180 181 int lc_opt_std_dump(char *buf, size_t n, const char *name, lc_opt_type_t type, void *data, size_t length); 182 183 int lc_opt_bool_dump_vals(char *buf, size_t n, const char *name, lc_opt_type_t type, void *data, size_t length); 184 185 #define lc_opt_add_opt_int(grp, name, desc, value, err) \ 186 lc_opt_add_opt(grp, name, desc, lc_opt_type_int, value, 0, lc_opt_std_cb, lc_opt_std_dump, NULL, err) 187 188 #define lc_opt_add_opt_double(grp, name, desc, value, err) \ 189 lc_opt_add_opt(grp, name, desc, lc_opt_type_double, value, 0, lc_opt_std_cb, lc_opt_std_dump, NULL, err) 190 191 #define lc_opt_add_opt_string(grp, name, desc, buf, len, err) \ 192 lc_opt_add_opt(grp, name, desc, lc_opt_type_string, buf, len, lc_opt_std_cb, lc_opt_std_dump, NULL, err) 193 194 #define lc_opt_add_opt_bit(grp, name, desc, value, mask, err) \ 195 lc_opt_add_opt(grp, name, desc, lc_opt_type_bit, value, mask, lc_opt_std_cb, lc_opt_std_dump, NULL, err) 196 197 198 /** 199 * Find a group inside another group. 200 * @param grp The group to search inside. 201 * @param name The name of the group you are looking for. 202 * @param err Error info (may be NULL). 203 * @return The group or NULL, if no such group can be found. 204 */ 205 lc_opt_entry_t *lc_opt_find_grp(const lc_opt_entry_t *grp, const char *name, lc_opt_err_info_t *err); 206 207 /** 208 * Find an option inside another group. 209 * @param grp The group to search inside. 210 * @param name The name of the option you are looking for. 211 * @param err Error info (may be NULL). 212 * @return The group or NULL, if no such option can be found. 213 */ 214 lc_opt_entry_t *lc_opt_find_opt(const lc_opt_entry_t *grp, const char *name, lc_opt_err_info_t *err); 215 216 /** 217 * Resolve a group. 218 * @param root The group to start resolving from. 219 * @param names A string array containing the path to the group. 220 * @param n Number of entries in @p names to consider. 221 * @param err Error information (may be NULL). 222 * @return The group or NULL, if none is found. 223 */ 224 lc_opt_entry_t *lc_opt_resolve_grp(const lc_opt_entry_t *root, 225 const char * const *names, int n, lc_opt_err_info_t *err); 226 227 /** 228 * Resolve an option. 229 * @param root The group to start resolving from. 230 * @param names A string array containing the path to the option. 231 * @param n Number of entries in @p names to consider. 232 * @param err Error information (may be NULL). 233 * @return The option or NULL, if none is found. 234 */ 235 lc_opt_entry_t *lc_opt_resolve_opt(const lc_opt_entry_t *root, 236 const char * const *names, int n, lc_opt_err_info_t *err); 237 238 /** 239 * Set the value of an option. 240 * @param opt The option to set. 241 * @param value The value of the option in a string representation. 242 * @param err Error information (may be NULL). 243 * @return 0, if an error occurred, 1 else. 244 */ 245 int lc_opt_occurs(lc_opt_entry_t *opt, const char *value, lc_opt_err_info_t *err); 246 247 /** 248 * Convert the option to a string representation. 249 * @param buf The string buffer to put the string representation to. 250 * @param len The length of @p buf. 251 * @param ent The option to process. 252 * @return @p buf. 253 */ 254 char *lc_opt_value_to_string(char *buf, size_t len, const lc_opt_entry_t *ent); 255 256 /** 257 * Get the name of the type of an option. 258 * @param ent The option. 259 * @return The name of the type of the option. 260 */ 261 const char *lc_opt_get_type_name(const lc_opt_entry_t *ent); 262 263 /** 264 * Print the help screen for the given entity to the given file. 265 */ 266 void lc_opt_print_help(lc_opt_entry_t *ent, FILE *f); 267 268 /** 269 * Print the help screen for the given entity to the given file. 270 * Use separator instead of '.' and ignore entities above ent, 271 * i.e. if ent is root.be and has option isa.mach, prints 272 * isa<separator>mach instead of root.be.isa.mach 273 */ 274 void lc_opt_print_help_for_entry(lc_opt_entry_t *ent, char separator, FILE *f); 275 276 void lc_opt_print_tree(lc_opt_entry_t *ent, FILE *f); 277 278 int lc_opt_add_table(lc_opt_entry_t *grp, const lc_opt_table_entry_t *table); 279 280 /** 281 * The same as lc_opt_from_single_arg() only for an array of arguments. 282 */ 283 int lc_opt_from_argv(const lc_opt_entry_t *root, 284 const char *opt_prefix, 285 int argc, const char *argv[], 286 lc_opt_error_handler_t *handler); 287 288 /** 289 * Set options from a single (command line) argument. 290 * @param root The root group we start resolving from. 291 * @param opt_prefix The option prefix which shall be stripped of (mostly --). 292 * @param arg The command line argument itself. 293 * @param handler An error handler. 294 * @return 1, if the argument was set, 0 if not. 295 */ 296 int lc_opt_from_single_arg(const lc_opt_entry_t *grp, 297 const char *opt_prefix, 298 const char *arg, 299 lc_opt_error_handler_t *handler); 300 301 /** 302 * Get printf environment for the option module. 303 * Currently implemented options are: 304 * %{opt:value} (%V) Value of an option. 305 * %{opt:type} (%T) Type of an option. 306 * %{opt:name} (%O) Name of an option. 307 * %{opt:desc} (%D) Description of an option. 308 * @return The option printf environment. 309 */ 310 const lc_arg_env_t *lc_opt_get_arg_env(void); 311 312 #endif 313