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