TIOCGPGRP copies an int out of the kernel
[unix-history] / usr / src / lib / libc / gen / unvis.c
CommitLineData
d6a13ceb 1/*-
1af61e06
MT
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
d6a13ceb 5 * %sccs.include.redist.c%
1af61e06
MT
6 */
7
8#if defined(LIBC_SCCS) && !defined(lint)
c5980113 9static char sccsid[] = "@(#)unvis.c 1.4 (Berkeley) %G%";
1af61e06
MT
10#endif /* LIBC_SCCS and not lint */
11
12#include <sys/types.h>
13#include <ctype.h>
14#include <vis.h>
15
16/*
17 * decode driven by state machine
18 */
19#define S_GROUND 0 /* haven't seen escape char */
20#define S_START 1 /* start decoding special sequence */
21#define S_META 2 /* metachar started (M) */
22#define S_META1 3 /* metachar more, regular char (-) */
23#define S_CTRL 4 /* control char started (^) */
24#define S_OCTAL2 5 /* octal digit 2 */
25#define S_OCTAL3 6 /* octal digit 3 */
26
d6a13ceb
MT
27#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
28
1af61e06
MT
29/*
30 * unvis - decode characters previously encoded by vis
31 */
c5980113
DS
32int
33#if __STDC__
34unvis(char *cp, char c, int *astate, int flag)
35#else
1af61e06 36unvis(cp, c, astate, flag)
c5980113 37 char *cp, c;
1af61e06 38 int *astate, flag;
c5980113 39#endif
1af61e06
MT
40{
41
42 if (flag & UNVIS_END) {
43 if (*astate == S_OCTAL2 || *astate == S_OCTAL3) {
44 *astate = S_GROUND;
45 return (UNVIS_VALID);
46 }
47 return (*astate == S_GROUND ? UNVIS_NOCHAR : UNVIS_SYNBAD);
48 }
49
50 switch (*astate) {
51
52 case S_GROUND:
53 *cp = 0;
54 if (c == '\\') {
55 *astate = S_START;
56 return (0);
57 }
58 *cp = c;
59 return (UNVIS_VALID);
60
61 case S_START:
62 switch(c) {
63 case '\\':
64 *cp = c;
65 *astate = S_GROUND;
66 return (UNVIS_VALID);
67 case '0': case '1': case '2': case '3':
68 case '4': case '5': case '6': case '7':
69 *cp = (c - '0');
70 *astate = S_OCTAL2;
71 return (0);
72 case 'M':
73 *cp = 0200;
74 *astate = S_META;
75 return (0);
76 case '^':
77 *astate = S_CTRL;
78 return (0);
79 case 'n':
80 *cp = '\n';
81 *astate = S_GROUND;
82 return (UNVIS_VALID);
83 case 'r':
84 *cp = '\r';
85 *astate = S_GROUND;
86 return (UNVIS_VALID);
87 case 'b':
88 *cp = '\b';
89 *astate = S_GROUND;
90 return (UNVIS_VALID);
91 case 'a':
92 *cp = '\007';
93 *astate = S_GROUND;
94 return (UNVIS_VALID);
95 case 'v':
96 *cp = '\v';
97 *astate = S_GROUND;
98 return (UNVIS_VALID);
99 case 't':
100 *cp = '\t';
101 *astate = S_GROUND;
102 return (UNVIS_VALID);
103 case 'f':
104 *cp = '\f';
105 *astate = S_GROUND;
106 return (UNVIS_VALID);
107 case 's':
108 *cp = ' ';
109 *astate = S_GROUND;
110 return (UNVIS_VALID);
111 case 'E':
112 *cp = '\033';
113 *astate = S_GROUND;
114 return (UNVIS_VALID);
115 case '\n':
116 /*
117 * hidden newline
118 */
119 *astate = S_GROUND;
120 return (UNVIS_NOCHAR);
d6a13ceb
MT
121 case '$':
122 /*
123 * hidden marker
124 */
125 *astate = S_GROUND;
126 return (UNVIS_NOCHAR);
1af61e06
MT
127 }
128 *astate = S_GROUND;
129 return (UNVIS_SYNBAD);
130
131 case S_META:
132 if (c == '-')
133 *astate = S_META1;
134 else if (c == '^')
135 *astate = S_CTRL;
136 else {
137 *astate = S_GROUND;
138 return (UNVIS_SYNBAD);
139 }
140 return (0);
141
142 case S_META1:
143 *astate = S_GROUND;
144 *cp |= c;
145 return (UNVIS_VALID);
146
147 case S_CTRL:
148 if (c == '?')
149 *cp |= 0177;
150 else
151 *cp |= c & 037;
152 *astate = S_GROUND;
153 return (UNVIS_VALID);
154
155 case S_OCTAL2: /* second possible octal digit */
156 if (isoctal(c)) {
157 /*
158 * yes - and maybe a third
159 */
160 *cp = (*cp << 3) + (c - '0');
161 *astate = S_OCTAL3;
162 return (0);
163 }
164 /*
165 * no - done with current sequence, push back passed char
166 */
167 *astate = S_GROUND;
168 return (UNVIS_VALIDPUSH);
169
170 case S_OCTAL3: /* third possible octal digit */
171 *astate = S_GROUND;
172 if (isoctal(c)) {
173 *cp = (*cp << 3) + (c - '0');
174 return (UNVIS_VALID);
175 }
176 /*
177 * we were done, push back passed char
178 */
179 return (UNVIS_VALIDPUSH);
180
181 default:
182 /*
183 * decoder in unknown state - (probably uninitialized)
184 */
2e93102d
MT
185 *astate = S_GROUND;
186 return (UNVIS_SYNBAD);
1af61e06
MT
187 }
188}
189
190/*
d6a13ceb 191 * strunvis - decode src into dst
1af61e06 192 *
d6a13ceb
MT
193 * Number of chars decoded into dst is returned, -1 on error.
194 * Dst is null terminated.
1af61e06 195 */
d6a13ceb 196
c5980113 197int
d6a13ceb 198strunvis(dst, src)
c5980113
DS
199 register char *dst;
200 register const char *src;
1af61e06 201{
d6a13ceb 202 register char c;
1af61e06 203 char *start = dst;
2e93102d 204 int state = 0;
1af61e06 205
d6a13ceb
MT
206 while (c = *src++) {
207 again:
208 switch (unvis(dst, c, &state, 0)) {
209 case UNVIS_VALID:
210 dst++;
1af61e06 211 break;
d6a13ceb
MT
212 case UNVIS_VALIDPUSH:
213 dst++;
214 goto again;
215 case 0:
216 case UNVIS_NOCHAR:
217 break;
218 default:
219 return (-1);
220 }
1af61e06 221 }
2e93102d
MT
222 if (unvis(dst, c, &state, UNVIS_END) == UNVIS_VALID)
223 dst++;
d6a13ceb 224 *dst = '\0';
1af61e06
MT
225 return (dst - start);
226}