"Fossies" - the Fresh Open Source Software Archive

Member "tnftp-20200705/libedit/chartype.c" (4 Jul 2020, 7882 Bytes) of package /linux/privat/tnftp-20200705.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "chartype.c" see the Fossies "Dox" file reference documentation.

    1 /*  $NetBSD: chartype.c,v 1.3 2020/07/04 13:43:21 lukem Exp $   */
    2 /*  from    NetBSD: chartype.c,v 1.35 2019/07/23 10:18:52 christos Exp  */
    3 
    4 /*-
    5  * Copyright (c) 2009 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   20  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   27  * POSSIBILITY OF SUCH DAMAGE.
   28  */
   29 
   30 /*
   31  * chartype.c: character classification and meta information
   32  */
   33 #include "config.h"
   34 
   35 #if 0 /* tnftp */
   36 #if !defined(lint) && !defined(SCCSID)
   37 __RCSID(" NetBSD: chartype.c,v 1.35 2019/07/23 10:18:52 christos Exp  ");
   38 #endif /* not lint && not SCCSID */
   39 
   40 #include <ctype.h>
   41 #include <limits.h>
   42 #include <stdlib.h>
   43 #include <string.h>
   44 #endif /* tnftp */
   45 
   46 #include "el.h"
   47 
   48 #define CT_BUFSIZ ((size_t)1024)
   49 
   50 static int ct_conv_cbuff_resize(ct_buffer_t *, size_t);
   51 static int ct_conv_wbuff_resize(ct_buffer_t *, size_t);
   52 
   53 static int
   54 ct_conv_cbuff_resize(ct_buffer_t *conv, size_t csize)
   55 {
   56     void *p;
   57 
   58     if (csize <= conv->csize)
   59         return 0;
   60 
   61     conv->csize = csize;
   62 
   63     p = el_realloc(conv->cbuff, conv->csize * sizeof(*conv->cbuff));
   64     if (p == NULL) {
   65         conv->csize = 0;
   66         el_free(conv->cbuff);
   67         conv->cbuff = NULL;
   68         return -1;
   69     }
   70     conv->cbuff = p;
   71     return 0;
   72 }
   73 
   74 static int
   75 ct_conv_wbuff_resize(ct_buffer_t *conv, size_t wsize)
   76 {
   77     void *p;
   78 
   79     if (wsize <= conv->wsize)
   80         return 0;
   81 
   82     conv->wsize = wsize;
   83 
   84     p = el_realloc(conv->wbuff, conv->wsize * sizeof(*conv->wbuff));
   85     if (p == NULL) {
   86         conv->wsize = 0;
   87         el_free(conv->wbuff);
   88         conv->wbuff = NULL;
   89         return -1;
   90     }
   91     conv->wbuff = p;
   92     return 0;
   93 }
   94 
   95 
   96 char *
   97 ct_encode_string(const wchar_t *s, ct_buffer_t *conv)
   98 {
   99     char *dst;
  100     ssize_t used;
  101 
  102     if (!s)
  103         return NULL;
  104 
  105     dst = conv->cbuff;
  106     for (;;) {
  107         used = (ssize_t)(dst - conv->cbuff);
  108         if ((conv->csize - (size_t)used) < 5) {
  109             if (ct_conv_cbuff_resize(conv,
  110                 conv->csize + CT_BUFSIZ) == -1)
  111                 return NULL;
  112             dst = conv->cbuff + used;
  113         }
  114         if (!*s)
  115             break;
  116         used = ct_encode_char(dst, (size_t)5, *s);
  117         if (used == -1) /* failed to encode, need more buffer space */
  118             abort();
  119         ++s;
  120         dst += used;
  121     }
  122     *dst = '\0';
  123     return conv->cbuff;
  124 }
  125 
  126 wchar_t *
  127 ct_decode_string(const char *s, ct_buffer_t *conv)
  128 {
  129     size_t len;
  130 
  131     if (!s)
  132         return NULL;
  133 
  134     len = mbstowcs(NULL, s, (size_t)0);
  135     if (len == (size_t)-1)
  136         return NULL;
  137 
  138     if (conv->wsize < ++len)
  139         if (ct_conv_wbuff_resize(conv, len + CT_BUFSIZ) == -1)
  140             return NULL;
  141 
  142     mbstowcs(conv->wbuff, s, conv->wsize);
  143     return conv->wbuff;
  144 }
  145 
  146 
  147 libedit_private wchar_t **
  148 ct_decode_argv(int argc, const char *argv[], ct_buffer_t *conv)
  149 {
  150     size_t bufspace;
  151     int i;
  152     wchar_t *p;
  153     wchar_t **wargv;
  154     ssize_t bytes;
  155 
  156     /* Make sure we have enough space in the conversion buffer to store all
  157      * the argv strings. */
  158     for (i = 0, bufspace = 0; i < argc; ++i)
  159         bufspace += argv[i] ? strlen(argv[i]) + 1 : 0;
  160     if (conv->wsize < ++bufspace)
  161         if (ct_conv_wbuff_resize(conv, bufspace + CT_BUFSIZ) == -1)
  162             return NULL;
  163 
  164     wargv = el_calloc((size_t)(argc + 1), sizeof(*wargv));
  165 
  166     for (i = 0, p = conv->wbuff; i < argc; ++i) {
  167         if (!argv[i]) {   /* don't pass null pointers to mbstowcs */
  168             wargv[i] = NULL;
  169             continue;
  170         } else {
  171             wargv[i] = p;
  172             bytes = (ssize_t)mbstowcs(p, argv[i], bufspace);
  173         }
  174         if (bytes == -1) {
  175             el_free(wargv);
  176             return NULL;
  177         } else
  178             bytes++;  /* include '\0' in the count */
  179         bufspace -= (size_t)bytes;
  180         p += bytes;
  181     }
  182     wargv[i] = NULL;
  183 
  184     return wargv;
  185 }
  186 
  187 
  188 libedit_private size_t
  189 ct_enc_width(wchar_t c)
  190 {
  191     mbstate_t mbs;
  192     char buf[MB_LEN_MAX];
  193     size_t size;
  194     memset(&mbs, 0, sizeof(mbs));
  195 
  196     if ((size = wcrtomb(buf, c, &mbs)) == (size_t)-1)
  197         return 0;
  198     return size;
  199 }
  200 
  201 libedit_private ssize_t
  202 ct_encode_char(char *dst, size_t len, wchar_t c)
  203 {
  204     ssize_t l = 0;
  205     if (len < ct_enc_width(c))
  206         return -1;
  207     l = wctomb(dst, c);
  208 
  209     if (l < 0) {
  210         wctomb(NULL, L'\0');
  211         l = 0;
  212     }
  213     return l;
  214 }
  215 
  216 libedit_private const wchar_t *
  217 ct_visual_string(const wchar_t *s, ct_buffer_t *conv)
  218 {
  219     wchar_t *dst;
  220     ssize_t used;
  221 
  222     if (!s)
  223         return NULL;
  224 
  225     if (ct_conv_wbuff_resize(conv, CT_BUFSIZ) == -1)
  226         return NULL;
  227 
  228     used = 0;
  229     dst = conv->wbuff;
  230     while (*s) {
  231         used = ct_visual_char(dst,
  232             conv->wsize - (size_t)(dst - conv->wbuff), *s);
  233         if (used != -1) {
  234             ++s;
  235             dst += used;
  236             continue;
  237         }
  238 
  239         /* failed to encode, need more buffer space */
  240         used = dst - conv->wbuff;
  241         if (ct_conv_wbuff_resize(conv, conv->wsize + CT_BUFSIZ) == -1)
  242             return NULL;
  243         dst = conv->wbuff + used;
  244     }
  245 
  246     if (dst >= (conv->wbuff + conv->wsize)) { /* sigh */
  247         used = dst - conv->wbuff;
  248         if (ct_conv_wbuff_resize(conv, conv->wsize + CT_BUFSIZ) == -1)
  249             return NULL;
  250         dst = conv->wbuff + used;
  251     }
  252 
  253     *dst = L'\0';
  254     return conv->wbuff;
  255 }
  256 
  257 
  258 
  259 libedit_private int
  260 ct_visual_width(wchar_t c)
  261 {
  262     int t = ct_chr_class(c);
  263     switch (t) {
  264     case CHTYPE_ASCIICTL:
  265         return 2; /* ^@ ^? etc. */
  266     case CHTYPE_TAB:
  267         return 1; /* Hmm, this really need to be handled outside! */
  268     case CHTYPE_NL:
  269         return 0; /* Should this be 1 instead? */
  270     case CHTYPE_PRINT:
  271         return wcwidth(c);
  272     case CHTYPE_NONPRINT:
  273         if (c > 0xffff) /* prefer standard 4-byte display over 5-byte */
  274             return 8; /* \U+12345 */
  275         else
  276             return 7; /* \U+1234 */
  277     default:
  278         return 0; /* should not happen */
  279     }
  280 }
  281 
  282 
  283 libedit_private ssize_t
  284 ct_visual_char(wchar_t *dst, size_t len, wchar_t c)
  285 {
  286     int t = ct_chr_class(c);
  287     switch (t) {
  288     case CHTYPE_TAB:
  289     case CHTYPE_NL:
  290     case CHTYPE_ASCIICTL:
  291         if (len < 2)
  292             return -1;   /* insufficient space */
  293         *dst++ = '^';
  294         if (c == '\177')
  295             *dst = '?'; /* DEL -> ^? */
  296         else
  297             *dst = c | 0100;    /* uncontrolify it */
  298         return 2;
  299     case CHTYPE_PRINT:
  300         if (len < 1)
  301             return -1;  /* insufficient space */
  302         *dst = c;
  303         return 1;
  304     case CHTYPE_NONPRINT:
  305         /* we only use single-width glyphs for display,
  306          * so this is right */
  307         if ((ssize_t)len < ct_visual_width(c))
  308             return -1;   /* insufficient space */
  309         *dst++ = '\\';
  310         *dst++ = 'U';
  311         *dst++ = '+';
  312 #define tohexdigit(v) "0123456789ABCDEF"[v]
  313         if (c > 0xffff) /* prefer standard 4-byte display over 5-byte */
  314             *dst++ = tohexdigit(((unsigned int) c >> 16) & 0xf);
  315         *dst++ = tohexdigit(((unsigned int) c >> 12) & 0xf);
  316         *dst++ = tohexdigit(((unsigned int) c >>  8) & 0xf);
  317         *dst++ = tohexdigit(((unsigned int) c >>  4) & 0xf);
  318         *dst   = tohexdigit(((unsigned int) c      ) & 0xf);
  319         return c > 0xffff ? 8 : 7;
  320         /*FALLTHROUGH*/
  321     /* these two should be handled outside this function */
  322     default:            /* we should never hit the default */
  323         return 0;
  324     }
  325 }
  326 
  327 
  328 
  329 
  330 libedit_private int
  331 ct_chr_class(wchar_t c)
  332 {
  333     if (c == '\t')
  334         return CHTYPE_TAB;
  335     else if (c == '\n')
  336         return CHTYPE_NL;
  337     else if (c < 0x100 && iswcntrl(c))
  338         return CHTYPE_ASCIICTL;
  339     else if (iswprint(c))
  340         return CHTYPE_PRINT;
  341     else
  342         return CHTYPE_NONPRINT;
  343 }