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

Annotation of src/lib/libc/gen/vis.c, Revision 1.58

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

CVSweb <webmaster@jp.NetBSD.org>