r47 - in trunk/varnish-cache: include lib/libvarnish

phk at projects.linpro.no phk at projects.linpro.no
Tue Mar 14 10:15:37 CET 2006


Author: phk
Date: 2006-03-14 10:15:36 +0100 (Tue, 14 Mar 2006)
New Revision: 47

Added:
   trunk/varnish-cache/include/libvarnish.h
   trunk/varnish-cache/lib/libvarnish/argv.c
Modified:
   trunk/varnish-cache/include/Makefile.am
   trunk/varnish-cache/lib/libvarnish/Makefile.am
Log:
Add a function to break a command line like string into an argv[].
This will be useful for the various text based protocols etc.


Modified: trunk/varnish-cache/include/Makefile.am
===================================================================
--- trunk/varnish-cache/include/Makefile.am	2006-03-13 14:23:15 UTC (rev 46)
+++ trunk/varnish-cache/include/Makefile.am	2006-03-14 09:15:36 UTC (rev 47)
@@ -2,9 +2,9 @@
 
 include_HEADERS = \
 	hash.h \
+	libvarnish.h \
 	queue.h \
 	sbuf.h \
 	tree.h \
 	varnish/assert.h \
 	varnishapi.h
-

Added: trunk/varnish-cache/include/libvarnish.h
===================================================================
--- trunk/varnish-cache/include/libvarnish.h	2006-03-13 14:23:15 UTC (rev 46)
+++ trunk/varnish-cache/include/libvarnish.h	2006-03-14 09:15:36 UTC (rev 47)
@@ -0,0 +1,7 @@
+/*
+ * $Id$
+ */
+
+/* from libvarnish/argv.c */
+void FreeArgv(char **argv);
+char **ParseArgv(const char *s, int comment);

Modified: trunk/varnish-cache/lib/libvarnish/Makefile.am
===================================================================
--- trunk/varnish-cache/lib/libvarnish/Makefile.am	2006-03-13 14:23:15 UTC (rev 46)
+++ trunk/varnish-cache/lib/libvarnish/Makefile.am	2006-03-14 09:15:36 UTC (rev 47)
@@ -4,4 +4,5 @@
 
 lib_LTLIBRARIES = libvarnish.la
 
-libvarnish_la_SOURCES =
+libvarnish_la_SOURCES = \
+	argv.c

Added: trunk/varnish-cache/lib/libvarnish/argv.c
===================================================================
--- trunk/varnish-cache/lib/libvarnish/argv.c	2006-03-13 14:23:15 UTC (rev 46)
+++ trunk/varnish-cache/lib/libvarnish/argv.c	2006-03-14 09:15:36 UTC (rev 47)
@@ -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




More information about the varnish-commit mailing list