[BACK]Return to vis.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libc / gen

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/lib/libc/gen/vis.c between version 1.44 and 1.44.4.2

version 1.44, 2011/03/12 19:52:48 version 1.44.4.2, 2014/05/22 11:36:52
Line 59 
Line 59 
 #if defined(LIBC_SCCS) && !defined(lint)  #if defined(LIBC_SCCS) && !defined(lint)
 __RCSID("$NetBSD$");  __RCSID("$NetBSD$");
 #endif /* LIBC_SCCS and not lint */  #endif /* LIBC_SCCS and not lint */
   #ifdef __FBSDID
   __FBSDID("$FreeBSD$");
   #define _DIAGASSERT(x)  assert(x)
   #endif
   
 #include "namespace.h"  #include "namespace.h"
 #include <sys/types.h>  #include <sys/types.h>
   #include <sys/param.h>
   
 #include <assert.h>  #include <assert.h>
 #include <vis.h>  #include <vis.h>
 #include <errno.h>  #include <errno.h>
 #include <stdlib.h>  #include <stdlib.h>
   #include <wchar.h>
   #include <wctype.h>
   
 #ifdef __weak_alias  #ifdef __weak_alias
 __weak_alias(strvisx,_strvisx)  __weak_alias(strvisx,_strvisx)
Line 78  __weak_alias(strvisx,_strvisx)
Line 85  __weak_alias(strvisx,_strvisx)
 #include <stdio.h>  #include <stdio.h>
 #include <string.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  #undef BELL
 #define BELL '\a'  #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
   
 #define isoctal(c)      (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')  #if !HAVE_NBTOOL_CONFIG_H
 #define iswhite(c)      (c == ' ' || c == '\t' || c == '\n')  #ifndef __NetBSD__
 #define issafe(c)       (c == '\b' || c == BELL || c == '\r')  /*
 #define xtoa(c)         "0123456789abcdef"[c]   * On NetBSD MB_LEN_MAX is currently 32 which does not fit on any integer
 #define XTOA(c)         "0123456789ABCDEF"[c]   * integral type and it is probably wrong, since currently the maximum
    * number of bytes and character needs is 6. Until this is fixed, the
 #define MAXEXTRAS       5   * loops below are using sizeof(uint64_t) - 1 instead of MB_LEN_MAX, and
    * the assertion is commented out.
 #define MAKEEXTRALIST(flag, extra, orig_str)                                  \   */
 do {                                                                          \  #ifdef __FreeBSD__
         const char *orig = orig_str;                                          \  /*
         const char *o = orig;                                                 \   * On FreeBSD including <sys/systm.h> for CTASSERT only works in kernel
         char *e;                                                              \   * mode.
         while (*o++)                                                          \   */
                 continue;                                                     \  #ifndef CTASSERT
         extra = malloc((size_t)((o - orig) + MAXEXTRAS));                     \  #define CTASSERT(x)             _CTASSERT(x, __LINE__)
         if (!extra) break;                                                    \  #define _CTASSERT(x, y)         __CTASSERT(x, y)
         for (o = orig, e = extra; (*e++ = *o++) != '\0';)                     \  #define __CTASSERT(x, y)        typedef char __assert ## y[(x) ? 1 : -1]
                 continue;                                                     \  #endif
         e--;                                                                  \  #endif /* __FreeBSD__ */
         if (flag & VIS_SP) *e++ = ' ';                                        \  CTASSERT(MB_LEN_MAX <= sizeof(uint64_t));
         if (flag & VIS_TAB) *e++ = '\t';                                      \  #endif /* !__NetBSD__ */
         if (flag & VIS_NL) *e++ = '\n';                                       \  #endif
         if ((flag & VIS_NOSLASH) == 0) *e++ = '\\';                           \  
         *e = '\0';                                                            \  
 } while (/*CONSTCOND*/0)  
   
 /*  /*
  * This is do_hvis, for HTTP style (RFC 1808)   * This is do_hvis, for HTTP style (RFC 1808)
  */   */
 static char *  static wchar_t *
 do_hvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra)  do_hvis(wchar_t *dst, wint_t c, int flags, wint_t nextc, const wchar_t *extra)
 {  {
           if (iswalnum(c)
         if ((isascii(c) && isalnum(c))  
             /* safe */              /* safe */
             || c == '$' || c == '-' || c == '_' || c == '.' || c == '+'              || c == L'$' || c == L'-' || c == L'_' || c == L'.' || c == L'+'
             /* extra */              /* extra */
             || c == '!' || c == '*' || c == '\'' || c == '(' || c == ')'              || c == L'!' || c == L'*' || c == L'\'' || c == L'(' || c == L')'
             || c == ',') {              || c == L',')
                 dst = do_svis(dst, dlen, c, flag, nextc, extra);                  dst = do_svis(dst, c, flags, nextc, extra);
         } else {          else {
                 if (dlen) {                  *dst++ = L'%';
                         if (*dlen < 3)  
                                 return NULL;  
                         *dlen -= 3;  
                 }  
                 *dst++ = '%';  
                 *dst++ = xtoa(((unsigned int)c >> 4) & 0xf);                  *dst++ = xtoa(((unsigned int)c >> 4) & 0xf);
                 *dst++ = xtoa((unsigned int)c & 0xf);                  *dst++ = xtoa((unsigned int)c & 0xf);
         }          }
Line 142  do_hvis(char *dst, size_t *dlen, int c, 
Line 156  do_hvis(char *dst, size_t *dlen, int c, 
  * This is do_mvis, for Quoted-Printable MIME (RFC 2045)   * This is do_mvis, for Quoted-Printable MIME (RFC 2045)
  * NB: No handling of long lines or CRLF.   * NB: No handling of long lines or CRLF.
  */   */
 static char *  static wchar_t *
 do_mvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra)  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 */              /* Space at the end of the line */
             ((isspace(c) && (nextc == '\r' || nextc == '\n')) ||              ((iswspace(c) && (nextc == L'\r' || nextc == L'\n')) ||
             /* Out of range */              /* Out of range */
             (!isspace(c) && (c < 33 || (c > 60 && c < 62) || c > 126)) ||              (!iswspace(c) && (c < 33 || (c > 60 && c < 62) || c > 126)) ||
             /* Specific char to be escaped */              /* Specific char to be escaped */
             strchr("#$@[\\]^`{|}~", c) != NULL)) {              wcschr(L"#$@[\\]^`{|}~", c) != NULL)) {
                 if (dlen) {                  *dst++ = L'=';
                         if (*dlen < 3)  
                                 return NULL;  
                         *dlen -= 3;  
                 }  
                 *dst++ = '=';  
                 *dst++ = XTOA(((unsigned int)c >> 4) & 0xf);                  *dst++ = XTOA(((unsigned int)c >> 4) & 0xf);
                 *dst++ = XTOA((unsigned int)c & 0xf);                  *dst++ = XTOA((unsigned int)c & 0xf);
         } else {          } else
                 dst = do_svis(dst, dlen, c, flag, nextc, extra);                  dst = do_svis(dst, c, flags, nextc, extra);
         }  
         return dst;          return dst;
 }  }
   
 /*  /*
  * This is do_vis, the central code of vis.   * Output single byte of multibyte character.
  * 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.  
  */   */
 static char *  static wchar_t *
 do_svis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra)  do_mbyte(wchar_t *dst, wint_t c, int flags, wint_t nextc, int iswextra)
 {  {
         int isextra;          if (flags & VIS_CSTYLE) {
         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);  
                 switch (c) {                  switch (c) {
                 case '\n':                  case L'\n':
                         *dst++ = '\\'; *dst++ = 'n';                          *dst++ = L'\\'; *dst++ = L'n';
                         return dst;                          return dst;
                 case '\r':                  case L'\r':
                         *dst++ = '\\'; *dst++ = 'r';                          *dst++ = L'\\'; *dst++ = L'r';
                         return dst;                          return dst;
                 case '\b':                  case L'\b':
                         *dst++ = '\\'; *dst++ = 'b';                          *dst++ = L'\\'; *dst++ = L'b';
                         return dst;                          return dst;
                 case BELL:                  case BELL:
                         *dst++ = '\\'; *dst++ = 'a';                          *dst++ = L'\\'; *dst++ = L'a';
                         return dst;                          return dst;
                 case '\v':                  case L'\v':
                         *dst++ = '\\'; *dst++ = 'v';                          *dst++ = L'\\'; *dst++ = L'v';
                         return dst;                          return dst;
                 case '\t':                  case L'\t':
                         *dst++ = '\\'; *dst++ = 't';                          *dst++ = L'\\'; *dst++ = L't';
                         return dst;                          return dst;
                 case '\f':                  case L'\f':
                         *dst++ = '\\'; *dst++ = 'f';                          *dst++ = L'\\'; *dst++ = L'f';
                         return dst;                          return dst;
                 case ' ':                  case L' ':
                         *dst++ = '\\'; *dst++ = 's';                          *dst++ = L'\\'; *dst++ = L's';
                         return dst;                          return dst;
                 case '\0':                  case L'\0':
                         *dst++ = '\\'; *dst++ = '0';                          *dst++ = L'\\'; *dst++ = L'0';
                         if (isoctal(nextc)) {                          if (iswoctal(nextc)) {
                                 HAVE(2);                                  *dst++ = L'0';
                                 *dst++ = '0';                                  *dst++ = L'0';
                                 *dst++ = '0';  
                         }                          }
                         return dst;                          return dst;
                 default:                  default:
                         if (isgraph(c)) {                          if (iswgraph(c)) {
                                 *dst++ = '\\'; *dst++ = c;                                  *dst++ = L'\\';
                                   *dst++ = c;
                                 return dst;                                  return dst;
                         }                          }
                         if (dlen)  
                                 *dlen = odlen;  
                 }                  }
         }          }
         if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) {          if (iswextra || ((c & 0177) == L' ') || (flags & VIS_OCTAL)) {
                 HAVE(4);                  *dst++ = L'\\';
                 *dst++ = '\\';                  *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + L'0';
                 *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + '0';                  *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + L'0';
                 *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + '0';                  *dst++ =                             (c       & 07) + L'0';
                 *dst++ =                             (c       & 07) + '0';  
         } else {          } else {
                 if ((flag & VIS_NOSLASH) == 0) {                  if ((flags & VIS_NOSLASH) == 0)
                         HAVE(1);                          *dst++ = L'\\';
                         *dst++ = '\\';  
                 }  
   
                 if (c & 0200) {                  if (c & 0200) {
                         HAVE(1);                          c &= 0177;
                         c &= 0177; *dst++ = 'M';                          *dst++ = L'M';
                 }                  }
   
                 if (iscntrl(c)) {                  if (iswcntrl(c)) {
                         HAVE(2);                          *dst++ = L'^';
                         *dst++ = '^';  
                         if (c == 0177)                          if (c == 0177)
                                 *dst++ = '?';                                  *dst++ = L'?';
                         else                          else
                                 *dst++ = c + '@';                                  *dst++ = c + L'@';
                 } else {                  } else {
                         HAVE(2);                          *dst++ = L'-';
                         *dst++ = '-'; *dst++ = c;                          *dst++ = c;
                 }                  }
         }          }
   
           return dst;
   }
   
   /*
    * 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;          return dst;
 out:  
         *dlen = odlen;  
         return NULL;  
 }  }
   
 typedef char *(*visfun_t)(char *, size_t *, int, int, int, const char *);  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.   * Return the appropriate encoding function depending on the flags given.
  */   */
 static visfun_t  static visfun_t
 getvisfun(int flag)  getvisfun(int flags)
 {  {
         if (flag & VIS_HTTPSTYLE)          if (flags & VIS_HTTPSTYLE)
                 return do_hvis;                  return do_hvis;
         if (flag & VIS_MIMESTYLE)          if (flags & VIS_MIMESTYLE)
                 return do_mvis;                  return do_mvis;
         return do_svis;          return do_svis;
 }  }
   
 /*  /*
  * isnvis - visually encode characters, also encoding the characters   * Expand list of extra characters to not visually encode.
  *        pointed to by `extra'  
  */   */
 static char *  static wchar_t *
 isnvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra)  makeextralist(int flags, const char *src)
 {  {
         char *nextra = NULL;          wchar_t *dst, *d;
         visfun_t f;          size_t len;
   
         _DIAGASSERT(dst != NULL);          len = strlen(src);
         _DIAGASSERT(extra != NULL);          if ((dst = calloc(len + MAXEXTRAS, sizeof(*dst))) == 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;  
                 return NULL;                  return NULL;
         }  
         *dst = '\0';  
         return dst;  
 }  
   
 char *          if (mbstowcs(dst, src, len) == (size_t)-1) {
 svis(char *dst, int c, int flag, int nextc, const char *extra)                  size_t i;
 {                  for (i = 0; i < len; i++)
         return isnvis(dst, NULL, c, flag, nextc, extra);                          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'#';
           }
   
           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 *          return dst;
 snvis(char *dst, size_t dlen, int c, int flag, int nextc, const char *extra)  
 {  
         return isnvis(dst, &dlen, c, flag, nextc, extra);  
 }  }
   
   
 /*  /*
  * strsvis, strsvisx - visually encode characters from src into dst   * istrsenvisx()
  *   *      The main internal function.
  *      Extra is a pointer to a \0-terminated list of characters to   *      All user-visible functions call this one.
  *      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.  
  */   */
 static int  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;          wchar_t *dst, *src, *pdst, *psrc, *start, *extra;
         char *start;          size_t len, olen;
         char *nextra = NULL;          uint64_t bmsk, wmsk;
         const unsigned char *src = (const unsigned char *)csrc;          wint_t c;
         visfun_t f;          visfun_t f;
           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;
   
         _DIAGASSERT(dst != NULL);          /* Convert extra argument to list of characters for this mode. */
         _DIAGASSERT(src != NULL);          extra = makeextralist(flags, mbextra);
         _DIAGASSERT(extra != NULL);          if (!extra) {
         MAKEEXTRALIST(flag, nextra, extra);                  if (dlen && *dlen == 0) {
         if (!nextra) {                          errno = ENOSPC;
                 *dst = '\0';            /* can't create nextra, return "" */                          goto out;
                 return 0;                  }
                   *mbdst = '\0';          /* can't create extra, return "" */
                   error = 0;
                   goto out;
         }          }
         f = getvisfun(flag);  
         for (start = dst; (c = *src++) != '\0'; /* empty */) {          /* Look up which processing function to call. */
                 dst = (*f)(dst, dlen, c, flag, *src, nextra);          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) {                  if (dst == NULL) {
                         errno = ENOSPC;                          errno = ENOSPC;
                         return -1;                          goto out;
                 }                  }
         }          }
         free(nextra);  
         if (dlen && *dlen == 0) {          /* Terminate the string in the buffer. */
                 errno = ENOSPC;          *dst = L'\0';
                 return -1;  
         }          /*
         *dst = '\0';           * Output loop.
         return (int)(dst - start);           * 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;
           }
   
           /* 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  #if !HAVE_SVIS
 strsvis(char *dst, const char *csrc, int flag, const char *extra)  /*
    *      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  char *
 strsnvis(char *dst, size_t dlen, const char *csrc, int flag, const char *extra)  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  int
 istrsnvisx(char *dst, size_t *dlen, const char *csrc, size_t len, int flag,  strsvis(char *mbdst, const char *mbsrc, int flags, const char *mbextra)
     const char *extra)  
 {  {
         unsigned char c;          return istrsenvisx(mbdst, NULL, mbsrc, 0, flags, mbextra, NULL);
         char *start;  }
         char *nextra = NULL;  
         const unsigned char *src = (const unsigned char *)csrc;  
         visfun_t f;  
   
         _DIAGASSERT(dst != NULL);  int
         _DIAGASSERT(src != NULL);  strsnvis(char *mbdst, size_t dlen, const char *mbsrc, int flags, const char *mbextra)
         _DIAGASSERT(extra != NULL);  {
         MAKEEXTRALIST(flag, nextra, extra);          return istrsenvisx(mbdst, &dlen, mbsrc, 0, flags, mbextra, NULL);
         if (! nextra) {  }
                 if (dlen && *dlen == 0) {  
                         errno = ENOSPC;  
                         return -1;  
                 }  
                 *dst = '\0';            /* can't create nextra, return "" */  
                 return 0;  
         }  
   
         f = getvisfun(flag);  int
         for (start = dst; len > 0; len--) {  strsvisx(char *mbdst, const char *mbsrc, size_t len, int flags, const char *mbextra)
                 c = *src++;  {
                 dst = (*f)(dst, dlen, c, flag, len > 1 ? *src : '\0', nextra);          return istrsenvisx(mbdst, NULL, mbsrc, len, flags, mbextra, NULL);
                 if (dst == NULL) {  
                         errno = ENOSPC;  
                         return -1;  
                 }  
         }  
         free(nextra);  
         if (dlen && *dlen == 0) {  
                 errno = ENOSPC;  
                 return -1;  
         }  
         *dst = '\0';  
         return (int)(dst - start);  
 }  }
   
 int  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  int
 strsnvisx(char *dst, size_t dlen, const char *csrc, size_t len, int flag,  strsenvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags,
     const char *extra)      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  #endif
   
Line 455  strsnvisx(char *dst, size_t dlen, const 
Line 605  strsnvisx(char *dst, size_t dlen, const 
 /*  /*
  * vis - visually encode characters   * vis - visually encode characters
  */   */
 static char *  char *
 invis(char *dst, size_t *dlen, int c, int flag, int nextc)  vis(char *mbdst, int c, int flags, int nextc)
 {  {
         char *extra = NULL;          char cc[2];
         unsigned char uc = (unsigned char)c;          int ret;
         visfun_t f;  
   
         _DIAGASSERT(dst != NULL);          cc[0] = c;
           cc[1] = nextc;
   
         MAKEEXTRALIST(flag, extra, "");          ret = istrsenvisx(mbdst, NULL, cc, 1, flags, "", NULL);
         if (! extra) {          if (ret < 0)
                 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;  
                 return NULL;                  return NULL;
         }          return mbdst + ret;
         *dst = '\0';  
         return dst;  
 }  }
   
 char *  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 *          cc[0] = c;
 nvis(char *dst, size_t dlen, int c, int flag, int nextc)          cc[1] = nextc;
 {  
         return invis(dst, &dlen, c, flag, 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   *      Dst must be 4 times the size of src to account for possible
  *      expansion.  The length of dst, not including the trailing NULL,   *      expansion.  The length of dst, not including the trailing NULL,
  *      is returned.   *      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  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  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)   * strvisx - visually encode characters from src into dst
 {   *
         char *extra = NULL;   *      Dst must be 4 times the size of src to account for possible
         int rv;   *      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, "");  int
         if (!extra) {  strvisx(char *mbdst, const char *mbsrc, size_t len, int flags)
                 if (dlen && *dlen == 0) {  {
                         errno = ENOSPC;          return istrsenvisx(mbdst, NULL, mbsrc, len, flags, "", NULL);
                         return -1;  
                 }  
                 *dst = '\0';            /* can't create extra, return "" */  
                 return 0;  
         }  
         rv = istrsnvisx(dst, dlen, src, len, flag, extra);  
         free(extra);  
         return rv;  
 }  }
   
 int  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  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  #endif

Legend:
Removed from v.1.44  
changed lines
  Added in v.1.44.4.2

CVSweb <webmaster@jp.NetBSD.org>