[RFC PATCH 1/3] notmuch-opts.[ch]: new argument parsing framework for notmuch.

David Bremner bremner at debian.org
Wed Nov 30 17:15:28 PST 2011


As we noticed when Jani kindly converted things to getopt_long, much
of the work in argument parsing in notmuch is due to the the key-value
style arguments like --format=(raw|json|text).  In this intitial
attempt at factoring out some of the argument processing, we include
support for this kind of arguments roughly in the style of getopt_long.
---
 Makefile.local |    1 +
 notmuch-opts.c |   71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 notmuch-opts.h |   34 ++++++++++++++++++++++++++
 3 files changed, 106 insertions(+), 0 deletions(-)
 create mode 100644 notmuch-opts.c
 create mode 100644 notmuch-opts.h

diff --git a/Makefile.local b/Makefile.local
index c94402b..6606be8 100644
--- a/Makefile.local
+++ b/Makefile.local
@@ -303,6 +303,7 @@ notmuch_client_srcs =		\
 	notmuch-count.c		\
 	notmuch-dump.c		\
 	notmuch-new.c		\
+	notmuch-opts.c		\
 	notmuch-reply.c		\
 	notmuch-restore.c	\
 	notmuch-search.c	\
diff --git a/notmuch-opts.c b/notmuch-opts.c
new file mode 100644
index 0000000..6aac94c
--- /dev/null
+++ b/notmuch-opts.c
@@ -0,0 +1,71 @@
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include "notmuch-opts.h"
+
+notmuch_bool_t
+parse_argument(const char *name,
+	       const char *arg,
+	       const notmuch_opt_desc_t *options,
+	       notmuch_opt_t *state){
+
+    assert(arg);
+    assert(name);
+    assert(options);
+    assert(state);
+
+    state->arg_id = 0;
+    state->keyword_id = 0;
+
+    if (strncmp (arg,"--",2) != 0) {
+	state->arg_id = '*';
+	state->string = arg;
+	return TRUE;
+    }
+
+    if (strlen (arg) == 2) {
+	state->arg_id = '-';
+	return FALSE;
+    }
+
+    arg += 2;
+
+    const notmuch_opt_desc_t *try = options;
+    while (try->name) {
+	if (strncmp (arg, try->name, strlen(try->name) ) == 0) {
+	    state->arg_id = try->arg_id;
+	    if (try->opt_type == NOTMUCH_OPT_KEYWORD) {
+		notmuch_keyword_t *try_arg = try->keywords;
+		const char *arg_str=arg + strlen(try->name);
+
+		if (arg_str[0] != ':' && arg_str[0] != '=') {
+		    fprintf (stderr, "%s %s: syntax error\n", name, arg);
+		    return FALSE;
+		}
+
+		/* skip delimiter */
+		arg_str++;
+
+		while (try_arg->name && state->keyword_id == 0) {
+		    if (strcmp (arg_str, try_arg->name) == 0) {
+			state->keyword_id = try_arg->keyword_id;
+		    }
+		    try_arg++;
+		}
+		if (state->keyword_id == 0) {
+		    fprintf (stderr, "%s %s: missing keyword\n", name, arg);
+		    return FALSE;
+		}
+
+
+	    }
+	}
+	try++;
+    }
+    if (state->arg_id == 0) {
+	fprintf (stderr, "%s %s: unknown argument\n", name, arg);
+	return FALSE;
+    }
+
+    return TRUE;
+}
diff --git a/notmuch-opts.h b/notmuch-opts.h
new file mode 100644
index 0000000..c442e3f
--- /dev/null
+++ b/notmuch-opts.h
@@ -0,0 +1,34 @@
+#ifndef NOTMUCH_OPTS_H
+#define NOTMUCH_OPTS_H
+
+#include "notmuch.h"
+
+enum notmuch_opt_type {
+    NOTMUCH_OPT_NULL = 0,
+    NOTMUCH_OPT_NO_ARG,
+    NOTMUCH_OPT_KEYWORD
+};
+
+typedef struct notmuch_keyword {
+    const char *name;
+    int keyword_id;
+} notmuch_keyword_t;
+
+typedef struct notmuch_opt_desc {
+    const char *name;
+    int  arg_id;
+    enum notmuch_opt_type opt_type;
+    struct notmuch_keyword *keywords;
+} notmuch_opt_desc_t;
+
+typedef struct notmuch_opt {
+    int arg_id;
+    int keyword_id;
+    const char *string;
+} notmuch_opt_t;
+
+notmuch_bool_t
+parse_argument (const char* name, const char *arg, const notmuch_opt_desc_t *options,
+		notmuch_opt_t *result);
+
+#endif
-- 
1.7.5.4



More information about the notmuch mailing list