]> err.no Git - varnish/commitdiff
Add a function to break a command line like string into an argv[].
authorphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Tue, 14 Mar 2006 09:15:36 +0000 (09:15 +0000)
committerphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Tue, 14 Mar 2006 09:15:36 +0000 (09:15 +0000)
This will be useful for the various text based protocols etc.

git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@47 d4fa192b-c00b-0410-8231-f00ffab90ce4

varnish-cache/include/Makefile.am
varnish-cache/include/libvarnish.h [new file with mode: 0644]
varnish-cache/lib/libvarnish/Makefile.am
varnish-cache/lib/libvarnish/argv.c [new file with mode: 0644]

index 2f0e8db44c2144cea088025209dcbe8e92820002..57aaabb90d8c0861f543858641d2355963138365 100644 (file)
@@ -2,9 +2,9 @@
 
 include_HEADERS = \
        hash.h \
+       libvarnish.h \
        queue.h \
        sbuf.h \
        tree.h \
        varnish/assert.h \
        varnishapi.h
-
diff --git a/varnish-cache/include/libvarnish.h b/varnish-cache/include/libvarnish.h
new file mode 100644 (file)
index 0000000..b50fcd2
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * $Id$
+ */
+
+/* from libvarnish/argv.c */
+void FreeArgv(char **argv);
+char **ParseArgv(const char *s, int comment);
index 098bb4f96832f63a5eac9d0118bdf9209be65db6..6b1ed7c66cc889ad40594a89e985b6ff7b8e583f 100644 (file)
@@ -4,4 +4,5 @@ INCLUDES = -I$(top_srcdir)/include
 
 lib_LTLIBRARIES = libvarnish.la
 
-libvarnish_la_SOURCES =
+libvarnish_la_SOURCES = \
+       argv.c
diff --git a/varnish-cache/lib/libvarnish/argv.c b/varnish-cache/lib/libvarnish/argv.c
new file mode 100644 (file)
index 0000000..5245230
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * $Id$
+ *
+ * char **ParseArgv(const char *s, int comment)
+ *     Parse a command like line into an argv[]
+ *     Index zero contains NULL or an error message
+ *     "double quotes" and backslash substitution is handled.
+ *
+ * void FreeArgv(char **argv)
+ *     Free the result of ParseArgv()
+ *
+ */
+
+#include <ctype.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#include "libvarnish.h"
+
+static int
+BackSlash(const char *s, int *res)
+{
+       int i, r;
+
+       assert(*s == '\\');
+       r = i = 0;
+       switch(s[1]) {
+       case 'n':
+               i = '\n';
+               r = 2;
+               break;
+       case 'r':
+               i = '\r';
+               r = 2;
+               break;
+       case 't':
+               i = '\t';
+               r = 2;
+               break;
+       case '"':
+               i = '"';
+               r = 2;
+               break;
+       case '\\':
+               i = '\\';
+               r = 2;
+               break;
+       case '0': case '1': case '2': case 3:
+       case '4': case '5': case '6': case 7:
+               for (r = 1; r < 4; r++) {
+                       if (!isdigit(s[r]))
+                               break;
+                       if (digittoint(s[r]) > 7)
+                               break;
+                       i <<= 3;
+                       i |= digittoint(s[r]);
+               }
+               break;
+       case 'x':
+               if (1 == sscanf(s + 1, "x%02x", &i))
+                       r = 4;
+               break;
+       default:
+               break;
+       }
+       if (res != NULL)
+               *res = i;
+       return (r);
+}
+
+static char *
+BackSlashDecode(const char *s, const char *e)
+{
+       const char *q;
+       char *p, *r;
+       int i, j;
+
+       p = calloc((e - s) + 1, 1);
+       if (p == NULL)
+               return (p);
+       for (r = p, q = s; q < e; ) {
+               if (*q != '\\') {
+                       *r++ = *q++;
+                       continue;
+               }
+               i = BackSlash(q, &j);
+               q += i;
+               *r++ = j;
+       }
+       *r = '\0';
+       return (p);
+}
+
+char **
+ParseArgv(const char *s, int comment)
+{
+       char **argv;
+       const char *p;
+       int nargv, largv;
+       int i, quote;
+
+       assert(s != NULL);
+       nargv = 1;
+       largv = 16;
+       argv = calloc(sizeof *argv, largv);
+       if (argv == NULL)
+               return (NULL);
+
+       for (;;) {
+               if (*s == '\0')
+                       break;
+               if (isspace(*s)) {
+                       s++;
+                       continue;
+               }
+               if (comment && *s == '#')
+                       break;
+               if (*s == '"') {
+                       p = ++s;
+                       quote = 1;
+               } else {
+                       p = s;
+                       quote = 0;
+               }
+               while (1) {
+                       if (*s == '\\') {
+                               i = BackSlash(s, NULL);
+                               if (i == 0) {
+                                       argv[0] = __DECONST(void *,
+                                           "Illegal backslash sequence");
+                                       return (argv);
+                               }
+                               s += i;
+                               continue;
+                       }
+                       if (!quote) {
+                               if (*s == '\0' || isspace(*s))
+                                       break;
+                               s++;
+                               continue;
+                       }
+                       if (*s == '"')
+                               break;
+                       if (*s == '\0') {
+                               argv[0] = __DECONST(void *,
+                                   "Missing '\"'");
+                               return (argv);
+                       }
+                       s++;
+               }
+               if (nargv + 1 >= largv) {
+                       argv = realloc(argv, sizeof (*argv) * (largv += largv));
+                       assert(argv != NULL);
+               }
+               argv[nargv++] = BackSlashDecode(p, s);
+               if (*s != '\0')
+                       s++;
+       }
+       argv[nargv++] = NULL;
+       return (argv);
+}
+
+void
+FreeArgv(char **argv)
+{
+       int i;
+       
+       for (i = 1; argv[i] != NULL; i++)
+               free(argv[i]);
+       free(argv);
+}
+
+#ifdef TESTPROG
+
+#include <printf.h>
+
+static void
+PrintArgv(char **argv)
+{
+       int i;
+
+       printf("---- %p\n", argv);
+       if (argv[0] != NULL)
+               printf("err %V\n", argv[0]);
+       for (i = 1; argv[i] != NULL; i++)
+               printf("%3d %V\n", i, argv[i]);
+}
+
+static void
+Test(const char *str)
+{
+       char **av;
+
+       printf("Test: <%V>\n", str);
+       av = ParseArgv(str, 0);
+       PrintArgv(av);
+}
+
+int
+main(int argc __unused, char **argv __unused)
+{
+       char buf[BUFSIZ];
+
+        register_printf_render_std("V");
+
+       while (fgets(buf, sizeof buf, stdin))
+               Test(buf);
+
+       return (0);
+}
+#endif