summaryrefslogtreecommitdiffstats
path: root/src/util/mystrtok.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/mystrtok.c')
-rw-r--r--src/util/mystrtok.c143
1 files changed, 143 insertions, 0 deletions
diff --git a/src/util/mystrtok.c b/src/util/mystrtok.c
new file mode 100644
index 0000000..91e3c47
--- /dev/null
+++ b/src/util/mystrtok.c
@@ -0,0 +1,143 @@
+/*++
+/* NAME
+/* mystrtok 3
+/* SUMMARY
+/* safe tokenizer
+/* SYNOPSIS
+/* #include <stringops.h>
+/*
+/* char *mystrtok(bufp, delimiters)
+/* char **bufp;
+/* const char *delimiters;
+/*
+/* char *mystrtokq(bufp, delimiters, parens)
+/* char **bufp;
+/* const char *delimiters;
+/* const char *parens;
+/* DESCRIPTION
+/* mystrtok() splits a buffer on the specified \fIdelimiters\fR.
+/* Tokens are delimited by runs of delimiters, so this routine
+/* cannot return zero-length tokens.
+/*
+/* mystrtokq() is like mystrtok() but will not split text
+/* between balanced parentheses. \fIparens\fR specifies the
+/* opening and closing parenthesis (one of each). The set of
+/* \fIparens\fR must be distinct from the set of \fIdelimiters\fR.
+/*
+/* The \fIbufp\fR argument specifies the start of the search; it
+/* is updated with each call. The input is destroyed.
+/*
+/* The result value is the next token, or a null pointer when the
+/* end of the buffer was reached.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include "sys_defs.h"
+#include <string.h>
+
+/* Utility library. */
+
+#include "stringops.h"
+
+/* mystrtok - safe tokenizer */
+
+char *mystrtok(char **src, const char *sep)
+{
+ char *start = *src;
+ char *end;
+
+ /*
+ * Skip over leading delimiters.
+ */
+ start += strspn(start, sep);
+ if (*start == 0) {
+ *src = start;
+ return (0);
+ }
+
+ /*
+ * Separate off one token.
+ */
+ end = start + strcspn(start, sep);
+ if (*end != 0)
+ *end++ = 0;
+ *src = end;
+ return (start);
+}
+
+/* mystrtokq - safe tokenizer with quoting support */
+
+char *mystrtokq(char **src, const char *sep, const char *parens)
+{
+ char *start = *src;
+ static char *cp;
+ int ch;
+ int level;
+
+ /*
+ * Skip over leading delimiters.
+ */
+ start += strspn(start, sep);
+ if (*start == 0) {
+ *src = start;
+ return (0);
+ }
+
+ /*
+ * Parse out the next token.
+ */
+ for (level = 0, cp = start; (ch = *(unsigned char *) cp) != 0; cp++) {
+ if (ch == parens[0]) {
+ level++;
+ } else if (level > 0 && ch == parens[1]) {
+ level--;
+ } else if (level == 0 && strchr(sep, ch) != 0) {
+ *cp++ = 0;
+ break;
+ }
+ }
+ *src = cp;
+ return (start);
+}
+
+#ifdef TEST
+
+ /*
+ * Test program: read lines from stdin, split on whitespace.
+ */
+#include "vstring.h"
+#include "vstream.h"
+#include "vstring_vstream.h"
+
+int main(void)
+{
+ VSTRING *vp = vstring_alloc(100);
+ char *start;
+ char *str;
+
+ while (vstring_fgets(vp, VSTREAM_IN) && VSTRING_LEN(vp) > 0) {
+ start = vstring_str(vp);
+ if (strchr(start, CHARS_BRACE[0]) == 0) {
+ while ((str = mystrtok(&start, CHARS_SPACE)) != 0)
+ vstream_printf(">%s<\n", str);
+ } else {
+ while ((str = mystrtokq(&start, CHARS_SPACE, CHARS_BRACE)) != 0)
+ vstream_printf(">%s<\n", str);
+ }
+ vstream_fflush(VSTREAM_OUT);
+ }
+ vstring_free(vp);
+ return (0);
+}
+
+#endif