Annotation of src/lib/libc/gen/vis.c, Revision 1.29
1.29 ! lukem 1: /* $NetBSD: vis.c,v 1.28 2005/04/17 17:27:11 christos Exp $ */
1.6 cgd 2:
1.1 cgd 3: /*-
1.6 cgd 4: * Copyright (c) 1989, 1993
1.16 wennmach 5: * The Regents of the University of California. All rights reserved.
1.1 cgd 6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
1.29 ! lukem 15: * 3. Neither the name of the University nor the names of its contributors
1.1 cgd 16: * may be used to endorse or promote products derived from this software
17: * without specific prior written permission.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29: * SUCH DAMAGE.
30: */
31:
1.26 agc 32: /*-
33: * Copyright (c) 1999 The NetBSD Foundation, Inc.
34: *
35: * Redistribution and use in source and binary forms, with or without
36: * modification, are permitted provided that the following conditions
37: * are met:
38: * 1. Redistributions of source code must retain the above copyright
39: * notice, this list of conditions and the following disclaimer.
40: * 2. Redistributions in binary form must reproduce the above copyright
41: * notice, this list of conditions and the following disclaimer in the
42: * documentation and/or other materials provided with the distribution.
43: * 3. All advertising materials mentioning features or use of this software
44: * must display the following acknowledgement:
45: * This product includes software developed by the University of
46: * California, Berkeley and its contributors.
47: * 4. Neither the name of the University nor the names of its contributors
48: * may be used to endorse or promote products derived from this software
49: * without specific prior written permission.
50: *
51: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61: * SUCH DAMAGE.
62: */
63:
1.7 christos 64: #include <sys/cdefs.h>
1.21 tv 65: #if defined(LIBC_SCCS) && !defined(lint)
1.29 ! lukem 66: __RCSID("$NetBSD: vis.c,v 1.28 2005/04/17 17:27:11 christos Exp $");
1.21 tv 67: #endif /* LIBC_SCCS and not lint */
1.1 cgd 68:
1.8 jtc 69: #include "namespace.h"
1.1 cgd 70: #include <sys/types.h>
1.12 lukem 71:
72: #include <assert.h>
1.1 cgd 73: #include <vis.h>
1.22 christos 74: #include <stdlib.h>
1.8 jtc 75:
76: #ifdef __weak_alias
1.18 mycroft 77: __weak_alias(strsvis,_strsvis)
78: __weak_alias(strsvisx,_strsvisx)
79: __weak_alias(strvis,_strvis)
80: __weak_alias(strvisx,_strvisx)
81: __weak_alias(svis,_svis)
82: __weak_alias(vis,_vis)
1.20 tv 83: #endif
84:
1.24 pooka 85: #if !HAVE_VIS || !HAVE_SVIS
1.20 tv 86: #include <ctype.h>
87: #include <limits.h>
88: #include <stdio.h>
89: #include <string.h>
1.1 cgd 90:
1.15 wennmach 91: #undef BELL
92: #define BELL '\a'
93:
1.16 wennmach 94: #define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
95: #define iswhite(c) (c == ' ' || c == '\t' || c == '\n')
96: #define issafe(c) (c == '\b' || c == BELL || c == '\r')
1.22 christos 97: #define xtoa(c) "0123456789abcdef"[c]
1.16 wennmach 98:
1.27 enami 99: #define MAXEXTRAS 5
1.15 wennmach 100:
101:
1.22 christos 102: #define MAKEEXTRALIST(flag, extra, orig) \
1.16 wennmach 103: do { \
1.22 christos 104: const char *o = orig; \
1.27 enami 105: char *e; \
1.22 christos 106: while (*o++) \
107: continue; \
1.27 enami 108: extra = alloca((size_t)((o - orig) + MAXEXTRAS)); \
1.22 christos 109: for (o = orig, e = extra; (*e++ = *o++) != '\0';) \
110: continue; \
111: e--; \
1.27 enami 112: if (flag & VIS_SP) *e++ = ' '; \
1.22 christos 113: if (flag & VIS_TAB) *e++ = '\t'; \
1.27 enami 114: if (flag & VIS_NL) *e++ = '\n'; \
115: if ((flag & VIS_NOSLASH) == 0) *e++ = '\\'; \
1.22 christos 116: *e = '\0'; \
1.19 mycroft 117: } while (/*CONSTCOND*/0)
1.15 wennmach 118:
1.22 christos 119:
120: /*
121: * This is HVIS, the macro of vis used to HTTP style (RFC 1808)
122: */
123: #define HVIS(dst, c, flag, nextc, extra) \
1.27 enami 124: do \
1.22 christos 125: if (!isascii(c) || !isalnum(c) || strchr("$-_.+!*'(),", c) != NULL) { \
126: *dst++ = '%'; \
127: *dst++ = xtoa(((unsigned int)c >> 4) & 0xf); \
128: *dst++ = xtoa((unsigned int)c & 0xf); \
129: } else { \
130: SVIS(dst, c, flag, nextc, extra); \
131: } \
132: while (/*CONSTCOND*/0)
1.27 enami 133:
1.15 wennmach 134: /*
135: * This is SVIS, the central macro of vis.
1.16 wennmach 136: * dst: Pointer to the destination buffer
137: * c: Character to encode
1.15 wennmach 138: * flag: Flag word
139: * nextc: The character following 'c'
140: * extra: Pointer to the list of extra characters to be
1.16 wennmach 141: * backslash-protected.
1.15 wennmach 142: */
1.16 wennmach 143: #define SVIS(dst, c, flag, nextc, extra) \
144: do { \
1.25 dsl 145: int isextra; \
1.16 wennmach 146: isextra = strchr(extra, c) != NULL; \
1.17 wennmach 147: if (!isextra && isascii(c) && (isgraph(c) || iswhite(c) || \
148: ((flag & VIS_SAFE) && issafe(c)))) { \
1.16 wennmach 149: *dst++ = c; \
150: break; \
151: } \
152: if (flag & VIS_CSTYLE) { \
153: switch (c) { \
154: case '\n': \
1.25 dsl 155: *dst++ = '\\'; *dst++ = 'n'; \
156: continue; \
1.16 wennmach 157: case '\r': \
1.25 dsl 158: *dst++ = '\\'; *dst++ = 'r'; \
159: continue; \
1.16 wennmach 160: case '\b': \
1.25 dsl 161: *dst++ = '\\'; *dst++ = 'b'; \
162: continue; \
1.16 wennmach 163: case BELL: \
1.25 dsl 164: *dst++ = '\\'; *dst++ = 'a'; \
165: continue; \
1.16 wennmach 166: case '\v': \
1.25 dsl 167: *dst++ = '\\'; *dst++ = 'v'; \
168: continue; \
1.16 wennmach 169: case '\t': \
1.25 dsl 170: *dst++ = '\\'; *dst++ = 't'; \
171: continue; \
1.16 wennmach 172: case '\f': \
1.25 dsl 173: *dst++ = '\\'; *dst++ = 'f'; \
174: continue; \
1.16 wennmach 175: case ' ': \
1.25 dsl 176: *dst++ = '\\'; *dst++ = 's'; \
177: continue; \
1.16 wennmach 178: case '\0': \
1.25 dsl 179: *dst++ = '\\'; *dst++ = '0'; \
1.16 wennmach 180: if (isoctal(nextc)) { \
181: *dst++ = '0'; \
182: *dst++ = '0'; \
183: } \
1.25 dsl 184: continue; \
185: default: \
186: if (isgraph(c)) { \
187: *dst++ = '\\'; *dst++ = c; \
188: continue; \
189: } \
1.16 wennmach 190: } \
191: } \
1.17 wennmach 192: if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) { \
1.16 wennmach 193: *dst++ = '\\'; \
194: *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + '0'; \
195: *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + '0'; \
196: *dst++ = (c & 07) + '0'; \
197: } else { \
198: if ((flag & VIS_NOSLASH) == 0) *dst++ = '\\'; \
199: if (c & 0200) { \
200: c &= 0177; *dst++ = 'M'; \
201: } \
202: if (iscntrl(c)) { \
203: *dst++ = '^'; \
204: if (c == 0177) \
205: *dst++ = '?'; \
206: else \
207: *dst++ = c + '@'; \
208: } else { \
209: *dst++ = '-'; *dst++ = c; \
210: } \
211: } \
1.19 mycroft 212: } while (/*CONSTCOND*/0)
1.15 wennmach 213:
214:
215: /*
1.17 wennmach 216: * svis - visually encode characters, also encoding the characters
217: * pointed to by `extra'
1.15 wennmach 218: */
219: char *
220: svis(dst, c, flag, nextc, extra)
1.16 wennmach 221: char *dst;
222: int c, flag, nextc;
223: const char *extra;
1.15 wennmach 224: {
1.22 christos 225: char *nextra;
1.16 wennmach 226: _DIAGASSERT(dst != NULL);
227: _DIAGASSERT(extra != NULL);
1.22 christos 228: MAKEEXTRALIST(flag, nextra, extra);
229: if (flag & VIS_HTTPSTYLE)
230: HVIS(dst, c, flag, nextc, nextra);
231: else
232: SVIS(dst, c, flag, nextc, nextra);
1.16 wennmach 233: *dst = '\0';
234: return(dst);
1.15 wennmach 235: }
236:
237:
238: /*
239: * strsvis, strsvisx - visually encode characters from src into dst
240: *
1.16 wennmach 241: * Extra is a pointer to a \0-terminated list of characters to
1.17 wennmach 242: * be encoded, too. These functions are useful e. g. to
243: * encode strings in such a way so that they are not interpreted
1.16 wennmach 244: * by a shell.
1.27 enami 245: *
1.16 wennmach 246: * Dst must be 4 times the size of src to account for possible
247: * expansion. The length of dst, not including the trailing NULL,
1.27 enami 248: * is returned.
1.15 wennmach 249: *
1.16 wennmach 250: * Strsvisx encodes exactly len bytes from src into dst.
251: * This is useful for encoding a block of data.
1.15 wennmach 252: */
253: int
1.25 dsl 254: strsvis(dst, csrc, flag, extra)
1.16 wennmach 255: char *dst;
1.25 dsl 256: const char *csrc;
1.16 wennmach 257: int flag;
258: const char *extra;
1.15 wennmach 259: {
1.25 dsl 260: int c;
1.16 wennmach 261: char *start;
1.22 christos 262: char *nextra;
1.25 dsl 263: const unsigned char *src = (const unsigned char *)csrc;
1.15 wennmach 264:
1.16 wennmach 265: _DIAGASSERT(dst != NULL);
266: _DIAGASSERT(src != NULL);
267: _DIAGASSERT(extra != NULL);
1.22 christos 268: MAKEEXTRALIST(flag, nextra, extra);
269: if (flag & VIS_HTTPSTYLE) {
270: for (start = dst; (c = *src++) != '\0'; /* empty */)
271: HVIS(dst, c, flag, *src, nextra);
272: } else {
273: for (start = dst; (c = *src++) != '\0'; /* empty */)
274: SVIS(dst, c, flag, *src, nextra);
275: }
1.16 wennmach 276: *dst = '\0';
277: return (dst - start);
1.15 wennmach 278: }
279:
280:
281: int
1.25 dsl 282: strsvisx(dst, csrc, len, flag, extra)
1.16 wennmach 283: char *dst;
1.25 dsl 284: const char *csrc;
1.16 wennmach 285: size_t len;
286: int flag;
287: const char *extra;
1.15 wennmach 288: {
1.28 christos 289: unsigned char c;
1.16 wennmach 290: char *start;
1.22 christos 291: char *nextra;
1.25 dsl 292: const unsigned char *src = (const unsigned char *)csrc;
1.15 wennmach 293:
1.16 wennmach 294: _DIAGASSERT(dst != NULL);
295: _DIAGASSERT(src != NULL);
296: _DIAGASSERT(extra != NULL);
1.22 christos 297: MAKEEXTRALIST(flag, nextra, extra);
1.16 wennmach 298:
1.22 christos 299: if (flag & VIS_HTTPSTYLE) {
300: for (start = dst; len > 0; len--) {
301: c = *src++;
302: HVIS(dst, c, flag, len ? *src : '\0', nextra);
303: }
304: } else {
305: for (start = dst; len > 0; len--) {
306: c = *src++;
307: SVIS(dst, c, flag, len ? *src : '\0', nextra);
308: }
1.16 wennmach 309: }
310: *dst = '\0';
311: return (dst - start);
1.15 wennmach 312: }
1.24 pooka 313: #endif
1.15 wennmach 314:
1.24 pooka 315: #if !HAVE_VIS
1.1 cgd 316: /*
317: * vis - visually encode characters
318: */
319: char *
320: vis(dst, c, flag, nextc)
1.16 wennmach 321: char *dst;
322: int c, flag, nextc;
1.27 enami 323:
1.15 wennmach 324: {
1.22 christos 325: char *extra;
1.28 christos 326: unsigned char uc = (unsigned char)c;
1.15 wennmach 327:
1.16 wennmach 328: _DIAGASSERT(dst != NULL);
1.15 wennmach 329:
1.22 christos 330: MAKEEXTRALIST(flag, extra, "");
331: if (flag & VIS_HTTPSTYLE)
1.28 christos 332: HVIS(dst, uc, flag, nextc, extra);
1.22 christos 333: else
1.28 christos 334: SVIS(dst, uc, flag, nextc, extra);
1.16 wennmach 335: *dst = '\0';
336: return (dst);
1.1 cgd 337: }
338:
1.15 wennmach 339:
1.1 cgd 340: /*
341: * strvis, strvisx - visually encode characters from src into dst
1.27 enami 342: *
1.16 wennmach 343: * Dst must be 4 times the size of src to account for possible
344: * expansion. The length of dst, not including the trailing NULL,
1.27 enami 345: * is returned.
1.1 cgd 346: *
1.16 wennmach 347: * Strvisx encodes exactly len bytes from src into dst.
348: * This is useful for encoding a block of data.
1.1 cgd 349: */
350: int
351: strvis(dst, src, flag)
1.16 wennmach 352: char *dst;
353: const char *src;
354: int flag;
1.15 wennmach 355: {
1.22 christos 356: char *extra;
1.15 wennmach 357:
1.22 christos 358: MAKEEXTRALIST(flag, extra, "");
1.16 wennmach 359: return (strsvis(dst, src, flag, extra));
1.1 cgd 360: }
361:
1.15 wennmach 362:
1.1 cgd 363: int
364: strvisx(dst, src, len, flag)
1.16 wennmach 365: char *dst;
366: const char *src;
367: size_t len;
368: int flag;
1.15 wennmach 369: {
1.22 christos 370: char *extra;
1.1 cgd 371:
1.22 christos 372: MAKEEXTRALIST(flag, extra, "");
1.16 wennmach 373: return (strsvisx(dst, src, len, flag, extra));
1.1 cgd 374: }
1.20 tv 375: #endif
CVSweb <webmaster@jp.NetBSD.org>