Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 23 Oct 2010 21:56:50 +0000 (UTC)
From:      Pawel Jakub Dawidek <pjd@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r214252 - stable/8/sbin/geom/core
Message-ID:  <201010232156.o9NLuoFh003140@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201010232156.o9NLuoFh003140>