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