172445Sassar/* $NetBSD: unvis.c,v 1.19 2000/01/22 22:19:13 mycroft Exp $ */ 272445Sassar 372445Sassar/*- 472445Sassar * Copyright (c) 1989, 1993 572445Sassar * The Regents of the University of California. All rights reserved. 672445Sassar * 772445Sassar * Redistribution and use in source and binary forms, with or without 872445Sassar * modification, are permitted provided that the following conditions 972445Sassar * are met: 1072445Sassar * 1. Redistributions of source code must retain the above copyright 1172445Sassar * notice, this list of conditions and the following disclaimer. 1272445Sassar * 2. Redistributions in binary form must reproduce the above copyright 1372445Sassar * notice, this list of conditions and the following disclaimer in the 1472445Sassar * documentation and/or other materials provided with the distribution. 15178825Sdfr * 3. Neither the name of the University nor the names of its contributors 1672445Sassar * may be used to endorse or promote products derived from this software 1772445Sassar * without specific prior written permission. 1872445Sassar * 1972445Sassar * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2072445Sassar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2172445Sassar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2272445Sassar * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2372445Sassar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2472445Sassar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2572445Sassar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2672445Sassar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2772445Sassar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2872445Sassar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2972445Sassar * SUCH DAMAGE. 3072445Sassar */ 3172445Sassar 3272445Sassar#if 1 3372445Sassar#include <config.h> 34178825Sdfr#include "roken.h" 3572445Sassar#ifndef _DIAGASSERT 3672445Sassar#define _DIAGASSERT(X) 3772445Sassar#endif 3872445Sassar#else 3972445Sassar#include <sys/cdefs.h> 4072445Sassar#if defined(LIBC_SCCS) && !defined(lint) 4172445Sassar#if 0 4272445Sassarstatic char sccsid[] = "@(#)unvis.c 8.1 (Berkeley) 6/4/93"; 4372445Sassar#else 4472445Sassar__RCSID("$NetBSD: unvis.c,v 1.19 2000/01/22 22:19:13 mycroft Exp $"); 4572445Sassar#endif 4672445Sassar#endif /* LIBC_SCCS and not lint */ 4772445Sassar 4872445Sassar#define __LIBC12_SOURCE__ 4972445Sassar 5072445Sassar#include "namespace.h" 5172445Sassar#endif 5272445Sassar#include <sys/types.h> 5372445Sassar 5472445Sassar#include <assert.h> 5572445Sassar#include <ctype.h> 5672445Sassar#include <stdio.h> 5772445Sassar#include <vis.h> 5872445Sassar 5972445Sassar#if 0 6072445Sassar#ifdef __weak_alias 6172445Sassar__weak_alias(strunvis,_strunvis) 6272445Sassar__weak_alias(unvis,_unvis) 6372445Sassar#endif 6472445Sassar 6572445Sassar__warn_references(unvis, 6672445Sassar "warning: reference to compatibility unvis(); include <vis.h> for correct reference") 6772445Sassar#endif 6872445Sassar 6972445Sassar/* 7072445Sassar * decode driven by state machine 7172445Sassar */ 7272445Sassar#define S_GROUND 0 /* haven't seen escape char */ 7372445Sassar#define S_START 1 /* start decoding special sequence */ 7472445Sassar#define S_META 2 /* metachar started (M) */ 7572445Sassar#define S_META1 3 /* metachar more, regular char (-) */ 7672445Sassar#define S_CTRL 4 /* control char started (^) */ 7772445Sassar#define S_OCTAL2 5 /* octal digit 2 */ 7872445Sassar#define S_OCTAL3 6 /* octal digit 3 */ 7972445Sassar 8072445Sassar#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') 8172445Sassar 82233294SstasROKEN_LIB_FUNCTION int ROKEN_LIB_CALL 83178825Sdfr rk_strunvis (char *, const char *); 84233294SstasROKEN_LIB_FUNCTION int ROKEN_LIB_CALL 85178825Sdfr rk_unvis (char *, int, int *, int); 86178825Sdfr 8772445Sassar/* 8872445Sassar * unvis - decode characters previously encoded by vis 8972445Sassar */ 90178825Sdfr 91233294SstasROKEN_LIB_FUNCTION int ROKEN_LIB_CALL 92178825Sdfrrk_unvis(char *cp, int c, int *astate, int flag) 9372445Sassar{ 9472445Sassar 9572445Sassar _DIAGASSERT(cp != NULL); 9672445Sassar _DIAGASSERT(astate != NULL); 9772445Sassar 9872445Sassar if (flag & UNVIS_END) { 9972445Sassar if (*astate == S_OCTAL2 || *astate == S_OCTAL3) { 10072445Sassar *astate = S_GROUND; 10172445Sassar return (UNVIS_VALID); 102233294Sstas } 10372445Sassar return (*astate == S_GROUND ? UNVIS_NOCHAR : UNVIS_SYNBAD); 10472445Sassar } 10572445Sassar 10672445Sassar switch (*astate) { 10772445Sassar 10872445Sassar case S_GROUND: 10972445Sassar *cp = 0; 11072445Sassar if (c == '\\') { 11172445Sassar *astate = S_START; 11272445Sassar return (0); 113233294Sstas } 11472445Sassar *cp = c; 11572445Sassar return (UNVIS_VALID); 11672445Sassar 11772445Sassar case S_START: 11872445Sassar switch(c) { 11972445Sassar case '\\': 12072445Sassar *cp = c; 12172445Sassar *astate = S_GROUND; 12272445Sassar return (UNVIS_VALID); 12372445Sassar case '0': case '1': case '2': case '3': 12472445Sassar case '4': case '5': case '6': case '7': 12572445Sassar *cp = (c - '0'); 12672445Sassar *astate = S_OCTAL2; 12772445Sassar return (0); 12872445Sassar case 'M': 129233294Sstas *cp = (u_char)0200; 13072445Sassar *astate = S_META; 13172445Sassar return (0); 13272445Sassar case '^': 13372445Sassar *astate = S_CTRL; 13472445Sassar return (0); 13572445Sassar case 'n': 13672445Sassar *cp = '\n'; 13772445Sassar *astate = S_GROUND; 13872445Sassar return (UNVIS_VALID); 13972445Sassar case 'r': 14072445Sassar *cp = '\r'; 14172445Sassar *astate = S_GROUND; 14272445Sassar return (UNVIS_VALID); 14372445Sassar case 'b': 14472445Sassar *cp = '\b'; 14572445Sassar *astate = S_GROUND; 14672445Sassar return (UNVIS_VALID); 14772445Sassar case 'a': 14872445Sassar *cp = '\007'; 14972445Sassar *astate = S_GROUND; 15072445Sassar return (UNVIS_VALID); 15172445Sassar case 'v': 15272445Sassar *cp = '\v'; 15372445Sassar *astate = S_GROUND; 15472445Sassar return (UNVIS_VALID); 15572445Sassar case 't': 15672445Sassar *cp = '\t'; 15772445Sassar *astate = S_GROUND; 15872445Sassar return (UNVIS_VALID); 15972445Sassar case 'f': 16072445Sassar *cp = '\f'; 16172445Sassar *astate = S_GROUND; 16272445Sassar return (UNVIS_VALID); 16372445Sassar case 's': 16472445Sassar *cp = ' '; 16572445Sassar *astate = S_GROUND; 16672445Sassar return (UNVIS_VALID); 16772445Sassar case 'E': 16872445Sassar *cp = '\033'; 16972445Sassar *astate = S_GROUND; 17072445Sassar return (UNVIS_VALID); 17172445Sassar case '\n': 17272445Sassar /* 17372445Sassar * hidden newline 17472445Sassar */ 17572445Sassar *astate = S_GROUND; 17672445Sassar return (UNVIS_NOCHAR); 17772445Sassar case '$': 17872445Sassar /* 17972445Sassar * hidden marker 18072445Sassar */ 18172445Sassar *astate = S_GROUND; 18272445Sassar return (UNVIS_NOCHAR); 18372445Sassar } 18472445Sassar *astate = S_GROUND; 18572445Sassar return (UNVIS_SYNBAD); 186233294Sstas 18772445Sassar case S_META: 18872445Sassar if (c == '-') 18972445Sassar *astate = S_META1; 19072445Sassar else if (c == '^') 19172445Sassar *astate = S_CTRL; 19272445Sassar else { 19372445Sassar *astate = S_GROUND; 19472445Sassar return (UNVIS_SYNBAD); 19572445Sassar } 19672445Sassar return (0); 197233294Sstas 19872445Sassar case S_META1: 19972445Sassar *astate = S_GROUND; 20072445Sassar *cp |= c; 20172445Sassar return (UNVIS_VALID); 202233294Sstas 20372445Sassar case S_CTRL: 20472445Sassar if (c == '?') 20572445Sassar *cp |= 0177; 20672445Sassar else 20772445Sassar *cp |= c & 037; 20872445Sassar *astate = S_GROUND; 20972445Sassar return (UNVIS_VALID); 21072445Sassar 21172445Sassar case S_OCTAL2: /* second possible octal digit */ 21272445Sassar if (isoctal(c)) { 213233294Sstas /* 214233294Sstas * yes - and maybe a third 21572445Sassar */ 21672445Sassar *cp = (*cp << 3) + (c - '0'); 217233294Sstas *astate = S_OCTAL3; 21872445Sassar return (0); 219233294Sstas } 220233294Sstas /* 221233294Sstas * no - done with current sequence, push back passed char 22272445Sassar */ 22372445Sassar *astate = S_GROUND; 22472445Sassar return (UNVIS_VALIDPUSH); 22572445Sassar 22672445Sassar case S_OCTAL3: /* third possible octal digit */ 22772445Sassar *astate = S_GROUND; 22872445Sassar if (isoctal(c)) { 22972445Sassar *cp = (*cp << 3) + (c - '0'); 23072445Sassar return (UNVIS_VALID); 23172445Sassar } 23272445Sassar /* 23372445Sassar * we were done, push back passed char 23472445Sassar */ 23572445Sassar return (UNVIS_VALIDPUSH); 236233294Sstas 237233294Sstas default: 238233294Sstas /* 239233294Sstas * decoder in unknown state - (probably uninitialized) 24072445Sassar */ 24172445Sassar *astate = S_GROUND; 24272445Sassar return (UNVIS_SYNBAD); 24372445Sassar } 24472445Sassar} 24572445Sassar 24672445Sassar/* 247233294Sstas * strunvis - decode src into dst 24872445Sassar * 24972445Sassar * Number of chars decoded into dst is returned, -1 on error. 25072445Sassar * Dst is null terminated. 25172445Sassar */ 25272445Sassar 253233294SstasROKEN_LIB_FUNCTION int ROKEN_LIB_CALL 254178825Sdfrrk_strunvis(char *dst, const char *src) 25572445Sassar{ 25672445Sassar char c; 25772445Sassar char *start = dst; 25872445Sassar int state = 0; 25972445Sassar 26072445Sassar _DIAGASSERT(src != NULL); 26172445Sassar _DIAGASSERT(dst != NULL); 26272445Sassar 26372445Sassar while ((c = *src++) != '\0') { 26472445Sassar again: 265178825Sdfr switch (rk_unvis(dst, (unsigned char)c, &state, 0)) { 26672445Sassar case UNVIS_VALID: 26772445Sassar dst++; 26872445Sassar break; 26972445Sassar case UNVIS_VALIDPUSH: 27072445Sassar dst++; 27172445Sassar goto again; 27272445Sassar case 0: 27372445Sassar case UNVIS_NOCHAR: 27472445Sassar break; 27572445Sassar default: 27672445Sassar return (-1); 27772445Sassar } 27872445Sassar } 279178825Sdfr if (unvis(dst, (unsigned char)c, &state, UNVIS_END) == UNVIS_VALID) 28072445Sassar dst++; 28172445Sassar *dst = '\0'; 28272445Sassar return (dst - start); 28372445Sassar} 284