Branch data Line data Source code
1 : : /* $OpenBSD: vis.c,v 1.19 2005/09/01 17:15:49 millert Exp $ */
2 : : /*-
3 : : * Copyright (c) 1989, 1993
4 : : * The Regents of the University of California. All rights reserved.
5 : : *
6 : : * Redistribution and use in source and binary forms, with or without
7 : : * modification, are permitted provided that the following conditions
8 : : * are met:
9 : : * 1. Redistributions of source code must retain the above copyright
10 : : * notice, this list of conditions and the following disclaimer.
11 : : * 2. Redistributions in binary form must reproduce the above copyright
12 : : * notice, this list of conditions and the following disclaimer in the
13 : : * documentation and/or other materials provided with the distribution.
14 : : * 3. Neither the name of the University nor the names of its contributors
15 : : * may be used to endorse or promote products derived from this software
16 : : * without specific prior written permission.
17 : : *
18 : : * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 : : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 : : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 : : * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 : : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 : : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 : : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 : : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 : : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 : : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 : : * SUCH DAMAGE.
29 : : */
30 : :
31 : : /* OPENBSD ORIGINAL: lib/libc/gen/vis.c */
32 : :
33 : : #include "includes.h"
34 : : #if !defined(HAVE_STRNVIS) || defined(BROKEN_STRNVIS)
35 : :
36 : : #include <ctype.h>
37 : : #include <string.h>
38 : :
39 : : #include "vis.h"
40 : :
41 : : #define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
42 : : #define isvisible(c) \
43 : : (((u_int)(c) <= UCHAR_MAX && isascii((u_char)(c)) && \
44 : : (((c) != '*' && (c) != '?' && (c) != '[' && (c) != '#') || \
45 : : (flag & VIS_GLOB) == 0) && isgraph((u_char)(c))) || \
46 : : ((flag & VIS_SP) == 0 && (c) == ' ') || \
47 : : ((flag & VIS_TAB) == 0 && (c) == '\t') || \
48 : : ((flag & VIS_NL) == 0 && (c) == '\n') || \
49 : : ((flag & VIS_SAFE) && ((c) == '\b' || \
50 : : (c) == '\007' || (c) == '\r' || \
51 : : isgraph((u_char)(c)))))
52 : :
53 : : /*
54 : : * vis - visually encode characters
55 : : */
56 : : char *
57 : 0 : vis(char *dst, int c, int flag, int nextc)
58 : : {
59 [ # # ][ # # ]: 0 : if (isvisible(c)) {
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
60 : 0 : *dst++ = c;
61 [ # # ][ # # ]: 0 : if (c == '\\' && (flag & VIS_NOSLASH) == 0)
62 : 0 : *dst++ = '\\';
63 : 0 : *dst = '\0';
64 : 0 : return (dst);
65 : : }
66 : :
67 [ # # ]: 0 : if (flag & VIS_CSTYLE) {
68 [ # # # # : 0 : switch(c) {
# # # # #
# ]
69 : : case '\n':
70 : 0 : *dst++ = '\\';
71 : 0 : *dst++ = 'n';
72 : 0 : goto done;
73 : : case '\r':
74 : 0 : *dst++ = '\\';
75 : 0 : *dst++ = 'r';
76 : 0 : goto done;
77 : : case '\b':
78 : 0 : *dst++ = '\\';
79 : 0 : *dst++ = 'b';
80 : 0 : goto done;
81 : : case '\a':
82 : 0 : *dst++ = '\\';
83 : 0 : *dst++ = 'a';
84 : 0 : goto done;
85 : : case '\v':
86 : 0 : *dst++ = '\\';
87 : 0 : *dst++ = 'v';
88 : 0 : goto done;
89 : : case '\t':
90 : 0 : *dst++ = '\\';
91 : 0 : *dst++ = 't';
92 : 0 : goto done;
93 : : case '\f':
94 : 0 : *dst++ = '\\';
95 : 0 : *dst++ = 'f';
96 : 0 : goto done;
97 : : case ' ':
98 : 0 : *dst++ = '\\';
99 : 0 : *dst++ = 's';
100 : 0 : goto done;
101 : : case '\0':
102 : 0 : *dst++ = '\\';
103 : 0 : *dst++ = '0';
104 [ # # ]: 0 : if (isoctal(nextc)) {
105 : 0 : *dst++ = '0';
106 : 0 : *dst++ = '0';
107 : : }
108 : : goto done;
109 : : }
110 : : }
111 [ # # ][ # # ]: 0 : if (((c & 0177) == ' ') || (flag & VIS_OCTAL) ||
[ # # ]
112 [ # # ][ # # ]: 0 : ((flag & VIS_GLOB) && (c == '*' || c == '?' || c == '[' || c == '#'))) {
113 : 0 : *dst++ = '\\';
114 : 0 : *dst++ = ((u_char)c >> 6 & 07) + '0';
115 : 0 : *dst++ = ((u_char)c >> 3 & 07) + '0';
116 : 0 : *dst++ = ((u_char)c & 07) + '0';
117 : 0 : goto done;
118 : : }
119 [ # # ]: 0 : if ((flag & VIS_NOSLASH) == 0)
120 : 0 : *dst++ = '\\';
121 [ # # ]: 0 : if (c & 0200) {
122 : 0 : c &= 0177;
123 : 0 : *dst++ = 'M';
124 : : }
125 [ # # ]: 0 : if (iscntrl((u_char)c)) {
126 : 0 : *dst++ = '^';
127 [ # # ]: 0 : if (c == 0177)
128 : 0 : *dst++ = '?';
129 : : else
130 : 0 : *dst++ = c + '@';
131 : : } else {
132 : 0 : *dst++ = '-';
133 : 0 : *dst++ = c;
134 : : }
135 : : done:
136 : 0 : *dst = '\0';
137 : 0 : 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 : : */
153 : : int
154 : 0 : strvis(char *dst, const char *src, int flag)
155 : : {
156 : : char c;
157 : : char *start;
158 : :
159 [ # # ]: 0 : for (start = dst; (c = *src);)
160 : 0 : dst = vis(dst, c, flag, *++src);
161 : 0 : *dst = '\0';
162 : 0 : return (dst - start);
163 : : }
164 : :
165 : : int
166 : 328208 : strnvis(char *dst, const char *src, size_t siz, int flag)
167 : : {
168 : : char *start, *end;
169 : : char tbuf[5];
170 : : int c, i;
171 : :
172 : 328208 : i = 0;
173 [ + + ][ + - ]: 21633856 : for (start = dst, end = start + siz - 1; (c = *src) && dst < end; ) {
174 [ + - ][ + - ]: 21305648 : if (isvisible(c)) {
[ + + ][ + + ]
[ + - ][ + + ]
[ + - ][ + + ]
[ + - ][ + - ]
[ + - ][ + + ]
[ + - ][ - + ]
[ # # ]
175 : 21305648 : i = 1;
176 : 21305648 : *dst++ = c;
177 [ + + ][ + - ]: 21305648 : if (c == '\\' && (flag & VIS_NOSLASH) == 0) {
178 : : /* need space for the extra '\\' */
179 [ + - ]: 6 : if (dst < end)
180 : 6 : *dst++ = '\\';
181 : : else {
182 : : dst--;
183 : : i = 2;
184 : : break;
185 : : }
186 : : }
187 : 21305648 : src++;
188 : : } else {
189 : 0 : i = vis(tbuf, c, flag, *++src) - tbuf;
190 [ # # ]: 0 : if (dst + i <= end) {
191 : 0 : memcpy(dst, tbuf, i);
192 : 21305648 : dst += i;
193 : : } else {
194 : : src--;
195 : : break;
196 : : }
197 : : }
198 : : }
199 [ + - ]: 328208 : if (siz > 0)
200 : 328208 : *dst = '\0';
201 [ + + ]: 328208 : if (dst + i > end) {
202 : : /* adjust return value for truncation */
203 [ - + ]: 34 : while ((c = *src))
204 : 0 : dst += vis(tbuf, c, flag, *++src) - tbuf;
205 : : }
206 : 328208 : return (dst - start);
207 : : }
208 : :
209 : : int
210 : 0 : strvisx(char *dst, const char *src, size_t len, int flag)
211 : : {
212 : : char c;
213 : : char *start;
214 : :
215 [ # # ]: 0 : for (start = dst; len > 1; len--) {
216 : 0 : c = *src;
217 : 0 : dst = vis(dst, c, flag, *++src);
218 : : }
219 [ # # ]: 0 : if (len)
220 : 0 : dst = vis(dst, *src, flag, '\0');
221 : 0 : *dst = '\0';
222 : 0 : return (dst - start);
223 : : }
224 : :
225 : : #endif
|