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