Added silc_getopt.
authorPekka Riikonen <priikone@silcnet.org>
Tue, 25 Dec 2007 11:56:14 +0000 (11:56 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Tue, 25 Dec 2007 11:56:14 +0000 (11:56 +0000)
CHANGES.RUNTIME
TODO
includes/silc.h.in
lib/silcutil/Makefile.ad
lib/silcutil/silcgetopt.c [new file with mode: 0644]
lib/silcutil/silcgetopt.h [new file with mode: 0644]
lib/silcutil/tests/test_silchashtable.c

index f0995733a291817c93f8038e36d84154944434e6..4c2cef6413d20edbb7915359dd9f75e21d2216fd 100644 (file)
@@ -1,3 +1,7 @@
+Tue Dec 25 13:53:07 EET 2007  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added silc_getopt to lib/silcutil/silcgetopt.[ch].
+
 Sat Dec 22 19:55:28 EET 2007  Pekka Riikonen <priikone@silcnet.org>
 
        * Added SILC errno API to lib/silcutil/silcerrno.[ch].  Added
 Sat Dec 22 19:55:28 EET 2007  Pekka Riikonen <priikone@silcnet.org>
 
        * Added SILC errno API to lib/silcutil/silcerrno.[ch].  Added
diff --git a/TODO b/TODO
index 3dccfb86103c677db86737ba366b273745a7c29e..8fbf2c34e1f9e2788f83ba68f05f78cd31002b87 100644 (file)
--- a/TODO
+++ b/TODO
@@ -103,15 +103,7 @@ Runtime library, lib/silcutil/
 
  o Add directory opening/traversing functions
 
 
  o Add directory opening/traversing functions
 
- o silc_getopt routines
-
- o Add silc_stream_get_root and add get_root stream operation.  It
-   returns the root of the stream or NULL if stream doesn't have root.
-
- o Change some stream routines (like socket stream API) to accept ANY
-   stream and use silc_stream_get_root to get the socket stream from the
-   given stream.  This will make various stream APIs more easier to use
-   when user doesn't have to dig up the correct stream.
+ o silc_getopt routines (***DONE)
 
  o The SILC Event signals.  Asynchronous events that can be created,
    connected to and signalled.  Either own event routines or glued into
 
  o The SILC Event signals.  Asynchronous events that can be created,
    connected to and signalled.  Either own event routines or glued into
@@ -201,13 +193,6 @@ Runtime library, lib/silcutil/
 
  o Thread pool API.  Add this to lib/silcutil/silcthread.[ch].         (***DONE)
 
 
  o Thread pool API.  Add this to lib/silcutil/silcthread.[ch].         (***DONE)
 
- o Fast mutex implementation.  Fast rwlock implementation.  Mutex and
-   rwlock implementation using atomic operations.
-
- o Compression routines are missing.  The protocol supports packet
-   compression thus it must be implemented.  SILC Zip API must be
-   defined.
-
  o Add new functions to SilcStack API in lib/silcutil/silcstack.[ch].  Add
    silc_stack_[set|get]_alignment.  It defines the default alignment used
    when allocating memory from stack.  It can be used to specify special
  o Add new functions to SilcStack API in lib/silcutil/silcstack.[ch].  Add
    silc_stack_[set|get]_alignment.  It defines the default alignment used
    when allocating memory from stack.  It can be used to specify special
@@ -252,6 +237,18 @@ Runtime library, lib/silcutil/
  o Generic SilcResult that includes all possible status and
    error conditions and generic errno API. (***DONE)
 
  o Generic SilcResult that includes all possible status and
    error conditions and generic errno API. (***DONE)
 
+ (o Change some stream routines (like socket stream API) to accept ANY
+   stream and use silc_stream_get_root to get the socket stream from the
+   given stream.  This will make various stream APIs more easier to use
+   when user doesn't have to dig up the correct stream.
+
+   Add silc_stream_get_root and add get_root stream operation.  It
+   returns the root of the stream or NULL if stream doesn't have root.) maybe
+
+ (o Compression routines are missing.  The protocol supports packet
+   compression thus it must be implemented.  SILC Zip API must be
+   defined.) maybe
+
  (o SilcIpAddr abstraction.  Ipv4 and Ipv6 support to the abstaction.)
   maybe
 
  (o SilcIpAddr abstraction.  Ipv4 and Ipv6 support to the abstaction.)
   maybe
 
@@ -259,6 +256,9 @@ Runtime library, lib/silcutil/
   to all send(), recv(), sendto() etc.  Bad thing is that we'd have to
   define all socket options, sockaddrs, etc.) maybe
 
   to all send(), recv(), sendto() etc.  Bad thing is that we'd have to
   define all socket options, sockaddrs, etc.) maybe
 
+ (o Fast mutex implementation.  Fast rwlock implementation.  Mutex and
+   rwlock implementation using atomic operations.) not for now.
+
  (o mmap) maybe
 
 
  (o mmap) maybe
 
 
index 4a20535e7e381ea1a96a9a6aad736fc052febbb4..8ef23141d5824e57248c277da9e9b868e0621abb 100644 (file)
@@ -254,6 +254,7 @@ extern "C" {
 #include "silcversion.h"
 
 /* SILC util library includes */
 #include "silcversion.h"
 
 /* SILC util library includes */
+#include "silcgetopt.h"
 #include "silclist.h"
 #include "silcstack.h"
 #include "silcmemory.h"
 #include "silclist.h"
 #include "silcstack.h"
 #include "silcmemory.h"
index 3999d3b754952bb3feba75f1691f1cfe22e8b367..b841e4421f024b60c750dbd616915a24604c8ca1 100644 (file)
@@ -75,7 +75,8 @@ libsilcutil_la_SOURCES = \
        silcenv.c       \
        silcbase64.c    \
        silcbitops.c    \
        silcenv.c       \
        silcbase64.c    \
        silcbitops.c    \
-       silcerrno.c
+       silcerrno.c     \
+       silcgetopt.c
 
 #ifdef SILC_DIST_TOOLKIT
 include_HEADERS =      \
 
 #ifdef SILC_DIST_TOOLKIT
 include_HEADERS =      \
@@ -124,7 +125,8 @@ include_HEADERS =   \
        silcenv.h       \
        silcbase64.h    \
        silcbitops.h    \
        silcenv.h       \
        silcbase64.h    \
        silcbitops.h    \
-       silcerrno.h
+       silcerrno.h     \
+       silcgetopt.h
 
 SILC_EXTRA_DIST = tests
 #endif SILC_DIST_TOOLKIT
 
 SILC_EXTRA_DIST = tests
 #endif SILC_DIST_TOOLKIT
diff --git a/lib/silcutil/silcgetopt.c b/lib/silcutil/silcgetopt.c
new file mode 100644 (file)
index 0000000..5697617
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+
+  silcgetopt.c
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2007 Pekka Riikonen
+
+  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; version 2 of the License.
+
+  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.
+
+*/
+
+#include "silc.h"
+
+/* Getopt, like getopt(3). */
+
+int silc_getopt(int argc, char **argv, const char *optstring, SilcGetOpt op)
+{
+  register int c;
+  register char *cp;
+  SilcBool optional = FALSE, optional_found = FALSE;
+
+  SILC_VERIFY(op);
+
+  op->opt_arg = NULL;
+
+  if (op->opt_sp == 1) {
+    if (op->opt_index >= argc ||
+       argv[op->opt_index][0] != '-' || argv[op->opt_index][1] == '\0') {
+      return -1;
+    } else if (strcmp(argv[op->opt_index], "--") == 0) {
+      op->opt_index++;
+      return -1;
+    }
+  }
+  op->opt_option = c = argv[op->opt_index][op->opt_sp];
+
+  if (c == ':' || (cp = strchr(optstring, c)) == NULL) {
+    if (op->opt_error)
+      fprintf(stderr, "%s: illegal option -- %c\n", argv[0], c);
+    if (argv[op->opt_index][++op->opt_sp] == '\0') {
+      op->opt_index++;
+      op->opt_sp = 1;
+    }
+    return '?';
+  }
+
+  if (*++cp == ':') {
+    /* Check for optional argument (::), must be written -oarg, not -o arg. */
+    if (strlen(cp) && *(cp + 1) == ':') {
+      optional = TRUE;
+      if (argv[op->opt_index][op->opt_sp + 1] != '\0')
+       optional_found = TRUE;
+    }
+
+    if (argv[op->opt_index][op->opt_sp + 1] != '\0')
+      op->opt_arg = &argv[op->opt_index++][op->opt_sp + 1];
+    else if (++op->opt_index >= argc) {
+      if (!optional && !optional_found) {
+       if (op->opt_error)
+         fprintf(stderr, "%s: option requires an argument -- %c\n",
+                 argv[0], c);
+       op->opt_sp = 1;
+       return ':';
+      }
+    } else if (!optional || optional_found)
+      op->opt_arg = argv[op->opt_index++];
+    op->opt_sp = 1;
+  } else {
+    if (argv[op->opt_index][++op->opt_sp] == '\0') {
+      op->opt_sp = 1;
+      op->opt_index++;
+    }
+    op->opt_arg = NULL;
+  }
+
+  return c;
+}
diff --git a/lib/silcutil/silcgetopt.h b/lib/silcutil/silcgetopt.h
new file mode 100644 (file)
index 0000000..ac6b216
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+
+  silcgetopt.h
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2007 Pekka Riikonen
+
+  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; version 2 of the License.
+
+  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.
+
+*/
+
+#ifndef SILCGETOPT_H
+#define SILCGETOPT_H
+
+/****s* silcutil/SilcGetOptAPI/SilcGetOpt
+ *
+ * NAME
+ *
+ *    typedef struct SilcGetOptObject { ... } *SilcGetOpt, SilcGetOptStruct;
+ *
+ * DESCRIPTION
+ *
+ *    Command line option parsers structure given to silc_getopt as argument.
+ *    It contains the current parsed command line option data.
+ *
+ * SOURCE
+ */
+typedef struct SilcGetOptObject {
+  int opt_index;               /* Current option index in argv[] array */
+  int opt_option;              /* Current option character */
+  char *opt_arg;               /* Current parsed option argument */
+  SilcBool opt_error;          /* Set this to TRUE to make silc_getopt print
+                                  errors or FALSE to suppress them. */
+
+  SilcUInt16 opt_sp;           /* Internal parser index */
+} *SilcGetOpt, SilcGetOptStruct;
+/***/
+
+/****d* silcutil/SilcGetOptAPI/SILC_GETOPT_INIT
+ *
+ * NAME
+ *
+ *    #define SILC_GETOPT_INIT ...
+ *
+ * DESCRIPTION
+ *
+ *    Macro used to initialize SilcGetOptStruct before calling silc_getopt.
+ *
+ * EXAMPLE
+ *
+ *    SilcGetOptStruct op = SILC_GETOPT_INIT;
+ *
+ ***/
+#define SILC_GETOPT_INIT { 1, 0, NULL, TRUE, 1 }
+
+/****f* silcutil/SilcGetOptAPI/silc_getopt
+ *
+ * SYNOPSIS
+ *
+ *    int silc_getopt(int argc, char **argv, const char *optstring,
+ *                    SilcGetOpt op)
+ *
+ * DESCRIPTION
+ *
+ *    Parses comand line options.  This function is equivalent to getopt(3).
+ *    Returns the current parsed option, '?' if option was unknown, ':' if
+ *    required argument was missing or -1 after all options have been parsed.
+ *    If options require arguments they are available from the `op' structure,
+ *    to where the options are parsed.  The parsing is stopped immediately
+ *    when first non-option character, which is not an argument for an option,
+ *    is encountered.
+ *
+ *    The `optstring' contains the supported option characters.  One character
+ *    per option is required.  If colon (':') follows option character the
+ *    option requires an argument.  If two colons ('::') follows option
+ *    character the argument is optional.  In that case the argument must
+ *    follow the option in command line, for example -oarg, instead of -o arg.
+ *
+ * EXAMPLE
+ *
+ *    int main(int argc, char **argv)
+ *    {
+ *      SilcGetOptStruct op = SILC_GETOPT_INIT;
+ *
+ *      while ((option = silc_getopt(argc, argv, "ab:t::", &op)) != -1) {
+ *        switch (option) {
+ *          case 'a':
+ *            ...
+ *            break;
+ *          case 'b':
+ *            argument = silc_strdup(op.opt_arg);
+ *            break;
+ *          case 't':
+ *            if (op.opt_arg)
+ *              optional_argument = silc_strdup(op.opt_arg);
+ *            break;
+ *          default:
+ *            exit(1);
+ *            break;
+ *        }
+ *      }
+ *    }
+ *
+ ***/
+int silc_getopt(int argc, char **argv, const char *optstring, SilcGetOpt op);
+
+#endif /* SILCGETOPT_H */
index 30e370d55b18360dac0b5b50eddc23ab7d8b9b88..742b372872c9e7172f21b9e8c26d450110946390 100644 (file)
@@ -208,19 +208,38 @@ SilcBool dump_table()
 int main(int argc, char **argv)
 {
   SilcBool success = FALSE;
 int main(int argc, char **argv)
 {
   SilcBool success = FALSE;
+  SilcGetOptStruct op = SILC_GETOPT_INIT;
+  int opt;
   int i;
 
   int i;
 
-  if (argc > 1 && !strcmp(argv[1], "-d")) {
-    silc_log_debug(TRUE);
-    silc_log_debug_hexdump(TRUE);
-    silc_log_quick(TRUE);
-    silc_log_set_debug_string("*table*,*errno*");
-  }
-
-  if (argc > 1 && !strcmp(argv[1], "-D")) {
-    silc_log_debug(TRUE);
-    dump = TRUE;
-    silc_log_set_debug_string("*table*,*errno*");
+  while ((opt = silc_getopt(argc, argv, "de::D", &op)) != -1) {
+    switch (opt) {
+      case 'd':
+       silc_log_debug(TRUE);
+       silc_log_debug_hexdump(TRUE);
+       silc_log_quick(TRUE);
+       silc_log_set_debug_string("*table*,*errno*");
+       break;
+
+      case 'D':
+       silc_log_debug(TRUE);
+       dump = TRUE;
+       silc_log_set_debug_string("*table*,*errno*");
+       break;
+
+      case 'e':
+       silc_log_debug(TRUE);
+       fprintf(stderr, "%s\n", op.opt_arg);
+       if (op.opt_arg) {
+         dump = TRUE;
+         silc_log_set_debug_string(op.opt_arg);
+       }
+       break;
+
+      default:
+       exit(1);
+       break;
+    }
   }
 
   if (!alloc_table())
   }
 
   if (!alloc_table())