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