diff options
Diffstat (limited to 'contrib/libc-vis/vis.c')
-rw-r--r-- | contrib/libc-vis/vis.c | 800 |
1 files changed, 452 insertions, 348 deletions
diff --git a/contrib/libc-vis/vis.c b/contrib/libc-vis/vis.c index 040c28c25e28..2ba6b5b23d71 100644 --- a/contrib/libc-vis/vis.c +++ b/contrib/libc-vis/vis.c @@ -1,4 +1,4 @@ -/* $NetBSD: vis.c,v 1.45 2012/12/14 21:38:18 christos Exp $ */ +/* $NetBSD: vis.c,v 1.60 2013/02/21 16:21:20 joerg Exp $ */ /*- * Copyright (c) 1989, 1993 @@ -57,19 +57,23 @@ #include <sys/cdefs.h> #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: vis.c,v 1.45 2012/12/14 21:38:18 christos Exp $"); +__RCSID("$NetBSD: vis.c,v 1.60 2013/02/21 16:21:20 joerg Exp $"); #endif /* LIBC_SCCS and not lint */ +#ifdef __FBSDID __FBSDID("$FreeBSD$"); +#define _DIAGASSERT(x) assert(x) +#endif #include "namespace.h" #include <sys/types.h> +#include <sys/param.h> #include <assert.h> #include <vis.h> #include <errno.h> #include <stdlib.h> - -#define _DIAGASSERT(x) assert(x) +#include <wchar.h> +#include <wctype.h> #ifdef __weak_alias __weak_alias(strvisx,_strvisx) @@ -81,65 +85,66 @@ __weak_alias(strvisx,_strvisx) #include <stdio.h> #include <string.h> -static char *do_svis(char *, size_t *, int, int, int, const char *); +/* + * The reason for going through the trouble to deal with character encodings + * in vis(3), is that we use this to safe encode output of commands. This + * safe encoding varies depending on the character set. For example if we + * display ps output in French, we don't want to display French characters + * as M-foo. + */ + +static wchar_t *do_svis(wchar_t *, wint_t, int, wint_t, const wchar_t *); #undef BELL -#define BELL '\a' - -#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') -#define iswhite(c) (c == ' ' || c == '\t' || c == '\n') -#define issafe(c) (c == '\b' || c == BELL || c == '\r') -#define xtoa(c) "0123456789abcdef"[c] -#define XTOA(c) "0123456789ABCDEF"[c] - -#define MAXEXTRAS 9 - -#define MAKEEXTRALIST(flag, extra, orig_str) \ -do { \ - const char *orig = orig_str; \ - const char *o = orig; \ - char *e; \ - while (*o++) \ - continue; \ - extra = malloc((size_t)((o - orig) + MAXEXTRAS)); \ - if (!extra) break; \ - for (o = orig, e = extra; (*e++ = *o++) != '\0';) \ - continue; \ - e--; \ - if (flag & VIS_GLOB) { \ - *e++ = '*'; \ - *e++ = '?'; \ - *e++ = '['; \ - *e++ = '#'; \ - } \ - if (flag & VIS_SP) *e++ = ' '; \ - if (flag & VIS_TAB) *e++ = '\t'; \ - if (flag & VIS_NL) *e++ = '\n'; \ - if ((flag & VIS_NOSLASH) == 0) *e++ = '\\'; \ - *e = '\0'; \ -} while (/*CONSTCOND*/0) +#define BELL L'\a' + +#define iswoctal(c) (((u_char)(c)) >= L'0' && ((u_char)(c)) <= L'7') +#define iswwhite(c) (c == L' ' || c == L'\t' || c == L'\n') +#define iswsafe(c) (c == L'\b' || c == BELL || c == L'\r') +#define xtoa(c) L"0123456789abcdef"[c] +#define XTOA(c) L"0123456789ABCDEF"[c] + +#define MAXEXTRAS 10 + +#if !HAVE_NBTOOL_CONFIG_H +#ifndef __NetBSD__ +/* + * On NetBSD MB_LEN_MAX is currently 32 which does not fit on any integer + * integral type and it is probably wrong, since currently the maximum + * number of bytes and character needs is 6. Until this is fixed, the + * loops below are using sizeof(uint64_t) - 1 instead of MB_LEN_MAX, and + * the assertion is commented out. + */ +#ifdef __FreeBSD__ +/* + * On FreeBSD including <sys/systm.h> for CTASSERT only works in kernel + * mode. + */ +#ifndef CTASSERT +#define CTASSERT(x) _CTASSERT(x, __LINE__) +#define _CTASSERT(x, y) __CTASSERT(x, y) +#define __CTASSERT(x, y) typedef char __assert ## y[(x) ? 1 : -1] +#endif +#endif /* __FreeBSD__ */ +CTASSERT(MB_LEN_MAX <= sizeof(uint64_t)); +#endif /* !__NetBSD__ */ +#endif /* * This is do_hvis, for HTTP style (RFC 1808) */ -static char * -do_hvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra) +static wchar_t * +do_hvis(wchar_t *dst, wint_t c, int flags, wint_t nextc, const wchar_t *extra) { - - if ((isascii(c) && isalnum(c)) + if (iswalnum(c) /* safe */ - || c == '$' || c == '-' || c == '_' || c == '.' || c == '+' + || c == L'$' || c == L'-' || c == L'_' || c == L'.' || c == L'+' /* extra */ - || c == '!' || c == '*' || c == '\'' || c == '(' || c == ')' - || c == ',') { - dst = do_svis(dst, dlen, c, flag, nextc, extra); - } else { - if (dlen) { - if (*dlen < 3) - return NULL; - *dlen -= 3; - } - *dst++ = '%'; + || c == L'!' || c == L'*' || c == L'\'' || c == L'(' || c == L')' + || c == L',') + dst = do_svis(dst, c, flags, nextc, extra); + else { + *dst++ = L'%'; *dst++ = xtoa(((unsigned int)c >> 4) & 0xf); *dst++ = xtoa((unsigned int)c & 0xf); } @@ -151,312 +156,448 @@ do_hvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra) * This is do_mvis, for Quoted-Printable MIME (RFC 2045) * NB: No handling of long lines or CRLF. */ -static char * -do_mvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra) +static wchar_t * +do_mvis(wchar_t *dst, wint_t c, int flags, wint_t nextc, const wchar_t *extra) { - if ((c != '\n') && + if ((c != L'\n') && /* Space at the end of the line */ - ((isspace(c) && (nextc == '\r' || nextc == '\n')) || + ((iswspace(c) && (nextc == L'\r' || nextc == L'\n')) || /* Out of range */ - (!isspace(c) && (c < 33 || (c > 60 && c < 62) || c > 126)) || - /* Specific char to be escaped */ - strchr("#$@[\\]^`{|}~", c) != NULL)) { - if (dlen) { - if (*dlen < 3) - return NULL; - *dlen -= 3; - } - *dst++ = '='; + (!iswspace(c) && (c < 33 || (c > 60 && c < 62) || c > 126)) || + /* Specific char to be escaped */ + wcschr(L"#$@[\\]^`{|}~", c) != NULL)) { + *dst++ = L'='; *dst++ = XTOA(((unsigned int)c >> 4) & 0xf); *dst++ = XTOA((unsigned int)c & 0xf); - } else { - dst = do_svis(dst, dlen, c, flag, nextc, extra); - } + } else + dst = do_svis(dst, c, flags, nextc, extra); return dst; } /* - * This is do_vis, the central code of vis. - * dst: Pointer to the destination buffer - * c: Character to encode - * flag: Flag word - * nextc: The character following 'c' - * extra: Pointer to the list of extra characters to be - * backslash-protected. + * Output single byte of multibyte character. */ -static char * -do_svis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra) +static wchar_t * +do_mbyte(wchar_t *dst, wint_t c, int flags, wint_t nextc, int iswextra) { - int isextra; - size_t odlen = dlen ? *dlen : 0; - - isextra = strchr(extra, c) != NULL; -#define HAVE(x) \ - do { \ - if (dlen) { \ - if (*dlen < (x)) \ - goto out; \ - *dlen -= (x); \ - } \ - } while (/*CONSTCOND*/0) - if (!isextra && isascii(c) && (isgraph(c) || iswhite(c) || - ((flag & VIS_SAFE) && issafe(c)))) { - HAVE(1); - *dst++ = c; - return dst; - } - if (flag & VIS_CSTYLE) { - HAVE(2); + if (flags & VIS_CSTYLE) { switch (c) { - case '\n': - *dst++ = '\\'; *dst++ = 'n'; + case L'\n': + *dst++ = L'\\'; *dst++ = L'n'; return dst; - case '\r': - *dst++ = '\\'; *dst++ = 'r'; + case L'\r': + *dst++ = L'\\'; *dst++ = L'r'; return dst; - case '\b': - *dst++ = '\\'; *dst++ = 'b'; + case L'\b': + *dst++ = L'\\'; *dst++ = L'b'; return dst; case BELL: - *dst++ = '\\'; *dst++ = 'a'; + *dst++ = L'\\'; *dst++ = L'a'; return dst; - case '\v': - *dst++ = '\\'; *dst++ = 'v'; + case L'\v': + *dst++ = L'\\'; *dst++ = L'v'; return dst; - case '\t': - *dst++ = '\\'; *dst++ = 't'; + case L'\t': + *dst++ = L'\\'; *dst++ = L't'; return dst; - case '\f': - *dst++ = '\\'; *dst++ = 'f'; + case L'\f': + *dst++ = L'\\'; *dst++ = L'f'; return dst; - case ' ': - *dst++ = '\\'; *dst++ = 's'; + case L' ': + *dst++ = L'\\'; *dst++ = L's'; return dst; - case '\0': - *dst++ = '\\'; *dst++ = '0'; - if (isoctal(nextc)) { - HAVE(2); - *dst++ = '0'; - *dst++ = '0'; + case L'\0': + *dst++ = L'\\'; *dst++ = L'0'; + if (iswoctal(nextc)) { + *dst++ = L'0'; + *dst++ = L'0'; } return dst; default: - if (isgraph(c)) { - *dst++ = '\\'; *dst++ = c; + if (iswgraph(c)) { + *dst++ = L'\\'; + *dst++ = c; return dst; } - if (dlen) - *dlen = odlen; } } - if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) { - HAVE(4); - *dst++ = '\\'; - *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + '0'; - *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + '0'; - *dst++ = (c & 07) + '0'; + if (iswextra || ((c & 0177) == L' ') || (flags & VIS_OCTAL)) { + *dst++ = L'\\'; + *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + L'0'; + *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + L'0'; + *dst++ = (c & 07) + L'0'; } else { - if ((flag & VIS_NOSLASH) == 0) { - HAVE(1); - *dst++ = '\\'; - } + if ((flags & VIS_NOSLASH) == 0) + *dst++ = L'\\'; if (c & 0200) { - HAVE(1); - c &= 0177; *dst++ = 'M'; + c &= 0177; + *dst++ = L'M'; } - if (iscntrl(c)) { - HAVE(2); - *dst++ = '^'; + if (iswcntrl(c)) { + *dst++ = L'^'; if (c == 0177) - *dst++ = '?'; + *dst++ = L'?'; else - *dst++ = c + '@'; + *dst++ = c + L'@'; } else { - HAVE(2); - *dst++ = '-'; *dst++ = c; + *dst++ = L'-'; + *dst++ = c; } } + return dst; -out: - *dlen = odlen; - return NULL; } -typedef char *(*visfun_t)(char *, size_t *, int, int, int, const char *); +/* + * This is do_vis, the central code of vis. + * dst: Pointer to the destination buffer + * c: Character to encode + * flags: Flags word + * nextc: The character following 'c' + * extra: Pointer to the list of extra characters to be + * backslash-protected. + */ +static wchar_t * +do_svis(wchar_t *dst, wint_t c, int flags, wint_t nextc, const wchar_t *extra) +{ + int iswextra, i, shft; + uint64_t bmsk, wmsk; + + iswextra = wcschr(extra, c) != NULL; + if (!iswextra && (iswgraph(c) || iswwhite(c) || + ((flags & VIS_SAFE) && iswsafe(c)))) { + *dst++ = c; + return dst; + } + + /* See comment in istrsenvisx() output loop, below. */ + wmsk = 0; + for (i = sizeof(wmsk) - 1; i >= 0; i--) { + shft = i * NBBY; + bmsk = (uint64_t)0xffLL << shft; + wmsk |= bmsk; + if ((c & wmsk) || i == 0) + dst = do_mbyte(dst, (wint_t)( + (uint64_t)(c & bmsk) >> shft), + flags, nextc, iswextra); + } + + return dst; +} + +typedef wchar_t *(*visfun_t)(wchar_t *, wint_t, int, wint_t, const wchar_t *); /* * Return the appropriate encoding function depending on the flags given. */ static visfun_t -getvisfun(int flag) +getvisfun(int flags) { - if (flag & VIS_HTTPSTYLE) + if (flags & VIS_HTTPSTYLE) return do_hvis; - if (flag & VIS_MIMESTYLE) + if (flags & VIS_MIMESTYLE) return do_mvis; return do_svis; } /* - * isnvis - visually encode characters, also encoding the characters - * pointed to by `extra' + * Expand list of extra characters to not visually encode. */ -static char * -isnvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra) +static wchar_t * +makeextralist(int flags, const char *src) { - char *nextra = NULL; - visfun_t f; + wchar_t *dst, *d; + size_t len; - _DIAGASSERT(dst != NULL); - _DIAGASSERT(extra != NULL); - MAKEEXTRALIST(flag, nextra, extra); - if (!nextra) { - if (dlen && *dlen == 0) { - errno = ENOSPC; - return NULL; - } - *dst = '\0'; /* can't create nextra, return "" */ - return dst; - } - f = getvisfun(flag); - dst = (*f)(dst, dlen, c, flag, nextc, nextra); - free(nextra); - if (dst == NULL || (dlen && *dlen == 0)) { - errno = ENOSPC; + len = strlen(src); + if ((dst = calloc(len + MAXEXTRAS, sizeof(*dst))) == NULL) return NULL; + + if (mbstowcs(dst, src, len) == (size_t)-1) { + size_t i; + for (i = 0; i < len; i++) + dst[i] = (wint_t)(u_char)src[i]; + d = dst + len; + } else + d = dst + wcslen(dst); + + if (flags & VIS_GLOB) { + *d++ = L'*'; + *d++ = L'?'; + *d++ = L'['; + *d++ = L'#'; } - *dst = '\0'; - return dst; -} -char * -svis(char *dst, int c, int flag, int nextc, const char *extra) -{ - return isnvis(dst, NULL, c, flag, nextc, extra); -} + if (flags & VIS_SP) *d++ = L' '; + if (flags & VIS_TAB) *d++ = L'\t'; + if (flags & VIS_NL) *d++ = L'\n'; + if ((flags & VIS_NOSLASH) == 0) *d++ = L'\\'; + *d = L'\0'; -char * -snvis(char *dst, size_t dlen, int c, int flag, int nextc, const char *extra) -{ - return isnvis(dst, &dlen, c, flag, nextc, extra); + return dst; } - /* - * strsvis, strsvisx - visually encode characters from src into dst - * - * Extra is a pointer to a \0-terminated list of characters to - * be encoded, too. These functions are useful e. g. to - * encode strings in such a way so that they are not interpreted - * by a shell. - * - * Dst must be 4 times the size of src to account for possible - * expansion. The length of dst, not including the trailing NULL, - * is returned. - * - * Strsvisx encodes exactly len bytes from src into dst. - * This is useful for encoding a block of data. + * istrsenvisx() + * The main internal function. + * All user-visible functions call this one. */ static int -istrsnvis(char *dst, size_t *dlen, const char *csrc, int flag, const char *extra) +istrsenvisx(char *mbdst, size_t *dlen, const char *mbsrc, size_t mblength, + int flags, const char *mbextra, int *cerr_ptr) { - int c; - char *start; - char *nextra = NULL; - const unsigned char *src = (const unsigned char *)csrc; + wchar_t *dst, *src, *pdst, *psrc, *start, *extra; + size_t len, olen; + uint64_t bmsk, wmsk; + wint_t c; visfun_t f; - - _DIAGASSERT(dst != NULL); - _DIAGASSERT(src != NULL); - _DIAGASSERT(extra != NULL); - MAKEEXTRALIST(flag, nextra, extra); - if (!nextra) { - *dst = '\0'; /* can't create nextra, return "" */ - return 0; + int clen = 0, cerr = 0, error = -1, i, shft; + ssize_t mbslength, maxolen; + + _DIAGASSERT(mbdst != NULL); + _DIAGASSERT(mbsrc != NULL); + _DIAGASSERT(mbextra != NULL); + + /* + * Input (mbsrc) is a char string considered to be multibyte + * characters. The input loop will read this string pulling + * one character, possibly multiple bytes, from mbsrc and + * converting each to wchar_t in src. + * + * The vis conversion will be done using the wide char + * wchar_t string. + * + * This will then be converted back to a multibyte string to + * return to the caller. + */ + + /* Allocate space for the wide char strings */ + psrc = pdst = extra = NULL; + if (!mblength) + mblength = strlen(mbsrc); + if ((psrc = calloc(mblength + 1, sizeof(*psrc))) == NULL) + return -1; + if ((pdst = calloc((4 * mblength) + 1, sizeof(*pdst))) == NULL) + goto out; + dst = pdst; + src = psrc; + + /* Use caller's multibyte conversion error flag. */ + if (cerr_ptr) + cerr = *cerr_ptr; + + /* + * Input loop. + * Handle up to mblength characters (not bytes). We do not + * stop at NULs because we may be processing a block of data + * that includes NULs. + */ + mbslength = (ssize_t)mblength; + /* + * When inputing a single character, must also read in the + * next character for nextc, the look-ahead character. + */ + if (mbslength == 1) + mbslength++; + while (mbslength > 0) { + /* Convert one multibyte character to wchar_t. */ + if (!cerr) + clen = mbtowc(src, mbsrc, MB_LEN_MAX); + if (cerr || clen < 0) { + /* Conversion error, process as a byte instead. */ + *src = (wint_t)(u_char)*mbsrc; + clen = 1; + cerr = 1; + } + if (clen == 0) + /* + * NUL in input gives 0 return value. process + * as single NUL byte and keep going. + */ + clen = 1; + /* Advance buffer character pointer. */ + src++; + /* Advance input pointer by number of bytes read. */ + mbsrc += clen; + /* Decrement input byte count. */ + mbslength -= clen; + } + len = src - psrc; + src = psrc; + /* + * In the single character input case, we will have actually + * processed two characters, c and nextc. Reset len back to + * just a single character. + */ + if (mblength < len) + len = mblength; + + /* Convert extra argument to list of characters for this mode. */ + extra = makeextralist(flags, mbextra); + if (!extra) { + if (dlen && *dlen == 0) { + errno = ENOSPC; + goto out; + } + *mbdst = '\0'; /* can't create extra, return "" */ + error = 0; + goto out; } - f = getvisfun(flag); - for (start = dst; (c = *src++) != '\0'; /* empty */) { - dst = (*f)(dst, dlen, c, flag, *src, nextra); + + /* Look up which processing function to call. */ + f = getvisfun(flags); + + /* + * Main processing loop. + * Call do_Xvis processing function one character at a time + * with next character available for look-ahead. + */ + for (start = dst; len > 0; len--) { + c = *src++; + dst = (*f)(dst, c, flags, len >= 1 ? *src : L'\0', extra); if (dst == NULL) { errno = ENOSPC; - return -1; + goto out; } } - free(nextra); - if (dlen && *dlen == 0) { - errno = ENOSPC; - return -1; + + /* Terminate the string in the buffer. */ + *dst = L'\0'; + + /* + * Output loop. + * Convert wchar_t string back to multibyte output string. + * If we have hit a multi-byte conversion error on input, + * output byte-by-byte here. Else use wctomb(). + */ + len = wcslen(start); + maxolen = dlen ? *dlen : (wcslen(start) * MB_LEN_MAX + 1); + olen = 0; + for (dst = start; len > 0; len--) { + if (!cerr) + clen = wctomb(mbdst, *dst); + if (cerr || clen < 0) { + /* + * Conversion error, process as a byte(s) instead. + * Examine each byte and higher-order bytes for + * data. E.g., + * 0x000000000000a264 -> a2 64 + * 0x000000001f00a264 -> 1f 00 a2 64 + */ + clen = 0; + wmsk = 0; + for (i = sizeof(wmsk) - 1; i >= 0; i--) { + shft = i * NBBY; + bmsk = (uint64_t)0xffLL << shft; + wmsk |= bmsk; + if ((*dst & wmsk) || i == 0) + mbdst[clen++] = (char)( + (uint64_t)(*dst & bmsk) >> + shft); + } + cerr = 1; + } + /* If this character would exceed our output limit, stop. */ + if (olen + clen > (size_t)maxolen) + break; + /* Advance output pointer by number of bytes written. */ + mbdst += clen; + /* Advance buffer character pointer. */ + dst++; + /* Incrment output character count. */ + olen += clen; } - *dst = '\0'; - return (int)(dst - start); + + /* Terminate the output string. */ + *mbdst = '\0'; + + /* Pass conversion error flag out. */ + if (cerr_ptr) + *cerr_ptr = cerr; + + free(extra); + free(pdst); + free(psrc); + + return (int)olen; +out: + free(extra); + free(pdst); + free(psrc); + return error; } +#endif -int -strsvis(char *dst, const char *csrc, int flag, const char *extra) +#if !HAVE_SVIS +/* + * The "svis" variants all take an "extra" arg that is a pointer + * to a NUL-terminated list of characters to be encoded, too. + * These functions are useful e. g. to encode strings in such a + * way so that they are not interpreted by a shell. + */ + +char * +svis(char *mbdst, int c, int flags, int nextc, const char *mbextra) { - return istrsnvis(dst, NULL, csrc, flag, extra); + char cc[2]; + int ret; + + cc[0] = c; + cc[1] = nextc; + + ret = istrsenvisx(mbdst, NULL, cc, 1, flags, mbextra, NULL); + if (ret < 0) + return NULL; + return mbdst + ret; } -int -strsnvis(char *dst, size_t dlen, const char *csrc, int flag, const char *extra) +char * +snvis(char *mbdst, size_t dlen, int c, int flags, int nextc, const char *mbextra) { - return istrsnvis(dst, &dlen, csrc, flag, extra); + char cc[2]; + int ret; + + cc[0] = c; + cc[1] = nextc; + + ret = istrsenvisx(mbdst, &dlen, cc, 1, flags, mbextra, NULL); + if (ret < 0) + return NULL; + return mbdst + ret; } -static int -istrsnvisx(char *dst, size_t *dlen, const char *csrc, size_t len, int flag, - const char *extra) +int +strsvis(char *mbdst, const char *mbsrc, int flags, const char *mbextra) { - unsigned char c; - char *start; - char *nextra = NULL; - const unsigned char *src = (const unsigned char *)csrc; - visfun_t f; + return istrsenvisx(mbdst, NULL, mbsrc, 0, flags, mbextra, NULL); +} - _DIAGASSERT(dst != NULL); - _DIAGASSERT(src != NULL); - _DIAGASSERT(extra != NULL); - MAKEEXTRALIST(flag, nextra, extra); - if (! nextra) { - if (dlen && *dlen == 0) { - errno = ENOSPC; - return -1; - } - *dst = '\0'; /* can't create nextra, return "" */ - return 0; - } +int +strsnvis(char *mbdst, size_t dlen, const char *mbsrc, int flags, const char *mbextra) +{ + return istrsenvisx(mbdst, &dlen, mbsrc, 0, flags, mbextra, NULL); +} - f = getvisfun(flag); - for (start = dst; len > 0; len--) { - c = *src++; - dst = (*f)(dst, dlen, c, flag, len > 1 ? *src : '\0', nextra); - if (dst == NULL) { - errno = ENOSPC; - return -1; - } - } - free(nextra); - if (dlen && *dlen == 0) { - errno = ENOSPC; - return -1; - } - *dst = '\0'; - return (int)(dst - start); +int +strsvisx(char *mbdst, const char *mbsrc, size_t len, int flags, const char *mbextra) +{ + return istrsenvisx(mbdst, NULL, mbsrc, len, flags, mbextra, NULL); } int -strsvisx(char *dst, const char *csrc, size_t len, int flag, const char *extra) +strsnvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags, + const char *mbextra) { - return istrsnvisx(dst, NULL, csrc, len, flag, extra); + return istrsenvisx(mbdst, &dlen, mbsrc, len, flags, mbextra, NULL); } int -strsnvisx(char *dst, size_t dlen, const char *csrc, size_t len, int flag, - const char *extra) +strsenvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags, + const char *mbextra, int *cerr_ptr) { - return istrsnvisx(dst, &dlen, csrc, len, flag, extra); + return istrsenvisx(mbdst, &dlen, mbsrc, len, flags, mbextra, cerr_ptr); } #endif @@ -464,120 +605,83 @@ strsnvisx(char *dst, size_t dlen, const char *csrc, size_t len, int flag, /* * vis - visually encode characters */ -static char * -invis(char *dst, size_t *dlen, int c, int flag, int nextc) +char * +vis(char *mbdst, int c, int flags, int nextc) { - char *extra = NULL; - unsigned char uc = (unsigned char)c; - visfun_t f; + char cc[2]; + int ret; - _DIAGASSERT(dst != NULL); + cc[0] = c; + cc[1] = nextc; - MAKEEXTRALIST(flag, extra, ""); - if (! extra) { - if (dlen && *dlen == 0) { - errno = ENOSPC; - return NULL; - } - *dst = '\0'; /* can't create extra, return "" */ - return dst; - } - f = getvisfun(flag); - dst = (*f)(dst, dlen, uc, flag, nextc, extra); - free(extra); - if (dst == NULL || (dlen && *dlen == 0)) { - errno = ENOSPC; + ret = istrsenvisx(mbdst, NULL, cc, 1, flags, "", NULL); + if (ret < 0) return NULL; - } - *dst = '\0'; - return dst; + return mbdst + ret; } char * -vis(char *dst, int c, int flag, int nextc) +nvis(char *mbdst, size_t dlen, int c, int flags, int nextc) { - return invis(dst, NULL, c, flag, nextc); -} + char cc[2]; + int ret; -char * -nvis(char *dst, size_t dlen, int c, int flag, int nextc) -{ - return invis(dst, &dlen, c, flag, nextc); -} + cc[0] = c; + cc[1] = nextc; + ret = istrsenvisx(mbdst, &dlen, cc, 1, flags, "", NULL); + if (ret < 0) + return NULL; + return mbdst + ret; +} /* - * strvis, strvisx - visually encode characters from src into dst + * strvis - visually encode characters from src into dst * * Dst must be 4 times the size of src to account for possible * expansion. The length of dst, not including the trailing NULL, * is returned. - * - * Strvisx encodes exactly len bytes from src into dst. - * This is useful for encoding a block of data. */ -static int -istrnvis(char *dst, size_t *dlen, const char *src, int flag) -{ - char *extra = NULL; - int rv; - - MAKEEXTRALIST(flag, extra, ""); - if (!extra) { - if (dlen && *dlen == 0) { - errno = ENOSPC; - return -1; - } - *dst = '\0'; /* can't create extra, return "" */ - return 0; - } - rv = istrsnvis(dst, dlen, src, flag, extra); - free(extra); - return rv; -} int -strvis(char *dst, const char *src, int flag) +strvis(char *mbdst, const char *mbsrc, int flags) { - return istrnvis(dst, NULL, src, flag); + return istrsenvisx(mbdst, NULL, mbsrc, 0, flags, "", NULL); } int -strnvis(char *dst, size_t dlen, const char *src, int flag) +strnvis(char *mbdst, size_t dlen, const char *mbsrc, int flags) { - return istrnvis(dst, &dlen, src, flag); + return istrsenvisx(mbdst, &dlen, mbsrc, 0, flags, "", NULL); } -static int -istrnvisx(char *dst, size_t *dlen, const char *src, size_t len, int flag) -{ - char *extra = NULL; - int rv; +/* + * strvisx - visually encode characters from src into dst + * + * Dst must be 4 times the size of src to account for possible + * expansion. The length of dst, not including the trailing NULL, + * is returned. + * + * Strvisx encodes exactly len characters from src into dst. + * This is useful for encoding a block of data. + */ - MAKEEXTRALIST(flag, extra, ""); - if (!extra) { - if (dlen && *dlen == 0) { - errno = ENOSPC; - return -1; - } - *dst = '\0'; /* can't create extra, return "" */ - return 0; - } - rv = istrsnvisx(dst, dlen, src, len, flag, extra); - free(extra); - return rv; +int +strvisx(char *mbdst, const char *mbsrc, size_t len, int flags) +{ + return istrsenvisx(mbdst, NULL, mbsrc, len, flags, "", NULL); } int -strvisx(char *dst, const char *src, size_t len, int flag) +strnvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags) { - return istrnvisx(dst, NULL, src, len, flag); + return istrsenvisx(mbdst, &dlen, mbsrc, len, flags, "", NULL); } int -strnvisx(char *dst, size_t dlen, const char *src, size_t len, int flag) +strenvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags, + int *cerr_ptr) { - return istrnvisx(dst, &dlen, src, len, flag); + return istrsenvisx(mbdst, &dlen, mbsrc, len, flags, "", cerr_ptr); } - #endif |