xref: /minix3/lib/libc/gen/vis.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: vis.c,v 1.70 2015/05/26 21:42:46 christos Exp $	*/
22fe8fb19SBen Gras 
32fe8fb19SBen Gras /*-
42fe8fb19SBen Gras  * Copyright (c) 1989, 1993
52fe8fb19SBen Gras  *	The Regents of the University of California.  All rights reserved.
62fe8fb19SBen Gras  *
72fe8fb19SBen Gras  * Redistribution and use in source and binary forms, with or without
82fe8fb19SBen Gras  * modification, are permitted provided that the following conditions
92fe8fb19SBen Gras  * are met:
102fe8fb19SBen Gras  * 1. Redistributions of source code must retain the above copyright
112fe8fb19SBen Gras  *    notice, this list of conditions and the following disclaimer.
122fe8fb19SBen Gras  * 2. Redistributions in binary form must reproduce the above copyright
132fe8fb19SBen Gras  *    notice, this list of conditions and the following disclaimer in the
142fe8fb19SBen Gras  *    documentation and/or other materials provided with the distribution.
152fe8fb19SBen Gras  * 3. Neither the name of the University nor the names of its contributors
162fe8fb19SBen Gras  *    may be used to endorse or promote products derived from this software
172fe8fb19SBen Gras  *    without specific prior written permission.
182fe8fb19SBen Gras  *
192fe8fb19SBen Gras  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
202fe8fb19SBen Gras  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
212fe8fb19SBen Gras  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
222fe8fb19SBen Gras  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
232fe8fb19SBen Gras  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
242fe8fb19SBen Gras  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
252fe8fb19SBen Gras  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
262fe8fb19SBen Gras  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
272fe8fb19SBen Gras  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
282fe8fb19SBen Gras  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
292fe8fb19SBen Gras  * SUCH DAMAGE.
302fe8fb19SBen Gras  */
312fe8fb19SBen Gras 
322fe8fb19SBen Gras /*-
332fe8fb19SBen Gras  * Copyright (c) 1999, 2005 The NetBSD Foundation, Inc.
342fe8fb19SBen Gras  * All rights reserved.
352fe8fb19SBen Gras  *
362fe8fb19SBen Gras  * Redistribution and use in source and binary forms, with or without
372fe8fb19SBen Gras  * modification, are permitted provided that the following conditions
382fe8fb19SBen Gras  * are met:
392fe8fb19SBen Gras  * 1. Redistributions of source code must retain the above copyright
402fe8fb19SBen Gras  *    notice, this list of conditions and the following disclaimer.
412fe8fb19SBen Gras  * 2. Redistributions in binary form must reproduce the above copyright
422fe8fb19SBen Gras  *    notice, this list of conditions and the following disclaimer in the
432fe8fb19SBen Gras  *    documentation and/or other materials provided with the distribution.
442fe8fb19SBen Gras  *
452fe8fb19SBen Gras  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
462fe8fb19SBen Gras  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
472fe8fb19SBen Gras  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
482fe8fb19SBen Gras  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
492fe8fb19SBen Gras  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
502fe8fb19SBen Gras  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
512fe8fb19SBen Gras  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
522fe8fb19SBen Gras  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
532fe8fb19SBen Gras  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
542fe8fb19SBen Gras  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
552fe8fb19SBen Gras  * POSSIBILITY OF SUCH DAMAGE.
562fe8fb19SBen Gras  */
572fe8fb19SBen Gras 
582fe8fb19SBen Gras #include <sys/cdefs.h>
592fe8fb19SBen Gras #if defined(LIBC_SCCS) && !defined(lint)
60*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: vis.c,v 1.70 2015/05/26 21:42:46 christos Exp $");
612fe8fb19SBen Gras #endif /* LIBC_SCCS and not lint */
6284d9c625SLionel Sambuc #ifdef __FBSDID
6384d9c625SLionel Sambuc __FBSDID("$FreeBSD$");
6484d9c625SLionel Sambuc #define	_DIAGASSERT(x)	assert(x)
6584d9c625SLionel Sambuc #endif
662fe8fb19SBen Gras 
672fe8fb19SBen Gras #include "namespace.h"
682fe8fb19SBen Gras #include <sys/types.h>
6984d9c625SLionel Sambuc #include <sys/param.h>
702fe8fb19SBen Gras 
712fe8fb19SBen Gras #include <assert.h>
722fe8fb19SBen Gras #include <vis.h>
73f14fb602SLionel Sambuc #include <errno.h>
742fe8fb19SBen Gras #include <stdlib.h>
7584d9c625SLionel Sambuc #include <wchar.h>
7684d9c625SLionel Sambuc #include <wctype.h>
772fe8fb19SBen Gras 
782fe8fb19SBen Gras #ifdef __weak_alias
792fe8fb19SBen Gras __weak_alias(strvisx,_strvisx)
802fe8fb19SBen Gras #endif
812fe8fb19SBen Gras 
822fe8fb19SBen Gras #if !HAVE_VIS || !HAVE_SVIS
832fe8fb19SBen Gras #include <ctype.h>
842fe8fb19SBen Gras #include <limits.h>
852fe8fb19SBen Gras #include <stdio.h>
862fe8fb19SBen Gras #include <string.h>
872fe8fb19SBen Gras 
8884d9c625SLionel Sambuc /*
8984d9c625SLionel Sambuc  * The reason for going through the trouble to deal with character encodings
9084d9c625SLionel Sambuc  * in vis(3), is that we use this to safe encode output of commands. This
9184d9c625SLionel Sambuc  * safe encoding varies depending on the character set. For example if we
9284d9c625SLionel Sambuc  * display ps output in French, we don't want to display French characters
9384d9c625SLionel Sambuc  * as M-foo.
9484d9c625SLionel Sambuc  */
9584d9c625SLionel Sambuc 
9684d9c625SLionel Sambuc static wchar_t *do_svis(wchar_t *, wint_t, int, wint_t, const wchar_t *);
972fe8fb19SBen Gras 
982fe8fb19SBen Gras #undef BELL
9984d9c625SLionel Sambuc #define BELL L'\a'
1002fe8fb19SBen Gras 
101*0a6a1f1dSLionel Sambuc #if defined(LC_C_LOCALE)
102*0a6a1f1dSLionel Sambuc #define iscgraph(c)      isgraph_l(c, LC_C_LOCALE)
103*0a6a1f1dSLionel Sambuc #else
104*0a6a1f1dSLionel Sambuc /* Keep it simple for now, no locale stuff */
105*0a6a1f1dSLionel Sambuc #define iscgraph(c)	isgraph(c)
106*0a6a1f1dSLionel Sambuc #ifdef notyet
107*0a6a1f1dSLionel Sambuc #include <locale.h>
108*0a6a1f1dSLionel Sambuc static int
iscgraph(int c)109*0a6a1f1dSLionel Sambuc iscgraph(int c) {
110*0a6a1f1dSLionel Sambuc 	int rv;
111*0a6a1f1dSLionel Sambuc 	char *ol;
112*0a6a1f1dSLionel Sambuc 
113*0a6a1f1dSLionel Sambuc 	ol = setlocale(LC_CTYPE, "C");
114*0a6a1f1dSLionel Sambuc 	rv = isgraph(c);
115*0a6a1f1dSLionel Sambuc 	if (ol)
116*0a6a1f1dSLionel Sambuc 		setlocale(LC_CTYPE, ol);
117*0a6a1f1dSLionel Sambuc 	return rv;
118*0a6a1f1dSLionel Sambuc }
119*0a6a1f1dSLionel Sambuc #endif
120*0a6a1f1dSLionel Sambuc #endif
121*0a6a1f1dSLionel Sambuc 
122*0a6a1f1dSLionel Sambuc #define ISGRAPH(flags, c) \
123*0a6a1f1dSLionel Sambuc     (((flags) & VIS_NOLOCALE) ? iscgraph(c) : iswgraph(c))
124*0a6a1f1dSLionel Sambuc 
12584d9c625SLionel Sambuc #define iswoctal(c)	(((u_char)(c)) >= L'0' && ((u_char)(c)) <= L'7')
12684d9c625SLionel Sambuc #define iswwhite(c)	(c == L' ' || c == L'\t' || c == L'\n')
12784d9c625SLionel Sambuc #define iswsafe(c)	(c == L'\b' || c == BELL || c == L'\r')
12884d9c625SLionel Sambuc #define xtoa(c)		L"0123456789abcdef"[c]
12984d9c625SLionel Sambuc #define XTOA(c)		L"0123456789ABCDEF"[c]
1302fe8fb19SBen Gras 
131*0a6a1f1dSLionel Sambuc #define MAXEXTRAS	30
132*0a6a1f1dSLionel Sambuc 
133*0a6a1f1dSLionel Sambuc static const wchar_t char_shell[] = L"'`\";&<>()|{}]\\$!^~";
134*0a6a1f1dSLionel Sambuc static const wchar_t char_glob[] = L"*?[#";
1352fe8fb19SBen Gras 
13684d9c625SLionel Sambuc #if !HAVE_NBTOOL_CONFIG_H
13784d9c625SLionel Sambuc #if !defined(__NetBSD__) && ! defined(__minix)
13884d9c625SLionel Sambuc /*
13984d9c625SLionel Sambuc  * On NetBSD MB_LEN_MAX is currently 32 which does not fit on any integer
14084d9c625SLionel Sambuc  * integral type and it is probably wrong, since currently the maximum
14184d9c625SLionel Sambuc  * number of bytes and character needs is 6. Until this is fixed, the
14284d9c625SLionel Sambuc  * loops below are using sizeof(uint64_t) - 1 instead of MB_LEN_MAX, and
14384d9c625SLionel Sambuc  * the assertion is commented out.
14484d9c625SLionel Sambuc  */
14584d9c625SLionel Sambuc #ifdef __FreeBSD__
14684d9c625SLionel Sambuc /*
14784d9c625SLionel Sambuc  * On FreeBSD including <sys/systm.h> for CTASSERT only works in kernel
14884d9c625SLionel Sambuc  * mode.
14984d9c625SLionel Sambuc  */
15084d9c625SLionel Sambuc #ifndef CTASSERT
15184d9c625SLionel Sambuc #define CTASSERT(x)             _CTASSERT(x, __LINE__)
15284d9c625SLionel Sambuc #define _CTASSERT(x, y)         __CTASSERT(x, y)
15384d9c625SLionel Sambuc #define __CTASSERT(x, y)        typedef char __assert ## y[(x) ? 1 : -1]
15484d9c625SLionel Sambuc #endif
15584d9c625SLionel Sambuc #endif /* __FreeBSD__ */
15684d9c625SLionel Sambuc CTASSERT(MB_LEN_MAX <= sizeof(uint64_t));
15784d9c625SLionel Sambuc #endif /* !__NetBSD__ */
15884d9c625SLionel Sambuc #endif
1592fe8fb19SBen Gras 
1602fe8fb19SBen Gras /*
1612fe8fb19SBen Gras  * This is do_hvis, for HTTP style (RFC 1808)
1622fe8fb19SBen Gras  */
16384d9c625SLionel Sambuc static wchar_t *
do_hvis(wchar_t * dst,wint_t c,int flags,wint_t nextc,const wchar_t * extra)16484d9c625SLionel Sambuc do_hvis(wchar_t *dst, wint_t c, int flags, wint_t nextc, const wchar_t *extra)
1652fe8fb19SBen Gras {
16684d9c625SLionel Sambuc 	if (iswalnum(c)
1672fe8fb19SBen Gras 	    /* safe */
16884d9c625SLionel Sambuc 	    || c == L'$' || c == L'-' || c == L'_' || c == L'.' || c == L'+'
1692fe8fb19SBen Gras 	    /* extra */
17084d9c625SLionel Sambuc 	    || c == L'!' || c == L'*' || c == L'\'' || c == L'(' || c == L')'
17184d9c625SLionel Sambuc 	    || c == L',')
17284d9c625SLionel Sambuc 		dst = do_svis(dst, c, flags, nextc, extra);
17384d9c625SLionel Sambuc 	else {
17484d9c625SLionel Sambuc 		*dst++ = L'%';
1752fe8fb19SBen Gras 		*dst++ = xtoa(((unsigned int)c >> 4) & 0xf);
1762fe8fb19SBen Gras 		*dst++ = xtoa((unsigned int)c & 0xf);
1772fe8fb19SBen Gras 	}
1782fe8fb19SBen Gras 
1792fe8fb19SBen Gras 	return dst;
1802fe8fb19SBen Gras }
1812fe8fb19SBen Gras 
1822fe8fb19SBen Gras /*
1832fe8fb19SBen Gras  * This is do_mvis, for Quoted-Printable MIME (RFC 2045)
1842fe8fb19SBen Gras  * NB: No handling of long lines or CRLF.
1852fe8fb19SBen Gras  */
18684d9c625SLionel Sambuc static wchar_t *
do_mvis(wchar_t * dst,wint_t c,int flags,wint_t nextc,const wchar_t * extra)18784d9c625SLionel Sambuc do_mvis(wchar_t *dst, wint_t c, int flags, wint_t nextc, const wchar_t *extra)
1882fe8fb19SBen Gras {
18984d9c625SLionel Sambuc 	if ((c != L'\n') &&
1902fe8fb19SBen Gras 	    /* Space at the end of the line */
19184d9c625SLionel Sambuc 	    ((iswspace(c) && (nextc == L'\r' || nextc == L'\n')) ||
1922fe8fb19SBen Gras 	    /* Out of range */
19384d9c625SLionel Sambuc 	    (!iswspace(c) && (c < 33 || (c > 60 && c < 62) || c > 126)) ||
1942fe8fb19SBen Gras 	    /* Specific char to be escaped */
19584d9c625SLionel Sambuc 	    wcschr(L"#$@[\\]^`{|}~", c) != NULL)) {
19684d9c625SLionel Sambuc 		*dst++ = L'=';
1972fe8fb19SBen Gras 		*dst++ = XTOA(((unsigned int)c >> 4) & 0xf);
1982fe8fb19SBen Gras 		*dst++ = XTOA((unsigned int)c & 0xf);
19984d9c625SLionel Sambuc 	} else
20084d9c625SLionel Sambuc 		dst = do_svis(dst, c, flags, nextc, extra);
20184d9c625SLionel Sambuc 	return dst;
2022fe8fb19SBen Gras }
20384d9c625SLionel Sambuc 
20484d9c625SLionel Sambuc /*
20584d9c625SLionel Sambuc  * Output single byte of multibyte character.
20684d9c625SLionel Sambuc  */
20784d9c625SLionel Sambuc static wchar_t *
do_mbyte(wchar_t * dst,wint_t c,int flags,wint_t nextc,int iswextra)20884d9c625SLionel Sambuc do_mbyte(wchar_t *dst, wint_t c, int flags, wint_t nextc, int iswextra)
20984d9c625SLionel Sambuc {
21084d9c625SLionel Sambuc 	if (flags & VIS_CSTYLE) {
21184d9c625SLionel Sambuc 		switch (c) {
21284d9c625SLionel Sambuc 		case L'\n':
21384d9c625SLionel Sambuc 			*dst++ = L'\\'; *dst++ = L'n';
21484d9c625SLionel Sambuc 			return dst;
21584d9c625SLionel Sambuc 		case L'\r':
21684d9c625SLionel Sambuc 			*dst++ = L'\\'; *dst++ = L'r';
21784d9c625SLionel Sambuc 			return dst;
21884d9c625SLionel Sambuc 		case L'\b':
21984d9c625SLionel Sambuc 			*dst++ = L'\\'; *dst++ = L'b';
22084d9c625SLionel Sambuc 			return dst;
22184d9c625SLionel Sambuc 		case BELL:
22284d9c625SLionel Sambuc 			*dst++ = L'\\'; *dst++ = L'a';
22384d9c625SLionel Sambuc 			return dst;
22484d9c625SLionel Sambuc 		case L'\v':
22584d9c625SLionel Sambuc 			*dst++ = L'\\'; *dst++ = L'v';
22684d9c625SLionel Sambuc 			return dst;
22784d9c625SLionel Sambuc 		case L'\t':
22884d9c625SLionel Sambuc 			*dst++ = L'\\'; *dst++ = L't';
22984d9c625SLionel Sambuc 			return dst;
23084d9c625SLionel Sambuc 		case L'\f':
23184d9c625SLionel Sambuc 			*dst++ = L'\\'; *dst++ = L'f';
23284d9c625SLionel Sambuc 			return dst;
23384d9c625SLionel Sambuc 		case L' ':
23484d9c625SLionel Sambuc 			*dst++ = L'\\'; *dst++ = L's';
23584d9c625SLionel Sambuc 			return dst;
23684d9c625SLionel Sambuc 		case L'\0':
23784d9c625SLionel Sambuc 			*dst++ = L'\\'; *dst++ = L'0';
23884d9c625SLionel Sambuc 			if (iswoctal(nextc)) {
23984d9c625SLionel Sambuc 				*dst++ = L'0';
24084d9c625SLionel Sambuc 				*dst++ = L'0';
24184d9c625SLionel Sambuc 			}
24284d9c625SLionel Sambuc 			return dst;
243*0a6a1f1dSLionel Sambuc 		/* We cannot encode these characters in VIS_CSTYLE
244*0a6a1f1dSLionel Sambuc 		 * because they special meaning */
245*0a6a1f1dSLionel Sambuc 		case L'n':
246*0a6a1f1dSLionel Sambuc 		case L'r':
247*0a6a1f1dSLionel Sambuc 		case L'b':
248*0a6a1f1dSLionel Sambuc 		case L'a':
249*0a6a1f1dSLionel Sambuc 		case L'v':
250*0a6a1f1dSLionel Sambuc 		case L't':
251*0a6a1f1dSLionel Sambuc 		case L'f':
252*0a6a1f1dSLionel Sambuc 		case L's':
253*0a6a1f1dSLionel Sambuc 		case L'0':
254*0a6a1f1dSLionel Sambuc 		case L'M':
255*0a6a1f1dSLionel Sambuc 		case L'^':
256*0a6a1f1dSLionel Sambuc 		case L'$': /* vis(1) -l */
257*0a6a1f1dSLionel Sambuc 			break;
25884d9c625SLionel Sambuc 		default:
259*0a6a1f1dSLionel Sambuc 			if (ISGRAPH(flags, c) && !iswoctal(c)) {
26084d9c625SLionel Sambuc 				*dst++ = L'\\';
26184d9c625SLionel Sambuc 				*dst++ = c;
26284d9c625SLionel Sambuc 				return dst;
26384d9c625SLionel Sambuc 			}
26484d9c625SLionel Sambuc 		}
26584d9c625SLionel Sambuc 	}
26684d9c625SLionel Sambuc 	if (iswextra || ((c & 0177) == L' ') || (flags & VIS_OCTAL)) {
26784d9c625SLionel Sambuc 		*dst++ = L'\\';
26884d9c625SLionel Sambuc 		*dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + L'0';
26984d9c625SLionel Sambuc 		*dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + L'0';
27084d9c625SLionel Sambuc 		*dst++ =			     (c	      & 07) + L'0';
27184d9c625SLionel Sambuc 	} else {
27284d9c625SLionel Sambuc 		if ((flags & VIS_NOSLASH) == 0)
27384d9c625SLionel Sambuc 			*dst++ = L'\\';
27484d9c625SLionel Sambuc 
27584d9c625SLionel Sambuc 		if (c & 0200) {
27684d9c625SLionel Sambuc 			c &= 0177;
27784d9c625SLionel Sambuc 			*dst++ = L'M';
27884d9c625SLionel Sambuc 		}
27984d9c625SLionel Sambuc 
28084d9c625SLionel Sambuc 		if (iswcntrl(c)) {
28184d9c625SLionel Sambuc 			*dst++ = L'^';
28284d9c625SLionel Sambuc 			if (c == 0177)
28384d9c625SLionel Sambuc 				*dst++ = L'?';
28484d9c625SLionel Sambuc 			else
28584d9c625SLionel Sambuc 				*dst++ = c + L'@';
28684d9c625SLionel Sambuc 		} else {
28784d9c625SLionel Sambuc 			*dst++ = L'-';
28884d9c625SLionel Sambuc 			*dst++ = c;
28984d9c625SLionel Sambuc 		}
29084d9c625SLionel Sambuc 	}
29184d9c625SLionel Sambuc 
2922fe8fb19SBen Gras 	return dst;
2932fe8fb19SBen Gras }
2942fe8fb19SBen Gras 
2952fe8fb19SBen Gras /*
2962fe8fb19SBen Gras  * This is do_vis, the central code of vis.
2972fe8fb19SBen Gras  * dst:	      Pointer to the destination buffer
2982fe8fb19SBen Gras  * c:	      Character to encode
29984d9c625SLionel Sambuc  * flags:     Flags word
3002fe8fb19SBen Gras  * nextc:     The character following 'c'
3012fe8fb19SBen Gras  * extra:     Pointer to the list of extra characters to be
3022fe8fb19SBen Gras  *	      backslash-protected.
3032fe8fb19SBen Gras  */
30484d9c625SLionel Sambuc static wchar_t *
do_svis(wchar_t * dst,wint_t c,int flags,wint_t nextc,const wchar_t * extra)30584d9c625SLionel Sambuc do_svis(wchar_t *dst, wint_t c, int flags, wint_t nextc, const wchar_t *extra)
3062fe8fb19SBen Gras {
30784d9c625SLionel Sambuc 	int iswextra, i, shft;
30884d9c625SLionel Sambuc 	uint64_t bmsk, wmsk;
309f14fb602SLionel Sambuc 
31084d9c625SLionel Sambuc 	iswextra = wcschr(extra, c) != NULL;
311*0a6a1f1dSLionel Sambuc 	if (!iswextra && (ISGRAPH(flags, c) || iswwhite(c) ||
31284d9c625SLionel Sambuc 	    ((flags & VIS_SAFE) && iswsafe(c)))) {
3132fe8fb19SBen Gras 		*dst++ = c;
3142fe8fb19SBen Gras 		return dst;
3152fe8fb19SBen Gras 	}
31684d9c625SLionel Sambuc 
31784d9c625SLionel Sambuc 	/* See comment in istrsenvisx() output loop, below. */
31884d9c625SLionel Sambuc 	wmsk = 0;
31984d9c625SLionel Sambuc 	for (i = sizeof(wmsk) - 1; i >= 0; i--) {
32084d9c625SLionel Sambuc 		shft = i * NBBY;
32184d9c625SLionel Sambuc 		bmsk = (uint64_t)0xffLL << shft;
32284d9c625SLionel Sambuc 		wmsk |= bmsk;
32384d9c625SLionel Sambuc 		if ((c & wmsk) || i == 0)
32484d9c625SLionel Sambuc 			dst = do_mbyte(dst, (wint_t)(
32584d9c625SLionel Sambuc 			    (uint64_t)(c & bmsk) >> shft),
32684d9c625SLionel Sambuc 			    flags, nextc, iswextra);
327f14fb602SLionel Sambuc 	}
328f14fb602SLionel Sambuc 
3292fe8fb19SBen Gras 	return dst;
3302fe8fb19SBen Gras }
3312fe8fb19SBen Gras 
33284d9c625SLionel Sambuc typedef wchar_t *(*visfun_t)(wchar_t *, wint_t, int, wint_t, const wchar_t *);
3332fe8fb19SBen Gras 
3342fe8fb19SBen Gras /*
3352fe8fb19SBen Gras  * Return the appropriate encoding function depending on the flags given.
3362fe8fb19SBen Gras  */
3372fe8fb19SBen Gras static visfun_t
getvisfun(int flags)33884d9c625SLionel Sambuc getvisfun(int flags)
3392fe8fb19SBen Gras {
34084d9c625SLionel Sambuc 	if (flags & VIS_HTTPSTYLE)
3412fe8fb19SBen Gras 		return do_hvis;
34284d9c625SLionel Sambuc 	if (flags & VIS_MIMESTYLE)
3432fe8fb19SBen Gras 		return do_mvis;
3442fe8fb19SBen Gras 	return do_svis;
3452fe8fb19SBen Gras }
3462fe8fb19SBen Gras 
3472fe8fb19SBen Gras /*
34884d9c625SLionel Sambuc  * Expand list of extra characters to not visually encode.
3492fe8fb19SBen Gras  */
35084d9c625SLionel Sambuc static wchar_t *
makeextralist(int flags,const char * src)35184d9c625SLionel Sambuc makeextralist(int flags, const char *src)
3522fe8fb19SBen Gras {
35384d9c625SLionel Sambuc 	wchar_t *dst, *d;
35484d9c625SLionel Sambuc 	size_t len;
355*0a6a1f1dSLionel Sambuc 	const wchar_t *s;
3562fe8fb19SBen Gras 
35784d9c625SLionel Sambuc 	len = strlen(src);
35884d9c625SLionel Sambuc 	if ((dst = calloc(len + MAXEXTRAS, sizeof(*dst))) == NULL)
359f14fb602SLionel Sambuc 		return NULL;
36084d9c625SLionel Sambuc 
361*0a6a1f1dSLionel Sambuc 	if ((flags & VIS_NOLOCALE) || mbstowcs(dst, src, len) == (size_t)-1) {
36284d9c625SLionel Sambuc 		size_t i;
36384d9c625SLionel Sambuc 		for (i = 0; i < len; i++)
364*0a6a1f1dSLionel Sambuc 			dst[i] = (wchar_t)(u_char)src[i];
36584d9c625SLionel Sambuc 		d = dst + len;
36684d9c625SLionel Sambuc 	} else
36784d9c625SLionel Sambuc 		d = dst + wcslen(dst);
36884d9c625SLionel Sambuc 
369*0a6a1f1dSLionel Sambuc 	if (flags & VIS_GLOB)
370*0a6a1f1dSLionel Sambuc 		for (s = char_glob; *s; *d++ = *s++)
371*0a6a1f1dSLionel Sambuc 			continue;
372*0a6a1f1dSLionel Sambuc 
373*0a6a1f1dSLionel Sambuc 	if (flags & VIS_SHELL)
374*0a6a1f1dSLionel Sambuc 		for (s = char_shell; *s; *d++ = *s++)
375*0a6a1f1dSLionel Sambuc 			continue;
37684d9c625SLionel Sambuc 
37784d9c625SLionel Sambuc 	if (flags & VIS_SP) *d++ = L' ';
37884d9c625SLionel Sambuc 	if (flags & VIS_TAB) *d++ = L'\t';
37984d9c625SLionel Sambuc 	if (flags & VIS_NL) *d++ = L'\n';
38084d9c625SLionel Sambuc 	if ((flags & VIS_NOSLASH) == 0) *d++ = L'\\';
38184d9c625SLionel Sambuc 	*d = L'\0';
38284d9c625SLionel Sambuc 
3832fe8fb19SBen Gras 	return dst;
3842fe8fb19SBen Gras }
3852fe8fb19SBen Gras 
3862fe8fb19SBen Gras /*
38784d9c625SLionel Sambuc  * istrsenvisx()
38884d9c625SLionel Sambuc  * 	The main internal function.
38984d9c625SLionel Sambuc  *	All user-visible functions call this one.
3902fe8fb19SBen Gras  */
391f14fb602SLionel Sambuc static int
istrsenvisx(char * mbdst,size_t * dlen,const char * mbsrc,size_t mblength,int flags,const char * mbextra,int * cerr_ptr)39284d9c625SLionel Sambuc istrsenvisx(char *mbdst, size_t *dlen, const char *mbsrc, size_t mblength,
39384d9c625SLionel Sambuc     int flags, const char *mbextra, int *cerr_ptr)
3942fe8fb19SBen Gras {
39584d9c625SLionel Sambuc 	wchar_t *dst, *src, *pdst, *psrc, *start, *extra;
39684d9c625SLionel Sambuc 	size_t len, olen;
39784d9c625SLionel Sambuc 	uint64_t bmsk, wmsk;
39884d9c625SLionel Sambuc 	wint_t c;
3992fe8fb19SBen Gras 	visfun_t f;
400*0a6a1f1dSLionel Sambuc 	int clen = 0, cerr, error = -1, i, shft;
40184d9c625SLionel Sambuc 	ssize_t mbslength, maxolen;
4022fe8fb19SBen Gras 
40384d9c625SLionel Sambuc 	_DIAGASSERT(mbdst != NULL);
404*0a6a1f1dSLionel Sambuc 	_DIAGASSERT(mbsrc != NULL || mblength == 0);
40584d9c625SLionel Sambuc 	_DIAGASSERT(mbextra != NULL);
40684d9c625SLionel Sambuc 
40784d9c625SLionel Sambuc 	/*
40884d9c625SLionel Sambuc 	 * Input (mbsrc) is a char string considered to be multibyte
40984d9c625SLionel Sambuc 	 * characters.  The input loop will read this string pulling
41084d9c625SLionel Sambuc 	 * one character, possibly multiple bytes, from mbsrc and
41184d9c625SLionel Sambuc 	 * converting each to wchar_t in src.
41284d9c625SLionel Sambuc 	 *
41384d9c625SLionel Sambuc 	 * The vis conversion will be done using the wide char
41484d9c625SLionel Sambuc 	 * wchar_t string.
41584d9c625SLionel Sambuc 	 *
41684d9c625SLionel Sambuc 	 * This will then be converted back to a multibyte string to
41784d9c625SLionel Sambuc 	 * return to the caller.
41884d9c625SLionel Sambuc 	 */
41984d9c625SLionel Sambuc 
42084d9c625SLionel Sambuc 	/* Allocate space for the wide char strings */
42184d9c625SLionel Sambuc 	psrc = pdst = extra = NULL;
42284d9c625SLionel Sambuc 	if ((psrc = calloc(mblength + 1, sizeof(*psrc))) == NULL)
423f14fb602SLionel Sambuc 		return -1;
42484d9c625SLionel Sambuc 	if ((pdst = calloc((4 * mblength) + 1, sizeof(*pdst))) == NULL)
42584d9c625SLionel Sambuc 		goto out;
42684d9c625SLionel Sambuc 	dst = pdst;
42784d9c625SLionel Sambuc 	src = psrc;
42884d9c625SLionel Sambuc 
429*0a6a1f1dSLionel Sambuc 	if (flags & VIS_NOLOCALE) {
430*0a6a1f1dSLionel Sambuc 		/* Do one byte at a time conversion */
431*0a6a1f1dSLionel Sambuc 		cerr = 1;
432*0a6a1f1dSLionel Sambuc 	} else {
43384d9c625SLionel Sambuc 		/* Use caller's multibyte conversion error flag. */
434*0a6a1f1dSLionel Sambuc 		cerr = cerr_ptr ? *cerr_ptr : 0;
435*0a6a1f1dSLionel Sambuc 	}
43684d9c625SLionel Sambuc 
43784d9c625SLionel Sambuc 	/*
43884d9c625SLionel Sambuc 	 * Input loop.
43984d9c625SLionel Sambuc 	 * Handle up to mblength characters (not bytes).  We do not
44084d9c625SLionel Sambuc 	 * stop at NULs because we may be processing a block of data
44184d9c625SLionel Sambuc 	 * that includes NULs.
44284d9c625SLionel Sambuc 	 */
44384d9c625SLionel Sambuc 	mbslength = (ssize_t)mblength;
44484d9c625SLionel Sambuc 	/*
44584d9c625SLionel Sambuc 	 * When inputing a single character, must also read in the
44684d9c625SLionel Sambuc 	 * next character for nextc, the look-ahead character.
44784d9c625SLionel Sambuc 	 */
44884d9c625SLionel Sambuc 	if (mbslength == 1)
44984d9c625SLionel Sambuc 		mbslength++;
45084d9c625SLionel Sambuc 	while (mbslength > 0) {
45184d9c625SLionel Sambuc 		/* Convert one multibyte character to wchar_t. */
45284d9c625SLionel Sambuc 		if (!cerr)
45384d9c625SLionel Sambuc 			clen = mbtowc(src, mbsrc, MB_LEN_MAX);
45484d9c625SLionel Sambuc 		if (cerr || clen < 0) {
45584d9c625SLionel Sambuc 			/* Conversion error, process as a byte instead. */
45684d9c625SLionel Sambuc 			*src = (wint_t)(u_char)*mbsrc;
45784d9c625SLionel Sambuc 			clen = 1;
45884d9c625SLionel Sambuc 			cerr = 1;
459f14fb602SLionel Sambuc 		}
46084d9c625SLionel Sambuc 		if (clen == 0)
46184d9c625SLionel Sambuc 			/*
46284d9c625SLionel Sambuc 			 * NUL in input gives 0 return value. process
46384d9c625SLionel Sambuc 			 * as single NUL byte and keep going.
46484d9c625SLionel Sambuc 			 */
46584d9c625SLionel Sambuc 			clen = 1;
46684d9c625SLionel Sambuc 		/* Advance buffer character pointer. */
46784d9c625SLionel Sambuc 		src++;
46884d9c625SLionel Sambuc 		/* Advance input pointer by number of bytes read. */
46984d9c625SLionel Sambuc 		mbsrc += clen;
47084d9c625SLionel Sambuc 		/* Decrement input byte count. */
47184d9c625SLionel Sambuc 		mbslength -= clen;
472f14fb602SLionel Sambuc 	}
47384d9c625SLionel Sambuc 	len = src - psrc;
47484d9c625SLionel Sambuc 	src = psrc;
47584d9c625SLionel Sambuc 	/*
47684d9c625SLionel Sambuc 	 * In the single character input case, we will have actually
47784d9c625SLionel Sambuc 	 * processed two characters, c and nextc.  Reset len back to
47884d9c625SLionel Sambuc 	 * just a single character.
47984d9c625SLionel Sambuc 	 */
48084d9c625SLionel Sambuc 	if (mblength < len)
48184d9c625SLionel Sambuc 		len = mblength;
48284d9c625SLionel Sambuc 
48384d9c625SLionel Sambuc 	/* Convert extra argument to list of characters for this mode. */
48484d9c625SLionel Sambuc 	extra = makeextralist(flags, mbextra);
48584d9c625SLionel Sambuc 	if (!extra) {
486f14fb602SLionel Sambuc 		if (dlen && *dlen == 0) {
487f14fb602SLionel Sambuc 			errno = ENOSPC;
48884d9c625SLionel Sambuc 			goto out;
489f14fb602SLionel Sambuc 		}
49084d9c625SLionel Sambuc 		*mbdst = '\0';		/* can't create extra, return "" */
49184d9c625SLionel Sambuc 		error = 0;
49284d9c625SLionel Sambuc 		goto out;
4932fe8fb19SBen Gras 	}
4942fe8fb19SBen Gras 
49584d9c625SLionel Sambuc 	/* Look up which processing function to call. */
49684d9c625SLionel Sambuc 	f = getvisfun(flags);
4972fe8fb19SBen Gras 
49884d9c625SLionel Sambuc 	/*
49984d9c625SLionel Sambuc 	 * Main processing loop.
50084d9c625SLionel Sambuc 	 * Call do_Xvis processing function one character at a time
50184d9c625SLionel Sambuc 	 * with next character available for look-ahead.
50284d9c625SLionel Sambuc 	 */
5032fe8fb19SBen Gras 	for (start = dst; len > 0; len--) {
5042fe8fb19SBen Gras 		c = *src++;
50584d9c625SLionel Sambuc 		dst = (*f)(dst, c, flags, len >= 1 ? *src : L'\0', extra);
506f14fb602SLionel Sambuc 		if (dst == NULL) {
507f14fb602SLionel Sambuc 			errno = ENOSPC;
50884d9c625SLionel Sambuc 			goto out;
509f14fb602SLionel Sambuc 		}
5102fe8fb19SBen Gras 	}
51184d9c625SLionel Sambuc 
51284d9c625SLionel Sambuc 	/* Terminate the string in the buffer. */
51384d9c625SLionel Sambuc 	*dst = L'\0';
51484d9c625SLionel Sambuc 
51584d9c625SLionel Sambuc 	/*
51684d9c625SLionel Sambuc 	 * Output loop.
51784d9c625SLionel Sambuc 	 * Convert wchar_t string back to multibyte output string.
51884d9c625SLionel Sambuc 	 * If we have hit a multi-byte conversion error on input,
51984d9c625SLionel Sambuc 	 * output byte-by-byte here.  Else use wctomb().
52084d9c625SLionel Sambuc 	 */
52184d9c625SLionel Sambuc 	len = wcslen(start);
52284d9c625SLionel Sambuc 	maxolen = dlen ? *dlen : (wcslen(start) * MB_LEN_MAX + 1);
52384d9c625SLionel Sambuc 	olen = 0;
52484d9c625SLionel Sambuc 	for (dst = start; len > 0; len--) {
52584d9c625SLionel Sambuc 		if (!cerr)
52684d9c625SLionel Sambuc 			clen = wctomb(mbdst, *dst);
52784d9c625SLionel Sambuc 		if (cerr || clen < 0) {
52884d9c625SLionel Sambuc 			/*
52984d9c625SLionel Sambuc 			 * Conversion error, process as a byte(s) instead.
53084d9c625SLionel Sambuc 			 * Examine each byte and higher-order bytes for
53184d9c625SLionel Sambuc 			 * data.  E.g.,
53284d9c625SLionel Sambuc 			 *	0x000000000000a264 -> a2 64
53384d9c625SLionel Sambuc 			 *	0x000000001f00a264 -> 1f 00 a2 64
53484d9c625SLionel Sambuc 			 */
53584d9c625SLionel Sambuc 			clen = 0;
53684d9c625SLionel Sambuc 			wmsk = 0;
53784d9c625SLionel Sambuc 			for (i = sizeof(wmsk) - 1; i >= 0; i--) {
53884d9c625SLionel Sambuc 				shft = i * NBBY;
53984d9c625SLionel Sambuc 				bmsk = (uint64_t)0xffLL << shft;
54084d9c625SLionel Sambuc 				wmsk |= bmsk;
54184d9c625SLionel Sambuc 				if ((*dst & wmsk) || i == 0)
54284d9c625SLionel Sambuc 					mbdst[clen++] = (char)(
54384d9c625SLionel Sambuc 					    (uint64_t)(*dst & bmsk) >>
54484d9c625SLionel Sambuc 					    shft);
545f14fb602SLionel Sambuc 			}
54684d9c625SLionel Sambuc 			cerr = 1;
54784d9c625SLionel Sambuc 		}
54884d9c625SLionel Sambuc 		/* If this character would exceed our output limit, stop. */
54984d9c625SLionel Sambuc 		if (olen + clen > (size_t)maxolen)
55084d9c625SLionel Sambuc 			break;
55184d9c625SLionel Sambuc 		/* Advance output pointer by number of bytes written. */
55284d9c625SLionel Sambuc 		mbdst += clen;
55384d9c625SLionel Sambuc 		/* Advance buffer character pointer. */
55484d9c625SLionel Sambuc 		dst++;
55584d9c625SLionel Sambuc 		/* Incrment output character count. */
55684d9c625SLionel Sambuc 		olen += clen;
55784d9c625SLionel Sambuc 	}
55884d9c625SLionel Sambuc 
55984d9c625SLionel Sambuc 	/* Terminate the output string. */
56084d9c625SLionel Sambuc 	*mbdst = '\0';
56184d9c625SLionel Sambuc 
562*0a6a1f1dSLionel Sambuc 	if (flags & VIS_NOLOCALE) {
56384d9c625SLionel Sambuc 		/* Pass conversion error flag out. */
56484d9c625SLionel Sambuc 		if (cerr_ptr)
56584d9c625SLionel Sambuc 			*cerr_ptr = cerr;
566*0a6a1f1dSLionel Sambuc 	}
56784d9c625SLionel Sambuc 
56884d9c625SLionel Sambuc 	free(extra);
56984d9c625SLionel Sambuc 	free(pdst);
57084d9c625SLionel Sambuc 	free(psrc);
57184d9c625SLionel Sambuc 
57284d9c625SLionel Sambuc 	return (int)olen;
57384d9c625SLionel Sambuc out:
57484d9c625SLionel Sambuc 	free(extra);
57584d9c625SLionel Sambuc 	free(pdst);
57684d9c625SLionel Sambuc 	free(psrc);
57784d9c625SLionel Sambuc 	return error;
57884d9c625SLionel Sambuc }
579*0a6a1f1dSLionel Sambuc 
580*0a6a1f1dSLionel Sambuc static int
istrsenvisxl(char * mbdst,size_t * dlen,const char * mbsrc,int flags,const char * mbextra,int * cerr_ptr)581*0a6a1f1dSLionel Sambuc istrsenvisxl(char *mbdst, size_t *dlen, const char *mbsrc,
582*0a6a1f1dSLionel Sambuc     int flags, const char *mbextra, int *cerr_ptr)
583*0a6a1f1dSLionel Sambuc {
584*0a6a1f1dSLionel Sambuc 	return istrsenvisx(mbdst, dlen, mbsrc,
585*0a6a1f1dSLionel Sambuc 	    mbsrc != NULL ? strlen(mbsrc) : 0, flags, mbextra, cerr_ptr);
586*0a6a1f1dSLionel Sambuc }
587*0a6a1f1dSLionel Sambuc 
58884d9c625SLionel Sambuc #endif
58984d9c625SLionel Sambuc 
59084d9c625SLionel Sambuc #if !HAVE_SVIS
59184d9c625SLionel Sambuc /*
59284d9c625SLionel Sambuc  *	The "svis" variants all take an "extra" arg that is a pointer
59384d9c625SLionel Sambuc  *	to a NUL-terminated list of characters to be encoded, too.
59484d9c625SLionel Sambuc  *	These functions are useful e. g. to encode strings in such a
59584d9c625SLionel Sambuc  *	way so that they are not interpreted by a shell.
59684d9c625SLionel Sambuc  */
59784d9c625SLionel Sambuc 
59884d9c625SLionel Sambuc char *
svis(char * mbdst,int c,int flags,int nextc,const char * mbextra)59984d9c625SLionel Sambuc svis(char *mbdst, int c, int flags, int nextc, const char *mbextra)
60084d9c625SLionel Sambuc {
60184d9c625SLionel Sambuc 	char cc[2];
60284d9c625SLionel Sambuc 	int ret;
60384d9c625SLionel Sambuc 
60484d9c625SLionel Sambuc 	cc[0] = c;
60584d9c625SLionel Sambuc 	cc[1] = nextc;
60684d9c625SLionel Sambuc 
60784d9c625SLionel Sambuc 	ret = istrsenvisx(mbdst, NULL, cc, 1, flags, mbextra, NULL);
60884d9c625SLionel Sambuc 	if (ret < 0)
60984d9c625SLionel Sambuc 		return NULL;
61084d9c625SLionel Sambuc 	return mbdst + ret;
61184d9c625SLionel Sambuc }
61284d9c625SLionel Sambuc 
61384d9c625SLionel Sambuc char *
snvis(char * mbdst,size_t dlen,int c,int flags,int nextc,const char * mbextra)61484d9c625SLionel Sambuc snvis(char *mbdst, size_t dlen, int c, int flags, int nextc, const char *mbextra)
61584d9c625SLionel Sambuc {
61684d9c625SLionel Sambuc 	char cc[2];
61784d9c625SLionel Sambuc 	int ret;
61884d9c625SLionel Sambuc 
61984d9c625SLionel Sambuc 	cc[0] = c;
62084d9c625SLionel Sambuc 	cc[1] = nextc;
62184d9c625SLionel Sambuc 
62284d9c625SLionel Sambuc 	ret = istrsenvisx(mbdst, &dlen, cc, 1, flags, mbextra, NULL);
62384d9c625SLionel Sambuc 	if (ret < 0)
62484d9c625SLionel Sambuc 		return NULL;
62584d9c625SLionel Sambuc 	return mbdst + ret;
6262fe8fb19SBen Gras }
627f14fb602SLionel Sambuc 
628f14fb602SLionel Sambuc int
strsvis(char * mbdst,const char * mbsrc,int flags,const char * mbextra)62984d9c625SLionel Sambuc strsvis(char *mbdst, const char *mbsrc, int flags, const char *mbextra)
630f14fb602SLionel Sambuc {
631*0a6a1f1dSLionel Sambuc 	return istrsenvisxl(mbdst, NULL, mbsrc, flags, mbextra, NULL);
632f14fb602SLionel Sambuc }
633f14fb602SLionel Sambuc 
634f14fb602SLionel Sambuc int
strsnvis(char * mbdst,size_t dlen,const char * mbsrc,int flags,const char * mbextra)63584d9c625SLionel Sambuc strsnvis(char *mbdst, size_t dlen, const char *mbsrc, int flags, const char *mbextra)
636f14fb602SLionel Sambuc {
637*0a6a1f1dSLionel Sambuc 	return istrsenvisxl(mbdst, &dlen, mbsrc, flags, mbextra, NULL);
63884d9c625SLionel Sambuc }
63984d9c625SLionel Sambuc 
64084d9c625SLionel Sambuc int
strsvisx(char * mbdst,const char * mbsrc,size_t len,int flags,const char * mbextra)64184d9c625SLionel Sambuc strsvisx(char *mbdst, const char *mbsrc, size_t len, int flags, const char *mbextra)
64284d9c625SLionel Sambuc {
64384d9c625SLionel Sambuc 	return istrsenvisx(mbdst, NULL, mbsrc, len, flags, mbextra, NULL);
64484d9c625SLionel Sambuc }
64584d9c625SLionel Sambuc 
64684d9c625SLionel Sambuc int
strsnvisx(char * mbdst,size_t dlen,const char * mbsrc,size_t len,int flags,const char * mbextra)64784d9c625SLionel Sambuc strsnvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags,
64884d9c625SLionel Sambuc     const char *mbextra)
64984d9c625SLionel Sambuc {
65084d9c625SLionel Sambuc 	return istrsenvisx(mbdst, &dlen, mbsrc, len, flags, mbextra, NULL);
65184d9c625SLionel Sambuc }
65284d9c625SLionel Sambuc 
65384d9c625SLionel Sambuc int
strsenvisx(char * mbdst,size_t dlen,const char * mbsrc,size_t len,int flags,const char * mbextra,int * cerr_ptr)65484d9c625SLionel Sambuc strsenvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags,
65584d9c625SLionel Sambuc     const char *mbextra, int *cerr_ptr)
65684d9c625SLionel Sambuc {
65784d9c625SLionel Sambuc 	return istrsenvisx(mbdst, &dlen, mbsrc, len, flags, mbextra, cerr_ptr);
658f14fb602SLionel Sambuc }
6592fe8fb19SBen Gras #endif
6602fe8fb19SBen Gras 
6612fe8fb19SBen Gras #if !HAVE_VIS
6622fe8fb19SBen Gras /*
6632fe8fb19SBen Gras  * vis - visually encode characters
6642fe8fb19SBen Gras  */
66584d9c625SLionel Sambuc char *
vis(char * mbdst,int c,int flags,int nextc)66684d9c625SLionel Sambuc vis(char *mbdst, int c, int flags, int nextc)
6672fe8fb19SBen Gras {
66884d9c625SLionel Sambuc 	char cc[2];
66984d9c625SLionel Sambuc 	int ret;
6702fe8fb19SBen Gras 
67184d9c625SLionel Sambuc 	cc[0] = c;
67284d9c625SLionel Sambuc 	cc[1] = nextc;
6732fe8fb19SBen Gras 
67484d9c625SLionel Sambuc 	ret = istrsenvisx(mbdst, NULL, cc, 1, flags, "", NULL);
67584d9c625SLionel Sambuc 	if (ret < 0)
676f14fb602SLionel Sambuc 		return NULL;
67784d9c625SLionel Sambuc 	return mbdst + ret;
6782fe8fb19SBen Gras }
6792fe8fb19SBen Gras 
680f14fb602SLionel Sambuc char *
nvis(char * mbdst,size_t dlen,int c,int flags,int nextc)68184d9c625SLionel Sambuc nvis(char *mbdst, size_t dlen, int c, int flags, int nextc)
682f14fb602SLionel Sambuc {
68384d9c625SLionel Sambuc 	char cc[2];
68484d9c625SLionel Sambuc 	int ret;
685f14fb602SLionel Sambuc 
68684d9c625SLionel Sambuc 	cc[0] = c;
68784d9c625SLionel Sambuc 	cc[1] = nextc;
688f14fb602SLionel Sambuc 
68984d9c625SLionel Sambuc 	ret = istrsenvisx(mbdst, &dlen, cc, 1, flags, "", NULL);
69084d9c625SLionel Sambuc 	if (ret < 0)
69184d9c625SLionel Sambuc 		return NULL;
69284d9c625SLionel Sambuc 	return mbdst + ret;
69384d9c625SLionel Sambuc }
6942fe8fb19SBen Gras 
6952fe8fb19SBen Gras /*
69684d9c625SLionel Sambuc  * strvis - visually encode characters from src into dst
69784d9c625SLionel Sambuc  *
69884d9c625SLionel Sambuc  *	Dst must be 4 times the size of src to account for possible
69984d9c625SLionel Sambuc  *	expansion.  The length of dst, not including the trailing NULL,
70084d9c625SLionel Sambuc  *	is returned.
70184d9c625SLionel Sambuc  */
70284d9c625SLionel Sambuc 
70384d9c625SLionel Sambuc int
strvis(char * mbdst,const char * mbsrc,int flags)70484d9c625SLionel Sambuc strvis(char *mbdst, const char *mbsrc, int flags)
70584d9c625SLionel Sambuc {
706*0a6a1f1dSLionel Sambuc 	return istrsenvisxl(mbdst, NULL, mbsrc, flags, "", NULL);
70784d9c625SLionel Sambuc }
70884d9c625SLionel Sambuc 
70984d9c625SLionel Sambuc int
strnvis(char * mbdst,size_t dlen,const char * mbsrc,int flags)71084d9c625SLionel Sambuc strnvis(char *mbdst, size_t dlen, const char *mbsrc, int flags)
71184d9c625SLionel Sambuc {
712*0a6a1f1dSLionel Sambuc 	return istrsenvisxl(mbdst, &dlen, mbsrc, flags, "", NULL);
71384d9c625SLionel Sambuc }
71484d9c625SLionel Sambuc 
71584d9c625SLionel Sambuc /*
71684d9c625SLionel Sambuc  * strvisx - visually encode characters from src into dst
7172fe8fb19SBen Gras  *
7182fe8fb19SBen Gras  *	Dst must be 4 times the size of src to account for possible
7192fe8fb19SBen Gras  *	expansion.  The length of dst, not including the trailing NULL,
7202fe8fb19SBen Gras  *	is returned.
7212fe8fb19SBen Gras  *
72284d9c625SLionel Sambuc  *	Strvisx encodes exactly len characters from src into dst.
7232fe8fb19SBen Gras  *	This is useful for encoding a block of data.
7242fe8fb19SBen Gras  */
7252fe8fb19SBen Gras 
72684d9c625SLionel Sambuc int
strvisx(char * mbdst,const char * mbsrc,size_t len,int flags)72784d9c625SLionel Sambuc strvisx(char *mbdst, const char *mbsrc, size_t len, int flags)
72884d9c625SLionel Sambuc {
72984d9c625SLionel Sambuc 	return istrsenvisx(mbdst, NULL, mbsrc, len, flags, "", NULL);
7302fe8fb19SBen Gras }
7312fe8fb19SBen Gras 
732f14fb602SLionel Sambuc int
strnvisx(char * mbdst,size_t dlen,const char * mbsrc,size_t len,int flags)73384d9c625SLionel Sambuc strnvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags)
734f14fb602SLionel Sambuc {
73584d9c625SLionel Sambuc 	return istrsenvisx(mbdst, &dlen, mbsrc, len, flags, "", NULL);
736f14fb602SLionel Sambuc }
737f14fb602SLionel Sambuc 
738f14fb602SLionel Sambuc int
strenvisx(char * mbdst,size_t dlen,const char * mbsrc,size_t len,int flags,int * cerr_ptr)73984d9c625SLionel Sambuc strenvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags,
74084d9c625SLionel Sambuc     int *cerr_ptr)
741f14fb602SLionel Sambuc {
74284d9c625SLionel Sambuc 	return istrsenvisx(mbdst, &dlen, mbsrc, len, flags, "", cerr_ptr);
743f14fb602SLionel Sambuc }
7442fe8fb19SBen Gras #endif
745