1243730Srwatson/*- 2243730Srwatson * Copyright (c) 1989, 1993 3243730Srwatson * The Regents of the University of California. All rights reserved. 4243730Srwatson * 5243730Srwatson * Redistribution and use in source and binary forms, with or without 6243730Srwatson * modification, are permitted provided that the following conditions 7243730Srwatson * are met: 8243730Srwatson * 1. Redistributions of source code must retain the above copyright 9243730Srwatson * notice, this list of conditions and the following disclaimer. 10243730Srwatson * 2. Redistributions in binary form must reproduce the above copyright 11243730Srwatson * notice, this list of conditions and the following disclaimer in the 12243730Srwatson * documentation and/or other materials provided with the distribution. 13243730Srwatson * 4. Neither the name of the University nor the names of its contributors 14243730Srwatson * may be used to endorse or promote products derived from this software 15243730Srwatson * without specific prior written permission. 16243730Srwatson * 17243730Srwatson * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18243730Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19243730Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20243730Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21243730Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22243730Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23243730Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24243730Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25243730Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26243730Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27243730Srwatson * SUCH DAMAGE. 28243730Srwatson * 29243730Srwatson * Defived from FreeBSD head/lib/libc/gen/vis.c 165903, head/include/vis.h 30243730Srwatson * 203964. 31243730Srwatson */ 32243730Srwatson 33243730Srwatson#include <sys/types.h> 34243730Srwatson#include <limits.h> 35243730Srwatson#include <ctype.h> 36243730Srwatson#include <stdio.h> 37243730Srwatson 38243730Srwatson/* 39243730Srwatson * to select alternate encoding format 40243730Srwatson */ 41243730Srwatson#define VIS_OCTAL 0x01 /* use octal \ddd format */ 42243730Srwatson#define VIS_CSTYLE 0x02 /* use \[nrft0..] where appropriate */ 43243730Srwatson 44243730Srwatson/* 45243730Srwatson * to alter set of characters encoded (default is to encode all 46243730Srwatson * non-graphic except space, tab, and newline). 47243730Srwatson */ 48243730Srwatson#define VIS_SP 0x04 /* also encode space */ 49243730Srwatson#define VIS_TAB 0x08 /* also encode tab */ 50243730Srwatson#define VIS_NL 0x10 /* also encode newline */ 51243730Srwatson#define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL) 52243730Srwatson#define VIS_SAFE 0x20 /* only encode "unsafe" characters */ 53243730Srwatson 54243730Srwatson/* 55243730Srwatson * other 56243730Srwatson */ 57243730Srwatson#define VIS_NOSLASH 0x40 /* inhibit printing '\' */ 58243730Srwatson#define VIS_HTTPSTYLE 0x80 /* http-style escape % HEX HEX */ 59243730Srwatson#define VIS_GLOB 0x100 /* encode glob(3) magics */ 60243730Srwatson 61243730Srwatson/* 62243730Srwatson * unvis return codes 63243730Srwatson */ 64243730Srwatson#define UNVIS_VALID 1 /* character valid */ 65243730Srwatson#define UNVIS_VALIDPUSH 2 /* character valid, push back passed char */ 66243730Srwatson#define UNVIS_NOCHAR 3 /* valid sequence, no character produced */ 67243730Srwatson#define UNVIS_SYNBAD -1 /* unrecognized escape sequence */ 68243730Srwatson#define UNVIS_ERROR -2 /* decoder in unknown state (unrecoverable) */ 69243730Srwatson 70243730Srwatson/* 71243730Srwatson * unvis flags 72243730Srwatson */ 73243730Srwatson#define UNVIS_END 1 /* no more characters */ 74243730Srwatson 75243730Srwatson#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') 76243730Srwatson 77243730Srwatson/* 78243730Srwatson * vis - visually encode characters 79243730Srwatson */ 80243730Srwatsonchar * 81243730Srwatsonvis(dst, c, flag, nextc) 82243730Srwatson char *dst; 83243730Srwatson int c, nextc; 84243730Srwatson int flag; 85243730Srwatson{ 86243730Srwatson c = (unsigned char)c; 87243730Srwatson 88243730Srwatson if (flag & VIS_HTTPSTYLE) { 89243730Srwatson /* Described in RFC 1808 */ 90243730Srwatson if (!(isalnum(c) /* alpha-numeric */ 91243730Srwatson /* safe */ 92243730Srwatson || c == '$' || c == '-' || c == '_' || c == '.' || c == '+' 93243730Srwatson /* extra */ 94243730Srwatson || c == '!' || c == '*' || c == '\'' || c == '(' 95243730Srwatson || c == ')' || c == ',')) { 96243730Srwatson *dst++ = '%'; 97243730Srwatson snprintf(dst, 4, (c < 16 ? "0%X" : "%X"), c); 98243730Srwatson dst += 2; 99243730Srwatson goto done; 100243730Srwatson } 101243730Srwatson } 102243730Srwatson 103243730Srwatson if ((flag & VIS_GLOB) && 104243730Srwatson (c == '*' || c == '?' || c == '[' || c == '#')) 105243730Srwatson ; 106243730Srwatson else if (isgraph(c) || 107243730Srwatson ((flag & VIS_SP) == 0 && c == ' ') || 108243730Srwatson ((flag & VIS_TAB) == 0 && c == '\t') || 109243730Srwatson ((flag & VIS_NL) == 0 && c == '\n') || 110243730Srwatson ((flag & VIS_SAFE) && (c == '\b' || c == '\007' || c == '\r'))) { 111243730Srwatson *dst++ = c; 112243730Srwatson if (c == '\\' && (flag & VIS_NOSLASH) == 0) 113243730Srwatson *dst++ = '\\'; 114243730Srwatson *dst = '\0'; 115243730Srwatson return (dst); 116243730Srwatson } 117243730Srwatson 118243730Srwatson if (flag & VIS_CSTYLE) { 119243730Srwatson switch(c) { 120243730Srwatson case '\n': 121243730Srwatson *dst++ = '\\'; 122243730Srwatson *dst++ = 'n'; 123243730Srwatson goto done; 124243730Srwatson case '\r': 125243730Srwatson *dst++ = '\\'; 126243730Srwatson *dst++ = 'r'; 127243730Srwatson goto done; 128243730Srwatson case '\b': 129243730Srwatson *dst++ = '\\'; 130243730Srwatson *dst++ = 'b'; 131243730Srwatson goto done; 132243730Srwatson case '\a': 133243730Srwatson *dst++ = '\\'; 134243730Srwatson *dst++ = 'a'; 135243730Srwatson goto done; 136243730Srwatson case '\v': 137243730Srwatson *dst++ = '\\'; 138243730Srwatson *dst++ = 'v'; 139243730Srwatson goto done; 140243730Srwatson case '\t': 141243730Srwatson *dst++ = '\\'; 142243730Srwatson *dst++ = 't'; 143243730Srwatson goto done; 144243730Srwatson case '\f': 145243730Srwatson *dst++ = '\\'; 146243730Srwatson *dst++ = 'f'; 147243730Srwatson goto done; 148243730Srwatson case ' ': 149243730Srwatson *dst++ = '\\'; 150243730Srwatson *dst++ = 's'; 151243730Srwatson goto done; 152243730Srwatson case '\0': 153243730Srwatson *dst++ = '\\'; 154243730Srwatson *dst++ = '0'; 155243730Srwatson if (isoctal(nextc)) { 156243730Srwatson *dst++ = '0'; 157243730Srwatson *dst++ = '0'; 158243730Srwatson } 159243730Srwatson goto done; 160243730Srwatson } 161243730Srwatson } 162243730Srwatson if (((c & 0177) == ' ') || isgraph(c) || (flag & VIS_OCTAL)) { 163243730Srwatson *dst++ = '\\'; 164243730Srwatson *dst++ = ((u_char)c >> 6 & 07) + '0'; 165243730Srwatson *dst++ = ((u_char)c >> 3 & 07) + '0'; 166243730Srwatson *dst++ = ((u_char)c & 07) + '0'; 167243730Srwatson goto done; 168243730Srwatson } 169243730Srwatson if ((flag & VIS_NOSLASH) == 0) 170243730Srwatson *dst++ = '\\'; 171243730Srwatson if (c & 0200) { 172243730Srwatson c &= 0177; 173243730Srwatson *dst++ = 'M'; 174243730Srwatson } 175243730Srwatson if (iscntrl(c)) { 176243730Srwatson *dst++ = '^'; 177243730Srwatson if (c == 0177) 178243730Srwatson *dst++ = '?'; 179243730Srwatson else 180243730Srwatson *dst++ = c + '@'; 181243730Srwatson } else { 182243730Srwatson *dst++ = '-'; 183243730Srwatson *dst++ = c; 184243730Srwatson } 185243730Srwatsondone: 186243730Srwatson *dst = '\0'; 187243730Srwatson return (dst); 188243730Srwatson} 189