xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/mystrtok.c (revision c38e7cc395b1472a774ff828e46123de44c628e9)
1 /*	$NetBSD: mystrtok.c,v 1.2 2017/02/14 01:16:49 christos Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	mystrtok 3
6 /* SUMMARY
7 /*	safe tokenizer
8 /* SYNOPSIS
9 /*	#include <stringops.h>
10 /*
11 /*	char	*mystrtok(bufp, delimiters)
12 /*	char	**bufp;
13 /*	const char *delimiters;
14 /*
15 /*	char	*mystrtokq(bufp, delimiters, parens)
16 /*	char	**bufp;
17 /*	const char *delimiters;
18 /*	const char *parens;
19 /* DESCRIPTION
20 /*	mystrtok() splits a buffer on the specified \fIdelimiters\fR.
21 /*	Tokens are delimited by runs of delimiters, so this routine
22 /*	cannot return zero-length tokens.
23 /*
24 /*	mystrtokq() is like mystrtok() but will not split text
25 /*	between balanced parentheses.  \fIparens\fR specifies the
26 /*	opening and closing parenthesis (one of each).  The set of
27 /*	\fIparens\fR must be distinct from the set of \fIdelimiters\fR.
28 /*
29 /*	The \fIbufp\fR argument specifies the start of the search; it
30 /*	is updated with each call. The input is destroyed.
31 /*
32 /*	The result value is the next token, or a null pointer when the
33 /*	end of the buffer was reached.
34 /* LICENSE
35 /* .ad
36 /* .fi
37 /*	The Secure Mailer license must be distributed with this software.
38 /* AUTHOR(S)
39 /*	Wietse Venema
40 /*	IBM T.J. Watson Research
41 /*	P.O. Box 704
42 /*	Yorktown Heights, NY 10598, USA
43 /*--*/
44 
45 /* System library. */
46 
47 #include "sys_defs.h"
48 #include <string.h>
49 
50 /* Utility library. */
51 
52 #include "stringops.h"
53 
54 /* mystrtok - safe tokenizer */
55 
56 char   *mystrtok(char **src, const char *sep)
57 {
58     char   *start = *src;
59     char   *end;
60 
61     /*
62      * Skip over leading delimiters.
63      */
64     start += strspn(start, sep);
65     if (*start == 0) {
66 	*src = start;
67 	return (0);
68     }
69 
70     /*
71      * Separate off one token.
72      */
73     end = start + strcspn(start, sep);
74     if (*end != 0)
75 	*end++ = 0;
76     *src = end;
77     return (start);
78 }
79 
80 /* mystrtokq - safe tokenizer with quoting support */
81 
82 char   *mystrtokq(char **src, const char *sep, const char *parens)
83 {
84     char   *start = *src;
85     static char   *cp;
86     int     ch;
87     int     level;
88 
89     /*
90      * Skip over leading delimiters.
91      */
92     start += strspn(start, sep);
93     if (*start == 0) {
94 	*src = start;
95 	return (0);
96     }
97 
98     /*
99      * Parse out the next token.
100      */
101     for (level = 0, cp = start; (ch = *(unsigned char *) cp) != 0; cp++) {
102 	if (ch == parens[0]) {
103 	    level++;
104         } else if (level > 0 && ch == parens[1]) {
105 	    level--;
106 	} else if (level == 0 && strchr(sep, ch) != 0) {
107 	    *cp++ = 0;
108 	    break;
109 	}
110     }
111     *src = cp;
112     return (start);
113 }
114 
115 #ifdef TEST
116 
117  /*
118   * Test program: read lines from stdin, split on whitespace.
119   */
120 #include "vstring.h"
121 #include "vstream.h"
122 #include "vstring_vstream.h"
123 
124 int     main(void)
125 {
126     VSTRING *vp = vstring_alloc(100);
127     char   *start;
128     char   *str;
129 
130     while (vstring_fgets(vp, VSTREAM_IN) && VSTRING_LEN(vp) > 0) {
131 	start = vstring_str(vp);
132 	if (strchr(start, CHARS_BRACE[0]) == 0) {
133 	    while ((str = mystrtok(&start, CHARS_SPACE)) != 0)
134 		vstream_printf(">%s<\n", str);
135 	} else {
136 	    while ((str = mystrtokq(&start, CHARS_SPACE, CHARS_BRACE)) != 0)
137 		vstream_printf(">%s<\n", str);
138 	}
139 	vstream_fflush(VSTREAM_OUT);
140     }
141     vstring_free(vp);
142     return (0);
143 }
144 
145 #endif
146