Annotation of embedaddon/tmux/compat/unvis.c, revision 1.1
1.1 ! misho 1: /* $OpenBSD: unvis.c,v 1.12 2005/08/08 08:05:34 espie 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 <ctype.h>
! 33:
! 34: #include "compat.h"
! 35:
! 36: /*
! 37: * decode driven by state machine
! 38: */
! 39: #define S_GROUND 0 /* haven't seen escape char */
! 40: #define S_START 1 /* start decoding special sequence */
! 41: #define S_META 2 /* metachar started (M) */
! 42: #define S_META1 3 /* metachar more, regular char (-) */
! 43: #define S_CTRL 4 /* control char started (^) */
! 44: #define S_OCTAL2 5 /* octal digit 2 */
! 45: #define S_OCTAL3 6 /* octal digit 3 */
! 46:
! 47: #define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
! 48:
! 49: /*
! 50: * unvis - decode characters previously encoded by vis
! 51: */
! 52: int
! 53: unvis(char *cp, char c, int *astate, int flag)
! 54: {
! 55:
! 56: if (flag & UNVIS_END) {
! 57: if (*astate == S_OCTAL2 || *astate == S_OCTAL3) {
! 58: *astate = S_GROUND;
! 59: return (UNVIS_VALID);
! 60: }
! 61: return (*astate == S_GROUND ? UNVIS_NOCHAR : UNVIS_SYNBAD);
! 62: }
! 63:
! 64: switch (*astate) {
! 65:
! 66: case S_GROUND:
! 67: *cp = 0;
! 68: if (c == '\\') {
! 69: *astate = S_START;
! 70: return (0);
! 71: }
! 72: *cp = c;
! 73: return (UNVIS_VALID);
! 74:
! 75: case S_START:
! 76: switch(c) {
! 77: case '\\':
! 78: *cp = c;
! 79: *astate = S_GROUND;
! 80: return (UNVIS_VALID);
! 81: case '0': case '1': case '2': case '3':
! 82: case '4': case '5': case '6': case '7':
! 83: *cp = (c - '0');
! 84: *astate = S_OCTAL2;
! 85: return (0);
! 86: case 'M':
! 87: *cp = (char) 0200;
! 88: *astate = S_META;
! 89: return (0);
! 90: case '^':
! 91: *astate = S_CTRL;
! 92: return (0);
! 93: case 'n':
! 94: *cp = '\n';
! 95: *astate = S_GROUND;
! 96: return (UNVIS_VALID);
! 97: case 'r':
! 98: *cp = '\r';
! 99: *astate = S_GROUND;
! 100: return (UNVIS_VALID);
! 101: case 'b':
! 102: *cp = '\b';
! 103: *astate = S_GROUND;
! 104: return (UNVIS_VALID);
! 105: case 'a':
! 106: *cp = '\007';
! 107: *astate = S_GROUND;
! 108: return (UNVIS_VALID);
! 109: case 'v':
! 110: *cp = '\v';
! 111: *astate = S_GROUND;
! 112: return (UNVIS_VALID);
! 113: case 't':
! 114: *cp = '\t';
! 115: *astate = S_GROUND;
! 116: return (UNVIS_VALID);
! 117: case 'f':
! 118: *cp = '\f';
! 119: *astate = S_GROUND;
! 120: return (UNVIS_VALID);
! 121: case 's':
! 122: *cp = ' ';
! 123: *astate = S_GROUND;
! 124: return (UNVIS_VALID);
! 125: case 'E':
! 126: *cp = '\033';
! 127: *astate = S_GROUND;
! 128: return (UNVIS_VALID);
! 129: case '\n':
! 130: /*
! 131: * hidden newline
! 132: */
! 133: *astate = S_GROUND;
! 134: return (UNVIS_NOCHAR);
! 135: case '$':
! 136: /*
! 137: * hidden marker
! 138: */
! 139: *astate = S_GROUND;
! 140: return (UNVIS_NOCHAR);
! 141: }
! 142: *astate = S_GROUND;
! 143: return (UNVIS_SYNBAD);
! 144:
! 145: case S_META:
! 146: if (c == '-')
! 147: *astate = S_META1;
! 148: else if (c == '^')
! 149: *astate = S_CTRL;
! 150: else {
! 151: *astate = S_GROUND;
! 152: return (UNVIS_SYNBAD);
! 153: }
! 154: return (0);
! 155:
! 156: case S_META1:
! 157: *astate = S_GROUND;
! 158: *cp |= c;
! 159: return (UNVIS_VALID);
! 160:
! 161: case S_CTRL:
! 162: if (c == '?')
! 163: *cp |= 0177;
! 164: else
! 165: *cp |= c & 037;
! 166: *astate = S_GROUND;
! 167: return (UNVIS_VALID);
! 168:
! 169: case S_OCTAL2: /* second possible octal digit */
! 170: if (isoctal(c)) {
! 171: /*
! 172: * yes - and maybe a third
! 173: */
! 174: *cp = (*cp << 3) + (c - '0');
! 175: *astate = S_OCTAL3;
! 176: return (0);
! 177: }
! 178: /*
! 179: * no - done with current sequence, push back passed char
! 180: */
! 181: *astate = S_GROUND;
! 182: return (UNVIS_VALIDPUSH);
! 183:
! 184: case S_OCTAL3: /* third possible octal digit */
! 185: *astate = S_GROUND;
! 186: if (isoctal(c)) {
! 187: *cp = (*cp << 3) + (c - '0');
! 188: return (UNVIS_VALID);
! 189: }
! 190: /*
! 191: * we were done, push back passed char
! 192: */
! 193: return (UNVIS_VALIDPUSH);
! 194:
! 195: default:
! 196: /*
! 197: * decoder in unknown state - (probably uninitialized)
! 198: */
! 199: *astate = S_GROUND;
! 200: return (UNVIS_SYNBAD);
! 201: }
! 202: }
! 203:
! 204: /*
! 205: * strunvis - decode src into dst
! 206: *
! 207: * Number of chars decoded into dst is returned, -1 on error.
! 208: * Dst is null terminated.
! 209: */
! 210:
! 211: int
! 212: strunvis(char *dst, const char *src)
! 213: {
! 214: char c;
! 215: char *start = dst;
! 216: int state = 0;
! 217:
! 218: while ((c = *src++)) {
! 219: again:
! 220: switch (unvis(dst, c, &state, 0)) {
! 221: case UNVIS_VALID:
! 222: dst++;
! 223: break;
! 224: case UNVIS_VALIDPUSH:
! 225: dst++;
! 226: goto again;
! 227: case 0:
! 228: case UNVIS_NOCHAR:
! 229: break;
! 230: default:
! 231: *dst = '\0';
! 232: return (-1);
! 233: }
! 234: }
! 235: if (unvis(dst, c, &state, UNVIS_END) == UNVIS_VALID)
! 236: dst++;
! 237: *dst = '\0';
! 238: return (dst - start);
! 239: }
! 240:
! 241: ssize_t
! 242: strnunvis(char *dst, const char *src, size_t sz)
! 243: {
! 244: char c, p;
! 245: char *start = dst, *end = dst + sz - 1;
! 246: int state = 0;
! 247:
! 248: if (sz > 0)
! 249: *end = '\0';
! 250: while ((c = *src++)) {
! 251: again:
! 252: switch (unvis(&p, c, &state, 0)) {
! 253: case UNVIS_VALID:
! 254: if (dst < end)
! 255: *dst = p;
! 256: dst++;
! 257: break;
! 258: case UNVIS_VALIDPUSH:
! 259: if (dst < end)
! 260: *dst = p;
! 261: dst++;
! 262: goto again;
! 263: case 0:
! 264: case UNVIS_NOCHAR:
! 265: break;
! 266: default:
! 267: if (dst <= end)
! 268: *dst = '\0';
! 269: return (-1);
! 270: }
! 271: }
! 272: if (unvis(&p, c, &state, UNVIS_END) == UNVIS_VALID) {
! 273: if (dst < end)
! 274: *dst = p;
! 275: dst++;
! 276: }
! 277: if (dst <= end)
! 278: *dst = '\0';
! 279: return (dst - start);
! 280: }
! 281:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>