Annotation of src/lib/libc/gen/vis.c, Revision 1.31
1.31 ! lukem 1: /* $NetBSD: vis.c,v 1.30 2005/05/20 01:22:48 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.31 ! lukem 67: __RCSID("$NetBSD: vis.c,v 1.30 2005/05/20 01:22:48 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
219: * pointed to by `extra'
1.15 wennmach 220: */
221: char *
222: svis(dst, c, flag, nextc, extra)
1.16 wennmach 223: char *dst;
224: int c, flag, nextc;
225: const char *extra;
1.15 wennmach 226: {
1.31 ! lukem 227: char *nextra = NULL;
! 228:
1.16 wennmach 229: _DIAGASSERT(dst != NULL);
230: _DIAGASSERT(extra != NULL);
1.22 christos 231: MAKEEXTRALIST(flag, nextra, extra);
1.31 ! lukem 232: if (!nextra) {
! 233: *dst = '\0'; /* can't create nextra, return "" */
! 234: return (dst);
! 235: }
1.22 christos 236: if (flag & VIS_HTTPSTYLE)
237: HVIS(dst, c, flag, nextc, nextra);
238: else
239: SVIS(dst, c, flag, nextc, nextra);
1.31 ! lukem 240: free(nextra);
1.16 wennmach 241: *dst = '\0';
242: return(dst);
1.15 wennmach 243: }
244:
245:
246: /*
247: * strsvis, strsvisx - visually encode characters from src into dst
248: *
1.16 wennmach 249: * Extra is a pointer to a \0-terminated list of characters to
1.17 wennmach 250: * be encoded, too. These functions are useful e. g. to
251: * encode strings in such a way so that they are not interpreted
1.16 wennmach 252: * by a shell.
1.27 enami 253: *
1.16 wennmach 254: * Dst must be 4 times the size of src to account for possible
255: * expansion. The length of dst, not including the trailing NULL,
1.27 enami 256: * is returned.
1.15 wennmach 257: *
1.16 wennmach 258: * Strsvisx encodes exactly len bytes from src into dst.
259: * This is useful for encoding a block of data.
1.15 wennmach 260: */
261: int
1.25 dsl 262: strsvis(dst, csrc, flag, extra)
1.16 wennmach 263: char *dst;
1.25 dsl 264: const char *csrc;
1.16 wennmach 265: int flag;
266: const char *extra;
1.15 wennmach 267: {
1.25 dsl 268: int c;
1.16 wennmach 269: char *start;
1.31 ! lukem 270: char *nextra = NULL;
1.25 dsl 271: const unsigned char *src = (const unsigned char *)csrc;
1.15 wennmach 272:
1.16 wennmach 273: _DIAGASSERT(dst != NULL);
274: _DIAGASSERT(src != NULL);
275: _DIAGASSERT(extra != NULL);
1.22 christos 276: MAKEEXTRALIST(flag, nextra, extra);
1.31 ! lukem 277: if (!nextra) {
! 278: *dst = '\0'; /* can't create nextra, return "" */
! 279: return 0;
! 280: }
1.22 christos 281: if (flag & VIS_HTTPSTYLE) {
282: for (start = dst; (c = *src++) != '\0'; /* empty */)
283: HVIS(dst, c, flag, *src, nextra);
284: } else {
285: for (start = dst; (c = *src++) != '\0'; /* empty */)
286: SVIS(dst, c, flag, *src, nextra);
287: }
1.31 ! lukem 288: free(nextra);
1.16 wennmach 289: *dst = '\0';
290: return (dst - start);
1.15 wennmach 291: }
292:
293:
294: int
1.25 dsl 295: strsvisx(dst, csrc, len, flag, extra)
1.16 wennmach 296: char *dst;
1.25 dsl 297: const char *csrc;
1.16 wennmach 298: size_t len;
299: int flag;
300: const char *extra;
1.15 wennmach 301: {
1.28 christos 302: unsigned char c;
1.16 wennmach 303: char *start;
1.31 ! lukem 304: char *nextra = NULL;
1.25 dsl 305: const unsigned char *src = (const unsigned char *)csrc;
1.15 wennmach 306:
1.16 wennmach 307: _DIAGASSERT(dst != NULL);
308: _DIAGASSERT(src != NULL);
309: _DIAGASSERT(extra != NULL);
1.22 christos 310: MAKEEXTRALIST(flag, nextra, extra);
1.31 ! lukem 311: if (! nextra) {
! 312: *dst = '\0'; /* can't create nextra, return "" */
! 313: return 0;
! 314: }
1.16 wennmach 315:
1.22 christos 316: if (flag & VIS_HTTPSTYLE) {
317: for (start = dst; len > 0; len--) {
318: c = *src++;
319: HVIS(dst, c, flag, len ? *src : '\0', nextra);
320: }
321: } else {
322: for (start = dst; len > 0; len--) {
323: c = *src++;
324: SVIS(dst, c, flag, len ? *src : '\0', nextra);
325: }
1.16 wennmach 326: }
1.31 ! lukem 327: free(nextra);
1.16 wennmach 328: *dst = '\0';
329: return (dst - start);
1.15 wennmach 330: }
1.24 pooka 331: #endif
1.15 wennmach 332:
1.24 pooka 333: #if !HAVE_VIS
1.1 cgd 334: /*
335: * vis - visually encode characters
336: */
337: char *
338: vis(dst, c, flag, nextc)
1.16 wennmach 339: char *dst;
340: int c, flag, nextc;
1.27 enami 341:
1.15 wennmach 342: {
1.31 ! lukem 343: char *extra = NULL;
1.28 christos 344: unsigned char uc = (unsigned char)c;
1.15 wennmach 345:
1.16 wennmach 346: _DIAGASSERT(dst != NULL);
1.15 wennmach 347:
1.22 christos 348: MAKEEXTRALIST(flag, extra, "");
1.31 ! lukem 349: if (! extra) {
! 350: *dst = '\0'; /* can't create extra, return "" */
! 351: return (dst);
! 352: }
1.22 christos 353: if (flag & VIS_HTTPSTYLE)
1.28 christos 354: HVIS(dst, uc, flag, nextc, extra);
1.22 christos 355: else
1.28 christos 356: SVIS(dst, uc, flag, nextc, extra);
1.16 wennmach 357: *dst = '\0';
358: return (dst);
1.1 cgd 359: }
360:
1.15 wennmach 361:
1.1 cgd 362: /*
363: * strvis, strvisx - visually encode characters from src into dst
1.27 enami 364: *
1.16 wennmach 365: * Dst must be 4 times the size of src to account for possible
366: * expansion. The length of dst, not including the trailing NULL,
1.27 enami 367: * is returned.
1.1 cgd 368: *
1.16 wennmach 369: * Strvisx encodes exactly len bytes from src into dst.
370: * This is useful for encoding a block of data.
1.1 cgd 371: */
372: int
373: strvis(dst, src, flag)
1.16 wennmach 374: char *dst;
375: const char *src;
376: int flag;
1.15 wennmach 377: {
1.31 ! lukem 378: char *extra = NULL;
! 379: int rv;
1.15 wennmach 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 = strsvis(dst, src, flag, extra);
! 387: free(extra);
! 388: return (rv);
1.1 cgd 389: }
390:
1.15 wennmach 391:
1.1 cgd 392: int
393: strvisx(dst, src, len, flag)
1.16 wennmach 394: char *dst;
395: const char *src;
396: size_t len;
397: int flag;
1.15 wennmach 398: {
1.31 ! lukem 399: char *extra = NULL;
! 400: int rv;
1.1 cgd 401:
1.22 christos 402: MAKEEXTRALIST(flag, extra, "");
1.31 ! lukem 403: if (!extra) {
! 404: *dst = '\0'; /* can't create extra, return "" */
! 405: return 0;
! 406: }
! 407: rv = strsvisx(dst, src, len, flag, extra);
! 408: free(extra);
! 409: return (rv);
1.1 cgd 410: }
1.20 tv 411: #endif
CVSweb <webmaster@jp.NetBSD.org>