1 |
/* $NetBSD: unvis.c,v 1.41 2012/12/15 04:29:53 matt Exp $ */ |
2 |
|
3 |
/*- |
4 |
* Copyright (c) 1989, 1993 |
5 |
* The Regents of the University of California. All rights reserved. |
6 |
* |
7 |
* Redistribution and use in source and binary forms, with or without |
8 |
* modification, are permitted provided that the following conditions |
9 |
* are met: |
10 |
* 1. Redistributions of source code must retain the above copyright |
11 |
* notice, this list of conditions and the following disclaimer. |
12 |
* 2. Redistributions in binary form must reproduce the above copyright |
13 |
* notice, this list of conditions and the following disclaimer in the |
14 |
* documentation and/or other materials provided with the distribution. |
15 |
* 3. Neither the name of the University nor the names of its contributors |
16 |
* may be used to endorse or promote products derived from this software |
17 |
* without specific prior written permission. |
18 |
* |
19 |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
20 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
21 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
22 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
23 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
24 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
25 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
26 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
27 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
28 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
29 |
* SUCH DAMAGE. |
30 |
*/ |
31 |
|
32 |
#include <sys/cdefs.h> |
33 |
#if defined(LIBC_SCCS) && !defined(lint) |
34 |
#if 0 |
35 |
static char sccsid[] = "@(#)unvis.c 8.1 (Berkeley) 6/4/93"; |
36 |
#else |
37 |
__RCSID("$NetBSD: unvis.c,v 1.41 2012/12/15 04:29:53 matt Exp $"); |
38 |
#endif |
39 |
#endif /* LIBC_SCCS and not lint */ |
40 |
__FBSDID("$FreeBSD: release/9.2.0/contrib/libc-vis/unvis.c 249560 2013-04-16 19:27:09Z brooks $"); |
41 |
|
42 |
#include "namespace.h" |
43 |
#include <sys/types.h> |
44 |
|
45 |
#include <assert.h> |
46 |
#include <ctype.h> |
47 |
#include <stdint.h> |
48 |
#include <stdio.h> |
49 |
#include <errno.h> |
50 |
#include <vis.h> |
51 |
|
52 |
#define _DIAGASSERT(x) assert(x) |
53 |
|
54 |
/* |
55 |
* Return the number of elements in a statically-allocated array, |
56 |
* __x. |
57 |
*/ |
58 |
#define __arraycount(__x) (sizeof(__x) / sizeof(__x[0])) |
59 |
|
60 |
#ifdef __weak_alias |
61 |
__weak_alias(strnunvisx,_strnunvisx) |
62 |
#endif |
63 |
|
64 |
#if !HAVE_VIS |
65 |
/* |
66 |
* decode driven by state machine |
67 |
*/ |
68 |
#define S_GROUND 0 /* haven't seen escape char */ |
69 |
#define S_START 1 /* start decoding special sequence */ |
70 |
#define S_META 2 /* metachar started (M) */ |
71 |
#define S_META1 3 /* metachar more, regular char (-) */ |
72 |
#define S_CTRL 4 /* control char started (^) */ |
73 |
#define S_OCTAL2 5 /* octal digit 2 */ |
74 |
#define S_OCTAL3 6 /* octal digit 3 */ |
75 |
#define S_HEX 7 /* mandatory hex digit */ |
76 |
#define S_HEX1 8 /* http hex digit */ |
77 |
#define S_HEX2 9 /* http hex digit 2 */ |
78 |
#define S_MIME1 10 /* mime hex digit 1 */ |
79 |
#define S_MIME2 11 /* mime hex digit 2 */ |
80 |
#define S_EATCRNL 12 /* mime eating CRNL */ |
81 |
#define S_AMP 13 /* seen & */ |
82 |
#define S_NUMBER 14 /* collecting number */ |
83 |
#define S_STRING 15 /* collecting string */ |
84 |
|
85 |
#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') |
86 |
#define xtod(c) (isdigit(c) ? (c - '0') : ((tolower(c) - 'a') + 10)) |
87 |
#define XTOD(c) (isdigit(c) ? (c - '0') : ((c - 'A') + 10)) |
88 |
|
89 |
/* |
90 |
* RFC 1866 |
91 |
*/ |
92 |
static const struct nv { |
93 |
char name[7]; |
94 |
uint8_t value; |
95 |
} nv[] = { |
96 |
{ "AElig", 198 }, /* capital AE diphthong (ligature) */ |
97 |
{ "Aacute", 193 }, /* capital A, acute accent */ |
98 |
{ "Acirc", 194 }, /* capital A, circumflex accent */ |
99 |
{ "Agrave", 192 }, /* capital A, grave accent */ |
100 |
{ "Aring", 197 }, /* capital A, ring */ |
101 |
{ "Atilde", 195 }, /* capital A, tilde */ |
102 |
{ "Auml", 196 }, /* capital A, dieresis or umlaut mark */ |
103 |
{ "Ccedil", 199 }, /* capital C, cedilla */ |
104 |
{ "ETH", 208 }, /* capital Eth, Icelandic */ |
105 |
{ "Eacute", 201 }, /* capital E, acute accent */ |
106 |
{ "Ecirc", 202 }, /* capital E, circumflex accent */ |
107 |
{ "Egrave", 200 }, /* capital E, grave accent */ |
108 |
{ "Euml", 203 }, /* capital E, dieresis or umlaut mark */ |
109 |
{ "Iacute", 205 }, /* capital I, acute accent */ |
110 |
{ "Icirc", 206 }, /* capital I, circumflex accent */ |
111 |
{ "Igrave", 204 }, /* capital I, grave accent */ |
112 |
{ "Iuml", 207 }, /* capital I, dieresis or umlaut mark */ |
113 |
{ "Ntilde", 209 }, /* capital N, tilde */ |
114 |
{ "Oacute", 211 }, /* capital O, acute accent */ |
115 |
{ "Ocirc", 212 }, /* capital O, circumflex accent */ |
116 |
{ "Ograve", 210 }, /* capital O, grave accent */ |
117 |
{ "Oslash", 216 }, /* capital O, slash */ |
118 |
{ "Otilde", 213 }, /* capital O, tilde */ |
119 |
{ "Ouml", 214 }, /* capital O, dieresis or umlaut mark */ |
120 |
{ "THORN", 222 }, /* capital THORN, Icelandic */ |
121 |
{ "Uacute", 218 }, /* capital U, acute accent */ |
122 |
{ "Ucirc", 219 }, /* capital U, circumflex accent */ |
123 |
{ "Ugrave", 217 }, /* capital U, grave accent */ |
124 |
{ "Uuml", 220 }, /* capital U, dieresis or umlaut mark */ |
125 |
{ "Yacute", 221 }, /* capital Y, acute accent */ |
126 |
{ "aacute", 225 }, /* small a, acute accent */ |
127 |
{ "acirc", 226 }, /* small a, circumflex accent */ |
128 |
{ "acute", 180 }, /* acute accent */ |
129 |
{ "aelig", 230 }, /* small ae diphthong (ligature) */ |
130 |
{ "agrave", 224 }, /* small a, grave accent */ |
131 |
{ "amp", 38 }, /* ampersand */ |
132 |
{ "aring", 229 }, /* small a, ring */ |
133 |
{ "atilde", 227 }, /* small a, tilde */ |
134 |
{ "auml", 228 }, /* small a, dieresis or umlaut mark */ |
135 |
{ "brvbar", 166 }, /* broken (vertical) bar */ |
136 |
{ "ccedil", 231 }, /* small c, cedilla */ |
137 |
{ "cedil", 184 }, /* cedilla */ |
138 |
{ "cent", 162 }, /* cent sign */ |
139 |
{ "copy", 169 }, /* copyright sign */ |
140 |
{ "curren", 164 }, /* general currency sign */ |
141 |
{ "deg", 176 }, /* degree sign */ |
142 |
{ "divide", 247 }, /* divide sign */ |
143 |
{ "eacute", 233 }, /* small e, acute accent */ |
144 |
{ "ecirc", 234 }, /* small e, circumflex accent */ |
145 |
{ "egrave", 232 }, /* small e, grave accent */ |
146 |
{ "eth", 240 }, /* small eth, Icelandic */ |
147 |
{ "euml", 235 }, /* small e, dieresis or umlaut mark */ |
148 |
{ "frac12", 189 }, /* fraction one-half */ |
149 |
{ "frac14", 188 }, /* fraction one-quarter */ |
150 |
{ "frac34", 190 }, /* fraction three-quarters */ |
151 |
{ "gt", 62 }, /* greater than */ |
152 |
{ "iacute", 237 }, /* small i, acute accent */ |
153 |
{ "icirc", 238 }, /* small i, circumflex accent */ |
154 |
{ "iexcl", 161 }, /* inverted exclamation mark */ |
155 |
{ "igrave", 236 }, /* small i, grave accent */ |
156 |
{ "iquest", 191 }, /* inverted question mark */ |
157 |
{ "iuml", 239 }, /* small i, dieresis or umlaut mark */ |
158 |
{ "laquo", 171 }, /* angle quotation mark, left */ |
159 |
{ "lt", 60 }, /* less than */ |
160 |
{ "macr", 175 }, /* macron */ |
161 |
{ "micro", 181 }, /* micro sign */ |
162 |
{ "middot", 183 }, /* middle dot */ |
163 |
{ "nbsp", 160 }, /* no-break space */ |
164 |
{ "not", 172 }, /* not sign */ |
165 |
{ "ntilde", 241 }, /* small n, tilde */ |
166 |
{ "oacute", 243 }, /* small o, acute accent */ |
167 |
{ "ocirc", 244 }, /* small o, circumflex accent */ |
168 |
{ "ograve", 242 }, /* small o, grave accent */ |
169 |
{ "ordf", 170 }, /* ordinal indicator, feminine */ |
170 |
{ "ordm", 186 }, /* ordinal indicator, masculine */ |
171 |
{ "oslash", 248 }, /* small o, slash */ |
172 |
{ "otilde", 245 }, /* small o, tilde */ |
173 |
{ "ouml", 246 }, /* small o, dieresis or umlaut mark */ |
174 |
{ "para", 182 }, /* pilcrow (paragraph sign) */ |
175 |
{ "plusmn", 177 }, /* plus-or-minus sign */ |
176 |
{ "pound", 163 }, /* pound sterling sign */ |
177 |
{ "quot", 34 }, /* double quote */ |
178 |
{ "raquo", 187 }, /* angle quotation mark, right */ |
179 |
{ "reg", 174 }, /* registered sign */ |
180 |
{ "sect", 167 }, /* section sign */ |
181 |
{ "shy", 173 }, /* soft hyphen */ |
182 |
{ "sup1", 185 }, /* superscript one */ |
183 |
{ "sup2", 178 }, /* superscript two */ |
184 |
{ "sup3", 179 }, /* superscript three */ |
185 |
{ "szlig", 223 }, /* small sharp s, German (sz ligature) */ |
186 |
{ "thorn", 254 }, /* small thorn, Icelandic */ |
187 |
{ "times", 215 }, /* multiply sign */ |
188 |
{ "uacute", 250 }, /* small u, acute accent */ |
189 |
{ "ucirc", 251 }, /* small u, circumflex accent */ |
190 |
{ "ugrave", 249 }, /* small u, grave accent */ |
191 |
{ "uml", 168 }, /* umlaut (dieresis) */ |
192 |
{ "uuml", 252 }, /* small u, dieresis or umlaut mark */ |
193 |
{ "yacute", 253 }, /* small y, acute accent */ |
194 |
{ "yen", 165 }, /* yen sign */ |
195 |
{ "yuml", 255 }, /* small y, dieresis or umlaut mark */ |
196 |
}; |
197 |
|
198 |
/* |
199 |
* unvis - decode characters previously encoded by vis |
200 |
*/ |
201 |
int |
202 |
unvis(char *cp, int c, int *astate, int flag) |
203 |
{ |
204 |
unsigned char uc = (unsigned char)c; |
205 |
unsigned char st, ia, is, lc; |
206 |
|
207 |
/* |
208 |
* Bottom 8 bits of astate hold the state machine state. |
209 |
* Top 8 bits hold the current character in the http 1866 nv string decoding |
210 |
*/ |
211 |
#define GS(a) ((a) & 0xff) |
212 |
#define SS(a, b) (((uint32_t)(a) << 24) | (b)) |
213 |
#define GI(a) ((uint32_t)(a) >> 24) |
214 |
|
215 |
_DIAGASSERT(cp != NULL); |
216 |
_DIAGASSERT(astate != NULL); |
217 |
st = GS(*astate); |
218 |
|
219 |
if (flag & UNVIS_END) { |
220 |
switch (st) { |
221 |
case S_OCTAL2: |
222 |
case S_OCTAL3: |
223 |
case S_HEX2: |
224 |
*astate = SS(0, S_GROUND); |
225 |
return UNVIS_VALID; |
226 |
case S_GROUND: |
227 |
return UNVIS_NOCHAR; |
228 |
default: |
229 |
return UNVIS_SYNBAD; |
230 |
} |
231 |
} |
232 |
|
233 |
switch (st) { |
234 |
|
235 |
case S_GROUND: |
236 |
*cp = 0; |
237 |
if ((flag & VIS_NOESCAPE) == 0 && c == '\\') { |
238 |
*astate = SS(0, S_START); |
239 |
return UNVIS_NOCHAR; |
240 |
} |
241 |
if ((flag & VIS_HTTP1808) && c == '%') { |
242 |
*astate = SS(0, S_HEX1); |
243 |
return UNVIS_NOCHAR; |
244 |
} |
245 |
if ((flag & VIS_HTTP1866) && c == '&') { |
246 |
*astate = SS(0, S_AMP); |
247 |
return UNVIS_NOCHAR; |
248 |
} |
249 |
if ((flag & VIS_MIMESTYLE) && c == '=') { |
250 |
*astate = SS(0, S_MIME1); |
251 |
return UNVIS_NOCHAR; |
252 |
} |
253 |
*cp = c; |
254 |
return UNVIS_VALID; |
255 |
|
256 |
case S_START: |
257 |
switch(c) { |
258 |
case '\\': |
259 |
*cp = c; |
260 |
*astate = SS(0, S_GROUND); |
261 |
return UNVIS_VALID; |
262 |
case '0': case '1': case '2': case '3': |
263 |
case '4': case '5': case '6': case '7': |
264 |
*cp = (c - '0'); |
265 |
*astate = SS(0, S_OCTAL2); |
266 |
return UNVIS_NOCHAR; |
267 |
case 'M': |
268 |
*cp = (char)0200; |
269 |
*astate = SS(0, S_META); |
270 |
return UNVIS_NOCHAR; |
271 |
case '^': |
272 |
*astate = SS(0, S_CTRL); |
273 |
return UNVIS_NOCHAR; |
274 |
case 'n': |
275 |
*cp = '\n'; |
276 |
*astate = SS(0, S_GROUND); |
277 |
return UNVIS_VALID; |
278 |
case 'r': |
279 |
*cp = '\r'; |
280 |
*astate = SS(0, S_GROUND); |
281 |
return UNVIS_VALID; |
282 |
case 'b': |
283 |
*cp = '\b'; |
284 |
*astate = SS(0, S_GROUND); |
285 |
return UNVIS_VALID; |
286 |
case 'a': |
287 |
*cp = '\007'; |
288 |
*astate = SS(0, S_GROUND); |
289 |
return UNVIS_VALID; |
290 |
case 'v': |
291 |
*cp = '\v'; |
292 |
*astate = SS(0, S_GROUND); |
293 |
return UNVIS_VALID; |
294 |
case 't': |
295 |
*cp = '\t'; |
296 |
*astate = SS(0, S_GROUND); |
297 |
return UNVIS_VALID; |
298 |
case 'f': |
299 |
*cp = '\f'; |
300 |
*astate = SS(0, S_GROUND); |
301 |
return UNVIS_VALID; |
302 |
case 's': |
303 |
*cp = ' '; |
304 |
*astate = SS(0, S_GROUND); |
305 |
return UNVIS_VALID; |
306 |
case 'E': |
307 |
*cp = '\033'; |
308 |
*astate = SS(0, S_GROUND); |
309 |
return UNVIS_VALID; |
310 |
case 'x': |
311 |
*astate = SS(0, S_HEX); |
312 |
return UNVIS_NOCHAR; |
313 |
case '\n': |
314 |
/* |
315 |
* hidden newline |
316 |
*/ |
317 |
*astate = SS(0, S_GROUND); |
318 |
return UNVIS_NOCHAR; |
319 |
case '$': |
320 |
/* |
321 |
* hidden marker |
322 |
*/ |
323 |
*astate = SS(0, S_GROUND); |
324 |
return UNVIS_NOCHAR; |
325 |
} |
326 |
goto bad; |
327 |
|
328 |
case S_META: |
329 |
if (c == '-') |
330 |
*astate = SS(0, S_META1); |
331 |
else if (c == '^') |
332 |
*astate = SS(0, S_CTRL); |
333 |
else |
334 |
goto bad; |
335 |
return UNVIS_NOCHAR; |
336 |
|
337 |
case S_META1: |
338 |
*astate = SS(0, S_GROUND); |
339 |
*cp |= c; |
340 |
return UNVIS_VALID; |
341 |
|
342 |
case S_CTRL: |
343 |
if (c == '?') |
344 |
*cp |= 0177; |
345 |
else |
346 |
*cp |= c & 037; |
347 |
*astate = SS(0, S_GROUND); |
348 |
return UNVIS_VALID; |
349 |
|
350 |
case S_OCTAL2: /* second possible octal digit */ |
351 |
if (isoctal(uc)) { |
352 |
/* |
353 |
* yes - and maybe a third |
354 |
*/ |
355 |
*cp = (*cp << 3) + (c - '0'); |
356 |
*astate = SS(0, S_OCTAL3); |
357 |
return UNVIS_NOCHAR; |
358 |
} |
359 |
/* |
360 |
* no - done with current sequence, push back passed char |
361 |
*/ |
362 |
*astate = SS(0, S_GROUND); |
363 |
return UNVIS_VALIDPUSH; |
364 |
|
365 |
case S_OCTAL3: /* third possible octal digit */ |
366 |
*astate = SS(0, S_GROUND); |
367 |
if (isoctal(uc)) { |
368 |
*cp = (*cp << 3) + (c - '0'); |
369 |
return UNVIS_VALID; |
370 |
} |
371 |
/* |
372 |
* we were done, push back passed char |
373 |
*/ |
374 |
return UNVIS_VALIDPUSH; |
375 |
|
376 |
case S_HEX: |
377 |
if (!isxdigit(uc)) |
378 |
goto bad; |
379 |
/*FALLTHROUGH*/ |
380 |
case S_HEX1: |
381 |
if (isxdigit(uc)) { |
382 |
*cp = xtod(uc); |
383 |
*astate = SS(0, S_HEX2); |
384 |
return UNVIS_NOCHAR; |
385 |
} |
386 |
/* |
387 |
* no - done with current sequence, push back passed char |
388 |
*/ |
389 |
*astate = SS(0, S_GROUND); |
390 |
return UNVIS_VALIDPUSH; |
391 |
|
392 |
case S_HEX2: |
393 |
*astate = S_GROUND; |
394 |
if (isxdigit(uc)) { |
395 |
*cp = xtod(uc) | (*cp << 4); |
396 |
return UNVIS_VALID; |
397 |
} |
398 |
return UNVIS_VALIDPUSH; |
399 |
|
400 |
case S_MIME1: |
401 |
if (uc == '\n' || uc == '\r') { |
402 |
*astate = SS(0, S_EATCRNL); |
403 |
return UNVIS_NOCHAR; |
404 |
} |
405 |
if (isxdigit(uc) && (isdigit(uc) || isupper(uc))) { |
406 |
*cp = XTOD(uc); |
407 |
*astate = SS(0, S_MIME2); |
408 |
return UNVIS_NOCHAR; |
409 |
} |
410 |
goto bad; |
411 |
|
412 |
case S_MIME2: |
413 |
if (isxdigit(uc) && (isdigit(uc) || isupper(uc))) { |
414 |
*astate = SS(0, S_GROUND); |
415 |
*cp = XTOD(uc) | (*cp << 4); |
416 |
return UNVIS_VALID; |
417 |
} |
418 |
goto bad; |
419 |
|
420 |
case S_EATCRNL: |
421 |
switch (uc) { |
422 |
case '\r': |
423 |
case '\n': |
424 |
return UNVIS_NOCHAR; |
425 |
case '=': |
426 |
*astate = SS(0, S_MIME1); |
427 |
return UNVIS_NOCHAR; |
428 |
default: |
429 |
*cp = uc; |
430 |
*astate = SS(0, S_GROUND); |
431 |
return UNVIS_VALID; |
432 |
} |
433 |
|
434 |
case S_AMP: |
435 |
*cp = 0; |
436 |
if (uc == '#') { |
437 |
*astate = SS(0, S_NUMBER); |
438 |
return UNVIS_NOCHAR; |
439 |
} |
440 |
*astate = SS(0, S_STRING); |
441 |
/*FALLTHROUGH*/ |
442 |
|
443 |
case S_STRING: |
444 |
ia = *cp; /* index in the array */ |
445 |
is = GI(*astate); /* index in the string */ |
446 |
lc = is == 0 ? 0 : nv[ia].name[is - 1]; /* last character */ |
447 |
|
448 |
if (uc == ';') |
449 |
uc = '\0'; |
450 |
|
451 |
for (; ia < __arraycount(nv); ia++) { |
452 |
if (is != 0 && nv[ia].name[is - 1] != lc) |
453 |
goto bad; |
454 |
if (nv[ia].name[is] == uc) |
455 |
break; |
456 |
} |
457 |
|
458 |
if (ia == __arraycount(nv)) |
459 |
goto bad; |
460 |
|
461 |
if (uc != 0) { |
462 |
*cp = ia; |
463 |
*astate = SS(is + 1, S_STRING); |
464 |
return UNVIS_NOCHAR; |
465 |
} |
466 |
|
467 |
*cp = nv[ia].value; |
468 |
*astate = SS(0, S_GROUND); |
469 |
return UNVIS_VALID; |
470 |
|
471 |
case S_NUMBER: |
472 |
if (uc == ';') |
473 |
return UNVIS_VALID; |
474 |
if (!isdigit(uc)) |
475 |
goto bad; |
476 |
*cp += (*cp * 10) + uc - '0'; |
477 |
return UNVIS_NOCHAR; |
478 |
|
479 |
default: |
480 |
bad: |
481 |
/* |
482 |
* decoder in unknown state - (probably uninitialized) |
483 |
*/ |
484 |
*astate = SS(0, S_GROUND); |
485 |
return UNVIS_SYNBAD; |
486 |
} |
487 |
} |
488 |
|
489 |
/* |
490 |
* strnunvisx - decode src into dst |
491 |
* |
492 |
* Number of chars decoded into dst is returned, -1 on error. |
493 |
* Dst is null terminated. |
494 |
*/ |
495 |
|
496 |
int |
497 |
strnunvisx(char *dst, size_t dlen, const char *src, int flag) |
498 |
{ |
499 |
char c; |
500 |
char t = '\0', *start = dst; |
501 |
int state = 0; |
502 |
|
503 |
_DIAGASSERT(src != NULL); |
504 |
_DIAGASSERT(dst != NULL); |
505 |
#define CHECKSPACE() \ |
506 |
do { \ |
507 |
if (dlen-- == 0) { \ |
508 |
errno = ENOSPC; \ |
509 |
return -1; \ |
510 |
} \ |
511 |
} while (/*CONSTCOND*/0) |
512 |
|
513 |
while ((c = *src++) != '\0') { |
514 |
again: |
515 |
switch (unvis(&t, c, &state, flag)) { |
516 |
case UNVIS_VALID: |
517 |
CHECKSPACE(); |
518 |
*dst++ = t; |
519 |
break; |
520 |
case UNVIS_VALIDPUSH: |
521 |
CHECKSPACE(); |
522 |
*dst++ = t; |
523 |
goto again; |
524 |
case 0: |
525 |
case UNVIS_NOCHAR: |
526 |
break; |
527 |
case UNVIS_SYNBAD: |
528 |
errno = EINVAL; |
529 |
return -1; |
530 |
default: |
531 |
_DIAGASSERT(/*CONSTCOND*/0); |
532 |
errno = EINVAL; |
533 |
return -1; |
534 |
} |
535 |
} |
536 |
if (unvis(&t, c, &state, UNVIS_END) == UNVIS_VALID) { |
537 |
CHECKSPACE(); |
538 |
*dst++ = t; |
539 |
} |
540 |
CHECKSPACE(); |
541 |
*dst = '\0'; |
542 |
return (int)(dst - start); |
543 |
} |
544 |
|
545 |
int |
546 |
strunvisx(char *dst, const char *src, int flag) |
547 |
{ |
548 |
return strnunvisx(dst, (size_t)~0, src, flag); |
549 |
} |
550 |
|
551 |
int |
552 |
strunvis(char *dst, const char *src) |
553 |
{ |
554 |
return strnunvisx(dst, (size_t)~0, src, 0); |
555 |
} |
556 |
|
557 |
int |
558 |
strnunvis(char *dst, size_t dlen, const char *src) |
559 |
{ |
560 |
return strnunvisx(dst, dlen, src, 0); |
561 |
} |
562 |
#endif |