Annotation of src/lib/libc/gen/vis.c, Revision 1.33
1.33 ! lukem 1: /* $NetBSD: vis.c,v 1.32 2005/05/28 13:06:14 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: /*-
1.31 lukem 33: * Copyright (c) 1999, 2005 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.33 ! lukem 67: __RCSID("$NetBSD: vis.c,v 1.32 2005/05/28 13:06:14 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.31 lukem 109: extra = malloc((size_t)((o - orig) + MAXEXTRAS)); \
110: if (!extra) break; \
1.22 christos 111: for (o = orig, e = extra; (*e++ = *o++) != '\0';) \
112: continue; \
113: e--; \
1.27 enami 114: if (flag & VIS_SP) *e++ = ' '; \
1.22 christos 115: if (flag & VIS_TAB) *e++ = '\t'; \
1.27 enami 116: if (flag & VIS_NL) *e++ = '\n'; \
117: if ((flag & VIS_NOSLASH) == 0) *e++ = '\\'; \
1.22 christos 118: *e = '\0'; \
1.19 mycroft 119: } while (/*CONSTCOND*/0)
1.15 wennmach 120:
1.22 christos 121:
122: /*
123: * This is HVIS, the macro of vis used to HTTP style (RFC 1808)
124: */
125: #define HVIS(dst, c, flag, nextc, extra) \
1.27 enami 126: do \
1.22 christos 127: if (!isascii(c) || !isalnum(c) || strchr("$-_.+!*'(),", c) != NULL) { \
128: *dst++ = '%'; \
129: *dst++ = xtoa(((unsigned int)c >> 4) & 0xf); \
130: *dst++ = xtoa((unsigned int)c & 0xf); \
131: } else { \
132: SVIS(dst, c, flag, nextc, extra); \
133: } \
134: while (/*CONSTCOND*/0)
1.27 enami 135:
1.15 wennmach 136: /*
137: * This is SVIS, the central macro of vis.
1.16 wennmach 138: * dst: Pointer to the destination buffer
139: * c: Character to encode
1.15 wennmach 140: * flag: Flag word
141: * nextc: The character following 'c'
142: * extra: Pointer to the list of extra characters to be
1.16 wennmach 143: * backslash-protected.
1.15 wennmach 144: */
1.16 wennmach 145: #define SVIS(dst, c, flag, nextc, extra) \
146: do { \
1.25 dsl 147: int isextra; \
1.16 wennmach 148: isextra = strchr(extra, c) != NULL; \
1.17 wennmach 149: if (!isextra && isascii(c) && (isgraph(c) || iswhite(c) || \
150: ((flag & VIS_SAFE) && issafe(c)))) { \
1.16 wennmach 151: *dst++ = c; \
152: break; \
153: } \
154: if (flag & VIS_CSTYLE) { \
155: switch (c) { \
156: case '\n': \
1.25 dsl 157: *dst++ = '\\'; *dst++ = 'n'; \
158: continue; \
1.16 wennmach 159: case '\r': \
1.25 dsl 160: *dst++ = '\\'; *dst++ = 'r'; \
161: continue; \
1.16 wennmach 162: case '\b': \
1.25 dsl 163: *dst++ = '\\'; *dst++ = 'b'; \
164: continue; \
1.16 wennmach 165: case BELL: \
1.25 dsl 166: *dst++ = '\\'; *dst++ = 'a'; \
167: continue; \
1.16 wennmach 168: case '\v': \
1.25 dsl 169: *dst++ = '\\'; *dst++ = 'v'; \
170: continue; \
1.16 wennmach 171: case '\t': \
1.25 dsl 172: *dst++ = '\\'; *dst++ = 't'; \
173: continue; \
1.16 wennmach 174: case '\f': \
1.25 dsl 175: *dst++ = '\\'; *dst++ = 'f'; \
176: continue; \
1.16 wennmach 177: case ' ': \
1.25 dsl 178: *dst++ = '\\'; *dst++ = 's'; \
179: continue; \
1.16 wennmach 180: case '\0': \
1.25 dsl 181: *dst++ = '\\'; *dst++ = '0'; \
1.16 wennmach 182: if (isoctal(nextc)) { \
183: *dst++ = '0'; \
184: *dst++ = '0'; \
185: } \
1.25 dsl 186: continue; \
187: default: \
188: if (isgraph(c)) { \
189: *dst++ = '\\'; *dst++ = c; \
190: continue; \
191: } \
1.16 wennmach 192: } \
193: } \
1.17 wennmach 194: if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) { \
1.16 wennmach 195: *dst++ = '\\'; \
196: *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + '0'; \
197: *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + '0'; \
198: *dst++ = (c & 07) + '0'; \
199: } else { \
200: if ((flag & VIS_NOSLASH) == 0) *dst++ = '\\'; \
201: if (c & 0200) { \
202: c &= 0177; *dst++ = 'M'; \
203: } \
204: if (iscntrl(c)) { \
205: *dst++ = '^'; \
206: if (c == 0177) \
207: *dst++ = '?'; \
208: else \
209: *dst++ = c + '@'; \
210: } else { \
211: *dst++ = '-'; *dst++ = c; \
212: } \
213: } \
1.19 mycroft 214: } while (/*CONSTCOND*/0)
1.15 wennmach 215:
216:
217: /*
1.17 wennmach 218: * svis - visually encode characters, also encoding the characters
1.33 ! lukem 219: * pointed to by `extra'
1.15 wennmach 220: */
221: char *
1.33 ! lukem 222: svis(char *dst, int c, int flag, int nextc, const char *extra)
1.15 wennmach 223: {
1.31 lukem 224: char *nextra = NULL;
225:
1.16 wennmach 226: _DIAGASSERT(dst != NULL);
227: _DIAGASSERT(extra != NULL);
1.22 christos 228: MAKEEXTRALIST(flag, nextra, extra);
1.31 lukem 229: if (!nextra) {
230: *dst = '\0'; /* can't create nextra, return "" */
1.33 ! lukem 231: return dst;
1.31 lukem 232: }
1.22 christos 233: if (flag & VIS_HTTPSTYLE)
234: HVIS(dst, c, flag, nextc, nextra);
235: else
236: SVIS(dst, c, flag, nextc, nextra);
1.31 lukem 237: free(nextra);
1.16 wennmach 238: *dst = '\0';
1.33 ! lukem 239: return dst;
1.15 wennmach 240: }
241:
242:
243: /*
244: * strsvis, strsvisx - visually encode characters from src into dst
245: *
1.16 wennmach 246: * Extra is a pointer to a \0-terminated list of characters to
1.17 wennmach 247: * be encoded, too. These functions are useful e. g. to
248: * encode strings in such a way so that they are not interpreted
1.16 wennmach 249: * by a shell.
1.27 enami 250: *
1.16 wennmach 251: * Dst must be 4 times the size of src to account for possible
252: * expansion. The length of dst, not including the trailing NULL,
1.27 enami 253: * is returned.
1.15 wennmach 254: *
1.16 wennmach 255: * Strsvisx encodes exactly len bytes from src into dst.
256: * This is useful for encoding a block of data.
1.15 wennmach 257: */
258: int
1.33 ! lukem 259: strsvis(char *dst, const char *csrc, int flag, const char *extra)
1.15 wennmach 260: {
1.25 dsl 261: int c;
1.16 wennmach 262: char *start;
1.31 lukem 263: char *nextra = NULL;
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);
1.31 lukem 270: if (!nextra) {
271: *dst = '\0'; /* can't create nextra, return "" */
272: return 0;
273: }
1.22 christos 274: if (flag & VIS_HTTPSTYLE) {
275: for (start = dst; (c = *src++) != '\0'; /* empty */)
276: HVIS(dst, c, flag, *src, nextra);
277: } else {
278: for (start = dst; (c = *src++) != '\0'; /* empty */)
279: SVIS(dst, c, flag, *src, nextra);
280: }
1.31 lukem 281: free(nextra);
1.16 wennmach 282: *dst = '\0';
283: return (dst - start);
1.15 wennmach 284: }
285:
286:
287: int
1.33 ! lukem 288: strsvisx(char *dst, const char *csrc, size_t len, int flag, const char *extra)
1.15 wennmach 289: {
1.28 christos 290: unsigned char c;
1.16 wennmach 291: char *start;
1.31 lukem 292: char *nextra = NULL;
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.31 lukem 299: if (! nextra) {
300: *dst = '\0'; /* can't create nextra, return "" */
301: return 0;
302: }
1.16 wennmach 303:
1.22 christos 304: if (flag & VIS_HTTPSTYLE) {
305: for (start = dst; len > 0; len--) {
306: c = *src++;
307: HVIS(dst, c, flag, len ? *src : '\0', nextra);
308: }
309: } else {
310: for (start = dst; len > 0; len--) {
311: c = *src++;
312: SVIS(dst, c, flag, len ? *src : '\0', nextra);
313: }
1.16 wennmach 314: }
1.31 lukem 315: free(nextra);
1.16 wennmach 316: *dst = '\0';
317: return (dst - start);
1.15 wennmach 318: }
1.24 pooka 319: #endif
1.15 wennmach 320:
1.24 pooka 321: #if !HAVE_VIS
1.1 cgd 322: /*
323: * vis - visually encode characters
324: */
325: char *
1.33 ! lukem 326: vis(char *dst, int c, int flag, int nextc)
1.15 wennmach 327: {
1.31 lukem 328: char *extra = NULL;
1.28 christos 329: unsigned char uc = (unsigned char)c;
1.15 wennmach 330:
1.16 wennmach 331: _DIAGASSERT(dst != NULL);
1.15 wennmach 332:
1.22 christos 333: MAKEEXTRALIST(flag, extra, "");
1.31 lukem 334: if (! extra) {
335: *dst = '\0'; /* can't create extra, return "" */
1.33 ! lukem 336: return dst;
1.31 lukem 337: }
1.22 christos 338: if (flag & VIS_HTTPSTYLE)
1.28 christos 339: HVIS(dst, uc, flag, nextc, extra);
1.22 christos 340: else
1.28 christos 341: SVIS(dst, uc, flag, nextc, extra);
1.32 lukem 342: free(extra);
1.16 wennmach 343: *dst = '\0';
1.33 ! lukem 344: return dst;
1.1 cgd 345: }
346:
1.15 wennmach 347:
1.1 cgd 348: /*
349: * strvis, strvisx - visually encode characters from src into dst
1.27 enami 350: *
1.16 wennmach 351: * Dst must be 4 times the size of src to account for possible
352: * expansion. The length of dst, not including the trailing NULL,
1.27 enami 353: * is returned.
1.1 cgd 354: *
1.16 wennmach 355: * Strvisx encodes exactly len bytes from src into dst.
356: * This is useful for encoding a block of data.
1.1 cgd 357: */
358: int
1.33 ! lukem 359: strvis(char *dst, const char *src, int flag)
1.15 wennmach 360: {
1.31 lukem 361: char *extra = NULL;
362: int rv;
1.15 wennmach 363:
1.22 christos 364: MAKEEXTRALIST(flag, extra, "");
1.31 lukem 365: if (!extra) {
366: *dst = '\0'; /* can't create extra, return "" */
367: return 0;
368: }
369: rv = strsvis(dst, src, flag, extra);
370: free(extra);
1.33 ! lukem 371: return rv;
1.1 cgd 372: }
373:
1.15 wennmach 374:
1.1 cgd 375: int
1.33 ! lukem 376: strvisx(char *dst, const char *src, size_t len, int flag)
1.15 wennmach 377: {
1.31 lukem 378: char *extra = NULL;
379: int rv;
1.1 cgd 380:
1.22 christos 381: MAKEEXTRALIST(flag, extra, "");
1.31 lukem 382: if (!extra) {
383: *dst = '\0'; /* can't create extra, return "" */
384: return 0;
385: }
386: rv = strsvisx(dst, src, len, flag, extra);
387: free(extra);
1.33 ! lukem 388: return rv;
1.1 cgd 389: }
1.20 tv 390: #endif
CVSweb <webmaster@jp.NetBSD.org>