summaryrefslogtreecommitdiff
path: root/usr/src/lib/libast/common/string/stropt.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libast/common/string/stropt.c')
-rw-r--r--usr/src/lib/libast/common/string/stropt.c188
1 files changed, 188 insertions, 0 deletions
diff --git a/usr/src/lib/libast/common/string/stropt.c b/usr/src/lib/libast/common/string/stropt.c
new file mode 100644
index 0000000000..9f28e9fb40
--- /dev/null
+++ b/usr/src/lib/libast/common/string/stropt.c
@@ -0,0 +1,188 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ */
+
+#include <ast.h>
+#include <ctype.h>
+
+/*
+ * parse option expression in s using options in tab with element size siz
+ * first element in tab must be a char*
+ * options match
+ *
+ * [no]name[[:]=['"]value["']][, ]...
+ *
+ * f is called for each option
+ *
+ * (*f)(void* a, char* p, int n, char* v)
+ *
+ * a from stropt
+ * p matching tab entry, or name if no table
+ * n 0 if option had ``no'' prefix, -1 if :=, 1 otherwise
+ * v option value pointer
+ *
+ * for unmatched options p is 0 and v is the offending option
+ *
+ * names in s may be shorter than tab names
+ * longer names must have a prefix that matches a tab name
+ * the first match is returned
+ * \ escapes value using chresc()
+ */
+
+int
+stropt(const char* as, const void* tab, int siz, int(*f)(void*, const void*, int, const char*), void* a)
+{
+ register int c;
+ register char* s;
+ register char* v;
+ register char* t;
+ char** p;
+ char* u;
+ char* x;
+ char* e;
+ int n;
+ int ql;
+ int qr;
+ int qc;
+
+ if (!as) n = 0;
+ else if (!(x = s = strdup(as))) n = -1;
+ else
+ {
+ for (;;)
+ {
+ while (isspace(*s) || *s == ',') s++;
+ if (*s == 'n' && *(s + 1) == 'o')
+ {
+ s += 2;
+ n = 0;
+ }
+ else n = 1;
+ if (!*s)
+ {
+ n = 0;
+ break;
+ }
+ if (tab)
+ {
+ for (p = (char**)tab; t = *p; p = (char**)((char*)p + siz))
+ {
+ for (v = s; *t && *t++ == *v; v++);
+ if (!*t || isspace(*v) || *v == ',' || *v == '=')
+ break;
+ if (*v == ':' && *(v + 1) == '=')
+ {
+ v++;
+ n = -1;
+ break;
+ }
+ }
+ if (!t)
+ {
+ u = v = s;
+ p = 0;
+ }
+ }
+ else
+ {
+ p = (char**)(v = s);
+ t = 0;
+ }
+ while (*v && !isspace(*v) && *v != '=' && *v != ',')
+ if (*v++ == ':' && *v == '=')
+ {
+ if (!t)
+ *(v - 1) = 0;
+ n = -n;
+ break;
+ }
+ if (*v == '=')
+ {
+ if (!t)
+ *v = 0;
+ t = s = ++v;
+ ql = qr = 0;
+ while (c = *s++)
+ {
+ if (c == '\\')
+ {
+ *t++ = chresc(s - 1, &e);
+ s = e;
+ }
+ else if (c == qr)
+ {
+ if (qr != ql)
+ *t++ = c;
+ if (--qc <= 0)
+ qr = ql = 0;
+ }
+ else if (c == ql)
+ {
+ *t++ = c;
+ qc++;
+ }
+ else if (qr)
+ *t++ = c;
+ else if (c == ',' || isspace(c))
+ break;
+ else if (c == '"' || c == '\'')
+ {
+ ql = qr = c;
+ qc = 1;
+ }
+ else
+ {
+ *t++ = c;
+ if (c == '{')
+ {
+ ql = c;
+ qr = '}';
+ qc = 1;
+ }
+ else if (c == '(')
+ {
+ ql = c;
+ qr = ')';
+ qc = 1;
+ }
+ }
+ }
+ *t = 0;
+ }
+ else
+ {
+ s = v;
+ c = *s;
+ *s++ = 0;
+ }
+ n = p ? (*f)(a, p, n, v) : (*f)(a, p, v - u, u);
+ if (n || !c)
+ break;
+ }
+ free(x);
+ }
+ return n;
+}