Annotation of embedaddon/tmux/compat/unvis.c, revision 1.1.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>