Annotation of src/lib/libc/gen/vis.c, Revision 1.59
1.59 ! christos 1: /* $NetBSD: vis.c,v 1.58 2013/02/20 19:59:34 tron Exp $ */
1.6 cgd 2:
1.1 cgd 3: /*-
1.6 cgd 4: * Copyright (c) 1989, 1993
1.16 wennmach 5: * The Regents of the University of California. All rights reserved.
1.1 cgd 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.
1.29 lukem 15: * 3. Neither the name of the University nor the names of its contributors
1.1 cgd 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:
1.26 agc 32: /*-
1.31 lukem 33: * Copyright (c) 1999, 2005 The NetBSD Foundation, Inc.
1.30 lukem 34: * All rights reserved.
1.26 agc 35: *
36: * Redistribution and use in source and binary forms, with or without
37: * modification, are permitted provided that the following conditions
38: * are met:
39: * 1. Redistributions of source code must retain the above copyright
40: * notice, this list of conditions and the following disclaimer.
41: * 2. Redistributions in binary form must reproduce the above copyright
42: * notice, this list of conditions and the following disclaimer in the
43: * documentation and/or other materials provided with the distribution.
44: *
1.30 lukem 45: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
46: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
47: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
48: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
49: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
50: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
51: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
52: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
53: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
54: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
55: * POSSIBILITY OF SUCH DAMAGE.
1.26 agc 56: */
57:
1.7 christos 58: #include <sys/cdefs.h>
1.21 tv 59: #if defined(LIBC_SCCS) && !defined(lint)
1.59 ! christos 60: __RCSID("$NetBSD: vis.c,v 1.58 2013/02/20 19:59:34 tron Exp $");
1.21 tv 61: #endif /* LIBC_SCCS and not lint */
1.46 christos 62: #ifdef __FBSDID
63: __FBSDID("$FreeBSD$");
64: #define _DIAGASSERT(x) assert(x)
65: #endif
1.1 cgd 66:
1.8 jtc 67: #include "namespace.h"
1.1 cgd 68: #include <sys/types.h>
1.59 ! christos 69: #include <sys/param.h>
1.12 lukem 70:
71: #include <assert.h>
1.1 cgd 72: #include <vis.h>
1.44 christos 73: #include <errno.h>
1.22 christos 74: #include <stdlib.h>
1.46 christos 75: #include <wchar.h>
76: #include <wctype.h>
1.8 jtc 77:
78: #ifdef __weak_alias
1.18 mycroft 79: __weak_alias(strvisx,_strvisx)
1.20 tv 80: #endif
81:
1.24 pooka 82: #if !HAVE_VIS || !HAVE_SVIS
1.20 tv 83: #include <ctype.h>
84: #include <limits.h>
85: #include <stdio.h>
86: #include <string.h>
1.1 cgd 87:
1.47 christos 88: /*
89: * The reason for going through the trouble to deal with character encodings
90: * in vis(3), is that we use this to safe encode output of commands. This
91: * safe encoding varies depending on the character set. For example if we
92: * display ps output in French, we don't want to display French characters
93: * as M-foo.
94: */
95:
1.48 pooka 96: static wchar_t *do_svis(wchar_t *, wint_t, int, wint_t, const wchar_t *);
1.37 dsl 97:
1.15 wennmach 98: #undef BELL
1.46 christos 99: #define BELL L'\a'
1.15 wennmach 100:
1.46 christos 101: #define iswoctal(c) (((u_char)(c)) >= L'0' && ((u_char)(c)) <= L'7')
102: #define iswwhite(c) (c == L' ' || c == L'\t' || c == L'\n')
103: #define iswsafe(c) (c == L'\b' || c == BELL || c == L'\r')
104: #define xtoa(c) L"0123456789abcdef"[c]
105: #define XTOA(c) L"0123456789ABCDEF"[c]
1.16 wennmach 106:
1.54 christos 107: #define MAXEXTRAS 10
1.15 wennmach 108:
1.59 ! christos 109: #ifndef __NetBSD__
1.57 christos 110: /*
111: * On NetBSD MB_LEN_MAX is currently 32 which does not fit on any integer
112: * integral type and it is probably wrong, since currently the maximum
113: * number of bytes and character needs is 6. Until this is fixed, the
114: * loops below are using sizeof(uint64_t) - 1 instead of MB_LEN_MAX, and
115: * the assertion is commented out.
116: */
1.59 ! christos 117: #ifdef __FreeBSD__
! 118: /*
! 119: * On FreeBSD including <sys/systm.h> for CTASSERT only works in kernel
! 120: * mode.
! 121: */
! 122: #ifndef CTASSERT
! 123: #define CTASSERT(x) _CTASSERT(x, __LINE__)
! 124: #define _CTASSERT(x, y) __CTASSERT(x, y)
! 125: #define __CTASSERT(x, y) typedef char __assert ## y[(x) ? 1 : -1]
1.57 christos 126: #endif
1.59 ! christos 127: #endif /* __FreeBSD__ */
! 128: CTASSERT(MB_LEN_MAX <= sizeof(uint64_t));
! 129: #endif /* !__NetBSD__ */
1.57 christos 130:
1.22 christos 131: /*
1.37 dsl 132: * This is do_hvis, for HTTP style (RFC 1808)
1.22 christos 133: */
1.46 christos 134: static wchar_t *
1.54 christos 135: do_hvis(wchar_t *dst, wint_t c, int flags, wint_t nextc, const wchar_t *extra)
1.37 dsl 136: {
1.46 christos 137: if (iswalnum(c)
1.41 plunky 138: /* safe */
1.46 christos 139: || c == L'$' || c == L'-' || c == L'_' || c == L'.' || c == L'+'
1.41 plunky 140: /* extra */
1.46 christos 141: || c == L'!' || c == L'*' || c == L'\'' || c == L'(' || c == L')'
142: || c == L',')
1.54 christos 143: dst = do_svis(dst, c, flags, nextc, extra);
1.46 christos 144: else {
145: *dst++ = L'%';
1.37 dsl 146: *dst++ = xtoa(((unsigned int)c >> 4) & 0xf);
147: *dst++ = xtoa((unsigned int)c & 0xf);
148: }
1.41 plunky 149:
1.37 dsl 150: return dst;
151: }
1.27 enami 152:
1.15 wennmach 153: /*
1.39 christos 154: * This is do_mvis, for Quoted-Printable MIME (RFC 2045)
155: * NB: No handling of long lines or CRLF.
156: */
1.46 christos 157: static wchar_t *
1.54 christos 158: do_mvis(wchar_t *dst, wint_t c, int flags, wint_t nextc, const wchar_t *extra)
1.39 christos 159: {
1.46 christos 160: if ((c != L'\n') &&
1.39 christos 161: /* Space at the end of the line */
1.46 christos 162: ((iswspace(c) && (nextc == L'\r' || nextc == L'\n')) ||
1.39 christos 163: /* Out of range */
1.46 christos 164: (!iswspace(c) && (c < 33 || (c > 60 && c < 62) || c > 126)) ||
1.55 christos 165: /* Specific char to be escaped */
1.46 christos 166: wcschr(L"#$@[\\]^`{|}~", c) != NULL)) {
167: *dst++ = L'=';
1.39 christos 168: *dst++ = XTOA(((unsigned int)c >> 4) & 0xf);
169: *dst++ = XTOA((unsigned int)c & 0xf);
1.46 christos 170: } else
1.54 christos 171: dst = do_svis(dst, c, flags, nextc, extra);
1.39 christos 172: return dst;
173: }
174:
175: /*
1.54 christos 176: * Output single byte of multibyte character.
1.15 wennmach 177: */
1.46 christos 178: static wchar_t *
1.54 christos 179: do_mbyte(wchar_t *dst, wint_t c, int flags, wint_t nextc, int iswextra)
1.37 dsl 180: {
1.54 christos 181: if (flags & VIS_CSTYLE) {
1.37 dsl 182: switch (c) {
1.46 christos 183: case L'\n':
184: *dst++ = L'\\'; *dst++ = L'n';
1.37 dsl 185: return dst;
1.46 christos 186: case L'\r':
187: *dst++ = L'\\'; *dst++ = L'r';
1.37 dsl 188: return dst;
1.46 christos 189: case L'\b':
190: *dst++ = L'\\'; *dst++ = L'b';
1.37 dsl 191: return dst;
192: case BELL:
1.46 christos 193: *dst++ = L'\\'; *dst++ = L'a';
1.37 dsl 194: return dst;
1.46 christos 195: case L'\v':
196: *dst++ = L'\\'; *dst++ = L'v';
1.37 dsl 197: return dst;
1.46 christos 198: case L'\t':
199: *dst++ = L'\\'; *dst++ = L't';
1.37 dsl 200: return dst;
1.46 christos 201: case L'\f':
202: *dst++ = L'\\'; *dst++ = L'f';
1.37 dsl 203: return dst;
1.46 christos 204: case L' ':
205: *dst++ = L'\\'; *dst++ = L's';
1.37 dsl 206: return dst;
1.46 christos 207: case L'\0':
208: *dst++ = L'\\'; *dst++ = L'0';
209: if (iswoctal(nextc)) {
210: *dst++ = L'0';
211: *dst++ = L'0';
1.37 dsl 212: }
213: return dst;
214: default:
1.46 christos 215: if (iswgraph(c)) {
216: *dst++ = L'\\';
217: *dst++ = c;
1.37 dsl 218: return dst;
219: }
220: }
221: }
1.54 christos 222: if (iswextra || ((c & 0177) == L' ') || (flags & VIS_OCTAL)) {
1.46 christos 223: *dst++ = L'\\';
224: *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + L'0';
225: *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + L'0';
226: *dst++ = (c & 07) + L'0';
1.37 dsl 227: } else {
1.54 christos 228: if ((flags & VIS_NOSLASH) == 0)
1.46 christos 229: *dst++ = L'\\';
1.55 christos 230:
1.37 dsl 231: if (c & 0200) {
1.46 christos 232: c &= 0177;
233: *dst++ = L'M';
1.37 dsl 234: }
1.55 christos 235:
1.46 christos 236: if (iswcntrl(c)) {
237: *dst++ = L'^';
1.37 dsl 238: if (c == 0177)
1.46 christos 239: *dst++ = L'?';
1.37 dsl 240: else
1.46 christos 241: *dst++ = c + L'@';
1.37 dsl 242: } else {
1.46 christos 243: *dst++ = L'-';
244: *dst++ = c;
1.37 dsl 245: }
246: }
1.54 christos 247:
248: return dst;
249: }
250:
251: /*
252: * This is do_vis, the central code of vis.
253: * dst: Pointer to the destination buffer
254: * c: Character to encode
1.59 ! christos 255: * flags: Flags word
1.54 christos 256: * nextc: The character following 'c'
257: * extra: Pointer to the list of extra characters to be
258: * backslash-protected.
259: */
260: static wchar_t *
261: do_svis(wchar_t *dst, wint_t c, int flags, wint_t nextc, const wchar_t *extra)
262: {
263: int iswextra, i, shft;
1.57 christos 264: uint64_t bmsk, wmsk;
1.54 christos 265:
266: iswextra = wcschr(extra, c) != NULL;
267: if (!iswextra && (iswgraph(c) || iswwhite(c) ||
268: ((flags & VIS_SAFE) && iswsafe(c)))) {
269: *dst++ = c;
270: return dst;
271: }
272:
273: /* See comment in istrsenvisx() output loop, below. */
274: wmsk = 0;
1.59 ! christos 275: for (i = sizeof(wmsk) - 1; i >= 0; i--) {
1.54 christos 276: shft = i * NBBY;
1.59 ! christos 277: bmsk = (uint64_t)0xffLL << shft;
1.54 christos 278: wmsk |= bmsk;
279: if ((c & wmsk) || i == 0)
280: dst = do_mbyte(dst, (wint_t)(
1.59 ! christos 281: (uint64_t)(c & bmsk) >> shft),
1.54 christos 282: flags, nextc, iswextra);
283: }
284:
1.37 dsl 285: return dst;
286: }
1.15 wennmach 287:
1.46 christos 288: typedef wchar_t *(*visfun_t)(wchar_t *, wint_t, int, wint_t, const wchar_t *);
1.39 christos 289:
290: /*
291: * Return the appropriate encoding function depending on the flags given.
292: */
293: static visfun_t
1.54 christos 294: getvisfun(int flags)
1.39 christos 295: {
1.54 christos 296: if (flags & VIS_HTTPSTYLE)
1.39 christos 297: return do_hvis;
1.54 christos 298: if (flags & VIS_MIMESTYLE)
1.39 christos 299: return do_mvis;
300: return do_svis;
301: }
1.15 wennmach 302:
303: /*
1.54 christos 304: * Expand list of extra characters to not visually encode.
305: */
306: static wchar_t *
307: makeextralist(int flags, const char *src)
308: {
309: wchar_t *dst, *d;
310: size_t len;
311:
312: len = strlen(src);
313: if ((dst = calloc(len + MAXEXTRAS, sizeof(*dst))) == NULL)
314: return NULL;
315:
316: if (mbstowcs(dst, src, len) == (size_t)-1) {
1.58 tron 317: size_t i;
318: for (i = 0; i < len; i++)
1.54 christos 319: dst[i] = (wint_t)(u_char)src[i];
320: d = dst + len;
321: } else
322: d = dst + wcslen(dst);
323:
324: if (flags & VIS_GLOB) {
325: *d++ = L'*';
326: *d++ = L'?';
327: *d++ = L'[';
328: *d++ = L'#';
329: }
330:
1.55 christos 331: if (flags & VIS_SP) *d++ = L' ';
332: if (flags & VIS_TAB) *d++ = L'\t';
1.54 christos 333: if (flags & VIS_NL) *d++ = L'\n';
334: if ((flags & VIS_NOSLASH) == 0) *d++ = L'\\';
335: *d = L'\0';
336:
337: return dst;
338: }
339:
340: /*
341: * istrsenvisx()
1.46 christos 342: * The main internal function.
343: * All user-visible functions call this one.
1.15 wennmach 344: */
1.46 christos 345: static int
1.54 christos 346: istrsenvisx(char *mbdst, size_t *dlen, const char *mbsrc, size_t mblength,
347: int flags, const char *mbextra, int *cerr_ptr)
1.15 wennmach 348: {
1.54 christos 349: wchar_t *dst, *src, *pdst, *psrc, *start, *extra;
1.50 christos 350: size_t len, olen;
1.57 christos 351: uint64_t bmsk, wmsk;
352: wint_t c;
1.39 christos 353: visfun_t f;
1.56 riz 354: int clen = 0, cerr = 0, error = -1, i, shft;
1.54 christos 355: ssize_t mbslength, maxolen;
1.46 christos 356:
357: _DIAGASSERT(mbdst != NULL);
358: _DIAGASSERT(mbsrc != NULL);
359: _DIAGASSERT(mbextra != NULL);
360:
1.53 christos 361: /*
362: * Input (mbsrc) is a char string considered to be multibyte
363: * characters. The input loop will read this string pulling
364: * one character, possibly multiple bytes, from mbsrc and
365: * converting each to wchar_t in src.
366: *
367: * The vis conversion will be done using the wide char
368: * wchar_t string.
369: *
370: * This will then be converted back to a multibyte string to
371: * return to the caller.
372: */
373:
374: /* Allocate space for the wide char strings */
1.54 christos 375: psrc = pdst = extra = NULL;
1.46 christos 376: if (!mblength)
377: mblength = strlen(mbsrc);
378: if ((psrc = calloc(mblength + 1, sizeof(*psrc))) == NULL)
379: return -1;
380: if ((pdst = calloc((4 * mblength) + 1, sizeof(*pdst))) == NULL)
381: goto out;
382: dst = pdst;
383: src = psrc;
384:
1.59 ! christos 385: /* Use caller's multibyte conversion error flag. */
1.54 christos 386: if (cerr_ptr)
387: cerr = *cerr_ptr;
388:
1.53 christos 389: /*
390: * Input loop.
391: * Handle up to mblength characters (not bytes). We do not
392: * stop at NULs because we may be processing a block of data
1.54 christos 393: * that includes NULs.
1.53 christos 394: */
1.50 christos 395: mbslength = (ssize_t)mblength;
1.53 christos 396: /*
397: * When inputing a single character, must also read in the
398: * next character for nextc, the look-ahead character.
399: */
400: if (mbslength == 1)
401: mbslength++;
402: while (mbslength > 0) {
403: /* Convert one multibyte character to wchar_t. */
1.54 christos 404: if (!cerr)
405: clen = mbtowc(src, mbsrc, MB_LEN_MAX);
406: if (cerr || clen < 0) {
1.53 christos 407: /* Conversion error, process as a byte instead. */
1.54 christos 408: *src = (wint_t)(u_char)*mbsrc;
1.50 christos 409: clen = 1;
1.54 christos 410: cerr = 1;
1.51 christos 411: }
1.50 christos 412: if (clen == 0)
1.53 christos 413: /*
414: * NUL in input gives 0 return value. process
1.54 christos 415: * as single NUL byte and keep going.
1.53 christos 416: */
1.50 christos 417: clen = 1;
1.54 christos 418: /* Advance buffer character pointer. */
1.50 christos 419: src++;
1.53 christos 420: /* Advance input pointer by number of bytes read. */
1.50 christos 421: mbsrc += clen;
1.54 christos 422: /* Decrement input byte count. */
1.50 christos 423: mbslength -= clen;
1.46 christos 424: }
1.55 christos 425: len = src - psrc;
1.50 christos 426: src = psrc;
1.53 christos 427: /*
428: * In the single character input case, we will have actually
429: * processed two characters, c and nextc. Reset len back to
430: * just a single character.
431: */
432: if (mblength < len)
433: len = mblength;
1.46 christos 434:
1.53 christos 435: /* Convert extra argument to list of characters for this mode. */
1.54 christos 436: extra = makeextralist(flags, mbextra);
437: if (!extra) {
1.44 christos 438: if (dlen && *dlen == 0) {
439: errno = ENOSPC;
1.46 christos 440: goto out;
1.44 christos 441: }
1.54 christos 442: *mbdst = '\0'; /* can't create extra, return "" */
1.46 christos 443: error = 0;
444: goto out;
1.31 lukem 445: }
1.46 christos 446:
1.53 christos 447: /* Look up which processing function to call. */
1.54 christos 448: f = getvisfun(flags);
1.46 christos 449:
1.53 christos 450: /*
451: * Main processing loop.
452: * Call do_Xvis processing function one character at a time
453: * with next character available for look-ahead.
454: */
1.46 christos 455: for (start = dst; len > 0; len--) {
456: c = *src++;
1.54 christos 457: dst = (*f)(dst, c, flags, len >= 1 ? *src : L'\0', extra);
1.46 christos 458: if (dst == NULL) {
459: errno = ENOSPC;
460: goto out;
461: }
462: }
463:
1.54 christos 464: /* Terminate the string in the buffer. */
465: *dst = L'\0';
466:
467: /*
468: * Output loop.
469: * Convert wchar_t string back to multibyte output string.
470: * If we have hit a multi-byte conversion error on input,
471: * output byte-by-byte here. Else use wctomb().
472: */
473: len = wcslen(start);
474: maxolen = dlen ? *dlen : (wcslen(start) * MB_LEN_MAX + 1);
475: olen = 0;
476: for (dst = start; len > 0; len--) {
477: if (!cerr)
478: clen = wctomb(mbdst, *dst);
479: if (cerr || clen < 0) {
480: /*
481: * Conversion error, process as a byte(s) instead.
482: * Examine each byte and higher-order bytes for
1.55 christos 483: * data. E.g.,
1.59 ! christos 484: * 0x000000000000a264 -> a2 64
! 485: * 0x000000001f00a264 -> 1f 00 a2 64
1.54 christos 486: */
487: clen = 0;
488: wmsk = 0;
1.59 ! christos 489: for (i = sizeof(wmsk) - 1; i >= 0; i--) {
1.54 christos 490: shft = i * NBBY;
1.59 ! christos 491: bmsk = (uint64_t)0xffLL << shft;
1.54 christos 492: wmsk |= bmsk;
493: if ((*dst & wmsk) || i == 0)
1.59 ! christos 494: mbdst[clen++] = (char)(
! 495: (uint64_t)(*dst & bmsk) >>
! 496: shft);
1.54 christos 497: }
498: cerr = 1;
499: }
500: /* If this character would exceed our output limit, stop. */
501: if (olen + clen > (size_t)maxolen)
502: break;
503: /* Advance output pointer by number of bytes written. */
504: mbdst += clen;
505: /* Advance buffer character pointer. */
506: dst++;
507: /* Incrment output character count. */
508: olen += clen;
509: }
510:
1.53 christos 511: /* Terminate the output string. */
1.54 christos 512: *mbdst = '\0';
1.46 christos 513:
1.59 ! christos 514: /* Pass conversion error flag out. */
1.54 christos 515: if (cerr_ptr)
516: *cerr_ptr = cerr;
1.46 christos 517:
518: free(extra);
519: free(pdst);
520: free(psrc);
521:
522: return (int)olen;
523: out:
524: free(extra);
525: free(pdst);
526: free(psrc);
527: return error;
1.15 wennmach 528: }
1.46 christos 529: #endif
530:
531: #if !HAVE_SVIS
532: /*
533: * The "svis" variants all take an "extra" arg that is a pointer
534: * to a NUL-terminated list of characters to be encoded, too.
535: * These functions are useful e. g. to encode strings in such a
536: * way so that they are not interpreted by a shell.
537: */
1.15 wennmach 538:
1.44 christos 539: char *
1.54 christos 540: svis(char *mbdst, int c, int flags, int nextc, const char *mbextra)
1.44 christos 541: {
1.46 christos 542: char cc[2];
543: int ret;
544:
545: cc[0] = c;
546: cc[1] = nextc;
547:
1.54 christos 548: ret = istrsenvisx(mbdst, NULL, cc, 1, flags, mbextra, NULL);
1.46 christos 549: if (ret < 0)
550: return NULL;
551: return mbdst + ret;
1.44 christos 552: }
553:
554: char *
1.54 christos 555: snvis(char *mbdst, size_t dlen, int c, int flags, int nextc, const char *mbextra)
1.44 christos 556: {
1.46 christos 557: char cc[2];
558: int ret;
1.44 christos 559:
1.46 christos 560: cc[0] = c;
561: cc[1] = nextc;
1.15 wennmach 562:
1.54 christos 563: ret = istrsenvisx(mbdst, &dlen, cc, 1, flags, mbextra, NULL);
1.46 christos 564: if (ret < 0)
565: return NULL;
566: return mbdst + ret;
1.15 wennmach 567: }
568:
1.44 christos 569: int
1.54 christos 570: strsvis(char *mbdst, const char *mbsrc, int flags, const char *mbextra)
1.44 christos 571: {
1.54 christos 572: return istrsenvisx(mbdst, NULL, mbsrc, 0, flags, mbextra, NULL);
1.44 christos 573: }
1.15 wennmach 574:
575: int
1.54 christos 576: strsnvis(char *mbdst, size_t dlen, const char *mbsrc, int flags, const char *mbextra)
1.44 christos 577: {
1.54 christos 578: return istrsenvisx(mbdst, &dlen, mbsrc, 0, flags, mbextra, NULL);
1.15 wennmach 579: }
1.44 christos 580:
581: int
1.54 christos 582: strsvisx(char *mbdst, const char *mbsrc, size_t len, int flags, const char *mbextra)
1.44 christos 583: {
1.54 christos 584: return istrsenvisx(mbdst, NULL, mbsrc, len, flags, mbextra, NULL);
1.44 christos 585: }
586:
587: int
1.54 christos 588: strsnvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags,
1.46 christos 589: const char *mbextra)
1.44 christos 590: {
1.54 christos 591: return istrsenvisx(mbdst, &dlen, mbsrc, len, flags, mbextra, NULL);
592: }
593:
594: int
595: strsenvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags,
596: const char *mbextra, int *cerr_ptr)
597: {
598: return istrsenvisx(mbdst, &dlen, mbsrc, len, flags, mbextra, cerr_ptr);
1.44 christos 599: }
1.24 pooka 600: #endif
1.15 wennmach 601:
1.24 pooka 602: #if !HAVE_VIS
1.1 cgd 603: /*
604: * vis - visually encode characters
605: */
1.46 christos 606: char *
1.54 christos 607: vis(char *mbdst, int c, int flags, int nextc)
1.15 wennmach 608: {
1.46 christos 609: char cc[2];
610: int ret;
1.15 wennmach 611:
1.46 christos 612: cc[0] = c;
613: cc[1] = nextc;
1.15 wennmach 614:
1.54 christos 615: ret = istrsenvisx(mbdst, NULL, cc, 1, flags, "", NULL);
1.46 christos 616: if (ret < 0)
1.44 christos 617: return NULL;
1.46 christos 618: return mbdst + ret;
1.1 cgd 619: }
620:
1.44 christos 621: char *
1.54 christos 622: nvis(char *mbdst, size_t dlen, int c, int flags, int nextc)
1.44 christos 623: {
1.46 christos 624: char cc[2];
625: int ret;
626:
627: cc[0] = c;
628: cc[1] = nextc;
1.44 christos 629:
1.54 christos 630: ret = istrsenvisx(mbdst, &dlen, cc, 1, flags, "", NULL);
1.46 christos 631: if (ret < 0)
632: return NULL;
633: return mbdst + ret;
1.44 christos 634: }
635:
1.1 cgd 636: /*
1.46 christos 637: * strvis - visually encode characters from src into dst
1.27 enami 638: *
1.16 wennmach 639: * Dst must be 4 times the size of src to account for possible
640: * expansion. The length of dst, not including the trailing NULL,
1.27 enami 641: * is returned.
1.1 cgd 642: */
643:
1.44 christos 644: int
1.54 christos 645: strvis(char *mbdst, const char *mbsrc, int flags)
1.44 christos 646: {
1.54 christos 647: return istrsenvisx(mbdst, NULL, mbsrc, 0, flags, "", NULL);
1.44 christos 648: }
1.15 wennmach 649:
1.1 cgd 650: int
1.54 christos 651: strnvis(char *mbdst, size_t dlen, const char *mbsrc, int flags)
1.44 christos 652: {
1.54 christos 653: return istrsenvisx(mbdst, &dlen, mbsrc, 0, flags, "", NULL);
1.44 christos 654: }
655:
1.46 christos 656: /*
657: * strvisx - visually encode characters from src into dst
658: *
659: * Dst must be 4 times the size of src to account for possible
660: * expansion. The length of dst, not including the trailing NULL,
661: * is returned.
662: *
663: * Strvisx encodes exactly len characters from src into dst.
664: * This is useful for encoding a block of data.
665: */
1.44 christos 666:
667: int
1.54 christos 668: strvisx(char *mbdst, const char *mbsrc, size_t len, int flags)
669: {
670: return istrsenvisx(mbdst, NULL, mbsrc, len, flags, "", NULL);
671: }
672:
673: int
674: strnvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags)
1.44 christos 675: {
1.54 christos 676: return istrsenvisx(mbdst, &dlen, mbsrc, len, flags, "", NULL);
1.44 christos 677: }
678:
679: int
1.54 christos 680: strenvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags,
681: int *cerr_ptr)
1.44 christos 682: {
1.54 christos 683: return istrsenvisx(mbdst, &dlen, mbsrc, len, flags, "", cerr_ptr);
1.44 christos 684: }
1.20 tv 685: #endif
CVSweb <webmaster@jp.NetBSD.org>