[gpm] [PATCH 5/18] optparser.patch

Dmitry Torokhov dtor_core@ameritech.net
Tue Aug 10 08:53:22 CEST 2004


===================================================================


ChangeSet@1.9, 2004-08-10 00:52:50-05:00, dtor_core@ameritech.net
  Split option parsing (-o text) into separate file suitable for
  use outside of mice.c. Also implement the following changes in
  option parsing:
   - make arguments for string and integer options mandatory;
   - warn user if option is present twice in the option string;
   - provide means to check whether an option is present or not.


 Makefile.in         |    4 
 gpm.c               |   53 -----------
 headers/gpmInt.h    |    3 
 headers/message.h   |    3 
 headers/optparser.h |   50 +++++++++++
 mice.c              |  234 +++++++++++++---------------------------------------
 optparser.c         |  155 ++++++++++++++++++++++++++++++++++
 prog/mouse-test.c   |    8 -
 8 files changed, 276 insertions(+), 234 deletions(-)


===================================================================



diff -Nru a/src/Makefile.in b/src/Makefile.in
--- a/src/Makefile.in	2004-08-10 01:17:58 -05:00
+++ b/src/Makefile.in	2004-08-10 01:17:58 -05:00
@@ -14,7 +14,7 @@
 # Main portion: regular build rules
 
 GSRC = main.c gpm.c gpn.c mice.c special.c twiddler.c synaptics.c \
-       startup.c server_tools.c console.c client.c
+       startup.c server_tools.c console.c client.c optparser.c
 
 GOBJ = $(GSRC:.c=.o) report.o tools.o
 
@@ -153,7 +153,7 @@
 	$(CC) -I. @CPPFLAGS@ $(CPPFLAGS) @CFLAGS@ $(CFLAGS) -c -o $@.o $<
 	$(CC) @LDFLAGS@ $(LDFLAGS) -o $@ $@.o @LIBS@ $(LIBS) lib/libgpm.a
 
-prog/mouse-test:	mice.o twiddler.o synaptics.o console.o
+prog/mouse-test:	mice.o twiddler.o synaptics.o console.o optparser.o
 
 $(PROG):	@SHLIB@ lib/libgpm.a
 
diff -Nru a/src/gpm.c b/src/gpm.c
--- a/src/gpm.c	2004-08-10 01:17:58 -05:00
+++ b/src/gpm.c	2004-08-10 01:17:58 -05:00
@@ -86,50 +86,6 @@
    int   clicks;
 } state;
 
-/* BRAINDEAD..ok not really, but got to leave anyway... FIXME */
-/* argc and argv for mice initialization */
-static int mouse_argc[3]; /* 0 for default (unused) and two mice */
-static char **mouse_argv[3]; /* 0 for default (unused) and two mice */
-
-/*===================================================================*/
-/*
- *      first, all the stuff that used to be in gpn.c (i.e., not main-loop)
- */
-/*-------------------------------------------------------------------*/
-
-/* build_argv is used for mouse initialization routines */
-static char **build_argv(char *argv0, char *str, int *argcptr, char sep)
-{
-   int argc = 1;
-   char **argv;
-   char *s;
-
-   /* argv0 is never NULL, but the extra string may well be */
-   if (str)
-      for (s=str; sep && (s = strchr(s, sep)); argc++) s++;
-   
-   argv = calloc(argc+2, sizeof(char **));
-   if (!argv) gpm_report(GPM_PR_OOPS,GPM_MESS_ALLOC_FAILED);
-   argv[0] = argv0;
-
-   if (!str) {
-      *argcptr = argc; /* 1 */
-      return argv;
-   }
-   /* else, add arguments */
-   s = argv[1] = strdup(str);
-   argc = 2; /* first to fill */
-
-   /* ok, now split: the first one is in place, and s is the whole string */
-   for ( ; sep && (s = strchr(s, sep)) ; argc++) {
-      *s = '\0';
-      s++;
-      argv[argc] = s;
-   }
-   *argcptr = argc;
-   return argv;
-}
-
 /*-------------------------------------------------------------------
  * fetch the actual device data from the mouse device, dependent on
  * what Gpm_Type is being passed.
@@ -497,13 +453,9 @@
       /* and then reset the flag */
       fcntl(fd,F_SETFL,fcntl(fd,F_GETFL) & ~O_NDELAY);
 
-      /* create argc and argv for this device */
-      mouse_argv[i] = build_argv(opt_type, opt_options, &mouse_argc[i], ',');
-
       /* init the device, and use the return value as new mouse type */
       if (m_type->init)
-         m_type=(m_type->init)(fd, m_type->flags, m_type, mouse_argc[i],
-         mouse_argv[i]);
+         m_type=(m_type->init)(fd, m_type->flags, m_type);
       if (!m_type) gpm_report(GPM_PR_OOPS,GPM_MESS_MOUSE_INIT);
 
       which_mouse->fd=fd;
@@ -581,8 +533,7 @@
          if ((mouse_table[i].fd = open(opt_dev, O_RDWR)) < 0)
             gpm_report(GPM_PR_OOPS, GPM_MESS_OPEN,opt_dev);
          if (m_type->init)
-            m_type->init(mouse_table[i].fd, m_type->flags, m_type, 
-                         mouse_argc[1], mouse_argv[1]);
+            m_type->init(mouse_table[i].fd, m_type->flags, m_type);
          maxfd = max(maxfd, mouse_table[1].fd);
          readySet = connSet;
          FD_SET(mouse_table[1].fd, &readySet);
diff -Nru a/src/headers/gpmInt.h b/src/headers/gpmInt.h
--- a/src/headers/gpmInt.h	2004-08-10 01:17:58 -05:00
+++ b/src/headers/gpmInt.h	2004-08-10 01:17:58 -05:00
@@ -115,8 +115,7 @@
   char *desc;             /* a descriptive line */
   char *synonyms;         /* extra names (the XFree name etc) as a list */
   int (*fun)(Gpm_Event *state, unsigned char *data);
-  struct Gpm_Type *(*init)(int fd, unsigned short flags,
-			   struct Gpm_Type *type, int argc, char **argv);
+  struct Gpm_Type *(*init)(int fd, unsigned short flags, struct Gpm_Type *type);
   unsigned short flags;
   unsigned char proto[4];
   int packetlen;
diff -Nru a/src/headers/message.h b/src/headers/message.h
--- a/src/headers/message.h	2004-08-10 01:17:58 -05:00
+++ b/src/headers/message.h	2004-08-10 01:17:58 -05:00
@@ -168,7 +168,8 @@
 #define GPM_MESS_SELECT_TIMES       "selected %i times"
 
 #define GPM_MESS_OPTION_NO_ARG      "%s: Option \"%s\" takes no argument: ignoring \"%s\""
-#define GPM_MESS_INVALID_ARG        "%s: Invalid arg. \"%s\" to \"%s\""
+#define GPM_MESS_INVALID_ARG        "%s: Invalid argument \"%s\" for option \"%s\""
+#define GPM_MESS_MISSING_ARG        "%s: Option \"%s\" requires an argument"
 #define GPM_MESS_CONT_WITH_ERR      "%s: Continuing despite errors in option parsing"
 #define GPM_MESS_TOO_MANY_OPTS      "%s: Too many options for \"-t %s\""
 
diff -Nru a/src/headers/optparser.h b/src/headers/optparser.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/src/headers/optparser.h	2004-08-10 01:17:58 -05:00
@@ -0,0 +1,50 @@
+/*
+ * optparser.h - GPM mouse options parser
+ *
+ * Copyright (C) 1993        Andrew Haylett <ajh@gec-mrc.co.uk>
+ * Copyright (C) 1994-2000   Alessandro Rubini <rubini@linux.it>
+ * Copyright (C) 1998,1999   Ian Zimmerman <itz@rahul.net>
+ * Copyright (C) 2001,2002   Nico Schottelius <nico-gpm@schottelius.org>
+ * Copyright (C) 2003        Dmitry Torokhov <dtor@mail.ru>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ ********/
+#ifndef __GPM_OPTPARSER_H_
+#define __GPM_OPTPARSER_H_
+
+enum option_type {
+   OPT_BOOL = 1,
+   OPT_INT, /* "%i" */
+   OPT_DEC, /* "%d" */
+   OPT_STRING,
+   /* other types must be added */
+   OPT_END = 0
+};
+
+struct option_helper {
+   char *name;
+   enum option_type type;
+   union u {
+      int *iptr;   /* used for int and bool arguments */
+      char **sptr; /* used for string arguments, by strdup()ing the value */
+   } u;
+   int value; /* used for boolean arguments */
+   int present;
+};
+
+int   parse_options(const char *who, const char *opt, char sep, struct option_helper *info);
+int   check_no_options(const char *proto, const char *opts, char sep);
+int   is_option_present(struct option_helper *info, const char *name);
+#endif
diff -Nru a/src/mice.c b/src/mice.c
--- a/src/mice.c	2004-08-10 01:17:58 -05:00
+++ b/src/mice.c	2004-08-10 01:17:58 -05:00
@@ -76,132 +76,36 @@
 #include "headers/twiddler.h"
 #include "headers/synaptics.h"
 #include "headers/message.h"
-
-/*========================================================================*/
-/* Parsing argv: helper dats struct function (should they get elsewhere?) */
-/*========================================================================*/
-
-enum argv_type {
-   ARGV_BOOL = 1,
-   ARGV_INT, /* "%i" */
-   ARGV_DEC, /* "%d" */
-   ARGV_STRING,
-   /* other types must be added */
-   ARGV_END = 0
-};
-
-typedef struct argv_helper {
-   char *name;
-   enum argv_type type;
-   union u {
-      int *iptr;   /* used for int and bool arguments */
-      char **sptr; /* used for string arguments, by strdup()ing the value */
-   } u;
-   int value; /* used for boolean arguments */
-} argv_helper;
-
-static int parse_argv(argv_helper *info, int argc, char **argv)
-{
-   int i, j = 0, errors = 0;
-   long l;
-   argv_helper *p;
-   char *s, *t;
-   int base = 0; /* for strtol */
-
-
-   for (i=1; i<argc; i++) {
-      for (p = info; p->type != ARGV_END; p++) {
-         j = strlen(p->name);
-         if (strncmp(p->name, argv[i], j))
-            continue;
-         if (isalnum(argv[i][j]))
-            continue;
-         break;
-      }
-      if (p->type == ARGV_END) { /* not found */
-         fprintf(stderr, "%s: Uknown option \"%s\" for pointer \"%s\"\n",
-                  option.progname, argv[i], argv[0]);
-         errors++;
-         continue;
-      }
-      /* Found. Look for trailing stuff, if any */
-      s = argv[i]+j;
-      while (*s && isspace(*s)) s++; /* skip spaces */
-      if (*s == '=') s++; /* skip equal */
-      while (*s && isspace(*s)) s++; /* skip other spaces */
-
-      /* Now parse what s is */
-      switch(p->type) {
-         case ARGV_BOOL:
-            if (*s) {
-               gpm_report(GPM_PR_ERR,GPM_MESS_OPTION_NO_ARG,option.progname,p->name,s);
-               errors++;
-            }
-            *(p->u.iptr) = p->value;
-            break;
-
-         case ARGV_DEC:
-            base = 10; /* and fall through */
-         case ARGV_INT:
-            l = strtol(s, &t, base);
-            if (*t) {
-               gpm_report(GPM_PR_ERR,GPM_MESS_INVALID_ARG, option.progname, s, p->name);
-               errors++;
-               break;
-            }
-            *(p->u.iptr) = (int)l;
-            break;
-
-         case ARGV_STRING:
-            *(p->u.sptr) = strdup(s);
-            break;
-
-         case ARGV_END: /* let's please "-Wall" */
-            break;
-      }
-   } /* for i in argc */
-   if (errors) gpm_report(GPM_PR_ERR,GPM_MESS_CONT_WITH_ERR, option.progname);
-   return errors;
-}
-
-/*========================================================================*/
-/* Provide a common error engine by parsing with an empty option-set */
-/*========================================================================*/
-static volatile int check_no_argv(int argc, char **argv)
-{
-   static argv_helper optioninfo[] = {
-      {"",       ARGV_END}
-      };
-   return parse_argv(optioninfo, argc, argv);
-}
+#include "headers/optparser.h"
 
 /*========================================================================*/
 /* Parse the "old" -o options */
 /*========================================================================*/
-static int option_modem_lines(int fd, int argc, char **argv)
+static int option_modem_lines(int fd, char *proto, char *opts)
 {
-   static unsigned int err, lines, reallines;
+   static unsigned int lines, reallines;
+   static struct option_helper optioninfo[] = {
+      {"dtr",  OPT_BOOL, u: {iptr: &lines}, value: TIOCM_DTR},
+      {"rts",  OPT_BOOL, u: {iptr: &lines}, value: TIOCM_RTS},
+      {"both", OPT_BOOL, u: {iptr: &lines}, value: TIOCM_DTR | TIOCM_RTS},
+      {"",     OPT_END}
+   };
 
-   static argv_helper optioninfo[] = {
-      {"dtr",  ARGV_BOOL, u: {iptr: &lines}, value: TIOCM_DTR},
-      {"rts",  ARGV_BOOL, u: {iptr: &lines}, value: TIOCM_RTS},
-      {"both", ARGV_BOOL, u: {iptr: &lines}, value: TIOCM_DTR | TIOCM_RTS},
-      {"",       ARGV_END}
-      };
+   int rslt = parse_options(proto, opts, ',', optioninfo);
 
-   if (argc<2) return 0;
-   if (argc > 2) {
-      gpm_report(GPM_PR_ERR,GPM_MESS_TOO_MANY_OPTS,option.progname, argv[0]);
+   if (rslt < 0) {
+      errno = EINVAL;
+      return -1;
+   } else if (rslt > 1) {
+      gpm_report(GPM_PR_ERR, GPM_MESS_TOO_MANY_OPTS, option.progname, proto);
       errno = EINVAL; /* used by gpm_oops(), if the caller reports failure */
       return -1;
+   } else if (rslt == 1) {
+      /* ok, move the lines */
+      ioctl(fd, TIOCMGET, &reallines);
+      reallines &= ~lines;
+      ioctl(fd, TIOCMSET, &reallines);
    }
-   err = parse_argv(optioninfo, argc, argv);
-   if(err) return 0; /* a message has been printed, but go on as good */
-
-   /* ok, move the lines */
-   ioctl(fd, TIOCMGET, &reallines);
-   reallines &= ~lines;
-   ioctl(fd, TIOCMSET, &reallines);
    return 0;
 }
 
@@ -709,8 +613,7 @@
 }
 
 /* standard ps2 */
-static Gpm_Type *I_ps2(int fd, unsigned short flags,
-        struct Gpm_Type *type, int argc, char **argv)
+static Gpm_Type *I_ps2(int fd, unsigned short flags, struct Gpm_Type *type)
 {
    static unsigned char s[] = { 246, 230, 244, 243, 100, 232, 3, };
    write (fd, s, sizeof (s));
@@ -719,13 +622,12 @@
    return type;
 }
 
-static Gpm_Type *I_netmouse(int fd, unsigned short flags,
-         struct Gpm_Type *type, int argc, char **argv)
+static Gpm_Type *I_netmouse(int fd, unsigned short flags, struct Gpm_Type *type)
 {
    unsigned char magic[6] = { 0xe8, 0x03, 0xe6, 0xe6, 0xe6, 0xe9 };
    int i;
 
-   if (check_no_argv(argc, argv)) return NULL;
+   if (!check_no_options(type->name, opt_options, ',')) return NULL;
    for (i=0; i<6; i++) {
       unsigned char c = 0;
       write( fd, magic+i, 1 );
@@ -1478,11 +1380,9 @@
 /*========================================================================*/
 /* Then, mice should be initialized */
 
-static Gpm_Type* I_empty(int fd, unsigned short flags,
-    struct Gpm_Type *type, int argc, char **argv)
+static Gpm_Type* I_empty(int fd, unsigned short flags, struct Gpm_Type *type)
 {
-    if (check_no_argv(argc, argv)) return NULL;
-    return type;
+    return check_no_options(type->name, opt_options, ',') ? type : NULL;
 }
 
 static int setspeed(int fd,int old,int new,int needtowrite,unsigned short flags)
@@ -1539,14 +1439,13 @@
     {125,"Q"},
     {1E9,"N"}, };
 
-static Gpm_Type* I_serial(int fd, unsigned short flags,
-    struct Gpm_Type *type, int argc, char **argv)
+static Gpm_Type* I_serial(int fd, unsigned short flags, struct Gpm_Type *type)
 {
    int i; unsigned char c;
    fd_set set; struct timeval timeout={0,0}; /* used when not debugging */
 
    /* accept "-o dtr", "-o rts" and "-o both" */
-   if (option_modem_lines(fd, argc, argv)) return NULL;
+   if (option_modem_lines(fd, type->name, opt_options)) return NULL;
 
 #ifndef DEBUG
    /* flush any pending input (thanks, Miguel) */
@@ -1615,14 +1514,13 @@
    return type;
 }
 
-static Gpm_Type* I_logi(int fd, unsigned short flags,
-       struct Gpm_Type *type, int argc, char **argv)
+static Gpm_Type* I_logi(int fd, unsigned short flags, struct Gpm_Type *type)
 {
    int i;
    struct stat buf;
    int busmouse;
 
-   if (check_no_argv(argc, argv)) return NULL;
+   if (!check_no_options(type->name, opt_options, ',')) return NULL;
 
    /* is this a serial- or a bus- mouse? */
    if(fstat(fd,&buf)==-1) gpm_report(GPM_PR_OOPS,GPM_MESS_FSTAT);
@@ -1651,8 +1549,7 @@
    return type;
 }
 
-static Gpm_Type *I_wacom(int fd, unsigned short flags,
-                         struct Gpm_Type *type, int argc, char **argv)
+static Gpm_Type *I_wacom(int fd, unsigned short flags, struct Gpm_Type *type)
 {
 /* wacom graphire tablet */
 #define UD_RESETBAUD     "\r$"      /* reset baud rate to default (wacom V) */
@@ -1731,12 +1628,13 @@
     */
 
    /* accept boolean options absolute and relative */
-   static argv_helper optioninfo[] = {
-         {"absolute",  ARGV_BOOL, u: {iptr: &WacomAbsoluteWanted}, value: !0},
-         {"relative",  ARGV_BOOL, u: {iptr: &WacomAbsoluteWanted}, value:  0},
-         {"",       ARGV_END} 
+   static struct option_helper optioninfo[] = {
+         {"absolute",  OPT_BOOL, u: {iptr: &WacomAbsoluteWanted}, value: !0},
+         {"relative",  OPT_BOOL, u: {iptr: &WacomAbsoluteWanted}, value:  0},
+         {"",          OPT_END}
    };
-   parse_argv(optioninfo, argc, argv); 
+   
+   parse_options(type->name, opt_options, ',', optioninfo);
    type->absolute = WacomAbsoluteWanted;
    reset_wacom();
 
@@ -1775,13 +1673,12 @@
    return type;
 }
 
-static Gpm_Type *I_pnp(int fd, unsigned short flags,
-             struct Gpm_Type *type, int argc, char **argv)
+static Gpm_Type *I_pnp(int fd, unsigned short flags, struct Gpm_Type *type)
 {  
    struct termios tty;
 
    /* accept "-o dtr", "-o rts" and "-o both" */
-   if (option_modem_lines(fd, argc, argv)) return NULL;
+   if (option_modem_lines(fd, type->name, opt_options)) return NULL;
 
    /*
     * Just put the device to 1200 baud. Thanks to Francois Chastrette
@@ -1851,8 +1748,7 @@
 
 /* intellimouse, ps2 version: Ben Pfaff and Colin Plumb */
 /* Autodetect: Steve Bennett */
-static Gpm_Type *I_imps2(int fd, unsigned short flags, struct Gpm_Type *type,
-                                                       int argc, char **argv)
+static Gpm_Type *I_imps2(int fd, unsigned short flags, struct Gpm_Type *type)
 {
    int id;
    static unsigned char basic_init[] = { GPM_AUX_ENABLE_DEV, GPM_AUX_SET_SAMPLE, 100 };
@@ -1907,12 +1803,11 @@
  * This works with Dexxa Optical Mouse, but because in X same initstring
  * is named ExplorerPS/2 so I named it in the same way.
  */
-static Gpm_Type *I_exps2(int fd, unsigned short flags,
-          struct Gpm_Type *type, int argc, char **argv)
+static Gpm_Type *I_exps2(int fd, unsigned short flags, struct Gpm_Type *type)
 {
    static unsigned char s1[] = { 243, 200, 243, 200, 243, 80, };
 
-   if (check_no_argv(argc, argv)) return NULL;
+   if (!check_no_options(type->name, opt_options, ',')) return NULL;
 
    write (fd, s1, sizeof (s1));
    usleep (30000);
@@ -1920,42 +1815,38 @@
    return type;
 }
 
-static Gpm_Type *I_twid(int fd, unsigned short flags,
-         struct Gpm_Type *type, int argc, char **argv)
+static Gpm_Type *I_twid(int fd, unsigned short flags, struct Gpm_Type *type)
 {
 
-   if (check_no_argv(argc, argv)) return NULL;
+   if (!check_no_options(type->name, opt_options, ',')) return NULL;
 
    if (twiddler_key_init() != 0) return NULL;
    /*
    * the twiddler is a serial mouse: just drop dtr
    * and run at 2400 (unless specified differently) 
    */
-   if(opt_baud==DEF_BAUD) opt_baud = 2400;
-   argv[1] = "dtr"; /* argv[1] is guaranteed to be NULL (this is dirty) */
-   return I_serial(fd, flags, type, argc, argv);
+   if (opt_baud == DEF_BAUD) opt_baud = 2400;
+   opt_options = "dtr";
+   return I_serial(fd, flags, type);
 }
 
-static Gpm_Type *I_calus(int fd, unsigned short flags,
-          struct Gpm_Type *type, int argc, char **argv)
+static Gpm_Type *I_calus(int fd, unsigned short flags, struct Gpm_Type *type)
 {
-   if (check_no_argv(argc, argv)) return NULL;
+   if (!check_no_options(type->name, opt_options, ',')) return NULL;
 
-   if (opt_baud == 1200) opt_baud=9600; /* default to 9600 */
-   return I_serial(fd, flags, type, argc, argv);
+   if (opt_baud == 1200) opt_baud = 9600; /* default to 9600 */
+   return I_serial(fd, flags, type);
 }
 
 /* synaptics touchpad, ps2 version: Henry Davies */
-static Gpm_Type *I_synps2(int fd, unsigned short flags,
-           struct Gpm_Type *type, int argc, char **argv)
+static Gpm_Type *I_synps2(int fd, unsigned short flags, struct Gpm_Type *type)
 {
    syn_ps2_init (fd);
    return type;
 }
 
 
-static Gpm_Type *I_summa(int fd, unsigned short flags,
-          struct Gpm_Type *type, int argc, char **argv) 
+static Gpm_Type *I_summa(int fd, unsigned short flags, struct Gpm_Type *type)
 {
    void resetsumma()
    {
@@ -2044,8 +1935,7 @@
    return type;
 }
 
-static Gpm_Type *I_mtouch(int fd, unsigned short flags,
-           struct Gpm_Type *type, int argc, char **argv)
+static Gpm_Type *I_mtouch(int fd, unsigned short flags, struct Gpm_Type *type)
 {
    struct termios tty;
 
@@ -2068,8 +1958,7 @@
 }
 
 /* simple initialization for the gunze touchscreen */
-static Gpm_Type *I_gunze(int fd, unsigned short flags,
-           struct Gpm_Type *type, int argc, char **argv)
+static Gpm_Type *I_gunze(int fd, unsigned short flags, struct Gpm_Type *type)
 {
    struct termios tty;
    FILE *f;
@@ -2078,18 +1967,18 @@
 
    #define GUNZE_CALIBRATION_FILE SYSCONFDIR "/gpm-calibration"
    /* accept a few options */
-   static argv_helper optioninfo[] = {
-      {"smooth",   ARGV_INT, u: {iptr: &gunze_avg}},
-      {"debounce", ARGV_INT, u: {iptr: &gunze_debounce}},
+   static struct option_helper optioninfo[] = {
+      {"smooth",   OPT_INT, u: {iptr: &gunze_avg}},
+      {"debounce", OPT_INT, u: {iptr: &gunze_debounce}},
       /* FIXME: add corner tapping */
-      {"",       ARGV_END}
+      {"",         OPT_END}
    };
-   parse_argv(optioninfo, argc, argv);
+   parse_options(type->name, opt_options, ',', optioninfo);
     
    /* check that the baud rate is valid */
    if (opt_baud == DEF_BAUD) opt_baud = 19200; /* force 19200 as default */
    if (opt_baud != 9600 && opt_baud != 19200) {
-      gpm_report(GPM_PR_ERR,GPM_MESS_GUNZE_WRONG_BAUD,option.progname, argv[0]);
+      gpm_report(GPM_PR_ERR, GPM_MESS_GUNZE_WRONG_BAUD, option.progname, type->name);
       opt_baud = 19200;
    }
    tcgetattr(fd, &tty);
@@ -2127,8 +2016,7 @@
 }
 
 /*  Genius Wizardpad tablet  --  Matt Kimball (mkimball@xmission.com)  */
-static Gpm_Type *I_wp(int fd, unsigned short flags,
-            struct Gpm_Type *type, int argc, char **argv)
+static Gpm_Type *I_wp(int fd, unsigned short flags, struct Gpm_Type *type)
 {
    struct termios tty;
    char tablet_info[256];
diff -Nru a/src/optparser.c b/src/optparser.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/src/optparser.c	2004-08-10 01:17:58 -05:00
@@ -0,0 +1,155 @@
+/*
+ * optparser.c - GPM mouse options parser
+ *
+ * Copyright (C) 1993        Andrew Haylett <ajh@gec-mrc.co.uk>
+ * Copyright (C) 1994-2000   Alessandro Rubini <rubini@linux.it>
+ * Copyright (C) 1998,1999   Ian Zimmerman <itz@rahul.net>
+ * Copyright (C) 2001,2002   Nico Schottelius <nico-gpm@schottelius.org>
+ * Copyright (C) 2003        Dmitry Torokhov <dtor@mail.ru>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ ********/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "headers/gpmInt.h"
+#include "headers/message.h"
+#include "headers/optparser.h"
+
+int parse_options(const char *proto, const char *opts, char sep, struct option_helper *info)
+{
+   int len, n, n_opts = 0, errors = 0;
+   long l;
+   struct option_helper *p;
+   char *s, *t, *str;
+   int base; /* for strtol */
+
+   for (p = info; p->type != OPT_END; p++)
+      p->present = 0;
+
+   if (!opts)
+      return 0;
+
+   if (!(str = strdup(opts)))
+      gpm_report(GPM_PR_OOPS, GPM_MESS_ALLOC_FAILED);
+
+   /* split input string */
+   for (s = str, n = 1; sep && (s = strchr(s, sep)); s++, n++)
+        *s = '\0';
+
+   for (s = str; n; s += strlen(s) + 1, n--) {
+      if (strlen(s) == 0)
+         continue;
+
+      for (p = info; p->type != OPT_END; p++) {
+         len = strlen(p->name);
+         if (!strncmp(p->name, s, len) && !isalnum(s[len]))
+            break;
+      }
+      if (p->type == OPT_END) { /* not found */
+         gpm_report(GPM_PR_ERR, "%s: Uknown option \"%s\" for protocol \"%s\"\n",
+                    option.progname, s, proto);
+         errors++;
+         continue;
+      }
+      if (p->present) {
+         gpm_report(GPM_PR_ERR, "%s: option \"%s\" has already been seen, ignored (\"%s\")\n",
+                    option.progname, s, proto);
+         continue;
+      }
+      p->present = 1;
+      n_opts++;
+      /* Found. Look for trailing stuff, if any */
+      s += strlen(p->name);
+      while (*s && isspace(*s)) s++; /* skip spaces */
+      if (*s == '=') s++; /* skip equal */
+      while (*s && isspace(*s)) s++; /* skip other spaces */
+
+      /* Now parse what s is */
+      base = 0;
+      switch(p->type) {
+         case OPT_BOOL:
+            if (*s) {
+               gpm_report(GPM_PR_ERR, GPM_MESS_OPTION_NO_ARG, option.progname, p->name, s);
+               errors++;
+            }
+            *(p->u.iptr) = p->value;
+            break;
+
+         case OPT_DEC:
+            base = 10; /* and fall through */
+
+         case OPT_INT:
+            if (*s == '\0') {
+               gpm_report(GPM_PR_ERR, GPM_MESS_MISSING_ARG, option.progname, p->name);
+            } else {
+               l = strtol(s, &t, base);
+               if (*t) {
+                  gpm_report(GPM_PR_ERR, GPM_MESS_INVALID_ARG, option.progname, s, p->name);
+                  errors++;
+                  break;
+               }
+               *(p->u.iptr) = (int)l;
+            }
+            break;
+
+         case OPT_STRING:
+            if (*s == '\0')
+               gpm_report(GPM_PR_ERR, GPM_MESS_MISSING_ARG, option.progname, p->name);
+            else
+               *(p->u.sptr) = strdup(s);
+            break;
+
+         case OPT_END: /* let's please "-Wall" */
+            break;
+      }
+   }
+
+   free(str);
+
+   if (errors) {
+      gpm_report(GPM_PR_ERR,GPM_MESS_CONT_WITH_ERR, option.progname);
+      return -errors;
+   }
+   return n_opts;
+}
+
+int check_no_options(const char *proto, const char *opts, char sep)
+{
+   static struct option_helper info[] = {
+      { "", OPT_END }
+   };
+
+   return parse_options(proto, opts, sep, info) == 0;
+}
+
+int is_option_present(struct option_helper *info, const char *name)
+{
+   struct option_helper *p;
+   int len;
+
+   for (p = info; p->type != OPT_END; p++) {
+      len = strlen(p->name);
+      if (!strncmp(p->name, name, len) && !isalnum(name[len]))
+         return p->present;
+   }
+
+   gpm_report(GPM_PR_ERR, "%s: Uknown option \"%s\"\n", option.progname, name);
+   return 0;
+}
+
diff -Nru a/src/prog/mouse-test.c b/src/prog/mouse-test.c
--- a/src/prog/mouse-test.c	2004-08-10 01:17:58 -05:00
+++ b/src/prog/mouse-test.c	2004-08-10 01:17:58 -05:00
@@ -172,8 +172,7 @@
    return &((*current)->next);
 }
 
-Gpm_Type *(*I_serial)(int fd, unsigned short flags, struct Gpm_Type *type,
-		      int argc, char **argv);
+Gpm_Type *(*I_serial)(int fd, unsigned short flags, struct Gpm_Type *type);
 
 
 /*----------------------------------------------------------------------------- 
@@ -187,7 +186,7 @@
    usleep(100000);
    fd=open(name,O_RDWR);
    if (fd < 0) gpm_report(GPM_PR_OOPS,name);
-   (*I_serial)(fd,type->flags,type,1,&type->name); /* ms initialization */
+   (*I_serial)(fd,type->flags,type); /* ms initialization */
    return fd;
 }
 
@@ -356,8 +355,7 @@
          printf("\t%s\r\n", (*nextdev)->name);
          FD_SET((*nextdev)->fd,&devSet);
          maxfd=max((*nextdev)->fd,maxfd);
-         (*I_serial)((*nextdev)->fd,(mice+1)->flags,mice+1,
-		  1, &(mice+1)->name); /* try ms mode */
+         (*I_serial)((*nextdev)->fd,(mice+1)->flags,mice+1); /* try ms mode */
       }
 
       savSet=devSet;


More information about the gpm mailing list