[brlcad-commits] SF.net SVN: brlcad:[45734] brlcad/trunk/src/libged/edit.c
Open Source Solid Modeling CAD
Brought to you by:
brlcad
From: <bhi...@us...> - 2011-07-30 06:38:07
|
Revision: 45734 http://brlcad.svn.sourceforge.net/brlcad/?rev=45734&view=rev Author: bhinesley Date: 2011-07-30 06:38:00 +0000 (Sat, 30 Jul 2011) Log Message: ----------- Finished the edit_translate_add_cl_args() function (previously *_add_args()), so the logic of unique cmd-line args for that cmd are validated (needed 1 done to proceed with edit()). Added flagging of common options to ged_edt(); now, only cmd-specific options are recorded as chars. Since bug fix in r45733, I was able to start enabling/testing '.' batch operator(WIP). Also, made an alias of '--'. Trimmed long lines/comments. Removed dead code. Modified Paths: -------------- brlcad/trunk/src/libged/edit.c Modified: brlcad/trunk/src/libged/edit.c =================================================================== --- brlcad/trunk/src/libged/edit.c 2011-07-30 00:09:00 UTC (rev 45733) +++ brlcad/trunk/src/libged/edit.c 2011-07-30 06:38:00 UTC (rev 45734) @@ -805,7 +805,7 @@ struct edit_arg *next; /* nodes rel to arg in cmd args grouping */ char cl_options[EDIT_MAX_ARG_OPTIONS]; /* cmd line options */ unsigned int coords_used : 6; /* flag which coords will be used */ - unsigned int type : 8; /* flag the arg type and type modifiers */ + unsigned int type : 7; /* flag the arg type and type modifiers */ struct db_full_path *object; /* 2 dir path_to/obj or just obj */ vect_t *vector; /* abs pos, or offset dist from obj */ }; @@ -832,24 +832,17 @@ */ /* argument types */ -/*FIXME: some of these first few flags can probably go away, as the - * edit_cmd union makes them redundant. The edit_cmd union object in - * ged_edit may require one or two of them, to distinguish between - * target object arguments and reference arguments. This is because - * ged_edit does not use the structs inside edit_cmd, in order to - * remain agnostic of subcommands. */ #define EDIT_FROM 0x01 /* aka keypoint */ -#define EDIT_CENTER 0x02 /* for rotate/scale */ -#define EDIT_TO 0x04 -#define EDIT_TARGET_OBJ 0x08 /* obj to operate on */ +#define EDIT_TO 0x02 +#define EDIT_TARGET_OBJ 0x04 /* obj to operate on */ /* argument "TO" type modifiers */ -#define EDIT_REL_DIST 0x10 -#define EDIT_ABS_POS 0x20 +#define EDIT_REL_DIST 0x08 +#define EDIT_ABS_POS 0x10 /* object argument type modifier flags */ -#define EDIT_NATURAL_ORIGIN 0x40 /* use natural origin of object instead of center */ -#define EDIT_USE_TARGETS 0x80 /* for batch ops */ +#define EDIT_NATURAL_ORIGIN 0x20 /* use n.o. of object */ +#define EDIT_USE_TARGETS 0x40 /* for batch ops */ /* * Arg groupings for each command. @@ -864,9 +857,8 @@ struct { const struct edit_cmd_tab *padding_for_cmd; - /* a synonym for 'objects', used when parsing cl args */ - struct edit_arg *args; - } cmd_line; + struct edit_arg *args; + } cmd_line; /* similar to common; used when parsing cl args */ struct { const struct edit_cmd_tab *padding_for_cmd; @@ -912,10 +904,11 @@ */ typedef void (*init_handler)(union edit_cmd *const cmd); typedef int (*exec_handler)(struct ged *gedp, const union edit_cmd *const cmd); -typedef int (*add_args_handler)(struct ged *gedp, union edit_cmd *const cmd, - struct edit_arg *args, const int flags); +typedef int (*add_cl_args_handler)(struct ged *gedp, union edit_cmd *const cmd, + const int flags); typedef struct edit_arg * (*get_next_arg_head_handler)( const union edit_cmd *const cmd); + struct edit_cmd_tab { char *name; char *opt_global; @@ -923,7 +916,7 @@ char *help; init_handler init; exec_handler exec; - add_args_handler add_args; + add_cl_args_handler add_cl_args; get_next_arg_head_handler get_next_arg_head; }; @@ -946,23 +939,7 @@ node->vector = (vect_t *)NULL; } -#if 0 /* unused */ /** - * Attach a node to the front of the list. - */ -HIDDEN void -edit_arg_prefix(struct edit_arg *dest_node, - struct edit_arg *src) -{ - struct edit_arg *pos = dest_node; - - while (pos->next) - pos = pos->next; - pos->next = src; -} -#endif - -/** * Attach a node to the end of the list. */ HIDDEN void @@ -993,22 +970,7 @@ return node; } -#if 0 /** - * Remove the head node and return its successor. - */ -HIDDEN struct edit_arg * -edit_arg_rm_prefix (struct edit_arg *head) -{ - struct edit_arg *old_head = head; - - head = head->next; - bu_free(old_head, "edit_arg"); - return head; -} -#endif - -/** * Free an argument node and all nodes down its list. */ HIDDEN void @@ -1133,16 +1095,16 @@ cmd->rotate.objects->object); } -/** - * +/* + * Add arguments to the command that were built from the cmd line. + * All arguments should be initialized to NULL before using. */ int -edit_rotate_add_args(struct ged *gedp, union edit_cmd *const cmd, - struct edit_arg *args, const int flags) +edit_rotate_add_cl_args(struct ged *gedp, union edit_cmd *const cmd, + const int flags) { (void)gedp; (void)cmd; - (void)args; (void)flags; return GED_OK; } @@ -1196,6 +1158,9 @@ return GED_OK; } +/** + * Initialize command argument-pointer members to NULL. + */ HIDDEN void edit_scale_init(union edit_cmd *const subcmd) { @@ -1227,13 +1192,16 @@ cmd->scale.objects->object); } +/* + * Add arguments to the command that were built from the cmd line. + * All arguments should be initialized to NULL before using. + */ int -edit_scale_add_args(struct ged *gedp, union edit_cmd *const cmd, - struct edit_arg *args, const int flags) +edit_scale_add_cl_args(struct ged *gedp, union edit_cmd *const cmd, + const int flags) { (void)gedp; (void)cmd; - (void)args; (void)flags; return GED_OK; } @@ -1270,7 +1238,10 @@ return GED_OK; } -HIDDEN void +/** + * Initialize command argument-pointer members to NULL. + */ +void edit_translate_init(union edit_cmd *const subcmd) { subcmd->translate.objects = @@ -1295,35 +1266,90 @@ cmd->translate.objects->object); } +/* + * Add arguments to the command that were built from the cmd line. + * All unique argument pointers in the command should be initialized + * to NULL before using. + * + * This command only accepts the standard options. + */ int -edit_translate_add_args(struct ged *gedp, union edit_cmd *const cmd, - struct edit_arg *args, const int flags) +edit_translate_add_cl_args(struct ged *gedp, union edit_cmd *const cmd, + const int flags) { - (void)gedp; - (void)cmd; - (void)args; - (void)flags; -#if 0 - struct edit_arg *cur_arg = args; - char *opt; - int i; /* iterator */ - - while (cur_arg) { - for (i = 0; i < EDIT_MAX_ARG_OPTIONS; ++i) { - switch (cur_arg->cl_options[i]) { - case 'n': - case 'k': - case 'a': - case 'r': - } + const int noisy = (flags & GED_ERROR); /* side with verbosity */ + struct edit_arg *cur_arg = cmd->cmd_line.args; - } + BU_ASSERT_PTR(cur_arg, !=, NULL); - cur_arg = cur_arg->next; + if (cur_arg->type & EDIT_FROM) { + /* if there isn't an EDIT_TO, this func shouldn't be called */ + BU_ASSERT_PTR(cur_arg->next, !=, NULL); + + /* a 'from' position is set; only flags that were possible + * when this function was last updated should be handled */ + BU_ASSERT(cur_arg->type ^ ~(EDIT_FROM | + EDIT_NATURAL_ORIGIN | + EDIT_USE_TARGETS)); + + /* disallow non-standard opts */ + if (cur_arg->cl_options[0] != '\0') + goto err_option_unknown; + + cmd->translate.ref_vector.from = cur_arg; + cur_arg = cmd->cmd_line.args = cmd->cmd_line.args->next; + cmd->translate.ref_vector.from->next = NULL; } -#endif + if (cur_arg->type & EDIT_TO) { + /* if there isn't an EDIT_TARGET_OBJECT, this func shouldn't + * be called */ + BU_ASSERT_PTR(cur_arg->next, !=, NULL); + + /* a 'to' position is set; only flags that were possible when + * this function was last updated should be handled */ + BU_ASSERT(cur_arg->type ^ ~(EDIT_TO | + EDIT_NATURAL_ORIGIN | + EDIT_REL_DIST | + EDIT_ABS_POS | + EDIT_USE_TARGETS)); + + /* disallow non-standard opts */ + if (cur_arg->cl_options[0] != '\0') + goto err_option_unknown; + + cmd->translate.ref_vector.to = cur_arg; + cur_arg = cmd->cmd_line.args = cmd->cmd_line.args->next; + cmd->translate.ref_vector.to->next = NULL; + } + + /* all that should be left is target objects; validate them */ + do { + if (!(cur_arg->type & EDIT_TARGET_OBJ)) { + if (noisy) + bu_vls_printf(gedp->ged_result_str, "invalid syntax\n" + "Usage: %s [help] | %s", + cmd->cmd->name, cmd->cmd->usage); + return GED_ERROR; + } else { + /* a target obj is set; only flags that were possible when + * this function was last updated should be handled */ + BU_ASSERT(cur_arg->type ^ ~(EDIT_TARGET_OBJ | + EDIT_NATURAL_ORIGIN)); + } + + /* disallow non-standard opts */ + if (cur_arg->cl_options[0] != '\0') + goto err_option_unknown; + } while ((cur_arg = cur_arg->next)); + return GED_OK; + +err_option_unknown: + if (noisy) + bu_vls_printf(gedp->ged_result_str, "unknown option \"-%c\"", + cur_arg->cl_options[0]); + return GED_ERROR; } struct edit_arg * @@ -1358,7 +1384,7 @@ "{ANGLE_TO_OBJECT | ANGLE_TO_POS}} OBJECT ...", &edit_rotate_init, &edit_rotate_wrapper, - &edit_rotate_add_args, + &edit_rotate_add_cl_args, &edit_rotate_get_next_arg_head }, {"scale", (char *)NULL, @@ -1371,7 +1397,7 @@ " OBJECT ...", &edit_scale_init, &edit_scale_wrapper, - &edit_scale_add_args, + &edit_scale_add_cl_args, &edit_scale_get_next_arg_head }, {"translate", (char *)NULL, @@ -1380,7 +1406,7 @@ "[-n] [-a | -r] {TO_OBJECT | TO_POS} OBJECT ...", &edit_translate_init, &edit_translate_wrapper, - &edit_translate_add_args, + &edit_translate_add_cl_args, &edit_translate_get_next_arg_head }, {(char *)NULL, (char *)NULL, (char *)NULL, (char *)NULL, NULL, NULL, NULL, @@ -1414,6 +1440,10 @@ * output to ged_result_str, respectively. * * Returns GED_ERROR on failure, and GED_OK on success. + * + * Note that this function ignores argument type flags, since it is + * expected that all args will be in the proper locations in the + * given command struct. Coordinate flags are respected. */ int edit(struct ged *gedp, union edit_cmd *const subcmd, const int flags) @@ -1421,7 +1451,7 @@ (void)gedp; (void)subcmd; (void)flags; - struct edit_arg *arg_head = subcmd->cmd_line.args;; + struct edit_arg *arg_head = subcmd->common.objects; struct edit_arg *cur_arg = arg_head; /* struct edit_arg *prev_arg = NULL; */ int i; @@ -1433,10 +1463,6 @@ #endif /* - * TODO: write one edit_*_add_args() function, for testing - */ - - /* * TODO: First pass: validate the general structure of *cmd, expand * all batch operators ("."), and do any other processing that is * not specific to a command. @@ -1462,7 +1488,6 @@ */ /* TODO: validate unique subcommand arguments */ - return GED_OK; } @@ -1479,24 +1504,30 @@ edit_str_to_arg(struct ged *gedp, const char *str, struct edit_arg *arg, const int flags) { - int noisy; + const int noisy = (flags & GED_ERROR); /* side with verbosity */ char const *first_slash = NULL; char *endchr = NULL; /* for strtod's */ vect_t coord; - /* if flags conflict (GED_ERROR/GED_QUIET), side with verbosity */ - noisy = (flags & GED_ERROR); - /* - * Here is how numbers that are also objects are intepreted: if an object is - * not yet set in *arg, try to treat the number as an object first. If the - * user has an object named, say '5', they can explicitly use the number 5 - * by adding .0 or something. If an arg->object has already been set, then - * the number was most likely intended to be an offset, so intepret it as as - * such. - * */ + * Here is how numbers that are also objects are intepreted: if + * an object is not yet set in *arg, try to treat the number as + * an object first. If the user has an object named, say '5', + * they can explicitly use the number 5 by adding .0 or + * something. If an arg->object has already been set, then the + * number was most likely intended to be an offset, so intepret + * it as as such. + */ - if (!arg->object) { + if (!arg->object && !(arg->type & EDIT_USE_TARGETS)) { + + /* identical batch operators; objs with the same name are + * masked */ + if (BU_STR_EQUAL(str, ".") || BU_STR_EQUAL(str, "--")) { + arg->type |= EDIT_USE_TARGETS; + return GED_OK; + } + /* an arg with a slash is always interpreted as a path */ first_slash = strchr(str, '/'); if (first_slash) { @@ -1527,21 +1558,23 @@ if (first_slash && ((char *)memchr((void *)(first_slash + 1), '/', (size_t)(path_end - first_slash - 1)))) { - /* FIXME: this conditional should be replaced by adding inner - * slash stripping to db_string_to_path (which is used below), - * and using a simple check for fp_len > 2 here */ + /* FIXME: this conditional should be replaced by adding + * inner slash stripping to db_string_to_path (which is + * used below), and using a simple check for fp_len > 2 + * here */ if (noisy) bu_vls_printf(gedp->ged_result_str, "invalid path, \"%s\"\n" "It is only meaningful to have one or two " "objects in a path in this context.\n" "Ex: OBJECT (equivalently, /OBJECT/) or " - "PATH/OBJECT (equivalently, /PATH/OBJECT/)", str); + "PATH/OBJECT (equivalently, /PATH/OBJECT/)", + str); return GED_ERROR; } goto convert_obj; } - /* it may still be an obj, so quietly check db for object name */ + /* it may still be an obj, so quietly check db for obj name */ if (db_lookup(gedp->ged_wdbp->dbip, str, LOOKUP_QUIET) != RT_DIR_NULL) goto convert_obj; } @@ -1582,7 +1615,7 @@ return GED_ERROR; } } else { - /* only set the specified coord; quietly overwrite if already set */ + /* only set specified coord; quietly overwrite if set */ BU_ASSERT(arg->coords_used != 0); if (arg->coords_used & EDIT_COORD_X) { (*arg->vector)[0] = coord[0]; @@ -1698,7 +1731,7 @@ /* initialize the subcommand */ subcmd.cmd = (const struct edit_cmd_tab *)NULL; - cur_arg = subcmd.cmd_line.args = (struct edit_arg *)bu_malloc( + cur_arg = subcmd.common.objects = (struct edit_arg *)bu_malloc( sizeof(struct edit_arg), "edit_arg block for ged_edit()"); edit_arg_init(cur_arg); @@ -1881,8 +1914,6 @@ return GED_ERROR; } - /* FIXME: crashes/mishandles '-' and '--', and '/'. Just needs to - * fail gracefully. */ bu_optind = 1; /* re-init bu_getopt() */ bu_opterr = 0; /* suppress errors; accept unknown options */ ++argc; /* bu_getopt doesn't expect first element to be an arg */ @@ -1898,6 +1929,9 @@ conv_flags = GED_ERROR; switch (c) { + case 'n': /* use natural coordinates of object */ + conv_flags = GED_QUIET; + break; case 'x': /* singular coord specif. sub-opts */ case 'y': case 'z': @@ -1944,14 +1978,42 @@ /* next element may be an arg */ /* FIXME: bu_optarg should be a ptr to const! */ conv_flags = GED_QUIET; + + /* record opt for validation/processing by subcmd */ + cur_arg->cl_options[idx_cur_opt] = c; + ++idx_cur_opt; break; case ':': goto err_missing_arg; } - /* record option */ - cur_arg->cl_options[idx_cur_opt] = c; - ++idx_cur_opt; + /* set flags for standard options. it's more readible to just + * switch on *c again than the alternative: to add several + * checks and/or goto's */ + switch (c) { + case 'x': + cur_arg->coords_used |= EDIT_COORD_X; + break; + case 'y': + cur_arg->coords_used |= EDIT_COORD_Y; + break; + case 'z': + cur_arg->coords_used |= EDIT_COORD_Z; + break; + case 'k': + cur_arg->type |= EDIT_FROM; + break; + case 'a': + cur_arg->type |= EDIT_TO | EDIT_ABS_POS; + break; + case 'r': + cur_arg->type |= EDIT_TO | EDIT_REL_DIST; + break; + case 'n': + cur_arg->type |= EDIT_NATURAL_ORIGIN; + default: + break; + } /* move to current arg */ argc -= 2; @@ -1992,11 +2054,10 @@ } } - /* remove command line arguments, and let command specific - * funtions reattach them in the proper locations */ - cur_arg = subcmd.cmd_line.args; - subcmd.cmd_line.args = (struct edit_arg *)NULL; - if (subcmd.cmd->add_args(gedp, &subcmd, cur_arg, GED_ERROR) == GED_ERROR) + /* let the cmd specific func validate/move args to the proper + * locations */ + if (subcmd.cmd->add_cl_args(gedp, &subcmd, GED_ERROR) == + GED_ERROR) return GED_ERROR; /* send the command off for further processing and execution */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |