Revision: 45753
          http://brlcad.svn.sourceforge.net/brlcad/?rev=45753&view=rev
Author:   bhinesley
Date:     2011-08-02 04:37:18 +0000 (Tue, 02 Aug 2011)

Log Message:
-----------
edit() will now "expand" batch operation args, by performing a deep copy of 
every target obj's edit_arg struct, consolidating option flags between the two 
as necessary. Added detection of keypoints missing their matching 'TO' arg, 
since every cmd should have that behavior. Replaced edit_arg_free_if_empty() 
with edit_arg_is_empty; a bit more versatile that way.

Modified Paths:
--------------
    brlcad/trunk/src/libged/edit.c

Modified: brlcad/trunk/src/libged/edit.c
===================================================================
--- brlcad/trunk/src/libged/edit.c      2011-08-02 01:51:11 UTC (rev 45752)
+++ brlcad/trunk/src/libged/edit.c      2011-08-02 04:37:18 UTC (rev 45753)
@@ -806,7 +806,7 @@
     char cl_options[EDIT_MAX_ARG_OPTIONS]; /* cmd line options */
     unsigned int coords_used : 6; /* flag which coords will be used */
     unsigned int type : 7; /* flag the arg type and type modifiers */
-    struct db_full_path *object; /* 2 dir path_to/obj or just obj */
+    struct db_full_path *object; /* 2 dir path_to/obj, or just obj */
     vect_t *vector; /* abs pos, or offset dist from obj */
 };
 
@@ -845,7 +845,13 @@
 #define EDIT_USE_TARGETS               0x40 /* for batch ops */
 
 /*
- * Arg groupings for each command. 
+ * when performing batch operations, these flags are not discarded
+ * from the target object*/
+#define EDIT_TARGET_OBJ_BATCH_TYPES (EDIT_NATURAL_ORIGIN)
+
+
+/*
+ * Arg groupings for each command.
  */
 union edit_cmd{
     const struct edit_cmd_tab *cmd;
@@ -962,16 +968,32 @@
 HIDDEN struct edit_arg *
 edit_arg_postfix_new(struct edit_arg *head)
 {
-    struct edit_arg *node;
+    struct edit_arg *arg;
 
-    node = (struct edit_arg *)bu_malloc(sizeof(struct edit_arg),
+    arg = (struct edit_arg *)bu_malloc(sizeof(struct edit_arg),
           "edit_arg block for edit_arg_postfix_new()");
-    edit_arg_postfix(head, node);
-    edit_arg_init(node);
-    return node;
+    edit_arg_postfix(head, arg);
+    edit_arg_init(arg);
+    return arg;
 }
 
 /**
+ * Returns GED_OK if arg is empty, otherwise GED_ERROR is returned
+ */
+HIDDEN int
+edit_arg_is_empty(struct edit_arg *arg)
+{
+    if (!arg->next &&
+       (arg->cl_options[0] == '\0') &&
+       (arg->coords_used & EDIT_COORDS_ALL) &&
+       (!arg->type) && 
+       (!arg->object) &&
+       (!arg->vector))
+       return GED_OK;
+    return GED_ERROR;
+}
+
+/**
  * Free an argument node.
  */
 HIDDEN void
@@ -987,21 +1009,6 @@
 }
 
 /**
- * Free an unused argument node.
- */
-HIDDEN void
-edit_arg_free_if_empty(struct edit_arg *arg)
-{
-    if (!arg->next &&
-       (arg->cl_options[0] == '\0') &&
-       (arg->coords_used & EDIT_COORDS_ALL) &&
-       (!arg->type) && 
-       (!arg->object) &&
-       (!arg->vector))
-    edit_arg_free(arg);
-}
-
-/**
  * Free the last argument node in the list.
  */
 HIDDEN void
@@ -1163,7 +1170,7 @@
 edit_rotate_get_next_arg_head(const union edit_cmd *const cmd)
 {
 #define EDIT_ROTATE_ARG_HEADS_LEN 7
-    static int idx = 0;
+    static int idx = -1;
     struct edit_arg *arg_heads[EDIT_ROTATE_ARG_HEADS_LEN];
 
     arg_heads[0] = cmd->rotate.objects;
@@ -1248,7 +1255,7 @@
 edit_scale_get_next_arg_head(const union edit_cmd *const cmd)
 {
 #define EDIT_SCALE_ARG_HEADS_LEN 6
-    static int idx = 0;
+    static int idx = -1;
     struct edit_arg *arg_heads[EDIT_SCALE_ARG_HEADS_LEN];
 
 
@@ -1310,7 +1317,7 @@
  * All unique argument pointers in the command should be initialized
  * to NULL before using.
  *
- * This command only accepts the standard options.
+ * This command happens to only accept the standard options.
  */
 int
 edit_translate_add_cl_args(struct ged *gedp, union edit_cmd *const cmd,
@@ -1372,16 +1379,15 @@
 
        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;
+       cmd->translate.ref_vector.to->next= NULL;
     } else {
-       if (cur_arg->type & EDIT_FROM) {
-           if (noisy)
+       if (noisy) {
+           if (cur_arg->type & EDIT_FROM)
                bu_vls_printf(gedp->ged_result_str,
                              "too many \"FROM\" arguments");
-           return GED_ERROR;
+           else
+               bu_vls_printf(gedp->ged_result_str, "missing \"TO\" argument");
        }
-       if (noisy)
-           bu_vls_printf(gedp->ged_result_str, "missing \"TO\" argument");
        return GED_ERROR;
     }
 
@@ -1419,7 +1425,7 @@
 {
 #define EDIT_TRANSLATE_ARG_HEADS_LEN 3
     struct edit_arg *arg_heads[EDIT_TRANSLATE_ARG_HEADS_LEN];
-    static int idx = 0;
+    static int idx = -1;
 
     arg_heads[0] = cmd->translate.objects;
     arg_heads[1] = cmd->translate.ref_vector.from;
@@ -1496,61 +1502,107 @@
 /**
  * A wrapper for the edit commands. It adds the capability to perform
  * batch operations, and accepts objects and distances in addition to
- * coordinates.
+ * coordinates. As a side effect, arguments flagged with
+ * EDIT_USE_TARGETS will be replaced (expanded) in performing batch
+ * commands.
  *
  * Set GED_QUIET or GED_ERROR bits in 'flags' to suppress or enable
  * 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.
+ * Note that this function ignores most argument type flags, since
+ * it's expected that all args will be in the proper locations in
+ * the given command struct. An exception is made for
+ * EDIT_TARGET_OBJ_BATCH_TYPES, which is respected since certain
+ * flags may propogate in batch operations. Coordinate flags are
+ * always respected.
  */
 int
 edit(struct ged *gedp, union edit_cmd *const subcmd, const int flags)
 {
-    struct edit_arg *arg_head = subcmd->common.objects;
-    struct edit_arg *cur_arg = arg_head;
-    /* struct edit_arg *prev_arg = NULL; */
-    int i;
-    (void)gedp;
-    (void)subcmd;
-    (void)flags;
+    struct edit_arg *arg_head;
+    struct edit_arg *cur_arg;
+    struct edit_arg *dest_arg;
+    int noisy = (flags & GED_ERROR); /* side with verbosity */
+
+    arg_head = subcmd->cmd->get_next_arg_head(subcmd);
+    /* TODO: do all processing of subcmd->common.objects first, so
+     * that they are not done again once the batch arguments are
+     * expanded (targets copied) */
 #if 0
-    int noisy;
+    /* no target objects should have vectors only */
+    BU_ASSERT(cur_arg->object || !dest_arg->vector);
 
-    /* if flags conflict (GED_ERROR/GED_QUIET), side with verbosity */
-    noisy = (flags & GED_ERROR); 
+    /* cmd line opts should have been handled/removed */
+    BU_ASSERT(cur_arg->cl_options[0] == '\0');
 #endif
 
-    /*
-     * 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. 
-     */
+    /* done with objects */
+    arg_head = subcmd->cmd->get_next_arg_head(subcmd);
+
     do {
-       for (cur_arg = arg_head; cur_arg; cur_arg = cur_arg->next) {
-           /* turn character options into flags */
-           /* XXX testing */
-           bu_vls_printf(gedp->ged_result_str, "(testing) options:");
-           for (i = 0; i < EDIT_MAX_ARG_OPTIONS; ++i) {
-               bu_vls_printf(gedp->ged_result_str, "%c",
-                             cur_arg->cl_options[i]);
+       if (arg_head->type & EDIT_USE_TARGETS) {
+           dest_arg = arg_head;
+
+           /* expand batch operator */
+           for (cur_arg = subcmd->common.objects; cur_arg;
+                cur_arg = cur_arg->next) {
+
+               /* copy target object to batch argument; freed when cmd is */
+               dest_arg->next = (struct edit_arg *)bu_malloc(
+                                 sizeof(struct edit_arg),
+                                 "edit_arg block for edit()");
+               dest_arg = dest_arg->next;
+               edit_arg_init(dest_arg);
+
+               dest_arg->next = NULL;
+               dest_arg->cl_options[0] = '\0';
+
+               /* never use coords that target obj didn't include */
+               dest_arg->coords_used &= arg_head->coords_used;
+               if (!dest_arg->coords_used) {
+                   if (noisy)
+                       bu_vls_printf(gedp->ged_result_str,
+                                     "coordinate filters for batch"
+                                     " operator and target objects result in"
+                                     " no coordinates being used");
+                   return GED_ERROR;
+               }
+
+               /* respect certain flags from the target object */
+               dest_arg->type |= (arg_head->type &
+                                  EDIT_TARGET_OBJ_BATCH_TYPES);
+
+               if (cur_arg->object) {
+                   dest_arg->object = (struct db_full_path *)bu_malloc(
+                                      sizeof(struct db_full_path),
+                                      "db_full_path block for edit()");
+                   db_full_path_init(dest_arg->object);
+                   db_dup_full_path(dest_arg->object, cur_arg->object);
+               }
+               if (cur_arg->vector) {
+                   cur_arg->vector = (vect_t *)bu_malloc(
+                                     sizeof(vect_t),
+                                     "vect_t block for edit()");
+                   *dest_arg->vector[0] = *cur_arg->vector[0];
+                   *dest_arg->vector[1] = *cur_arg->vector[1];
+                   *dest_arg->vector[2] = *cur_arg->vector[2];
+               }
            }
-           return GED_ERROR;
+           arg_head = subcmd->cmd->get_next_arg_head(subcmd);
+           continue;
        }
+
+       for (cur_arg = arg_head; cur_arg; cur_arg = cur_arg->next) {
+           /* cmd line opts should have been handled/removed */
+           BU_ASSERT(cur_arg->cl_options[0] == '\0');
+
+           /* TODO: convert objects + offsets to coords */
+       }
        arg_head = subcmd->cmd->get_next_arg_head(subcmd);
     } while (arg_head != subcmd->common.objects);
 
-    /* 
-     * TODO: Second pass: command specific processing. Simultaneously
-     * validate that the syntax is valid for the requested command,
-     * translate object/modifiers to coordinates, and copy arguments
-     * into the appropriate *cmd elements. 
-     */
- 
-    /* TODO: validate unique subcommand arguments */
     return GED_OK;
 }
 
@@ -1696,7 +1748,7 @@
 convert_obj:
     /* convert string to path/object */
     arg->object = (struct db_full_path *)bu_malloc(sizeof(struct db_full_path),
-                 "db_full_path block for ged_edit()");
+                 "db_full_path block for edit_str_to_arg()");
     if (db_string_to_path(arg->object, gedp->ged_wdbp->dbip,
                           str)) {
        db_free_full_path(arg->object);
@@ -1777,6 +1829,7 @@
     const char *const cmd_name = argv[0];
     const char *subcmd_name = NULL;
     struct edit_arg *cur_arg;
+    struct edit_arg *keypoint;
     union edit_cmd subcmd;
     int idx_cur_opt = 0; /* pos in options array for current arg */
     int conv_flags = 0; /* for edit_strs_to_arg */
@@ -1962,8 +2015,8 @@
     /* no options are required by default*/
     while (edit_strs_to_arg(gedp, &argc, &argv, cur_arg, GED_QUIET) != 
GED_ERROR) {
        if (argc == 0) {
-           /* free unused arg block */
-           edit_arg_free_if_empty(subcmd.cmd_line.args);
+           if (edit_arg_is_empty(subcmd.cmd_line.args))
+               edit_arg_free(subcmd.cmd_line.args);
 
            cur_arg = subcmd.cmd_line.args;
            if (cur_arg->next) {
@@ -2082,7 +2135,7 @@
        }
 
        /* set flags for standard options. it's more readible to just
-        * switch on *c again than the alternative: to add several
+        * switch on c again than the alternative: to add several
         * checks and/or goto's */
        switch (c) {
            case 'x':
@@ -2096,12 +2149,15 @@
                break;
            case 'k':
                cur_arg->type |= EDIT_FROM;
+               keypoint = cur_arg;
                break;
            case 'a':
                cur_arg->type |= EDIT_TO | EDIT_ABS_POS;
+               keypoint = NULL;
                break;
            case 'r':
                cur_arg->type |= EDIT_TO | EDIT_REL_DIST;
+               keypoint = NULL;
                break;
            case 'n':
                cur_arg->type |= EDIT_NATURAL_ORIGIN;
@@ -2138,6 +2194,13 @@
        --argv;
     }
 
+    if (keypoint) {
+       bu_vls_printf(gedp->ged_result_str,
+                     "a keypoint is missing its matching 'TO' argument");
+       edit_cmd_free(&subcmd);
+       return GED_ERROR;
+    }
+
     /* get final/trailing args */
     ++argv;
     --argc;


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

------------------------------------------------------------------------------
BlackBerry&reg; DevCon Americas, Oct. 18-20, San Francisco, CA
The must-attend event for mobile developers. Connect with experts. 
Get tools for creating Super Apps. See the latest technologies.
Sessions, hands-on labs, demos & much more. Register early & save!
http://p.sf.net/sfu/rim-blackberry-1
_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits

Reply via email to