Annotation of embedaddon/tmux/compat/vis.c, revision 1.1
1.1 ! misho 1: /* $OpenBSD: vis.c,v 1.24 2015/07/20 01:52:28 millert Exp $ */
! 2: /*-
! 3: * Copyright (c) 1989, 1993
! 4: * The Regents of the University of California. All rights reserved.
! 5: *
! 6: * Redistribution and use in source and binary forms, with or without
! 7: * modification, are permitted provided that the following conditions
! 8: * are met:
! 9: * 1. Redistributions of source code must retain the above copyright
! 10: * notice, this list of conditions and the following disclaimer.
! 11: * 2. Redistributions in binary form must reproduce the above copyright
! 12: * notice, this list of conditions and the following disclaimer in the
! 13: * documentation and/or other materials provided with the distribution.
! 14: * 3. Neither the name of the University nor the names of its contributors
! 15: * may be used to endorse or promote products derived from this software
! 16: * without specific prior written permission.
! 17: *
! 18: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 19: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 20: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 21: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 22: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 23: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 24: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 25: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 26: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 27: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 28: * SUCH DAMAGE.
! 29: */
! 30:
! 31: #include <sys/types.h>
! 32: #include <errno.h>
! 33: #include <ctype.h>
! 34: #include <limits.h>
! 35: #include <string.h>
! 36: #include <stdlib.h>
! 37:
! 38: #include "compat.h"
! 39:
! 40: #define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
! 41: #define isvisible(c,flag) \
! 42: (((c) == '\\' || (flag & VIS_ALL) == 0) && \
! 43: (((u_int)(c) <= UCHAR_MAX && isascii((u_char)(c)) && \
! 44: (((c) != '*' && (c) != '?' && (c) != '[' && (c) != '#') || \
! 45: (flag & VIS_GLOB) == 0) && isgraph((u_char)(c))) || \
! 46: ((flag & VIS_SP) == 0 && (c) == ' ') || \
! 47: ((flag & VIS_TAB) == 0 && (c) == '\t') || \
! 48: ((flag & VIS_NL) == 0 && (c) == '\n') || \
! 49: ((flag & VIS_SAFE) && ((c) == '\b' || \
! 50: (c) == '\007' || (c) == '\r' || \
! 51: isgraph((u_char)(c))))))
! 52:
! 53: /*
! 54: * vis - visually encode characters
! 55: */
! 56: char *
! 57: vis(char *dst, int c, int flag, int nextc)
! 58: {
! 59: if (isvisible(c, flag)) {
! 60: if ((c == '"' && (flag & VIS_DQ) != 0) ||
! 61: (c == '\\' && (flag & VIS_NOSLASH) == 0))
! 62: *dst++ = '\\';
! 63: *dst++ = c;
! 64: *dst = '\0';
! 65: return (dst);
! 66: }
! 67:
! 68: if (flag & VIS_CSTYLE) {
! 69: switch(c) {
! 70: case '\n':
! 71: *dst++ = '\\';
! 72: *dst++ = 'n';
! 73: goto done;
! 74: case '\r':
! 75: *dst++ = '\\';
! 76: *dst++ = 'r';
! 77: goto done;
! 78: case '\b':
! 79: *dst++ = '\\';
! 80: *dst++ = 'b';
! 81: goto done;
! 82: case '\a':
! 83: *dst++ = '\\';
! 84: *dst++ = 'a';
! 85: goto done;
! 86: case '\v':
! 87: *dst++ = '\\';
! 88: *dst++ = 'v';
! 89: goto done;
! 90: case '\t':
! 91: *dst++ = '\\';
! 92: *dst++ = 't';
! 93: goto done;
! 94: case '\f':
! 95: *dst++ = '\\';
! 96: *dst++ = 'f';
! 97: goto done;
! 98: case ' ':
! 99: *dst++ = '\\';
! 100: *dst++ = 's';
! 101: goto done;
! 102: case '\0':
! 103: *dst++ = '\\';
! 104: *dst++ = '0';
! 105: if (isoctal(nextc)) {
! 106: *dst++ = '0';
! 107: *dst++ = '0';
! 108: }
! 109: goto done;
! 110: }
! 111: }
! 112: if (((c & 0177) == ' ') || (flag & VIS_OCTAL) ||
! 113: ((flag & VIS_GLOB) && (c == '*' || c == '?' || c == '[' || c == '#'))) {
! 114: *dst++ = '\\';
! 115: *dst++ = ((u_char)c >> 6 & 07) + '0';
! 116: *dst++ = ((u_char)c >> 3 & 07) + '0';
! 117: *dst++ = ((u_char)c & 07) + '0';
! 118: goto done;
! 119: }
! 120: if ((flag & VIS_NOSLASH) == 0)
! 121: *dst++ = '\\';
! 122: if (c & 0200) {
! 123: c &= 0177;
! 124: *dst++ = 'M';
! 125: }
! 126: if (iscntrl((u_char)c)) {
! 127: *dst++ = '^';
! 128: if (c == 0177)
! 129: *dst++ = '?';
! 130: else
! 131: *dst++ = c + '@';
! 132: } else {
! 133: *dst++ = '-';
! 134: *dst++ = c;
! 135: }
! 136: done:
! 137: *dst = '\0';
! 138: return (dst);
! 139: }
! 140:
! 141: /*
! 142: * strvis, strnvis, strvisx - visually encode characters from src into dst
! 143: *
! 144: * Dst must be 4 times the size of src to account for possible
! 145: * expansion. The length of dst, not including the trailing NULL,
! 146: * is returned.
! 147: *
! 148: * Strnvis will write no more than siz-1 bytes (and will NULL terminate).
! 149: * The number of bytes needed to fully encode the string is returned.
! 150: *
! 151: * Strvisx encodes exactly len bytes from src into dst.
! 152: * This is useful for encoding a block of data.
! 153: */
! 154: int
! 155: strvis(char *dst, const char *src, int flag)
! 156: {
! 157: char c;
! 158: char *start;
! 159:
! 160: for (start = dst; (c = *src);)
! 161: dst = vis(dst, c, flag, *++src);
! 162: *dst = '\0';
! 163: return (dst - start);
! 164: }
! 165:
! 166: int
! 167: strnvis(char *dst, const char *src, size_t siz, int flag)
! 168: {
! 169: char *start, *end;
! 170: char tbuf[5];
! 171: int c, i;
! 172:
! 173: i = 0;
! 174: for (start = dst, end = start + siz - 1; (c = *src) && dst < end; ) {
! 175: if (isvisible(c, flag)) {
! 176: if ((c == '"' && (flag & VIS_DQ) != 0) ||
! 177: (c == '\\' && (flag & VIS_NOSLASH) == 0)) {
! 178: /* need space for the extra '\\' */
! 179: if (dst + 1 >= end) {
! 180: i = 2;
! 181: break;
! 182: }
! 183: *dst++ = '\\';
! 184: }
! 185: i = 1;
! 186: *dst++ = c;
! 187: src++;
! 188: } else {
! 189: i = vis(tbuf, c, flag, *++src) - tbuf;
! 190: if (dst + i <= end) {
! 191: memcpy(dst, tbuf, i);
! 192: dst += i;
! 193: } else {
! 194: src--;
! 195: break;
! 196: }
! 197: }
! 198: }
! 199: if (siz > 0)
! 200: *dst = '\0';
! 201: if (dst + i > end) {
! 202: /* adjust return value for truncation */
! 203: while ((c = *src))
! 204: dst += vis(tbuf, c, flag, *++src) - tbuf;
! 205: }
! 206: return (dst - start);
! 207: }
! 208:
! 209: int
! 210: stravis(char **outp, const char *src, int flag)
! 211: {
! 212: char *buf;
! 213: int len, serrno;
! 214:
! 215: buf = calloc(4, strlen(src) + 1);
! 216: if (buf == NULL)
! 217: return -1;
! 218: len = strvis(buf, src, flag);
! 219: serrno = errno;
! 220: *outp = realloc(buf, len + 1);
! 221: if (*outp == NULL) {
! 222: *outp = buf;
! 223: errno = serrno;
! 224: }
! 225: return (len);
! 226: }
! 227:
! 228: int
! 229: strvisx(char *dst, const char *src, size_t len, int flag)
! 230: {
! 231: char c;
! 232: char *start;
! 233:
! 234: for (start = dst; len > 1; len--) {
! 235: c = *src;
! 236: dst = vis(dst, c, flag, *++src);
! 237: }
! 238: if (len)
! 239: dst = vis(dst, *src, flag, '\0');
! 240: *dst = '\0';
! 241: return (dst - start);
! 242: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>