Author: pjd
Date: Sat Oct 23 21:56:50 2010
New Revision: 214252
URL: http://svn.freebsd.org/changeset/base/214252

Log:
  Implement G_TYPE_MULTI and G_VAL_OPTIONAL for stable/8.
  
  This should have been MFC, but I've no green light from marcel to remove
  G_TYPE_ASCNUM and gc_argname and to modify geom_part in stable/8, so this is
  reimplementation that doesn't touch gpart and hopefully doesn't break 
anything.

Modified:
  stable/8/sbin/geom/core/geom.c
  stable/8/sbin/geom/core/geom.h

Modified: stable/8/sbin/geom/core/geom.c
==============================================================================
--- stable/8/sbin/geom/core/geom.c      Sat Oct 23 21:25:50 2010        
(r214251)
+++ stable/8/sbin/geom/core/geom.c      Sat Oct 23 21:56:50 2010        
(r214252)
@@ -224,33 +224,61 @@ find_option(struct g_command *cmd, char 
  * Add given option to gctl_req.
  */
 static void
-set_option(struct gctl_req *req, struct g_option *opt, const char *val)
+set_option(struct g_command *cmd, struct gctl_req *req, struct g_option *opt,
+    const char *val)
 {
-       char *s;
-       intmax_t number;
+       const char *optname;
+       uint64_t number;
+       void *ptr;
 
-       if (G_OPT_TYPE(opt) == G_TYPE_NUMBER ||
-           G_OPT_TYPE(opt) == G_TYPE_ASCNUM) {
+       if (G_OPT_ISMULTI(opt)) {
+               size_t optnamesize;
+
+               if (G_OPT_NUM(opt) == UCHAR_MAX)
+                       errx(EXIT_FAILURE, "Too many -%c options.", 
opt->go_char);
+
+               /*
+                * Base option name length plus 3 bytes for option number
+                * (max. 255 options) plus 1 byte for terminating '\0'.
+                */
+               optnamesize = strlen(opt->go_name) + 3 + 1;
+               ptr = malloc(optnamesize);
+               if (ptr == NULL)
+                       errx(EXIT_FAILURE, "No memory.");
+               snprintf(ptr, optnamesize, "%s%u", opt->go_name, 
G_OPT_NUM(opt));
+               G_OPT_NUMINC(opt);
+               optname = ptr;
+       } else {
+               optname = opt->go_name;
+       }
+
+       if (G_OPT_TYPE(opt) == G_TYPE_NUMBER) {
                if (expand_number(val, &number) == -1) {
-                       err(EXIT_FAILURE, "Invalid value for '%c' argument.",
+                       err(EXIT_FAILURE, "Invalid value for '%c' argument",
                            opt->go_char);
                }
-               if (G_OPT_TYPE(opt) == G_TYPE_NUMBER)
-                       opt->go_val = malloc(sizeof(intmax_t));
-               else {
-                       asprintf(&s, "%jd", number);
-                       opt->go_val = s;
-               }
+               opt->go_val = malloc(sizeof(intmax_t));
                if (opt->go_val == NULL)
                        errx(EXIT_FAILURE, "No memory.");
-               if (G_OPT_TYPE(opt) == G_TYPE_NUMBER) {
-                       *(intmax_t *)opt->go_val = number;
-                       gctl_ro_param(req, opt->go_name, sizeof(intmax_t),
-                           opt->go_val);
-               } else
+               *(intmax_t *)opt->go_val = number;
+               gctl_ro_param(req, opt->go_name, sizeof(intmax_t), opt->go_val);
+       } else if (G_OPT_TYPE(opt) == G_TYPE_ASCNUM) {
+               if (cmd->gc_argname == NULL || *val != '\0') {
+                       char *s;
+
+                       if (expand_number(val, &number) == -1) {
+                               err(EXIT_FAILURE, "Invalid value for '%c' 
argument",
+                                   opt->go_char);
+                       }
+                       asprintf(&s, "%jd", number);
+                       if (s == NULL)
+                               errx(EXIT_FAILURE, "No memory.");
+                       opt->go_val = s;
                        gctl_ro_param(req, opt->go_name, -1, opt->go_val);
+               }
        } else if (G_OPT_TYPE(opt) == G_TYPE_STRING) {
-               gctl_ro_param(req, opt->go_name, -1, val);
+               if (cmd->gc_argname == NULL || *val != '\0')
+                       gctl_ro_param(req, opt->go_name, -1, val);
        } else if (G_OPT_TYPE(opt) == G_TYPE_BOOL) {
                opt->go_val = malloc(sizeof(int));
                if (opt->go_val == NULL)
@@ -260,6 +288,9 @@ set_option(struct gctl_req *req, struct 
        } else {
                assert(!"Invalid type");
        }
+
+       if (G_OPT_ISMULTI(opt))
+               free(__DECONST(char *, optname));
 }
 
 /*
@@ -284,7 +315,10 @@ parse_arguments(struct g_command *cmd, s
                if (opt->go_name == NULL)
                        break;
                assert(G_OPT_TYPE(opt) != 0);
-               assert((opt->go_type & ~G_TYPE_MASK) == 0);
+               assert((opt->go_type & ~(G_TYPE_MASK | G_TYPE_MULTI)) == 0);
+               /* Multiple bool arguments makes no sense. */
+               assert(G_OPT_TYPE(opt) != G_TYPE_BOOL ||
+                   (opt->go_type & G_TYPE_MULTI) == 0);
                strlcatf(opts, sizeof(opts), "%c", opt->go_char);
                if (G_OPT_TYPE(opt) != G_TYPE_BOOL)
                        strlcat(opts, ":", sizeof(opts));
@@ -304,16 +338,16 @@ parse_arguments(struct g_command *cmd, s
                opt = find_option(cmd, ch);
                if (opt == NULL)
                        usage();
-               if (G_OPT_ISDONE(opt)) {
+               if (!G_OPT_ISMULTI(opt) && G_OPT_ISDONE(opt)) {
                        warnx("Option '%c' specified twice.", opt->go_char);
                        usage();
                }
                G_OPT_DONE(opt);
 
                if (G_OPT_TYPE(opt) == G_TYPE_BOOL)
-                       set_option(req, opt, "1");
+                       set_option(cmd, req, opt, "1");
                else
-                       set_option(req, opt, optarg);
+                       set_option(cmd, req, opt, optarg);
        }
        *argc -= optind;
        *argv += optind;
@@ -330,26 +364,22 @@ parse_arguments(struct g_command *cmd, s
 
                if (G_OPT_TYPE(opt) == G_TYPE_BOOL) {
                        assert(opt->go_val == NULL);
-                       set_option(req, opt, "0");
+                       set_option(cmd, req, opt, "0");
                } else {
                        if (opt->go_val == NULL) {
                                warnx("Option '%c' not specified.",
                                    opt->go_char);
                                usage();
-                       } else {
-                               if (G_OPT_TYPE(opt) == G_TYPE_NUMBER) {
-                                       gctl_ro_param(req, opt->go_name,
-                                           sizeof(intmax_t), opt->go_val);
-                               } else if (G_OPT_TYPE(opt) == G_TYPE_STRING ||
-                                   G_OPT_TYPE(opt) == G_TYPE_ASCNUM) {
-                                       if (cmd->gc_argname == NULL ||
-                                           opt->go_val == NULL ||
-                                           *(char *)opt->go_val != '\0')
-                                               gctl_ro_param(req, opt->go_name,
-                                                   -1, opt->go_val);
-                               } else {
-                                       assert(!"Invalid type");
-                               }
+                       } else if (opt->go_val == G_VAL_OPTIONAL) {
+                               /* add nothing. */
+                       } else if (G_OPT_TYPE(opt) == G_TYPE_STRING) {
+                               set_option(cmd, req, opt, opt->go_val);
+                       } else if (G_OPT_TYPE(opt) == G_TYPE_NUMBER) {
+                               char val[64];
+
+                               snprintf(val, sizeof(val), "%jd",
+                                   *(intmax_t *)opt->go_val);
+                               set_option(cmd, req, opt, val);
                        }
                }
        }

Modified: stable/8/sbin/geom/core/geom.h
==============================================================================
--- stable/8/sbin/geom/core/geom.h      Sat Oct 23 21:25:50 2010        
(r214251)
+++ stable/8/sbin/geom/core/geom.h      Sat Oct 23 21:56:50 2010        
(r214252)
@@ -41,11 +41,19 @@
 #define        G_TYPE_ASCNUM   0x04
 #define        G_TYPE_MASK     0x0f
 #define        G_TYPE_DONE     0x10
+#define        G_TYPE_MULTI    0x20
+#define        G_TYPE_NUMMASK  0xff00
+#define        G_TYPE_NUMSHIFT 8
 
 #define        G_OPT_MAX       16
 #define        G_OPT_DONE(opt)         do { (opt)->go_type |= G_TYPE_DONE; } 
while (0)
 #define        G_OPT_ISDONE(opt)       ((opt)->go_type & G_TYPE_DONE)
+#define        G_OPT_ISMULTI(opt)      ((opt)->go_type & G_TYPE_MULTI)
 #define        G_OPT_TYPE(opt)         ((opt)->go_type & G_TYPE_MASK)
+#define        G_OPT_NUM(opt)          (((opt)->go_type & G_TYPE_NUMMASK) >> 
G_TYPE_NUMSHIFT)
+#define        G_OPT_NUMINC(opt)       ((opt)->go_type += (1 << 
G_TYPE_NUMSHIFT))
+
+#define        G_VAL_OPTIONAL  ((void *)-1)
 
 #define G_OPT_SENTINEL { '\0', NULL, NULL, G_TYPE_NONE }
 #define G_NULL_OPTS    { G_OPT_SENTINEL }
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to