Revision: 65190
http://sourceforge.net/p/brlcad/code/65190
Author: starseeker
Date: 2015-06-04 22:53:20 +0000 (Thu, 04 Jun 2015)
Log Message:
-----------
Start working on option handling based on validation routines instead of simple
string checks. This will set the stage for supporting options with negative
numbers, such as --num -9
Modified Paths:
--------------
brlcad/trunk/src/conv/gcv/gcv.cpp
brlcad/trunk/src/libbu/opt.c
brlcad/trunk/src/libbu/tests/opt.c
Modified: brlcad/trunk/src/conv/gcv/gcv.cpp
===================================================================
--- brlcad/trunk/src/conv/gcv/gcv.cpp 2015-06-04 21:30:13 UTC (rev 65189)
+++ brlcad/trunk/src/conv/gcv/gcv.cpp 2015-06-04 22:53:20 UTC (rev 65190)
@@ -226,12 +226,12 @@
if (!data) return 0;
if (!data->argv || data->argc == 0) {
data->valid = 0;
- return 0;
+ return 1;
}
if (!bu_file_exists(data->argv[0], NULL)){
data->valid = 0;
}
- return 0;
+ return 1;
}
int
@@ -240,13 +240,13 @@
if (!data) return 0;
if (!data->argv || data->argc == 0) {
data->valid = 0;
- return 0;
+ return 1;
}
if (bu_file_exists(data->argv[0], NULL)){
data->valid = 0;
if (msg) bu_vls_sprintf(msg, "Error - file %s already exists!\n",
data->argv[0]);
}
- return 0;
+ return 1;
}
int
@@ -257,15 +257,15 @@
if (!data) return 0;
if (!data->argv || data->argc == 0) {
data->valid = 0;
- return 0;
+ return 1;
}
type_int = bu_file_mime(data->argv[0], MIME_MODEL);
type = (type_int < 0) ? MIME_MODEL_UNKNOWN : (mime_model_t)type_int;
if (type == MIME_MODEL_UNKNOWN) {
data->valid = 0;
- return 0;
+ return 1;
}
- return 0;
+ return 1;
}
Modified: brlcad/trunk/src/libbu/opt.c
===================================================================
--- brlcad/trunk/src/libbu/opt.c 2015-06-04 21:30:13 UTC (rev 65189)
+++ brlcad/trunk/src/libbu/opt.c 2015-06-04 22:53:20 UTC (rev 65190)
@@ -141,7 +141,7 @@
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)) {
+ if ((name && BU_STR_EQUAL(opt->desc->shortopt, name)) || (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 */
@@ -302,7 +302,6 @@
return NULL;
}
-
HIDDEN char *
opt_process(char **eq_arg, const char *opt_candidate)
{
@@ -425,16 +424,14 @@
}
-/* This implements criteria for deciding when an argv string is
+/* This implements naive 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.
- * 3. Must be an option in ds.
- * 4. Must not be a valid numerical argument to an option expecting a number.
*/
HIDDEN int
-is_opt(const char *opt, struct bu_opt_desc *UNUSED(ds)) {
+can_be_opt(const char *opt) {
size_t i = 0;
if (!opt) return 0;
if (!strlen(opt)) return 0;
@@ -486,13 +483,14 @@
struct bu_opt_data *data = NULL;
struct bu_opt_desc *desc = NULL;
struct bu_ptbl data_args = BU_PTBL_INIT_ZERO;
- /* 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], ds)) {
+ /* If argv[i] isn't an option, stick the argv entry (and any
+ * immediately following non-option entries) into the
+ * unknown args table */
+ if (!can_be_opt(argv[i])) {
ns = bu_strdup(argv[i]);
bu_ptbl_ins(&unknown_args, (long *)ns);
i++;
- while (i < argc && !is_opt(argv[i], ds)) {
+ while (i < argc && !can_be_opt(argv[i])) {
ns = bu_strdup(argv[i]);
bu_ptbl_ins(&unknown_args, (long *)ns);
i++;
@@ -500,6 +498,11 @@
continue;
}
+ /* Now we're past the easy case, and whether something is an
+ * option or an argument depends on context. argv[i] is at least
+ * a possibility for a valid option, so the first order of business
+ * is to determine if it is one. */
+
/* 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 */
@@ -518,21 +521,18 @@
/* 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 (strlen(opt) == 1) {
- bu_vls_sprintf(&rebuilt_opt, "-%s", opt);
- } else {
- bu_vls_sprintf(&rebuilt_opt, "--%s", opt);
- }
- bu_ptbl_ins(&unknown_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(&unknown_args, (long *)eq_arg);
+ /* Since the equals sign is regarded as forcing an argument
+ * to map to a particular option (and is an error if that
+ * option isn't supposed to have arguments) we pass along
+ * the original option intact. */
+ ns = bu_strdup(argv[i]);
+ bu_ptbl_ins(&unknown_args, (long *)ns);
i++;
continue;
}
+ /* We've got a description of the option. Now the real work begins. */
+
/* Initialize with opt */
bu_opt_data_init_entry(&data, opt);
data->desc = desc;
@@ -550,50 +550,62 @@
/* 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],
ds)) {
- ns = bu_strdup(argv[i]);
- 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;
- data->argc = ptbl_to_argv(&(data->argv), &data_args);
- 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--;
+ /* If we might have args and we have a validator function,
+ * construct the greediest possible iterpretation of the option
+ * description and run the validator to determine the number of
+ * argv entries associated with this option (can_be_opt is not
+ * enough if the option is number based, since -9 may be both a
+ * valid option and a valid argument - the validator must make the
+ * decision. If we do not have a validator, the best we can do
+ * is the can_be_opt test as a terminating trigger. */
+ if (desc->arg_process) {
+ /* Construct the greedy interpretation of the bu_opt_data argv
*/
+ int k = 0;
+ int arg_offset = 0;
+ int g_argc = desc->arg_cnt_max;
+ const char **g_argv = (const char **)bu_calloc(g_argc + arg_cnt
+ 1, sizeof(char *), "greedy argv");
+ if (!g_argc && arg_cnt) g_argc = arg_cnt;
+ if (i != argc) {
+ if (arg_cnt)
+ g_argv[0] = eq_arg;
+ for (k = arg_cnt; k < g_argc; k++) {
+ g_argv[k] = argv[i + k];
+ }
+ data->argc = g_argc;
+ data->argv = g_argv;
+ arg_offset = (*desc->arg_process)(NULL, data);
+ i = i + arg_offset - arg_cnt;
+ if (!arg_offset && arg_cnt) arg_offset = arg_cnt;
+ /* If we used 1 or more args, construct the final argv
array that will
+ * be assigned to the bu_opt_data container */
+ if (arg_offset > 0) {
+ data->argc = arg_offset;
+ data->argv = (const char **)bu_calloc(arg_offset + 1,
sizeof(char *), "final array");
+ if (arg_cnt) data->argv[0] = eq_arg;
+ for (k = arg_cnt; k < arg_offset; k++) {
+ data->argv[k] = bu_strdup(g_argv[k - arg_cnt]);
+ }
+ }
+ } else {
+ /* Need args, but have none - invalid */
+ data->valid = 0;
+ data->argc = 0;
+ data->argv = NULL;
}
- bu_ptbl_trunc(&data_args, len + arg_offset);
- bu_opt_free_argv(data->argc, (char **)data->argv);
- data->argv = NULL;
+ bu_free(g_argv, "free greedy argv");
+ } else {
+ while (arg_cnt < desc->arg_cnt_max && i < argc &&
!can_be_opt(argv[i])) {
+ ns = bu_strdup(argv[i]);
+ bu_ptbl_ins(&data_args, (long *)ns);
+ i++;
+ arg_cnt++;
+ }
+ if (arg_cnt < desc->arg_cnt_min) {
+ data->valid = 0;
+ }
+ data->argc = ptbl_to_argv(&(data->argv), &data_args);
}
}
- if (!data->argv) {
- data->argc = ptbl_to_argv(&(data->argv), &data_args);
- }
bu_ptbl_free(&data_args);
bu_ptbl_ins(opt_data, (long *)data);
}
@@ -606,7 +618,6 @@
bu_ptbl_ins(opt_data, (long *)unknown);
}
-
(*tbl) = opt_data;
return 0;
}
Modified: brlcad/trunk/src/libbu/tests/opt.c
===================================================================
--- brlcad/trunk/src/libbu/tests/opt.c 2015-06-04 21:30:13 UTC (rev 65189)
+++ brlcad/trunk/src/libbu/tests/opt.c 2015-06-04 22:53:20 UTC (rev 65190)
@@ -28,11 +28,15 @@
d1_verbosity(struct bu_vls *msg, struct bu_opt_data *data)
{
int verb;
- if (!data || data->argc == 0) return -1;
+ if (!data) return 0;
+ if (!data->argv || data->argc == 0) {
+ data->valid = 0;
+ return 0;
+ }
if (msg) bu_vls_sprintf(msg, "d1");
sscanf(data->argv[0], "%d", &verb);
if (verb < 0 || verb > 3) data->valid = 0;
- return 0;
+ return 1;
}
int
@@ -71,20 +75,25 @@
if (rn != 1 || gn != 1 || bn != 1) {
data->valid = 0;
bu_free(rgb, "free rgb");
+ return 1;
} else {
data->user_data = (void *)rgb;
+ return 3;
}
} else {
+ /* Not valid with 1 and don't have 3 - we require at least one, so
+ * claim one argv as belonging to this option regardless. */
data->valid = 0;
bu_free(rgb, "free rgb");
+ return 1;
}
} else {
- /* yep - if we've got more args, tell the option parser we don't need
them */
+ /* yep, 1 did the job */
data->user_data = (void *)rgb;
- if (data->argc > 1) return 1 - data->argc;
+ return 1;
}
- return 0;
+ return 1;
}
void
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