Revision: 65122
http://sourceforge.net/p/brlcad/code/65122
Author: starseeker
Date: 2015-05-31 16:46:06 +0000 (Sun, 31 May 2015)
Log Message:
-----------
Add another typedef for clarity.
Modified Paths:
--------------
brlcad/trunk/include/bu/opt.h
brlcad/trunk/src/conv/gcv/gcv.cpp
brlcad/trunk/src/libbu/opt.c
brlcad/trunk/src/util/dsp_add_opt.c
Modified: brlcad/trunk/include/bu/opt.h
===================================================================
--- brlcad/trunk/include/bu/opt.h 2015-05-31 16:19:26 UTC (rev 65121)
+++ brlcad/trunk/include/bu/opt.h 2015-05-31 16:46:06 UTC (rev 65122)
@@ -43,8 +43,24 @@
* that were not associated with options */
#define BU_NON_OPTS -1
-struct bu_opt_data; /* Forward declaration for bu_opt_desc */
+/** Output format options for bu_opt */
+typedef enum {
+ BU_OPT_ASCII,
+ BU_OPT_DOCBOOK,
+ BU_OPT_HTML,
+ BU_OPT_LATEX,
+ BU_OPT_MARKDOWN
+} bu_opt_format_t;
+typedef enum {
+ BU_OPT_SHORT,
+ BU_OPT_FULL
+} bu_opt_desc_t;
+
+
+/* Forward declaration for bu_opt_desc and bu_opt_arg_process_t */
+struct bu_opt_data;
+
/**
* Convenience typedef for function callback to validate bu_opt
* arguments
@@ -52,7 +68,11 @@
typedef int (*bu_opt_arg_process_t)(struct bu_vls *, struct bu_opt_data *);
typedef struct bu_ptbl bu_opt_dtbl_t;
+typedef struct bu_ptbl bu_opt_data_t;
+
+
+
/**
* "Option description" structure
*/
@@ -70,7 +90,7 @@
#define BU_OPT_DESC_NULL {-1, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL}
/**
- * Initialize a bu_opt_desc ptbl. If ds is not NULL, populate the table
+ * Initialize a bu_opt_dtbl_t. If ds is not NULL, populate the table
* with the bu_opt_desc structs in the ds array. */
BU_EXPORT extern void bu_opt_desc_init(bu_opt_dtbl_t **dtbl, struct
bu_opt_desc *ds);
@@ -83,19 +103,50 @@
/**
* Remove option descriptions with index matching key from a bu_opt_desc ptbl
*/
BU_EXPORT extern void bu_opt_desc_del(bu_opt_dtbl_t *dtbl, int key);
+
/**
* Remove option descriptions with either a shortopt or a longopt matching name
* from a bu_opt_desc ptbl */
BU_EXPORT extern void bu_opt_desc_del_name(bu_opt_dtbl_t *dtbl, const char
*name);
+
/**
- * If bu_opt_desc instances aren't part of static arrays, they'll
- * be inside a table. This function frees them, but does not free
- * the bu_ptbl container.
+ * Free a bu_opt_dtbl_t.
*/
BU_EXPORT extern void bu_opt_desc_free(bu_opt_dtbl_t *tbl);
+
/**
+ * Construct a textual description of the options defined by
+ * the array.
+ *
+ * The structure is as follows:
+ *
+ * Offset Options Descriptions
+ * ******--------------*********************
+ * --test-option This is a test option
+ *
+ * Opt_col specifies how wide the options column is, and desc_cols
+ * specifies how wide the description column is.
+ *
+ *
+ */
+
+struct bu_opt_desc_opts {
+ bu_opt_desc_t desc_type;
+ bu_opt_format_t format_type;
+ int offset;
+ int option_columns;
+ int description_columns;
+};
+
+BU_EXPORT extern const char *bu_opt_describe(struct bu_opt_desc *ds, struct
bu_opt_desc_opts *settings);
+BU_EXPORT extern const char *bu_opt_describe_dtbl(bu_opt_dtbl_t *dtbl, struct
bu_opt_desc_opts *settings);
+
+
+
+
+/**
* Parsed option data container
*/
struct bu_opt_data {
@@ -106,34 +157,15 @@
void *user_data; /* place for arg_process to stash data */
};
#define BU_OPT_DATA_NULL {NULL, 0, NULL, NULL, NULL}
-/** Initialize a bu_opt_data structure to BU_OPT_DATA_NULL
- * TODO - does this need to be public? */
-BU_EXPORT extern void bu_opt_data_init(struct bu_opt_data *d);
-
/**
- * Note - description objects pointed to by bu_opt_data strucures
- * are not freed by this function, since they may be multiply
- * referenced by many bu_opt_data struct instances
- *
- * TODO - should this just take a table? all practical
- * cases will involve releasing the results of the parse step. */
-BU_EXPORT extern void bu_opt_data_free(struct bu_opt_data *d);
+ * Free a table of bu_opt_data results */
+BU_EXPORT extern void bu_opt_data_free(bu_opt_data_t *data);
/**
- * Most of the time bu_opt_data containers will be in bu_ptbl structs,
- * so handle that case
- *
- * TODO - collapse to just bu_opt_data_free on a table? */
-BU_EXPORT extern void bu_opt_data_free_tbl(struct bu_ptbl *t);
-
-
-/**
* Print a table of bu_opt_data structures. Caller
* is responsible for freeing return string. */
-BU_EXPORT extern void bu_opt_data_print(const char *title, struct bu_ptbl
*data);
+BU_EXPORT extern void bu_opt_data_print(bu_opt_data_t *data, const char
*title);
-
-
/**
* Convenience function for extracting args from a bu_opt_data container.
* Provided as an easy way to get either the first arg:
@@ -146,11 +178,43 @@
* Returns NULL if the specified arg is not present. index starts from 0. */
BU_EXPORT extern const char *bu_opt_data_arg(struct bu_opt_data *d, size_t
ind);
+/**
+ * Find and return a specific option from a bu_opt_data_t of options using an
enum
+ * integer as the lookup key. Will only return an option if its valid entry
+ * is set to 1. A key value of -1 retrieves the bu_opt_data struct with the
+ * unknown entries stored in its args table.
+ */
+BU_EXPORT extern struct bu_opt_data *bu_opt_find(int key, bu_opt_data_t
*results);
/**
+ * Find and return a specific option from a bu_opt_data_t of options using an
option
+ * string as the lookup key. Will only return an option if its valid entry
+ * is set to 1. A NULL value passed in for name retrieves the bu_opt_data
struct with the
+ * unknown entries stored in its args table.
+ */
+BU_EXPORT extern struct bu_opt_data *bu_opt_find_name(const char *name,
bu_opt_data_t *results);
+
+/**
+ * If an option has a message string associated with it, this function will
+ * get it. This works for both valid and invalid opts, to allow for error
+ * message retrieval. If multiple instances of a key are present, the msg
+ * from the last instance is returned. */
+BU_EXPORT extern const char *bu_opt_msg(int key, bu_opt_data_t *results);
+
+/**
+ * If an option has a message string associated with it, this function will
+ * get it. This works for both valid and invalid opts, to allow for error
+ * message retrieval. If multiple instances of a name are present, the msg
+ * from the last instance is returned. */
+BU_EXPORT extern const char *bu_opt_msg_name(const char *name, bu_opt_data_t
*results);
+
+
+
+
+/**
* Parse argv array using option descs.
*
- * returns a bu_ptbl of bu_opt_data structure pointers, or NULL if the parsing
+ * returns a bu_opt_data_t of bu_opt_data structure pointers, or NULL if the
parsing
* failed. If a desc has an arg process, function, the valid field in
* bu_opt_data for each option will indicate if the value in arg was
* successfully processed by arg_process. In situations where multiple options
@@ -172,12 +236,12 @@
* };
* bu_opt_parse(argc, argv, d1);
*/
-BU_EXPORT extern int bu_opt_parse(struct bu_ptbl **tbl, struct bu_vls *msgs,
int ac, const char **argv, struct bu_opt_desc *ds);
+BU_EXPORT extern int bu_opt_parse(bu_opt_data_t **results, struct bu_vls
*msgs, int ac, const char **argv, struct bu_opt_desc *ds);
/**
* Option parse an argv array defined as a space separated string. This
* is a convenience function that calls bu_opt_parse and also handles
* breaking str down into a proper argv array. */
-BU_EXPORT extern int bu_opt_parse_str(struct bu_ptbl **tbl, struct bu_vls
*msgs, const char *str, struct bu_opt_desc *ds);
+BU_EXPORT extern int bu_opt_parse_str(bu_opt_data_t **results, struct bu_vls
*msgs, const char *str, struct bu_opt_desc *ds);
/**
@@ -194,13 +258,13 @@
* bu_opt_desc_add(D1_O1, 0, 1, "v", "verbose", &(dtbl_v), "-v",
"--verbose", "Set verbosity");
* bu_opt_parse_ptbl(argc, argv, dtbl);
*/
-BU_EXPORT extern int bu_opt_parse_dtbl(struct bu_ptbl **tbl, struct bu_vls
*msgs, int ac, const char **argv, bu_opt_dtbl_t *dtbl);
+BU_EXPORT extern int bu_opt_parse_dtbl(bu_opt_data_t **results, struct bu_vls
*msgs, int ac, const char **argv, bu_opt_dtbl_t *dtbl);
/**
* Option parse an argv array defined as a space separated string. This
* is a convenience function that calls bu_opt_parse_dtbl and also handles
* breaking str down into a proper argv array. */
-BU_EXPORT extern int bu_opt_parse_str_dtbl(struct bu_ptbl **tbl, struct bu_vls
*msgs, const char *str, bu_opt_dtbl_t *dtbl);
+BU_EXPORT extern int bu_opt_parse_str_dtbl(bu_opt_data_t **results, struct
bu_vls *msgs, const char *str, bu_opt_dtbl_t *dtbl);
/**
* In situations where multiple options are present, the general rule is that
@@ -212,7 +276,7 @@
* of the input table before compacting if the user desires to examine the
original
* parsing data.
*/
-BU_EXPORT extern void bu_opt_compact(struct bu_ptbl *results);
+BU_EXPORT extern void bu_opt_compact(bu_opt_data_t *results);
/* Standard option validators - if a custom option argument
@@ -231,85 +295,6 @@
BU_EXPORT extern int bu_opt_arg_string(struct bu_vls *msg, struct bu_opt_data
*data);
-/**
- * Find and return a specific option from a bu_ptbl of options using an enum
- * integer as the lookup key. Will only return an option if its valid entry
- * is set to 1. A key value of -1 retrieves the bu_opt_data struct with the
- * unknown entries stored in its args table.
- */
-BU_EXPORT extern struct bu_opt_data *bu_opt_find(int key, struct bu_ptbl
*results);
-
-/**
- * Find and return a specific option from a bu_ptbl of options using an option
- * string as the lookup key. Will only return an option if its valid entry
- * is set to 1. A NULL value passed in for name retrieves the bu_opt_data
struct with the
- * unknown entries stored in its args table.
- */
-BU_EXPORT extern struct bu_opt_data *bu_opt_find_name(const char *name, struct
bu_ptbl *opts);
-
-
-
-/**
- * If an option has a message string associated with it, this function will
- * get it. This works for both valid and invalid opts, to allow for error
- * message retrieval. If multiple instances of a key are present, the msg
- * from the last instance is returned. */
-BU_EXPORT extern const char *bu_opt_msg(int key, struct bu_ptbl *results);
-
-/**
- * If an option has a message string associated with it, this function will
- * get it. This works for both valid and invalid opts, to allow for error
- * message retrieval. If multiple instances of a name are present, the msg
- * from the last instance is returned. */
-BU_EXPORT extern const char *bu_opt_msg_name(const char *name, struct bu_ptbl
*opts);
-
-
-/** Output format options for bu_opt */
-typedef enum {
- BU_OPT_ASCII,
- BU_OPT_DOCBOOK,
- BU_OPT_HTML,
- BU_OPT_LATEX,
- BU_OPT_MARKDOWN
-} bu_opt_format_t;
-
-typedef enum {
- BU_OPT_SHORT,
- BU_OPT_FULL
-} bu_opt_desc_t;
-
-
-/**
- * Construct a textual description of the options defined by
- * the array.
- *
- * The structure is as follows:
- *
- * Offset Options Descriptions
- * ******--------------*********************
- * --test-option This is a test option
- *
- * Opt_col specifies how wide the options column is, and desc_cols
- * specifies how wide the description column is.
- *
- *
- */
-
-struct bu_opt_desc_opts {
- bu_opt_desc_t desc_type;
- bu_opt_format_t format_type;
- int offset;
- int option_columns;
- int description_columns;
-};
-
-BU_EXPORT extern const char *bu_opt_describe(struct bu_opt_desc *ds, struct
bu_opt_desc_opts *settings);
-BU_EXPORT extern const char *bu_opt_describe_dtbl(bu_opt_dtbl_t *dtbl, struct
bu_opt_desc_opts *settings);
-
-
-
-
-
/** @} */
__END_DECLS
Modified: brlcad/trunk/src/conv/gcv/gcv.cpp
===================================================================
--- brlcad/trunk/src/conv/gcv/gcv.cpp 2015-05-31 16:19:26 UTC (rev 65121)
+++ brlcad/trunk/src/conv/gcv/gcv.cpp 2015-05-31 16:46:06 UTC (rev 65122)
@@ -41,7 +41,7 @@
void fast4_arg_process(const char *args) {
struct bu_opt_data *d;
- struct bu_ptbl *results;
+ bu_opt_data_t *results;
if (!args) return;
(void)bu_opt_parse_str(&results, NULL, args, fg4_opt_desc);
@@ -50,9 +50,9 @@
bu_log("FASTGEN 4 opt found: %s\n", d->name);
}
- bu_opt_data_print("FASTGEN4 option parsing results:", results);
+ bu_opt_data_print(results, "FASTGEN4 option parsing results:");
- bu_opt_data_free_tbl(results);
+ bu_opt_data_free(results);
}
/* Emulate a STL format option processer */
@@ -65,7 +65,7 @@
void stl_arg_process(const char *args) {
struct bu_opt_data *d;
- struct bu_ptbl *results;
+ bu_opt_data_t *results;
if (!args) return;
(void)bu_opt_parse_str(&results, NULL, args, stl_opt_desc);
@@ -74,10 +74,10 @@
bu_log("STL opt found: %s:%s\n", d->name, bu_opt_data_arg(d, 0));
}
- bu_opt_data_print("STL option parsing results:", results);
+ bu_opt_data_print(results, "STL option parsing results:");
- bu_opt_data_free_tbl(results);
+ bu_opt_data_free(results);
}
HIDDEN int
@@ -286,7 +286,6 @@
size_t i;
int fmt = 0;
int ret = 0;
- bu_opt_dtbl_t *top_opt_desc;
const char *in_fmt = NULL;
const char *out_fmt = NULL;
mime_model_t in_type = MIME_MODEL_UNKNOWN;
@@ -302,7 +301,8 @@
struct bu_vls output_opts = BU_VLS_INIT_ZERO;
struct bu_opt_data *d = NULL;
struct bu_ptbl *unknown_tbl = NULL;
- struct bu_ptbl *results = NULL;
+ bu_opt_data_t *results = NULL;
+ bu_opt_dtbl_t *top_opt_desc = NULL;
ac-=(ac>0); av+=(ac>0); // skip program name argv[0] if present
@@ -563,7 +563,7 @@
bu_vls_free(&log);
bu_vls_free(&input_opts);
bu_vls_free(&output_opts);
- bu_opt_data_free_tbl(results);
+ bu_opt_data_free(results);
if (top_opt_desc) bu_opt_desc_free(top_opt_desc);
return ret;
Modified: brlcad/trunk/src/libbu/opt.c
===================================================================
--- brlcad/trunk/src/libbu/opt.c 2015-05-31 16:19:26 UTC (rev 65121)
+++ brlcad/trunk/src/libbu/opt.c 2015-05-31 16:46:06 UTC (rev 65122)
@@ -31,417 +31,20 @@
#include "bu/str.h"
#include "bu/vls.h"
-#define BU_OPT_DATA_GET(_od, _name) {\
- BU_GET(_od, struct bu_opt_data); \
- if (_name) { \
- _od->name = _name; \
- } else { \
- _od->name = NULL; \
- } \
- _od->args = NULL; \
- _od->valid = 1; \
- _od->desc = NULL; \
- _od->user_data = NULL; \
-}
-
-HIDDEN char *
-opt_process(char **eq_arg, const char *opt_candidate)
+HIDDEN void
+bu_opt_data_init_entry(struct bu_opt_data *d, const char *name)
{
- int offset = 1;
- char *inputcpy;
- char *final_opt;
- char *equal_pos;
- if (!eq_arg && !opt_candidate) return NULL;
- inputcpy = bu_strdup(opt_candidate);
- if (inputcpy[1] == '-') offset++;
- equal_pos = strchr(inputcpy, '=');
-
- /* If we've got a single opt, things are handled differently */
- if (offset == 1) {
- if (strlen(opt_candidate+offset) == 1) {
- final_opt = bu_strdup(opt_candidate+offset);
- } else {
- /* single letter opt, but the string is longer - the
- * interpretation in this context is everything after
- * the first letter is arg.*/
- struct bu_vls vopt = BU_VLS_INIT_ZERO;
- struct bu_vls varg = BU_VLS_INIT_ZERO;
- bu_vls_strncat(&vopt, inputcpy+1, 1);
- bu_vls_sprintf(&varg, "%s", inputcpy);
- bu_vls_nibble(&varg, 2);
-
-#if 0
- /* A possible exception is an equals sign, e.g. -s=1024 - in that
- * instance, the expectation might be that = would be interpreted
- * as an assignment. This means that to get the literal =1024 as
- * an option, you would need a space after the s, e.g.: -s =1024
- *
- * For now, commented out to favor consistent behavior over what
- * "looks right" - may be worth revisiting or even an option at
- * some point...*/
-
- if (equal_pos && equal_pos == inputcpy+2) {
- bu_vls_nibble(&varg, 1);
- }
-#endif
-
- (*eq_arg) = bu_strdup(bu_vls_addr(&varg));
- final_opt = bu_strdup(bu_vls_addr(&vopt));
- bu_vls_free(&vopt);
- bu_vls_free(&varg);
- }
- } else {
- if (equal_pos) {
- struct bu_vls vopt = BU_VLS_INIT_ZERO;
- struct bu_vls varg = BU_VLS_INIT_ZERO;
- bu_vls_sprintf(&vopt, "%s", inputcpy);
- bu_vls_trunc(&vopt, -1 * strlen(equal_pos));
- bu_vls_nibble(&vopt, offset);
- bu_vls_sprintf(&varg, "%s", inputcpy);
- bu_vls_nibble(&varg, strlen(inputcpy) - strlen(equal_pos) + 1);
- (*eq_arg) = bu_strdup(bu_vls_addr(&varg));
- final_opt = bu_strdup(bu_vls_addr(&vopt));
- bu_vls_free(&vopt);
- bu_vls_free(&varg);
- } else {
- final_opt = bu_strdup(opt_candidate+offset);
- }
- }
- bu_free(inputcpy, "cleanup working copy");
- return final_opt;
-}
-
-void
-bu_opt_compact(struct bu_ptbl *opts)
-{
- int i;
- int ptblpos = BU_PTBL_LEN(opts) - 1;
- struct bu_ptbl tbl;
- bu_ptbl_init(&tbl, 8, "local table");
- while (ptblpos >= 0) {
- struct bu_opt_data *data = (struct bu_opt_data *)BU_PTBL_GET(opts,
ptblpos);
- if (!data) {
- ptblpos--;
- continue;
- }
- bu_ptbl_ins(&tbl, (long *)data);
- BU_PTBL_CLEAR_I(opts, ptblpos);
- for (i = ptblpos - 1; i >= 0; i--) {
- struct bu_opt_data *dc = (struct bu_opt_data *)BU_PTBL_GET(opts, i);
- if ((dc && dc->desc && data->desc) && dc->desc->index ==
data->desc->index) {
- bu_free(dc, "free duplicate");
- BU_PTBL_CLEAR_I(opts, i);
- }
- }
- ptblpos--;
- }
- bu_ptbl_reset(opts);
- for (i = BU_PTBL_LEN(&tbl) - 1; i >= 0; i--) {
- bu_ptbl_ins(opts, BU_PTBL_GET(&tbl, i));
- }
- bu_ptbl_free(&tbl);
-}
-
-/* This implements criteria for deciding when an argv string is
- * an option. Right now the criteria are:
- *
- * 1. Must have a '-' char as first character
- * 2. Must not have white space characters present in the string.
- */
-HIDDEN int
-is_opt(const char *opt) {
- size_t i = 0;
- if (!opt) return 0;
- if (!strlen(opt)) return 0;
- if (opt[0] != '-') return 0;
- for (i = 1; i < strlen(opt); i++) {
- if (isspace(opt[i])) return 0;
- }
- return 1;
-}
-
-HIDDEN struct bu_ptbl *
-bu_opt_parse_internal(int argc, const char **argv, struct bu_opt_desc *ds,
struct bu_ptbl *dptbl, struct bu_vls *UNUSED(msgs))
-{
- int i = 0;
- int offset = 0;
- const char *ns = NULL;
- struct bu_ptbl *opt_data;
- struct bu_opt_data *unknowns = NULL;
- if (!argv || (!ds && !dptbl) || (ds && dptbl)) return NULL;
-
- BU_GET(opt_data, struct bu_ptbl);
- bu_ptbl_init(opt_data, 8, "opt_data");
-
- /* Now identify opt/arg pairs.*/
- while (i < argc) {
- int desc_found = 0;
- int desc_ind = 0;
- size_t arg_cnt = 0;
- char *opt = NULL;
- char *eq_arg = NULL;
- struct bu_opt_data *data = NULL;
- struct bu_opt_desc *desc = NULL;
- /* If 'opt' isn't an option, make a container for non-option values and
build it up until
- * we reach an option */
- if (!is_opt(argv[i])) {
- if (!unknowns) {
- BU_OPT_DATA_GET(unknowns, NULL);
- BU_GET(unknowns->args, struct bu_ptbl);
- bu_ptbl_init(unknowns->args, 8, "args init");
- }
- ns = bu_strdup(argv[i]);
- bu_ptbl_ins(unknowns->args, (long *)ns);
- i++;
- while (i < argc && !is_opt(argv[i])) {
- ns = bu_strdup(argv[i]);
- bu_ptbl_ins(unknowns->args, (long *)ns);
- i++;
- }
- continue;
- }
-
- /* It may be that an = has been used instead of a space. Handle that,
and
- * strip leading '-' characters. Also, short-opt options may not have a
- * space between their option and the argument. That is also handled
here */
- opt = opt_process(&eq_arg, argv[i]);
-
- /* Find the corresponding desc, if we have one */
- if (ds) {
- desc = &(ds[0]);
- } else {
- desc = (struct bu_opt_desc *)BU_PTBL_GET(dptbl, 0);
- }
- while (!desc_found && (desc && desc->index != -1)) {
- if (BU_STR_EQUAL(opt+offset, desc->shortopt) ||
BU_STR_EQUAL(opt+offset, desc->longopt)) {
- desc_found = 1;
- continue;
- }
- desc_ind++;
- if (ds) {
- desc = &(ds[desc_ind]);
- } else {
- desc = (struct bu_opt_desc *)BU_PTBL_GET(dptbl, desc_ind);
- }
- }
-
- /* If we don't know what we're dealing with, keep going */
- if (!desc_found) {
- struct bu_vls rebuilt_opt = BU_VLS_INIT_ZERO;
- if (!unknowns) {
- BU_OPT_DATA_GET(unknowns, NULL);
- BU_GET(unknowns->args, struct bu_ptbl);
- bu_ptbl_init(unknowns->args, 8, "args init");
- }
- if (strlen(opt) == 1) {
- bu_vls_sprintf(&rebuilt_opt, "-%s", opt);
- } else {
- bu_vls_sprintf(&rebuilt_opt, "--%s", opt);
- }
- bu_ptbl_ins(unknowns->args, (long
*)bu_strdup(bu_vls_addr(&rebuilt_opt)));
- bu_free(opt, "free opt");
- bu_vls_free(&rebuilt_opt);
- if (eq_arg)
- bu_ptbl_ins(unknowns->args, (long *)eq_arg);
- i++;
- continue;
- }
-
- /* Initialize with opt */
- BU_OPT_DATA_GET(data, opt);
- data->desc = desc;
- if (eq_arg) {
- /* Okay, we actually need it - initialize the arg table */
- BU_GET(data->args, struct bu_ptbl);
- bu_ptbl_init(data->args, 8, "args init");
- bu_ptbl_ins(data->args, (long *)eq_arg);
- arg_cnt = 1;
- }
-
- /* handled the option - any remaining processing is on args, if any*/
- i = i + 1;
-
- /* If we already got an arg from the equals mechanism and we aren't
- * supposed to have one, we're invalid */
- if (arg_cnt > 0 && desc->arg_cnt_max == 0) data->valid = 0;
-
- /* If we're looking for args, do so */
- if (desc->arg_cnt_max > 0) {
- while (arg_cnt < desc->arg_cnt_max && i < argc && !is_opt(argv[i]))
{
- ns = bu_strdup(argv[i]);
- if (!data->args) {
- /* Okay, we actually need it - initialize the arg table */
- BU_GET(data->args, struct bu_ptbl);
- bu_ptbl_init(data->args, 8, "args init");
- }
- bu_ptbl_ins(data->args, (long *)ns);
- i++;
- arg_cnt++;
- }
- if (arg_cnt < desc->arg_cnt_min) {
- data->valid = 0;
- }
- }
-
- /* Now see if we need to validate the arg(s) */
- if (desc->arg_process) {
- int arg_offset = (*desc->arg_process)(NULL, data);
- if (arg_offset < 0) {
- /* arg(s) present but not associated with opt, back them out of
data
- *
- * test example for this - color option
- *
- * --color 200/30/10 input output (1 arg to color, 3 args
total)
- * --color 200 30 10 input output (3 args to color, 5 total)
- *
- * to handle the color case, need to process all three in
first case,
- * recognize that first one is sufficient, and release the
latter two.
- * for the second case all three are necessary
- *
- * */
- int len = BU_PTBL_LEN(data->args);
- int j = 0;
- i = i + arg_offset;
- while (j > arg_offset) {
- bu_free((void *)BU_PTBL_GET(data->args, len + j - 1), "free
str");
- j--;
- }
- bu_ptbl_trunc(data->args, len + arg_offset);
- }
- }
- bu_ptbl_ins(opt_data, (long *)data);
- }
- if (unknowns) bu_ptbl_ins(opt_data, (long *)unknowns);
-
- return opt_data;
-}
-
-int
-bu_opt_parse(struct bu_ptbl **tbl, struct bu_vls *msgs, int ac, const char
**argv, struct bu_opt_desc *ds)
-{
- struct bu_ptbl *results = NULL;
- if (!tbl || !argv || !ds) return 1;
- results = bu_opt_parse_internal(ac, argv, ds, NULL, msgs);
- if (results) {
- (*tbl) = results;
- return 0;
- } else {
- return 1;
- }
-}
-
-int
-bu_opt_parse_str(struct bu_ptbl **tbl, struct bu_vls *msgs, const char *str,
struct bu_opt_desc *ds)
-{
- int ret = 0;
- char *input = NULL;
- char **argv = NULL;
- int argc = 0;
- if (!tbl || !str || !ds) return 1;
- input = bu_strdup(str);
- argv = (char **)bu_calloc(strlen(input) + 1, sizeof(char *), "argv array");
- argc = bu_argv_from_string(argv, strlen(input), input);
-
- ret = bu_opt_parse(tbl, msgs, argc, (const char **)argv, ds);
-
- bu_free(input, "free str copy");
- bu_free(argv, "free argv memory");
- return ret;
-}
-
-int
-bu_opt_parse_dtbl(struct bu_ptbl **tbl, struct bu_vls *msgs, int ac, const
char **argv, struct bu_ptbl *dtbl)
-{
- struct bu_ptbl *results = NULL;
- if (!tbl || !argv || !dtbl) return 1;
- results = bu_opt_parse_internal(ac, argv, NULL, dtbl, msgs);
- if (results) {
- (*tbl) = results;
- return 0;
- } else {
- return 1;
- }
-}
-
-int
-bu_opt_parse_str_dtbl(struct bu_ptbl **tbl, struct bu_vls *msgs, const char
*str, struct bu_ptbl *dtbl)
-{
- int ret = 0;
- char *input = NULL;
- char **argv = NULL;
- int argc = 0;
- if (!tbl || !str || !dtbl) return 1;
- input = bu_strdup(str);
- argv = (char **)bu_calloc(strlen(input) + 1, sizeof(char *), "argv array");
- argc = bu_argv_from_string(argv, strlen(input), input);
-
- ret = bu_opt_parse_dtbl(tbl, msgs, argc, (const char **)argv, dtbl);
-
- bu_free(input, "free str copy");
- bu_free(argv, "free argv memory");
- return ret;
-}
-
-
-struct bu_opt_data *
-bu_opt_find_name(const char *name, struct bu_ptbl *opts)
-{
- size_t i;
- if (!opts) return NULL;
-
- for (i = 0; i < BU_PTBL_LEN(opts); i++) {
- struct bu_opt_data *opt = (struct bu_opt_data *)BU_PTBL_GET(opts, i);
- /* Don't check the unknown opts - they were already marked as not
- * valid opts per the current descriptions in the parsing pass */
- if (!name && !opt->name) return opt;
- if (!opt->name) continue;
- if (!opt->desc) continue;
- if (BU_STR_EQUAL(opt->desc->shortopt, name) ||
BU_STR_EQUAL(opt->desc->longopt, name)) {
- /* option culling guarantees us one "winner" if multiple instances
- * of an option were originally supplied, so if we find a match we
- * have found what we wanted. Now, just need to check validity */
- return (opt->valid) ? opt : NULL;
- }
- }
- return NULL;
-}
-
-struct bu_opt_data *
-bu_opt_find(int key, struct bu_ptbl *opts)
-{
- size_t i;
- if (!opts) return NULL;
-
- for (i = 0; i < BU_PTBL_LEN(opts); i++) {
- struct bu_opt_data *opt = (struct bu_opt_data *)BU_PTBL_GET(opts, i);
- /* Don't check the unknown opts - they were already marked as not
- * valid opts per the current descriptions in the parsing pass */
- if (key == -1 && !opt->name) return opt;
- if (!opt->name) continue;
- if (!opt->desc) continue;
- if (key == opt->desc->index) {
- /* option culling guarantees us one "winner" if multiple instances
- * of an option were originally supplied, so if we find a match we
- * have found what we wanted. Now, just need to check validity */
- return (opt->valid) ? opt : NULL;
- }
- }
- return NULL;
-}
-
-void
-bu_opt_data_init(struct bu_opt_data *d)
-{
if (!d) return;
+ BU_GET(d, struct bu_opt_data);
d->desc = NULL;
d->valid = 0;
- d->name = NULL;
+ d->name = name;
d->args = NULL;
d->user_data = NULL;
}
void
-bu_opt_data_free(struct bu_opt_data *d)
+bu_opt_data_free_entry(struct bu_opt_data *d)
{
if (!d) return;
if (d->name) bu_free((char *)d->name, "free data name");
@@ -459,18 +62,20 @@
void
-bu_opt_data_free_tbl(struct bu_ptbl *tbl)
+bu_opt_data_free(struct bu_ptbl *tbl)
{
size_t i;
if (!tbl) return;
for (i = 0; i < BU_PTBL_LEN(tbl); i++) {
struct bu_opt_data *opt = (struct bu_opt_data *)BU_PTBL_GET(tbl, i);
- bu_opt_data_free(opt);
+ bu_opt_data_free_entry(opt);
}
bu_ptbl_free(tbl);
BU_PUT(tbl, struct bu_ptbl);
}
+
+
const char *
bu_opt_data_arg(struct bu_opt_data *d, size_t ind)
{
@@ -483,7 +88,7 @@
}
void
-bu_opt_data_print(const char *title, struct bu_ptbl *data)
+bu_opt_data_print(struct bu_ptbl *data, const char *title)
{
size_t i = 0;
size_t j = 0;
@@ -529,7 +134,52 @@
bu_vls_free(&log);
}
+struct bu_opt_data *
+bu_opt_find_name(const char *name, struct bu_ptbl *opts)
+{
+ size_t i;
+ if (!opts) return NULL;
+ for (i = 0; i < BU_PTBL_LEN(opts); i++) {
+ struct bu_opt_data *opt = (struct bu_opt_data *)BU_PTBL_GET(opts, i);
+ /* Don't check the unknown opts - they were already marked as not
+ * valid opts per the current descriptions in the parsing pass */
+ if (!name && !opt->name) return opt;
+ if (!opt->name) continue;
+ if (!opt->desc) continue;
+ if (BU_STR_EQUAL(opt->desc->shortopt, name) ||
BU_STR_EQUAL(opt->desc->longopt, name)) {
+ /* option culling guarantees us one "winner" if multiple instances
+ * of an option were originally supplied, so if we find a match we
+ * have found what we wanted. Now, just need to check validity */
+ return (opt->valid) ? opt : NULL;
+ }
+ }
+ return NULL;
+}
+
+struct bu_opt_data *
+bu_opt_find(int key, struct bu_ptbl *opts)
+{
+ size_t i;
+ if (!opts) return NULL;
+
+ for (i = 0; i < BU_PTBL_LEN(opts); i++) {
+ struct bu_opt_data *opt = (struct bu_opt_data *)BU_PTBL_GET(opts, i);
+ /* Don't check the unknown opts - they were already marked as not
+ * valid opts per the current descriptions in the parsing pass */
+ if (key == -1 && !opt->name) return opt;
+ if (!opt->name) continue;
+ if (!opt->desc) continue;
+ if (key == opt->desc->index) {
+ /* option culling guarantees us one "winner" if multiple instances
+ * of an option were originally supplied, so if we find a match we
+ * have found what we wanted. Now, just need to check validity */
+ return (opt->valid) ? opt : NULL;
+ }
+ }
+ return NULL;
+}
+
HIDDEN void
bu_opt_desc_init_entry(struct bu_opt_desc *d)
{
@@ -839,7 +489,346 @@
}
+HIDDEN char *
+opt_process(char **eq_arg, const char *opt_candidate)
+{
+ int offset = 1;
+ char *inputcpy;
+ char *final_opt;
+ char *equal_pos;
+ if (!eq_arg && !opt_candidate) return NULL;
+ inputcpy = bu_strdup(opt_candidate);
+ if (inputcpy[1] == '-') offset++;
+ equal_pos = strchr(inputcpy, '=');
+ /* If we've got a single opt, things are handled differently */
+ if (offset == 1) {
+ if (strlen(opt_candidate+offset) == 1) {
+ final_opt = bu_strdup(opt_candidate+offset);
+ } else {
+ /* single letter opt, but the string is longer - the
+ * interpretation in this context is everything after
+ * the first letter is arg.*/
+ struct bu_vls vopt = BU_VLS_INIT_ZERO;
+ struct bu_vls varg = BU_VLS_INIT_ZERO;
+ bu_vls_strncat(&vopt, inputcpy+1, 1);
+ bu_vls_sprintf(&varg, "%s", inputcpy);
+ bu_vls_nibble(&varg, 2);
+
+#if 0
+ /* A possible exception is an equals sign, e.g. -s=1024 - in that
+ * instance, the expectation might be that = would be interpreted
+ * as an assignment. This means that to get the literal =1024 as
+ * an option, you would need a space after the s, e.g.: -s =1024
+ *
+ * For now, commented out to favor consistent behavior over what
+ * "looks right" - may be worth revisiting or even an option at
+ * some point...*/
+
+ if (equal_pos && equal_pos == inputcpy+2) {
+ bu_vls_nibble(&varg, 1);
+ }
+#endif
+
+ (*eq_arg) = bu_strdup(bu_vls_addr(&varg));
+ final_opt = bu_strdup(bu_vls_addr(&vopt));
+ bu_vls_free(&vopt);
+ bu_vls_free(&varg);
+ }
+ } else {
+ if (equal_pos) {
+ struct bu_vls vopt = BU_VLS_INIT_ZERO;
+ struct bu_vls varg = BU_VLS_INIT_ZERO;
+ bu_vls_sprintf(&vopt, "%s", inputcpy);
+ bu_vls_trunc(&vopt, -1 * strlen(equal_pos));
+ bu_vls_nibble(&vopt, offset);
+ bu_vls_sprintf(&varg, "%s", inputcpy);
+ bu_vls_nibble(&varg, strlen(inputcpy) - strlen(equal_pos) + 1);
+ (*eq_arg) = bu_strdup(bu_vls_addr(&varg));
+ final_opt = bu_strdup(bu_vls_addr(&vopt));
+ bu_vls_free(&vopt);
+ bu_vls_free(&varg);
+ } else {
+ final_opt = bu_strdup(opt_candidate+offset);
+ }
+ }
+ bu_free(inputcpy, "cleanup working copy");
+ return final_opt;
+}
+
+void
+bu_opt_compact(struct bu_ptbl *opts)
+{
+ int i;
+ int ptblpos = BU_PTBL_LEN(opts) - 1;
+ struct bu_ptbl tbl;
+ bu_ptbl_init(&tbl, 8, "local table");
+ while (ptblpos >= 0) {
+ struct bu_opt_data *data = (struct bu_opt_data *)BU_PTBL_GET(opts,
ptblpos);
+ if (!data) {
+ ptblpos--;
+ continue;
+ }
+ bu_ptbl_ins(&tbl, (long *)data);
+ BU_PTBL_CLEAR_I(opts, ptblpos);
+ for (i = ptblpos - 1; i >= 0; i--) {
+ struct bu_opt_data *dc = (struct bu_opt_data *)BU_PTBL_GET(opts, i);
+ if ((dc && dc->desc && data->desc) && dc->desc->index ==
data->desc->index) {
+ bu_free(dc, "free duplicate");
+ BU_PTBL_CLEAR_I(opts, i);
+ }
+ }
+ ptblpos--;
+ }
+ bu_ptbl_reset(opts);
+ for (i = BU_PTBL_LEN(&tbl) - 1; i >= 0; i--) {
+ bu_ptbl_ins(opts, BU_PTBL_GET(&tbl, i));
+ }
+ bu_ptbl_free(&tbl);
+}
+
+/* This implements criteria for deciding when an argv string is
+ * an option. Right now the criteria are:
+ *
+ * 1. Must have a '-' char as first character
+ * 2. Must not have white space characters present in the string.
+ */
+HIDDEN int
+is_opt(const char *opt) {
+ size_t i = 0;
+ if (!opt) return 0;
+ if (!strlen(opt)) return 0;
+ if (opt[0] != '-') return 0;
+ for (i = 1; i < strlen(opt); i++) {
+ if (isspace(opt[i])) return 0;
+ }
+ return 1;
+}
+
+HIDDEN struct bu_ptbl *
+bu_opt_parse_internal(int argc, const char **argv, struct bu_opt_desc *ds,
struct bu_ptbl *dptbl, struct bu_vls *UNUSED(msgs))
+{
+ int i = 0;
+ int offset = 0;
+ const char *ns = NULL;
+ struct bu_ptbl *opt_data;
+ struct bu_opt_data *unknowns = NULL;
+ if (!argv || (!ds && !dptbl) || (ds && dptbl)) return NULL;
+
+ BU_GET(opt_data, struct bu_ptbl);
+ bu_ptbl_init(opt_data, 8, "opt_data");
+
+ /* Now identify opt/arg pairs.*/
+ while (i < argc) {
+ int desc_found = 0;
+ int desc_ind = 0;
+ size_t arg_cnt = 0;
+ char *opt = NULL;
+ char *eq_arg = NULL;
+ struct bu_opt_data *data = NULL;
+ struct bu_opt_desc *desc = NULL;
+ /* If 'opt' isn't an option, make a container for non-option values and
build it up until
+ * we reach an option */
+ if (!is_opt(argv[i])) {
+ if (!unknowns) {
+ bu_opt_data_init_entry(unknowns, NULL);
+ BU_GET(unknowns->args, struct bu_ptbl);
+ bu_ptbl_init(unknowns->args, 8, "args init");
+ }
+ ns = bu_strdup(argv[i]);
+ bu_ptbl_ins(unknowns->args, (long *)ns);
+ i++;
+ while (i < argc && !is_opt(argv[i])) {
+ ns = bu_strdup(argv[i]);
+ bu_ptbl_ins(unknowns->args, (long *)ns);
+ i++;
+ }
+ continue;
+ }
+
+ /* It may be that an = has been used instead of a space. Handle that,
and
+ * strip leading '-' characters. Also, short-opt options may not have a
+ * space between their option and the argument. That is also handled
here */
+ opt = opt_process(&eq_arg, argv[i]);
+
+ /* Find the corresponding desc, if we have one */
+ if (ds) {
+ desc = &(ds[0]);
+ } else {
+ desc = (struct bu_opt_desc *)BU_PTBL_GET(dptbl, 0);
+ }
+ while (!desc_found && (desc && desc->index != -1)) {
+ if (BU_STR_EQUAL(opt+offset, desc->shortopt) ||
BU_STR_EQUAL(opt+offset, desc->longopt)) {
+ desc_found = 1;
+ continue;
+ }
+ desc_ind++;
+ if (ds) {
+ desc = &(ds[desc_ind]);
+ } else {
+ desc = (struct bu_opt_desc *)BU_PTBL_GET(dptbl, desc_ind);
+ }
+ }
+
+ /* If we don't know what we're dealing with, keep going */
+ if (!desc_found) {
+ struct bu_vls rebuilt_opt = BU_VLS_INIT_ZERO;
+ if (!unknowns) {
+ bu_opt_data_init_entry(unknowns, NULL);
+ BU_GET(unknowns->args, struct bu_ptbl);
+ bu_ptbl_init(unknowns->args, 8, "args init");
+ }
+ if (strlen(opt) == 1) {
+ bu_vls_sprintf(&rebuilt_opt, "-%s", opt);
+ } else {
+ bu_vls_sprintf(&rebuilt_opt, "--%s", opt);
+ }
+ bu_ptbl_ins(unknowns->args, (long
*)bu_strdup(bu_vls_addr(&rebuilt_opt)));
+ bu_free(opt, "free opt");
+ bu_vls_free(&rebuilt_opt);
+ if (eq_arg)
+ bu_ptbl_ins(unknowns->args, (long *)eq_arg);
+ i++;
+ continue;
+ }
+
+ /* Initialize with opt */
+ bu_opt_data_init_entry(data, opt);
+ data->desc = desc;
+ if (eq_arg) {
+ /* Okay, we actually need it - initialize the arg table */
+ BU_GET(data->args, struct bu_ptbl);
+ bu_ptbl_init(data->args, 8, "args init");
+ bu_ptbl_ins(data->args, (long *)eq_arg);
+ arg_cnt = 1;
+ }
+
+ /* handled the option - any remaining processing is on args, if any*/
+ i = i + 1;
+
+ /* If we already got an arg from the equals mechanism and we aren't
+ * supposed to have one, we're invalid */
+ if (arg_cnt > 0 && desc->arg_cnt_max == 0) data->valid = 0;
+
+ /* If we're looking for args, do so */
+ if (desc->arg_cnt_max > 0) {
+ while (arg_cnt < desc->arg_cnt_max && i < argc && !is_opt(argv[i]))
{
+ ns = bu_strdup(argv[i]);
+ if (!data->args) {
+ /* Okay, we actually need it - initialize the arg table */
+ BU_GET(data->args, struct bu_ptbl);
+ bu_ptbl_init(data->args, 8, "args init");
+ }
+ bu_ptbl_ins(data->args, (long *)ns);
+ i++;
+ arg_cnt++;
+ }
+ if (arg_cnt < desc->arg_cnt_min) {
+ data->valid = 0;
+ }
+ }
+
+ /* Now see if we need to validate the arg(s) */
+ if (desc->arg_process) {
+ int arg_offset = (*desc->arg_process)(NULL, data);
+ if (arg_offset < 0) {
+ /* arg(s) present but not associated with opt, back them out of
data
+ *
+ * test example for this - color option
+ *
+ * --color 200/30/10 input output (1 arg to color, 3 args
total)
+ * --color 200 30 10 input output (3 args to color, 5 total)
+ *
+ * to handle the color case, need to process all three in
first case,
+ * recognize that first one is sufficient, and release the
latter two.
+ * for the second case all three are necessary
+ *
+ * */
+ int len = BU_PTBL_LEN(data->args);
+ int j = 0;
+ i = i + arg_offset;
+ while (j > arg_offset) {
+ bu_free((void *)BU_PTBL_GET(data->args, len + j - 1), "free
str");
+ j--;
+ }
+ bu_ptbl_trunc(data->args, len + arg_offset);
+ }
+ }
+ bu_ptbl_ins(opt_data, (long *)data);
+ }
+ if (unknowns) bu_ptbl_ins(opt_data, (long *)unknowns);
+
+ return opt_data;
+}
+
+int
+bu_opt_parse(struct bu_ptbl **tbl, struct bu_vls *msgs, int ac, const char
**argv, struct bu_opt_desc *ds)
+{
+ struct bu_ptbl *results = NULL;
+ if (!tbl || !argv || !ds) return 1;
+ results = bu_opt_parse_internal(ac, argv, ds, NULL, msgs);
+ if (results) {
+ (*tbl) = results;
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+int
+bu_opt_parse_str(struct bu_ptbl **tbl, struct bu_vls *msgs, const char *str,
struct bu_opt_desc *ds)
+{
+ int ret = 0;
+ char *input = NULL;
+ char **argv = NULL;
+ int argc = 0;
+ if (!tbl || !str || !ds) return 1;
+ input = bu_strdup(str);
+ argv = (char **)bu_calloc(strlen(input) + 1, sizeof(char *), "argv array");
+ argc = bu_argv_from_string(argv, strlen(input), input);
+
+ ret = bu_opt_parse(tbl, msgs, argc, (const char **)argv, ds);
+
+ bu_free(input, "free str copy");
+ bu_free(argv, "free argv memory");
+ return ret;
+}
+
+int
+bu_opt_parse_dtbl(struct bu_ptbl **tbl, struct bu_vls *msgs, int ac, const
char **argv, struct bu_ptbl *dtbl)
+{
+ struct bu_ptbl *results = NULL;
+ if (!tbl || !argv || !dtbl) return 1;
+ results = bu_opt_parse_internal(ac, argv, NULL, dtbl, msgs);
+ if (results) {
+ (*tbl) = results;
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+int
+bu_opt_parse_str_dtbl(struct bu_ptbl **tbl, struct bu_vls *msgs, const char
*str, struct bu_ptbl *dtbl)
+{
+ int ret = 0;
+ char *input = NULL;
+ char **argv = NULL;
+ int argc = 0;
+ if (!tbl || !str || !dtbl) return 1;
+ input = bu_strdup(str);
+ argv = (char **)bu_calloc(strlen(input) + 1, sizeof(char *), "argv array");
+ argc = bu_argv_from_string(argv, strlen(input), input);
+
+ ret = bu_opt_parse_dtbl(tbl, msgs, argc, (const char **)argv, dtbl);
+
+ bu_free(input, "free str copy");
+ bu_free(argv, "free argv memory");
+ return ret;
+}
+
+
+
/*
* Local Variables:
* mode: C
Modified: brlcad/trunk/src/util/dsp_add_opt.c
===================================================================
--- brlcad/trunk/src/util/dsp_add_opt.c 2015-05-31 16:19:26 UTC (rev 65121)
+++ brlcad/trunk/src/util/dsp_add_opt.c 2015-05-31 16:46:06 UTC (rev 65122)
@@ -90,11 +90,11 @@
/*
* Parse command line flags
*/
-struct bu_ptbl *
+bu_opt_data_t *
parse_args(int ac, char *av[])
{
size_t i = 0;
- struct bu_ptbl *results;
+ bu_opt_data_t *results;
(void)bu_opt_parse(&results, NULL, ac, (const char **)av, dsp_opt_desc);
bu_opt_compact(results);
@@ -103,7 +103,7 @@
if (!d->valid || !d->name || !d->desc) continue;
switch(d->desc->shortopt[0]) {
default:
- bu_opt_data_free_tbl(results);
+ bu_opt_data_free(results);
print_usage();
}
}
@@ -193,7 +193,7 @@
main(int ac, char *av[])
{
struct bu_opt_data *non_opts;
- struct bu_ptbl *results;
+ bu_opt_data_t *results;
FILE *in1, *in2;
unsigned short *buf1, *buf2;
size_t count;
@@ -302,7 +302,7 @@
return -1;
}
- bu_opt_data_free_tbl(results);
+ bu_opt_data_free(results);
return 0;
}
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
------------------------------------------------------------------------------
_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits