Commit | Line | Data |
---|---|---|
9c260c06 MT |
1 | /* |
2 | * Copyright (c) 1989 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * Redistribution and use in source and binary forms are permitted | |
6 | * provided that the above copyright notice and this paragraph are | |
7 | * duplicated in all such forms and that any documentation, | |
8 | * advertising materials, and other materials related to such | |
9 | * distribution and use acknowledge that the software was developed | |
10 | * by the University of California, Berkeley. The name of the | |
11 | * University may not be used to endorse or promote products derived | |
12 | * from this software without specific prior written permission. | |
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
14 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
16 | */ | |
17 | ||
18 | #if defined(LIBC_SCCS) && !defined(lint) | |
19 | static char sccsid[] = "@(#)vis.c 5.1 (Berkeley) %G%"; | |
20 | #endif /* LIBC_SCCS and not lint */ | |
21 | ||
22 | #include <sys/types.h> | |
23 | #include <ctype.h> | |
24 | #include <cencode.h> | |
25 | ||
26 | #define iswhite(c) ((c)==' '||(c)=='\t'||(c)=='\n') | |
27 | #define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') | |
28 | ||
29 | /* | |
30 | * cencode | |
31 | */ | |
32 | ||
33 | /*VARARGS2*/ | |
34 | char * | |
35 | cencode(sc, flags, rachar) | |
36 | char sc, rachar; | |
37 | { | |
38 | static char buff[5]; | |
39 | register char *s = buff; | |
40 | register u_char c = sc; | |
41 | ||
42 | if (isgraph(c) || (!(flags&CENC_WHITE) && iswhite(c))) { | |
43 | if (c == '\\') | |
44 | *s++ = '\\'; | |
45 | *s++ = c; | |
46 | goto done; | |
47 | } | |
48 | *s++ = '\\'; | |
49 | if (flags&CENC_CSTYLE) { | |
50 | switch(c) { | |
51 | case '\n': | |
52 | *s++ = 'n'; | |
53 | goto done; | |
54 | case '\r': | |
55 | *s++ = 'r'; | |
56 | goto done; | |
57 | case '\b': | |
58 | *s++ = 'b'; | |
59 | goto done; | |
60 | case '\007': | |
61 | *s++ = 'a'; | |
62 | goto done; | |
63 | case '\v': | |
64 | *s++ = 'v'; | |
65 | goto done; | |
66 | case '\t': | |
67 | *s++ = 't'; | |
68 | goto done; | |
69 | case '\f': | |
70 | *s++ = 'f'; | |
71 | goto done; | |
72 | case ' ': | |
73 | *s++ = 's'; | |
74 | goto done; | |
75 | case '\0': | |
76 | *s++ = '0'; | |
77 | if (!(flags&CENC_RACHAR) || isoctal(rachar)) { | |
78 | *s++ = '0'; | |
79 | *s++ = '0'; | |
80 | } | |
81 | goto done; | |
82 | } | |
83 | } | |
84 | if ((flags&CENC_GRAPH) && (c&0177) != ' ') { | |
85 | if (c & 0200) { | |
86 | c &= 0177; | |
87 | *s++ = 'M'; | |
88 | } | |
89 | if (iscntrl(c)) { | |
90 | *s++ = '^'; | |
91 | if (c == 0177) | |
92 | *s++ = '?'; | |
93 | else | |
94 | *s++ = c + '@'; | |
95 | } else { | |
96 | *s++ = '-'; | |
97 | *s++ = c; | |
98 | } | |
99 | goto done; | |
100 | } | |
101 | if (flags&CENC_OCTAL) { | |
102 | if (flags&CENC_RACHAR && !isoctal(rachar)) | |
103 | (void)sprintf(s, "%o", (int)c); | |
104 | else | |
105 | (void)sprintf(s, "%03o", (int)c); | |
106 | while (*s++) | |
107 | ; | |
108 | goto done; | |
109 | } | |
110 | /* | |
111 | * Couldn't encode. | |
112 | */ | |
113 | s--; | |
114 | *s = c; | |
115 | done: | |
116 | *s = '\0'; | |
117 | return(buff); | |
118 | } | |
119 | ||
120 | /* | |
121 | * decode driven by state machine | |
122 | */ | |
123 | #define S_NORMAL 1 /* haven't seen escape char */ | |
124 | #define S_START 2 /* start decoding special sequence */ | |
125 | #define S_META 3 /* metachar started (M) */ | |
126 | #define S_META1 4 /* metachar more, regular char (-) */ | |
127 | #define S_CTRL 5 /* control char started (^) */ | |
128 | #define S_OCTAL 6 /* octal number */ | |
129 | ||
130 | /* | |
131 | * | |
132 | */ | |
133 | cdecode(c, cp, flags) | |
134 | char c; | |
135 | char *cp; | |
136 | { | |
137 | static int state = S_NORMAL; | |
138 | u_char buildchar; | |
139 | int octal; | |
140 | ||
141 | if (flags&CDEC_END) { | |
142 | int ostate = state; | |
143 | state = S_NORMAL; | |
144 | if (ostate == S_OCTAL) { | |
145 | *cp = buildchar; | |
146 | return(CDEC_OK); | |
147 | } else if (ostate == S_META1) { | |
148 | /* slightly forgiving, if not wrong */ | |
149 | *cp = ' ' | 0200; | |
150 | return(CDEC_OK); | |
151 | } else | |
152 | return(ostate == S_NORMAL ? CDEC_NOCHAR : CDEC_SYNBAD); | |
153 | } | |
154 | ||
155 | switch (state) { | |
156 | case S_NORMAL: | |
157 | buildchar = 0; | |
158 | if (c == '\\') { | |
159 | state = S_START; | |
160 | return(CDEC_NEEDMORE); | |
161 | } else if (flags&CDEC_HAT && c == '^') { | |
162 | state = S_CTRL; | |
163 | return(CDEC_NEEDMORE); | |
164 | } else { | |
165 | *cp = c; | |
166 | return(CDEC_OK); | |
167 | } | |
168 | break; | |
169 | case S_START: | |
170 | state = S_NORMAL; | |
171 | if (c == '\\') { | |
172 | *cp = c; | |
173 | return(CDEC_OK); | |
174 | } | |
175 | if (isoctal(c)) { | |
176 | buildchar = (c-'0'); | |
177 | octal = 1; | |
178 | state = S_OCTAL; | |
179 | return(CDEC_NEEDMORE); | |
180 | } | |
181 | switch(c) { | |
182 | case 'M': | |
183 | buildchar |= 0200; | |
184 | state = S_META; | |
185 | return(CDEC_NEEDMORE); | |
186 | case '^': | |
187 | state = S_CTRL; | |
188 | return(CDEC_NEEDMORE); | |
189 | case 'n': | |
190 | *cp = '\n'; | |
191 | return(CDEC_OK); | |
192 | case 'r': | |
193 | *cp = '\r'; | |
194 | return(CDEC_OK); | |
195 | case 'b': | |
196 | *cp = '\b'; | |
197 | return(CDEC_OK); | |
198 | case 'a': | |
199 | *cp = '\007'; | |
200 | return(CDEC_OK); | |
201 | case 'v': | |
202 | *cp = '\v'; | |
203 | return(CDEC_OK); | |
204 | case 't': | |
205 | *cp = '\t'; | |
206 | return(CDEC_OK); | |
207 | case 'f': | |
208 | *cp = '\f'; | |
209 | return(CDEC_OK); | |
210 | case 's': /* does anyone use this ? */ | |
211 | *cp = ' '; | |
212 | return(CDEC_OK); | |
213 | case 'E': | |
214 | *cp = '\033'; | |
215 | return(CDEC_OK); | |
216 | case '\n': | |
217 | return(CDEC_NOCHAR); /* hidden newline */ | |
218 | } | |
219 | state = S_NORMAL; | |
220 | return(CDEC_SYNBAD); | |
221 | case S_META: | |
222 | if (c == '-') | |
223 | state = S_META1; | |
224 | else if (c == '^') | |
225 | state = S_CTRL; | |
226 | else { | |
227 | state = S_NORMAL; | |
228 | return(CDEC_SYNBAD); | |
229 | } | |
230 | return(CDEC_NEEDMORE); | |
231 | case S_META1: | |
232 | state = S_NORMAL; | |
233 | *cp = c | buildchar; | |
234 | return(CDEC_OK); | |
235 | case S_CTRL: | |
236 | if (c == '?') | |
237 | buildchar |= 0177; | |
238 | else | |
239 | buildchar |= c&037; | |
240 | state = S_NORMAL; | |
241 | *cp = buildchar; | |
242 | return(CDEC_OK); | |
243 | case S_OCTAL: | |
244 | if (isoctal(c)) { | |
245 | buildchar = (buildchar<<3) + (c-'0'); | |
246 | if (++octal == 3) { | |
247 | state = S_NORMAL; | |
248 | *cp = buildchar; | |
249 | return(CDEC_OK); | |
250 | } else | |
251 | return(CDEC_NEEDMORE); | |
252 | } else { | |
253 | state = S_NORMAL; | |
254 | *cp = buildchar; | |
255 | return(CDEC_OKPUSH); | |
256 | } | |
257 | } | |
258 | } |