Revision: 45550
          http://brlcad.svn.sourceforge.net/brlcad/?rev=45550&view=rev
Author:   bhinesley
Date:     2011-07-20 03:07:39 +0000 (Wed, 20 Jul 2011)

Log Message:
-----------
Cut down on a lot of duplication. Fixed a few issues with subcmd arg helper 
functions (and most are enabled/used now). ged_edit() generic subcommand 
argument parsing is nearly done. Still a WIP. Some option combinations are 
accepted that shouldn't be. It is crashing right now, too. That is to be 
expected, as it needs edit_str_to_arg() to work properly, and that is 
incomplete/needs some modifications.

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

Modified: brlcad/trunk/src/libged/edit.c
===================================================================
--- brlcad/trunk/src/libged/edit.c      2011-07-20 00:56:35 UTC (rev 45549)
+++ brlcad/trunk/src/libged/edit.c      2011-07-20 03:07:39 UTC (rev 45550)
@@ -296,7 +296,7 @@
  *     represents either position, distance, degrees, or radians,
  *     depending on the context and supplied arguments.
  *
- *     AXIS_FROM_POS is always treated as an absolute position.
+ *     AXIS_FROM_POS is always interpreted as an absolute position.
  *     AXIS_TO_POS may be either an absolute position (-a), or a
  *     relative distance (-r) from AXIS_FROM. OFFSET_DIST is always a
  *     relative distance. A special case is made for ANGLE_TO_POS,
@@ -305,7 +305,7 @@
  *     ANGLE_FROM_POS (-r) or an absolute position (-a). See
  *     documentation of the -R option to see how it can be used to
  *     allow specification of radians. All *_TO_OBJECT arguments are
- *     always treated as absolute positions (-a).
+ *     always interpreted as absolute positions (-a).
  *
  *     By default, AXIS is interpreted as the axis to rotate upon
  *     (but does not specify where), with the rotation angle
@@ -664,7 +664,7 @@
  *                                                         
  */
 
-/* This function will be removed soon */
+/* This function is obsolete and will be removed soon */
 #if 0
 int
 translate(struct ged *gedp, vect_t *keypoint,
@@ -949,7 +949,6 @@
     } scale;
 };
 
-#if 0 /* unused */
 /**
  * Initialize a node.
  */
@@ -957,13 +956,14 @@
 edit_arg_init(struct edit_arg *node)
 {
     node->next = (struct edit_arg *)NULL;
-    node->cl_options[0] = '\0';
-    node->coords_used = 0;
+    (void)memset((void *)&node->cl_options[0], 0, EDIT_MAX_ARG_OPTIONS);
+    node->coords_used = EDIT_ALL_COORDS;
     node->type = 0;
     node->object = (struct db_full_path *)NULL;
     node->vector = (vect_t *)NULL;
 }
 
+#if 0 /* unused */
 /**
  * Attach a node to the front of the list.
  */
@@ -977,6 +977,7 @@
        pos = pos->next;
     pos->next = src;
 }
+#endif
 
 /**
  * Attach a node to the end of the list.
@@ -1000,14 +1001,16 @@
 HIDDEN struct edit_arg *
 edit_arg_postfix_new(struct edit_arg *head)
 {
-    edit_arg_postfix(head, (struct edit_arg *)bu_malloc(
-                          sizeof(struct edit_arg), "edit_arg block"
-                          "for edit_arg_postfix()"));
+    struct edit_arg *node;
 
-    edit_arg_init(head->next);
-    return head->next;
+    node = (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;
 }
 
+#if 0
 /**
  * Remove the head node and return its successor.
  */
@@ -1030,13 +1033,16 @@
 {
     if (arg->next)
        edit_arg_free_all(arg->next);
+    if (arg->object)
+       db_free_full_path(arg->object);
+    if (arg->vector)
+       bu_free(arg->vector, "vect_t");
     bu_free(arg, "edit_arg");
 }
 
 /**
  * Free any dynamically allocated arg that may exist
  */
-#if 0 /* unused */
 HIDDEN void
 edit_cmd_free(union edit_cmd *args)
 {
@@ -1044,7 +1050,6 @@
     if (args->common.objects.next)
        edit_arg_free_all(args->common.objects.next);
 }
-#endif
 
 #if 0
 int
@@ -1074,19 +1079,17 @@
 /**
  * A wrapper for the edit commands. It adds the capability to perform
  * batch operations, and accepts objects and distances in addition to
- * coordinates.
+ * coordinates. Normally, gedp should be set to NULL; it is only used
+ * when arguments are built via command line (see ged_edit).
  */
-#if 0
 int
-edit(struct ged *gedp, struct edit_arg *args_head, const char *global_opts)
+edit(struct ged *gedp, union edit_cmd * const cmd)
 {
     (void)gedp;
-    (void)args_head;
-    (void)global_opts;
+    (void)cmd;
 
     return GED_OK;
 }
-#endif
 
 /**
  * Convert a string to an edit_arg. The arg is NULL if the string
@@ -1098,9 +1101,9 @@
  */
 HIDDEN int
 edit_str_to_arg(struct ged *gedp, const char *str, struct edit_arg *arg) {
-    /* XXX if there is a slash, treat it as an object for sure. If
+    /* XXX if there is a slash, interpret it as an object for sure. If
      * there isn't a slash, then try to look it up in the db.  If that
-     * fails too, then try to treat it as a number.  If it isn't a
+     * fails too, then try to interpret it as a number.  If it isn't a
      * number either, then the argument is invalid. */
 
     char const *path_start;
@@ -1163,11 +1166,11 @@
        if (argd == RT_DIR_NULL)
            NULL;
            /* not an object */
-           /* XXX if it is a number, fall back to treating it
+           /* XXX if it is a number, fall back to intepreting it
             * as one, otherwise, throw an error saying that
             * it is an invalid object */
        else
-           /* treat it as an object */
+           /* interpret it as an object */
            NULL;
 #endif
        return GED_OK;
@@ -1184,8 +1187,9 @@
     const char * const cmd_name = argv[0];
     const char *subcmd_name = NULL;
     union edit_cmd subcmd;
-    struct edit_arg cur_arg = subcmd.cmd_line.args;
-    int cur_opt = 0; /* pos in options array for current arg */
+    struct edit_arg *cur_arg = &subcmd.cmd_line.args;
+    int idx_cur_opt = 0; /* pos in options array for current arg */
+    int last_arg_opt = 0; /* the last processed option that takes an arg */
     static const char * const usage = "[subcommand] [args]";
     int i; /* iterator */
     int c; /* for bu_getopt */
@@ -1218,7 +1222,7 @@
             * name */
            break; 
        }
-       /* treat first arg as a cmd, and search for it in table */
+       /* interpret first arg as a cmd, and search for it in table */
        if (!subcmd_name && argc > 1 &&
            BU_STR_EQUAL(edit_cmds[i].name, argv[1])) {
            subcmd_name = argv[1];
@@ -1301,7 +1305,7 @@
            }
 
            /* Handle "subcmd help" (identical to "help subcmd"),
-            * but only if there are no more args. Wouldn't want to
+            * but only if there are no more args; wouldn't want to
             * match an object named "help". This syntax is needed 
             * to access the help system when subcmd is an actual
             * command */
@@ -1317,7 +1321,7 @@
     }
 
     /*
-     * Create a linked list of all arguments to the subcommand.
+     * Parse all subcmd args and pass to edit()
      */
 
     /*
@@ -1341,7 +1345,8 @@
      *           (a, above), and parsed elsewhere
      *     2) keypoints ('FROM' arg options) are always preceded by
      *        '-k'
-     *     3) keypoints are all considered optional at this point
+     *     3) keypoints are all considered optional as far as this
+     *        function is concerned
      *     4) if a keypoint is specified, the argument is the first in
      *        a pair; therefore a matching 'TO' argument is required
      *     5) any object specification string may:
@@ -1356,112 +1361,116 @@
      *        writing)
      *     7) at least one object must be operated on
      *     8) the last argument is a list of objects to be operated on
-     *       
      */
 
-    goto disabled;
+    /* no options are required if none of the optional arguments are
+     * specified */
+    if (edit_str_to_arg(gedp, argv[0], cur_arg) == GED_OK) {
+       if (argc == 1)
+           return edit(gedp, &subcmd);
+       --argc;
+       ++argv;
+       cur_arg = edit_arg_postfix_new(&subcmd.cmd_line.args);
+    }
 
     bu_optind = 1; /* re-init bu_getopt() */
     bu_opterr = 0; /* suppress errors; accept unknown options */
+    --argv; /* bu_getopt doesn't expect the first element to be an arg */
+    ++argc;
     while ((c = bu_getopt(argc, (char * const *)argv, ":k:a:r:x:y:z:")) != -1) 
{
+       if (bu_optind + 1 >= argc)
+           /* last element is an option */
+           goto err_no_operand;
+
        switch (c) {
-           case 'k': /* keypoint; FROM* argument */
-           case 'a': /* relative TO* distance argument */
-           case 'r': /* absolute TO* position argument */
-               /* get coordinates or object */
-               cur_arg.cl_options[cur_opt] = bu_optopt;
-               cur_opt = 0;
-               break;
-           case 'x': /* individual coordinate argument */
+           case 'k': /* standard arg specification options */
+           case 'a':
+           case 'r':
+               if (last_arg_opt == c)
+                   goto err_redundant_options;
+               last_arg_opt = c;
+           case 'x': /* singular coordinate specification options */
            case 'y':
            case 'z':
-               /* get coordinate or object, and optionally an
-                * offset */
-               /* XXX */
-               bu_vls_printf(gedp->ged_result_str,
-                             "Specification of individual coordinates is not"
-                             " yet supported");
-               return GED_ERROR;
-               break;
+               break; /* nothing needed */
            case '?': /* nonstandard or unknown option */
-               /*
-                * if a non-option is next, the current option is an
-                * argument specifier
-                */
-
-               if (bu_optind + 1 >= argc)
-                   goto err_no_operand;
-
-               if (cur_opt >= EDIT_MAX_ARG_OPTIONS)
-                   goto err_option_overload;
-
                if (!isprint(bu_optopt)) {
                    bu_vls_printf(gedp->ged_result_str,
                                  "Unknown option character '\\x%x'",
                                  bu_optopt);
+                   edit_cmd_free(&subcmd);
                    return GED_ERROR;
                }
 
-               /* check next argv element to help intepret cur opt */
-               if (argv[bu_optind + 1][0] == '-' && 
-                   isalpha(argv[bu_optind + 1][1]))
-                   /* an opt is next; cur opt doesn't take an arg */
-                   cur_arg.cl_options[cur_opt++] = bu_optopt;
-               else {
-                   /* an arg is next; try to convert to cur_arg */
-                   if (edit_str_to_arg(gedp, argv[bu_optind + 1],
-                       &cur_arg) == GED_ERROR)
-                       return GED_ERROR;
-                   continue;
-               }
-               break;
+               if (last_arg_opt == c)
+                   goto err_redundant_options;
+               last_arg_opt = bu_optopt;
            case ':': /* missing arg */
                bu_vls_printf(gedp->ged_result_str,
                              "Missing argument for option -%c", bu_optopt);
+               edit_cmd_free(&subcmd);
                return GED_ERROR;
            default: /* quiet compiler */
                break;
        }
+
+       /* record option */
+       if ((idx_cur_opt + 1) >= EDIT_MAX_ARG_OPTIONS)
+           goto err_option_overflow;
+       cur_arg->cl_options[idx_cur_opt] = bu_optopt;
+       ++idx_cur_opt;
+
+       /* try to read in an argument */
+       if (bu_optind + 1 <= argc) {
+           if (edit_str_to_arg(gedp, argv[bu_optind + 1], cur_arg) == GED_OK) {
+               /* init for next arg */
+               cur_arg = edit_arg_postfix_new(&subcmd.cmd_line.args);
+           }
+       }
+
        continue;
 
-err_no_operand:
-       {
+    }
+
+    /* remaining arguments are interpreted as operands */
+    for (i = bu_optind; (i + 1) <= argc; ++i) {
+       if (edit_str_to_arg(gedp, argv[i], cur_arg) == GED_OK) {
+
+           /* init for next arg */
+           cur_arg = edit_arg_postfix_new(&subcmd.cmd_line.args);
+           idx_cur_opt = 0;
+       } else {
            bu_vls_printf(gedp->ged_result_str,
-                         "No OBJECT provided; nothing to operate on");
+                         "Unrecognized argument, \"%s\"",
+                         argv[i]);
            return GED_ERROR;
        }
-
-err_option_overload:
-       {
-           bu_vls_printf(gedp->ged_result_str, "too many options: ");
-           for (i = 0; i < EDIT_MAX_ARG_OPTIONS; ++i)
-               bu_vls_printf(gedp->ged_result_str, "-%c/",
-                             cur_arg.cl_options[i]);
-           bu_vls_printf(gedp->ged_result_str, "-%c", c);
-           return GED_ERROR;
-       }
     }
 
-    /*
-     * testing
-     */
+    edit_cmd_free(&subcmd);
+    return GED_OK;
 
-#if 0
-    edit_arg_postfix_new(&subcmd.common.objects);
-    edit_arg_postfix_new(&subcmd.common.objects);
+err_no_operand:
+    bu_vls_printf(gedp->ged_result_str,
+                 "No OBJECT provided; nothing to operate on");
     edit_cmd_free(&subcmd);
-#endif
+    return GED_ERROR;
 
-#if 0
-    struct db_i *dbip = gedp->ged_wdbp->dbip;
+err_option_overflow:
+    bu_vls_printf(gedp->ged_result_str, "too many options: ");
+    for (i = 0; i < EDIT_MAX_ARG_OPTIONS; ++i)
+       bu_vls_printf(gedp->ged_result_str, "-%c/", cur_arg->cl_options[i]);
+    bu_vls_printf(gedp->ged_result_str, "-%c", c);
+    edit_cmd_free(&subcmd);
+    return GED_ERROR;
 
-    static const char *id_obj_as_arg = ". ";
-    static const char *id_tuple[] = {"-x", "-y", "-z"};
+err_redundant_options:
+    bu_vls_printf(gedp->ged_result_str, "redundant -%c options", c);
+    edit_cmd_free(&subcmd);
+    return GED_ERROR;
+}
 
-    const char *const cmd_name = argv[0];
-    static const char *usage = "{translate | rotate | scale} ARGS OBJECT ...";
-#endif
-
+/* obsolete code; here temporarily for reference */
 #if 0
 
     int from_center_flag = 0;
@@ -1668,10 +1677,6 @@
     db_free_full_path(&path);
     db_free_full_path(&obj);
 #endif
-disabled:
-    bu_vls_printf(gedp->ged_result_str, "command not yet implemented");
-    return GED_ERROR;
-}
 
 
 /*


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

------------------------------------------------------------------------------
10 Tips for Better Web Security
Learn 10 ways to better secure your business today. Topics covered include:
Web security, SSL, hacker attacks & Denial of Service (DoS), private keys,
security Microsoft Exchange, secure Instant Messaging, and much more.
http://www.accelacomm.com/jaw/sfnl/114/51426210/
_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits

Reply via email to