vis.c revision 124208
1241675Suqs/*-
2241675Suqs * Copyright (c) 1989, 1993
3241675Suqs *	The Regents of the University of California.  All rights reserved.
4241675Suqs *
5241675Suqs * Redistribution and use in source and binary forms, with or without
6241675Suqs * modification, are permitted provided that the following conditions
7241675Suqs * are met:
8241675Suqs * 1. Redistributions of source code must retain the above copyright
9241675Suqs *    notice, this list of conditions and the following disclaimer.
10241675Suqs * 2. Redistributions in binary form must reproduce the above copyright
11241675Suqs *    notice, this list of conditions and the following disclaimer in the
12241675Suqs *    documentation and/or other materials provided with the distribution.
13241675Suqs * 3. Neither the name of the University nor the names of its contributors
14241675Suqs *    may be used to endorse or promote products derived from this software
15241675Suqs *    without specific prior written permission.
16241675Suqs *
17241675Suqs * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18241675Suqs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19241675Suqs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20241675Suqs * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21241675Suqs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22241675Suqs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23241675Suqs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24241675Suqs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25241675Suqs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26241675Suqs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27241675Suqs * SUCH DAMAGE.
28241675Suqs */
29241675Suqs#include "includes.h"
30241675Suqs#if !defined(HAVE_STRNVIS)
31241675Suqs
32241675Suqs#if defined(LIBC_SCCS) && !defined(lint)
33241675Suqsstatic char rcsid[] = "$OpenBSD: vis.c,v 1.12 2003/06/02 20:18:35 millert Exp $";
34241675Suqs#endif /* LIBC_SCCS and not lint */
35241675Suqs
36241675Suqs#include <ctype.h>
37241675Suqs#include <string.h>
38241675Suqs
39241675Suqs#include "vis.h"
40241675Suqs
41241675Suqs#define	isoctal(c)	(((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
42241675Suqs#define isvisible(c)	(((u_int)(c) <= UCHAR_MAX && isascii((u_char)(c)) && \
43241675Suqs				isgraph((u_char)(c))) ||		     \
44241675Suqs				((flag & VIS_SP) == 0 && (c) == ' ') ||	     \
45241675Suqs				((flag & VIS_TAB) == 0 && (c) == '\t') ||    \
46241675Suqs				((flag & VIS_NL) == 0 && (c) == '\n') ||     \
47241675Suqs				((flag & VIS_SAFE) && ((c) == '\b' ||	     \
48241675Suqs				(c) == '\007' || (c) == '\r' ||		     \
49241675Suqs				isgraph((u_char)(c)))))
50241675Suqs
51241675Suqs/*
52241675Suqs * vis - visually encode characters
53241675Suqs */
54241675Suqschar *
55241675Suqsvis(dst, c, flag, nextc)
56241675Suqs	register char *dst;
57241675Suqs	int c, nextc;
58241675Suqs	register int flag;
59241675Suqs{
60241675Suqs	if (isvisible(c)) {
61241675Suqs		*dst++ = c;
62241675Suqs		if (c == '\\' && (flag & VIS_NOSLASH) == 0)
63241675Suqs			*dst++ = '\\';
64241675Suqs		*dst = '\0';
65241675Suqs		return (dst);
66241675Suqs	}
67241675Suqs
68241675Suqs	if (flag & VIS_CSTYLE) {
69241675Suqs		switch(c) {
70241675Suqs		case '\n':
71241675Suqs			*dst++ = '\\';
72241675Suqs			*dst++ = 'n';
73241675Suqs			goto done;
74241675Suqs		case '\r':
75241675Suqs			*dst++ = '\\';
76241675Suqs			*dst++ = 'r';
77241675Suqs			goto done;
78241675Suqs		case '\b':
79241675Suqs			*dst++ = '\\';
80241675Suqs			*dst++ = 'b';
81241675Suqs			goto done;
82241675Suqs		case '\a':
83241675Suqs			*dst++ = '\\';
84241675Suqs			*dst++ = 'a';
85241675Suqs			goto done;
86241675Suqs		case '\v':
87241675Suqs			*dst++ = '\\';
88241675Suqs			*dst++ = 'v';
89241675Suqs			goto done;
90241675Suqs		case '\t':
91241675Suqs			*dst++ = '\\';
92241675Suqs			*dst++ = 't';
93241675Suqs			goto done;
94241675Suqs		case '\f':
95241675Suqs			*dst++ = '\\';
96241675Suqs			*dst++ = 'f';
97241675Suqs			goto done;
98241675Suqs		case ' ':
99241675Suqs			*dst++ = '\\';
100241675Suqs			*dst++ = 's';
101241675Suqs			goto done;
102241675Suqs		case '\0':
103241675Suqs			*dst++ = '\\';
104241675Suqs			*dst++ = '0';
105241675Suqs			if (isoctal(nextc)) {
106241675Suqs				*dst++ = '0';
107241675Suqs				*dst++ = '0';
108241675Suqs			}
109241675Suqs			goto done;
110241675Suqs		}
111	}
112	if (((c & 0177) == ' ') || (flag & VIS_OCTAL)) {
113		*dst++ = '\\';
114		*dst++ = ((u_char)c >> 6 & 07) + '0';
115		*dst++ = ((u_char)c >> 3 & 07) + '0';
116		*dst++ = ((u_char)c & 07) + '0';
117		goto done;
118	}
119	if ((flag & VIS_NOSLASH) == 0)
120		*dst++ = '\\';
121	if (c & 0200) {
122		c &= 0177;
123		*dst++ = 'M';
124	}
125	if (iscntrl(c)) {
126		*dst++ = '^';
127		if (c == 0177)
128			*dst++ = '?';
129		else
130			*dst++ = c + '@';
131	} else {
132		*dst++ = '-';
133		*dst++ = c;
134	}
135done:
136	*dst = '\0';
137	return (dst);
138}
139
140/*
141 * strvis, strnvis, strvisx - visually encode characters from src into dst
142 *
143 *	Dst must be 4 times the size of src to account for possible
144 *	expansion.  The length of dst, not including the trailing NULL,
145 *	is returned.
146 *
147 *	Strnvis will write no more than siz-1 bytes (and will NULL terminate).
148 *	The number of bytes needed to fully encode the string is returned.
149 *
150 *	Strvisx encodes exactly len bytes from src into dst.
151 *	This is useful for encoding a block of data.
152 */
153int
154strvis(dst, src, flag)
155	register char *dst;
156	register const char *src;
157	int flag;
158{
159	register char c;
160	char *start;
161
162	for (start = dst; (c = *src);)
163		dst = vis(dst, c, flag, *++src);
164	*dst = '\0';
165	return (dst - start);
166}
167
168int
169strnvis(dst, src, siz, flag)
170	char *dst;
171	const char *src;
172	size_t siz;
173	int flag;
174{
175	char c;
176	char *start, *end;
177	char tbuf[5];
178	int  i;
179
180	i = 0;
181	for (start = dst, end = start + siz - 1; (c = *src) && dst < end; ) {
182		if (isvisible(c)) {
183			i = 1;
184			*dst++ = c;
185			if (c == '\\' && (flag & VIS_NOSLASH) == 0) {
186				/* need space for the extra '\\' */
187				if (dst < end)
188					*dst++ = '\\';
189				else {
190					dst--;
191					i = 2;
192					break;
193				}
194			}
195			src++;
196		} else {
197			i = vis(tbuf, c, flag, *++src) - tbuf;
198			if (dst + i <= end) {
199				memcpy(dst, tbuf, i);
200				dst += i;
201			} else {
202				src--;
203				break;
204			}
205		}
206	}
207	if (siz > 0)
208		*dst = '\0';
209	if (dst + i > end) {
210		/* adjust return value for truncation */
211		while ((c = *src))
212			dst += vis(tbuf, c, flag, *++src) - tbuf;
213	}
214	return (dst - start);
215}
216
217int
218strvisx(dst, src, len, flag)
219	register char *dst;
220	register const char *src;
221	register size_t len;
222	int flag;
223{
224	register char c;
225	char *start;
226
227	for (start = dst; len > 1; len--) {
228		c = *src;
229		dst = vis(dst, c, flag, *++src);
230	}
231	if (len)
232		dst = vis(dst, *src, flag, '\0');
233	*dst = '\0';
234	return (dst - start);
235}
236
237#endif
238