xref: /original-bsd/lib/libc/gen/vis.c (revision a152d818)
1 /*-
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #if defined(LIBC_SCCS) && !defined(lint)
9 static char sccsid[] = "@(#)vis.c	5.4 (Berkeley) 02/23/91";
10 #endif /* LIBC_SCCS and not lint */
11 
12 #include <sys/types.h>
13 #include <ctype.h>
14 #include <vis.h>
15 
16 #define	isoctal(c)	(((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
17 
18 /*
19  * vis - visually encode characters
20  */
21 char *
22 #if __STDC__
23 vis(register char *dst, register char c, register int flag, char nextc)
24 #else
25 vis(dst, c, flag, nextc)
26 	register char *dst, c;
27 	char nextc;
28 	register int flag;
29 #endif
30 {
31 	if (isascii(c) && isgraph(c) ||
32 	   ((flag & VIS_SP) == 0 && c == ' ') ||
33 	   ((flag & VIS_TAB) == 0 && c == '\t') ||
34 	   ((flag & VIS_NL) == 0 && c == '\n') ||
35 	   ((flag & VIS_SAFE) && (c == '\b' || c == '\007' || c == '\r'))) {
36 		*dst++ = c;
37 		if (c == '\\' && (flag & VIS_NOSLASH) == 0)
38 			*dst++ = '\\';
39 		*dst = '\0';
40 		return (dst);
41 	}
42 
43 	if (flag & VIS_CSTYLE) {
44 		switch(c) {
45 		case '\n':
46 			*dst++ = '\\';
47 			*dst++ = 'n';
48 			goto done;
49 		case '\r':
50 			*dst++ = '\\';
51 			*dst++ = 'r';
52 			goto done;
53 		case '\b':
54 			*dst++ = '\\';
55 			*dst++ = 'b';
56 			goto done;
57 #if __STDC__
58 		case '\a':
59 #else
60 		case '\007':
61 #endif
62 			*dst++ = '\\';
63 			*dst++ = 'a';
64 			goto done;
65 		case '\v':
66 			*dst++ = '\\';
67 			*dst++ = 'v';
68 			goto done;
69 		case '\t':
70 			*dst++ = '\\';
71 			*dst++ = 't';
72 			goto done;
73 		case '\f':
74 			*dst++ = '\\';
75 			*dst++ = 'f';
76 			goto done;
77 		case ' ':
78 			*dst++ = '\\';
79 			*dst++ = 's';
80 			goto done;
81 		case '\0':
82 			*dst++ = '\\';
83 			*dst++ = '0';
84 			if (isoctal(nextc)) {
85 				*dst++ = '0';
86 				*dst++ = '0';
87 			}
88 			goto done;
89 		}
90 	}
91 	if (((c & 0177) == ' ') || (flag & VIS_OCTAL)) {
92 		*dst++ = '\\';
93 		*dst++ = ((u_char)c >> 6 & 07) + '0';
94 		*dst++ = ((u_char)c >> 3 & 07) + '0';
95 		*dst++ = ((u_char)c & 07) + '0';
96 		goto done;
97 	}
98 	if ((flag & VIS_NOSLASH) == 0)
99 		*dst++ = '\\';
100 	if (c & 0200) {
101 		c &= 0177;
102 		*dst++ = 'M';
103 	}
104 	if (iscntrl(c)) {
105 		*dst++ = '^';
106 		if (c == 0177)
107 			*dst++ = '?';
108 		else
109 			*dst++ = c + '@';
110 	} else {
111 		*dst++ = '-';
112 		*dst++ = c;
113 	}
114 done:
115 	*dst = '\0';
116 	return (dst);
117 }
118 
119 /*
120  * strvis, strvisx - visually encode characters from src into dst
121  *
122  *	Dst must be 4 times the size of src to account for possible
123  *	expansion.  The length of dst, not including the trailing NULL,
124  *	is returned.
125  *
126  *	Strvisx encodes exactly len bytes from src into dst.
127  *	This is useful for encoding a block of data.
128  */
129 int
130 strvis(dst, src, flag)
131 	register char *dst;
132 	register const char *src;
133 	int flag;
134 {
135 	register char c;
136 	char *start = dst;
137 
138 	for (;c = *src; src++)
139 		dst = vis(dst, c, flag, *(src+1));
140 
141 	return (dst - start);
142 }
143 
144 int
145 strvisx(dst, src, len, flag)
146 	register char *dst;
147 	register const char *src;
148 	register size_t len;
149 	int flag;
150 {
151 	char *start = dst;
152 
153 	while (len > 1) {
154 		dst = vis(dst, *src, flag, *(src+1));
155 		len--;
156 	}
157 	if (len)
158 		dst = vis(dst, *src, flag, '\0');
159 
160 	return (dst - start);
161 }
162