15e9cd1aeSAssar Westerlund /* $NetBSD: unvis.c,v 1.19 2000/01/22 22:19:13 mycroft Exp $ */
25e9cd1aeSAssar Westerlund
35e9cd1aeSAssar Westerlund /*-
45e9cd1aeSAssar Westerlund * Copyright (c) 1989, 1993
55e9cd1aeSAssar Westerlund * The Regents of the University of California. All rights reserved.
65e9cd1aeSAssar Westerlund *
75e9cd1aeSAssar Westerlund * Redistribution and use in source and binary forms, with or without
85e9cd1aeSAssar Westerlund * modification, are permitted provided that the following conditions
95e9cd1aeSAssar Westerlund * are met:
105e9cd1aeSAssar Westerlund * 1. Redistributions of source code must retain the above copyright
115e9cd1aeSAssar Westerlund * notice, this list of conditions and the following disclaimer.
125e9cd1aeSAssar Westerlund * 2. Redistributions in binary form must reproduce the above copyright
135e9cd1aeSAssar Westerlund * notice, this list of conditions and the following disclaimer in the
145e9cd1aeSAssar Westerlund * documentation and/or other materials provided with the distribution.
15c19800e8SDoug Rabson * 3. Neither the name of the University nor the names of its contributors
165e9cd1aeSAssar Westerlund * may be used to endorse or promote products derived from this software
175e9cd1aeSAssar Westerlund * without specific prior written permission.
185e9cd1aeSAssar Westerlund *
195e9cd1aeSAssar Westerlund * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
205e9cd1aeSAssar Westerlund * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
215e9cd1aeSAssar Westerlund * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
225e9cd1aeSAssar Westerlund * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
235e9cd1aeSAssar Westerlund * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
245e9cd1aeSAssar Westerlund * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
255e9cd1aeSAssar Westerlund * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
265e9cd1aeSAssar Westerlund * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
275e9cd1aeSAssar Westerlund * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
285e9cd1aeSAssar Westerlund * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
295e9cd1aeSAssar Westerlund * SUCH DAMAGE.
305e9cd1aeSAssar Westerlund */
315e9cd1aeSAssar Westerlund
325e9cd1aeSAssar Westerlund #if 1
335e9cd1aeSAssar Westerlund #include <config.h>
34c19800e8SDoug Rabson #include "roken.h"
355e9cd1aeSAssar Westerlund #ifndef _DIAGASSERT
365e9cd1aeSAssar Westerlund #define _DIAGASSERT(X)
375e9cd1aeSAssar Westerlund #endif
385e9cd1aeSAssar Westerlund #else
395e9cd1aeSAssar Westerlund #include <sys/cdefs.h>
405e9cd1aeSAssar Westerlund #if defined(LIBC_SCCS) && !defined(lint)
415e9cd1aeSAssar Westerlund #if 0
425e9cd1aeSAssar Westerlund static char sccsid[] = "@(#)unvis.c 8.1 (Berkeley) 6/4/93";
435e9cd1aeSAssar Westerlund #else
445e9cd1aeSAssar Westerlund __RCSID("$NetBSD: unvis.c,v 1.19 2000/01/22 22:19:13 mycroft Exp $");
455e9cd1aeSAssar Westerlund #endif
465e9cd1aeSAssar Westerlund #endif /* LIBC_SCCS and not lint */
475e9cd1aeSAssar Westerlund
485e9cd1aeSAssar Westerlund #define __LIBC12_SOURCE__
495e9cd1aeSAssar Westerlund
505e9cd1aeSAssar Westerlund #include "namespace.h"
515e9cd1aeSAssar Westerlund #endif
525e9cd1aeSAssar Westerlund #include <sys/types.h>
535e9cd1aeSAssar Westerlund
545e9cd1aeSAssar Westerlund #include <assert.h>
555e9cd1aeSAssar Westerlund #include <ctype.h>
565e9cd1aeSAssar Westerlund #include <stdio.h>
575e9cd1aeSAssar Westerlund #include <vis.h>
585e9cd1aeSAssar Westerlund
595e9cd1aeSAssar Westerlund #if 0
605e9cd1aeSAssar Westerlund #ifdef __weak_alias
615e9cd1aeSAssar Westerlund __weak_alias(strunvis,_strunvis)
625e9cd1aeSAssar Westerlund __weak_alias(unvis,_unvis)
635e9cd1aeSAssar Westerlund #endif
645e9cd1aeSAssar Westerlund
655e9cd1aeSAssar Westerlund __warn_references(unvis,
665e9cd1aeSAssar Westerlund "warning: reference to compatibility unvis(); include <vis.h> for correct reference")
675e9cd1aeSAssar Westerlund #endif
685e9cd1aeSAssar Westerlund
695e9cd1aeSAssar Westerlund /*
705e9cd1aeSAssar Westerlund * decode driven by state machine
715e9cd1aeSAssar Westerlund */
725e9cd1aeSAssar Westerlund #define S_GROUND 0 /* haven't seen escape char */
735e9cd1aeSAssar Westerlund #define S_START 1 /* start decoding special sequence */
745e9cd1aeSAssar Westerlund #define S_META 2 /* metachar started (M) */
755e9cd1aeSAssar Westerlund #define S_META1 3 /* metachar more, regular char (-) */
765e9cd1aeSAssar Westerlund #define S_CTRL 4 /* control char started (^) */
775e9cd1aeSAssar Westerlund #define S_OCTAL2 5 /* octal digit 2 */
785e9cd1aeSAssar Westerlund #define S_OCTAL3 6 /* octal digit 3 */
795e9cd1aeSAssar Westerlund
805e9cd1aeSAssar Westerlund #define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
815e9cd1aeSAssar Westerlund
82*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
83c19800e8SDoug Rabson rk_strunvis (char *, const char *);
84*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
85c19800e8SDoug Rabson rk_unvis (char *, int, int *, int);
86c19800e8SDoug Rabson
875e9cd1aeSAssar Westerlund /*
885e9cd1aeSAssar Westerlund * unvis - decode characters previously encoded by vis
895e9cd1aeSAssar Westerlund */
90c19800e8SDoug Rabson
91*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
rk_unvis(char * cp,int c,int * astate,int flag)92c19800e8SDoug Rabson rk_unvis(char *cp, int c, int *astate, int flag)
935e9cd1aeSAssar Westerlund {
945e9cd1aeSAssar Westerlund
955e9cd1aeSAssar Westerlund _DIAGASSERT(cp != NULL);
965e9cd1aeSAssar Westerlund _DIAGASSERT(astate != NULL);
975e9cd1aeSAssar Westerlund
985e9cd1aeSAssar Westerlund if (flag & UNVIS_END) {
995e9cd1aeSAssar Westerlund if (*astate == S_OCTAL2 || *astate == S_OCTAL3) {
1005e9cd1aeSAssar Westerlund *astate = S_GROUND;
1015e9cd1aeSAssar Westerlund return (UNVIS_VALID);
1025e9cd1aeSAssar Westerlund }
1035e9cd1aeSAssar Westerlund return (*astate == S_GROUND ? UNVIS_NOCHAR : UNVIS_SYNBAD);
1045e9cd1aeSAssar Westerlund }
1055e9cd1aeSAssar Westerlund
1065e9cd1aeSAssar Westerlund switch (*astate) {
1075e9cd1aeSAssar Westerlund
1085e9cd1aeSAssar Westerlund case S_GROUND:
1095e9cd1aeSAssar Westerlund *cp = 0;
1105e9cd1aeSAssar Westerlund if (c == '\\') {
1115e9cd1aeSAssar Westerlund *astate = S_START;
1125e9cd1aeSAssar Westerlund return (0);
1135e9cd1aeSAssar Westerlund }
1145e9cd1aeSAssar Westerlund *cp = c;
1155e9cd1aeSAssar Westerlund return (UNVIS_VALID);
1165e9cd1aeSAssar Westerlund
1175e9cd1aeSAssar Westerlund case S_START:
1185e9cd1aeSAssar Westerlund switch(c) {
1195e9cd1aeSAssar Westerlund case '\\':
1205e9cd1aeSAssar Westerlund *cp = c;
1215e9cd1aeSAssar Westerlund *astate = S_GROUND;
1225e9cd1aeSAssar Westerlund return (UNVIS_VALID);
1235e9cd1aeSAssar Westerlund case '0': case '1': case '2': case '3':
1245e9cd1aeSAssar Westerlund case '4': case '5': case '6': case '7':
1255e9cd1aeSAssar Westerlund *cp = (c - '0');
1265e9cd1aeSAssar Westerlund *astate = S_OCTAL2;
1275e9cd1aeSAssar Westerlund return (0);
1285e9cd1aeSAssar Westerlund case 'M':
129*ae771770SStanislav Sedov *cp = (u_char)0200;
1305e9cd1aeSAssar Westerlund *astate = S_META;
1315e9cd1aeSAssar Westerlund return (0);
1325e9cd1aeSAssar Westerlund case '^':
1335e9cd1aeSAssar Westerlund *astate = S_CTRL;
1345e9cd1aeSAssar Westerlund return (0);
1355e9cd1aeSAssar Westerlund case 'n':
1365e9cd1aeSAssar Westerlund *cp = '\n';
1375e9cd1aeSAssar Westerlund *astate = S_GROUND;
1385e9cd1aeSAssar Westerlund return (UNVIS_VALID);
1395e9cd1aeSAssar Westerlund case 'r':
1405e9cd1aeSAssar Westerlund *cp = '\r';
1415e9cd1aeSAssar Westerlund *astate = S_GROUND;
1425e9cd1aeSAssar Westerlund return (UNVIS_VALID);
1435e9cd1aeSAssar Westerlund case 'b':
1445e9cd1aeSAssar Westerlund *cp = '\b';
1455e9cd1aeSAssar Westerlund *astate = S_GROUND;
1465e9cd1aeSAssar Westerlund return (UNVIS_VALID);
1475e9cd1aeSAssar Westerlund case 'a':
1485e9cd1aeSAssar Westerlund *cp = '\007';
1495e9cd1aeSAssar Westerlund *astate = S_GROUND;
1505e9cd1aeSAssar Westerlund return (UNVIS_VALID);
1515e9cd1aeSAssar Westerlund case 'v':
1525e9cd1aeSAssar Westerlund *cp = '\v';
1535e9cd1aeSAssar Westerlund *astate = S_GROUND;
1545e9cd1aeSAssar Westerlund return (UNVIS_VALID);
1555e9cd1aeSAssar Westerlund case 't':
1565e9cd1aeSAssar Westerlund *cp = '\t';
1575e9cd1aeSAssar Westerlund *astate = S_GROUND;
1585e9cd1aeSAssar Westerlund return (UNVIS_VALID);
1595e9cd1aeSAssar Westerlund case 'f':
1605e9cd1aeSAssar Westerlund *cp = '\f';
1615e9cd1aeSAssar Westerlund *astate = S_GROUND;
1625e9cd1aeSAssar Westerlund return (UNVIS_VALID);
1635e9cd1aeSAssar Westerlund case 's':
1645e9cd1aeSAssar Westerlund *cp = ' ';
1655e9cd1aeSAssar Westerlund *astate = S_GROUND;
1665e9cd1aeSAssar Westerlund return (UNVIS_VALID);
1675e9cd1aeSAssar Westerlund case 'E':
1685e9cd1aeSAssar Westerlund *cp = '\033';
1695e9cd1aeSAssar Westerlund *astate = S_GROUND;
1705e9cd1aeSAssar Westerlund return (UNVIS_VALID);
1715e9cd1aeSAssar Westerlund case '\n':
1725e9cd1aeSAssar Westerlund /*
1735e9cd1aeSAssar Westerlund * hidden newline
1745e9cd1aeSAssar Westerlund */
1755e9cd1aeSAssar Westerlund *astate = S_GROUND;
1765e9cd1aeSAssar Westerlund return (UNVIS_NOCHAR);
1775e9cd1aeSAssar Westerlund case '$':
1785e9cd1aeSAssar Westerlund /*
1795e9cd1aeSAssar Westerlund * hidden marker
1805e9cd1aeSAssar Westerlund */
1815e9cd1aeSAssar Westerlund *astate = S_GROUND;
1825e9cd1aeSAssar Westerlund return (UNVIS_NOCHAR);
1835e9cd1aeSAssar Westerlund }
1845e9cd1aeSAssar Westerlund *astate = S_GROUND;
1855e9cd1aeSAssar Westerlund return (UNVIS_SYNBAD);
1865e9cd1aeSAssar Westerlund
1875e9cd1aeSAssar Westerlund case S_META:
1885e9cd1aeSAssar Westerlund if (c == '-')
1895e9cd1aeSAssar Westerlund *astate = S_META1;
1905e9cd1aeSAssar Westerlund else if (c == '^')
1915e9cd1aeSAssar Westerlund *astate = S_CTRL;
1925e9cd1aeSAssar Westerlund else {
1935e9cd1aeSAssar Westerlund *astate = S_GROUND;
1945e9cd1aeSAssar Westerlund return (UNVIS_SYNBAD);
1955e9cd1aeSAssar Westerlund }
1965e9cd1aeSAssar Westerlund return (0);
1975e9cd1aeSAssar Westerlund
1985e9cd1aeSAssar Westerlund case S_META1:
1995e9cd1aeSAssar Westerlund *astate = S_GROUND;
2005e9cd1aeSAssar Westerlund *cp |= c;
2015e9cd1aeSAssar Westerlund return (UNVIS_VALID);
2025e9cd1aeSAssar Westerlund
2035e9cd1aeSAssar Westerlund case S_CTRL:
2045e9cd1aeSAssar Westerlund if (c == '?')
2055e9cd1aeSAssar Westerlund *cp |= 0177;
2065e9cd1aeSAssar Westerlund else
2075e9cd1aeSAssar Westerlund *cp |= c & 037;
2085e9cd1aeSAssar Westerlund *astate = S_GROUND;
2095e9cd1aeSAssar Westerlund return (UNVIS_VALID);
2105e9cd1aeSAssar Westerlund
2115e9cd1aeSAssar Westerlund case S_OCTAL2: /* second possible octal digit */
2125e9cd1aeSAssar Westerlund if (isoctal(c)) {
2135e9cd1aeSAssar Westerlund /*
2145e9cd1aeSAssar Westerlund * yes - and maybe a third
2155e9cd1aeSAssar Westerlund */
2165e9cd1aeSAssar Westerlund *cp = (*cp << 3) + (c - '0');
2175e9cd1aeSAssar Westerlund *astate = S_OCTAL3;
2185e9cd1aeSAssar Westerlund return (0);
2195e9cd1aeSAssar Westerlund }
2205e9cd1aeSAssar Westerlund /*
2215e9cd1aeSAssar Westerlund * no - done with current sequence, push back passed char
2225e9cd1aeSAssar Westerlund */
2235e9cd1aeSAssar Westerlund *astate = S_GROUND;
2245e9cd1aeSAssar Westerlund return (UNVIS_VALIDPUSH);
2255e9cd1aeSAssar Westerlund
2265e9cd1aeSAssar Westerlund case S_OCTAL3: /* third possible octal digit */
2275e9cd1aeSAssar Westerlund *astate = S_GROUND;
2285e9cd1aeSAssar Westerlund if (isoctal(c)) {
2295e9cd1aeSAssar Westerlund *cp = (*cp << 3) + (c - '0');
2305e9cd1aeSAssar Westerlund return (UNVIS_VALID);
2315e9cd1aeSAssar Westerlund }
2325e9cd1aeSAssar Westerlund /*
2335e9cd1aeSAssar Westerlund * we were done, push back passed char
2345e9cd1aeSAssar Westerlund */
2355e9cd1aeSAssar Westerlund return (UNVIS_VALIDPUSH);
2365e9cd1aeSAssar Westerlund
2375e9cd1aeSAssar Westerlund default:
2385e9cd1aeSAssar Westerlund /*
2395e9cd1aeSAssar Westerlund * decoder in unknown state - (probably uninitialized)
2405e9cd1aeSAssar Westerlund */
2415e9cd1aeSAssar Westerlund *astate = S_GROUND;
2425e9cd1aeSAssar Westerlund return (UNVIS_SYNBAD);
2435e9cd1aeSAssar Westerlund }
2445e9cd1aeSAssar Westerlund }
2455e9cd1aeSAssar Westerlund
2465e9cd1aeSAssar Westerlund /*
2475e9cd1aeSAssar Westerlund * strunvis - decode src into dst
2485e9cd1aeSAssar Westerlund *
2495e9cd1aeSAssar Westerlund * Number of chars decoded into dst is returned, -1 on error.
2505e9cd1aeSAssar Westerlund * Dst is null terminated.
2515e9cd1aeSAssar Westerlund */
2525e9cd1aeSAssar Westerlund
253*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
rk_strunvis(char * dst,const char * src)254c19800e8SDoug Rabson rk_strunvis(char *dst, const char *src)
2555e9cd1aeSAssar Westerlund {
2565e9cd1aeSAssar Westerlund char c;
2575e9cd1aeSAssar Westerlund char *start = dst;
2585e9cd1aeSAssar Westerlund int state = 0;
2595e9cd1aeSAssar Westerlund
2605e9cd1aeSAssar Westerlund _DIAGASSERT(src != NULL);
2615e9cd1aeSAssar Westerlund _DIAGASSERT(dst != NULL);
2625e9cd1aeSAssar Westerlund
2635e9cd1aeSAssar Westerlund while ((c = *src++) != '\0') {
2645e9cd1aeSAssar Westerlund again:
265c19800e8SDoug Rabson switch (rk_unvis(dst, (unsigned char)c, &state, 0)) {
2665e9cd1aeSAssar Westerlund case UNVIS_VALID:
2675e9cd1aeSAssar Westerlund dst++;
2685e9cd1aeSAssar Westerlund break;
2695e9cd1aeSAssar Westerlund case UNVIS_VALIDPUSH:
2705e9cd1aeSAssar Westerlund dst++;
2715e9cd1aeSAssar Westerlund goto again;
2725e9cd1aeSAssar Westerlund case 0:
2735e9cd1aeSAssar Westerlund case UNVIS_NOCHAR:
2745e9cd1aeSAssar Westerlund break;
2755e9cd1aeSAssar Westerlund default:
2765e9cd1aeSAssar Westerlund return (-1);
2775e9cd1aeSAssar Westerlund }
2785e9cd1aeSAssar Westerlund }
279c19800e8SDoug Rabson if (unvis(dst, (unsigned char)c, &state, UNVIS_END) == UNVIS_VALID)
2805e9cd1aeSAssar Westerlund dst++;
2815e9cd1aeSAssar Westerlund *dst = '\0';
2825e9cd1aeSAssar Westerlund return (dst - start);
2835e9cd1aeSAssar Westerlund }
284