60{
61 static char *
storage = NULL;
/* store the local copy of the users
62 * string here */
63 static char *string = NULL; /* pointer into storage where to continue on
64 * next call */
65
66 /* variously abused variables: */
67 unsigned int offset;
69 char *p;
70
71 if (s)
72 {
74
75 /*
76 * We may need extra space to insert delimiter nulls for adjacent
77 * tokens. 2X the space is a gross overestimate, but it's unlikely
78 * that this code will be used on huge strings anyway.
79 */
83 }
84
86 return NULL;
87
88 /* skip leading whitespace */
89 offset = strspn(string, whitespace);
90 start = &
string[offset];
91
92 /* end of string reached? */
94 {
95 /* technically we don't need to free here, but we're nice */
98 string = NULL;
99 return NULL;
100 }
101
102 /* test if delimiter character */
103 if (delim && strchr(delim, *
start))
104 {
105 /*
106 * If not at end of string, we need to insert a null to terminate the
107 * returned token. We can just overwrite the next character if it
108 * happens to be in the whitespace set ... otherwise move over the
109 * rest of the string to make room. (This is why we allocated extra
110 * space above).
111 */
113 if (*p != '0円')
114 {
115 if (!strchr(whitespace, *p))
116 memmove(p + 1, p, strlen(p) + 1);
117 *p = '0円';
118 string = p + 1;
119 }
120 else
121 {
122 /* at end of string, so no extra work */
123 string = p;
124 }
125
127 }
128
129 /* check for E string */
131 if (e_strings &&
132 (*p == 'E' || *p == 'e') &&
133 p[1] == '\'')
134 {
135 quote = "'";
136 escape = '\\'; /* if std strings before, not any more */
137 p++;
138 }
139
140 /* test if quoting character */
141 if (quote && strchr(quote, *p))
142 {
143 /* okay, we have a quoted token, now scan for the closer */
144 char thisquote = *p++;
145
147 {
148 if (*p == escape && p[1] != '0円')
149 p++; /* process escaped anything */
150 else if (*p == thisquote && p[1] == thisquote)
151 p++; /* process doubled quote */
152 else if (*p == thisquote)
153 {
154 p++; /* skip trailing quote */
155 break;
156 }
157 }
158
159 /*
160 * If not at end of string, we need to insert a null to terminate the
161 * returned token. See notes above.
162 */
163 if (*p != '0円')
164 {
165 if (!strchr(whitespace, *p))
166 memmove(p + 1, p, strlen(p) + 1);
167 *p = '0円';
168 string = p + 1;
169 }
170 else
171 {
172 /* at end of string, so no extra work */
173 string = p;
174 }
175
176 /* Clean up the token if caller wants that */
177 if (del_quotes)
179
181 }
182
183 /*
184 * Otherwise no quoting character. Scan till next whitespace, delimiter
185 * or quote. NB: at this point, *start is known not to be '0円',
186 * whitespace, delim, or quote, so we will consume at least one character.
187 */
188 offset = strcspn(
start, whitespace);
189
190 if (delim)
191 {
192 unsigned int offset2 = strcspn(
start, delim);
193
194 if (offset > offset2)
195 offset = offset2;
196 }
197
198 if (quote)
199 {
200 unsigned int offset2 = strcspn(
start, quote);
201
202 if (offset > offset2)
203 offset = offset2;
204 }
205
207
208 /*
209 * If not at end of string, we need to insert a null to terminate the
210 * returned token. See notes above.
211 */
212 if (*p != '0円')
213 {
214 if (!strchr(whitespace, *p))
215 memmove(p + 1, p, strlen(p) + 1);
216 *p = '0円';
217 string = p + 1;
218 }
219 else
220 {
221 /* at end of string, so no extra work */
222 string = p;
223 }
224
226}
void strip_quotes(char *source, char quote, char escape, int encoding)