]> andersk Git - moira.git/blame - afssync/vis.c
Command line printer manipulation client, and build goo.
[moira.git] / afssync / vis.c
CommitLineData
302d677f 1/* $Id$
2 * vis functions - visually encode characters
3 * Originally from OpenBSD
4 */
5
6/*-
7 * Copyright (c) 1989, 1993
8 * The Regents of the University of California. All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38
39#ifndef HAVE_STRVIS
40#include "vis.h"
41/*
42 * vis - visually encode characters
43 */
44char *
45vis(dst, c, flag, nextc)
46 register char *dst;
47 int c, nextc;
48 register int flag;
49{
50 if (isvisible(c)) {
51 *dst++ = c;
52 if (c == '\\' && (flag & VIS_NOSLASH) == 0)
53 *dst++ = '\\';
54 *dst = '\0';
55 return (dst);
56 }
57
58 if (flag & VIS_CSTYLE) {
59 switch(c) {
60 case '\n':
61 *dst++ = '\\';
62 *dst++ = 'n';
63 goto done;
64 case '\r':
65 *dst++ = '\\';
66 *dst++ = 'r';
67 goto done;
68 case '\b':
69 *dst++ = '\\';
70 *dst++ = 'b';
71 goto done;
72#ifdef __STDC__
73 case '\a':
74#else
75 case '\007':
76#endif
77 *dst++ = '\\';
78 *dst++ = 'a';
79 goto done;
80 case '\v':
81 *dst++ = '\\';
82 *dst++ = 'v';
83 goto done;
84 case '\t':
85 *dst++ = '\\';
86 *dst++ = 't';
87 goto done;
88 case '\f':
89 *dst++ = '\\';
90 *dst++ = 'f';
91 goto done;
92 case ' ':
93 *dst++ = '\\';
94 *dst++ = 's';
95 goto done;
96 case '\0':
97 *dst++ = '\\';
98 *dst++ = '0';
99 if (isoctal(nextc)) {
100 *dst++ = '0';
101 *dst++ = '0';
102 }
103 goto done;
104 }
105 }
106 if (((c & 0177) == ' ') || (flag & VIS_OCTAL)) {
107 *dst++ = '\\';
108 *dst++ = ((u_char)c >> 6 & 07) + '0';
109 *dst++ = ((u_char)c >> 3 & 07) + '0';
110 *dst++ = ((u_char)c & 07) + '0';
111 goto done;
112 }
113 if ((flag & VIS_NOSLASH) == 0)
114 *dst++ = '\\';
115 if (c & 0200) {
116 c &= 0177;
117 *dst++ = 'M';
118 }
119 if (iscntrl(c)) {
120 *dst++ = '^';
121 if (c == 0177)
122 *dst++ = '?';
123 else
124 *dst++ = c + '@';
125 } else {
126 *dst++ = '-';
127 *dst++ = c;
128 }
129done:
130 *dst = '\0';
131 return (dst);
132}
133
134/*
135 * strvis, strnvis, strvisx - visually encode characters from src into dst
136 *
137 * Dst must be 4 times the size of src to account for possible
138 * expansion. The length of dst, not including the trailing NULL,
139 * is returned.
140 *
141 * Strnvis will write no more than siz-1 bytes (and will NULL terminate).
142 * The number of bytes needed to fully encode the string is returned.
143 *
144 * Strvisx encodes exactly len bytes from src into dst.
145 * This is useful for encoding a block of data.
146 */
147int
148strvis(dst, src, flag)
149 register char *dst;
150 register const char *src;
151 int flag;
152{
153 register char c;
154 char *start;
155
156 for (start = dst; (c = *src);)
157 dst = vis(dst, c, flag, *++src);
158 *dst = '\0';
159 return (dst - start);
160}
161
162int
163strnvis(dst, src, siz, flag)
164 register char *dst;
165 register const char *src;
166 size_t siz;
167 int flag;
168{
169 register char c;
170 char *start, *end;
171
172 for (start = dst, end = start + siz - 1; (c = *src) && dst < end; ) {
173 if (isvisible(c)) {
174 *dst++ = c;
175 if (c == '\\' && (flag & VIS_NOSLASH) == 0) {
176 /* need space for the extra '\\' */
177 if (dst < end)
178 *dst++ = '\\';
179 else {
180 dst--;
181 break;
182 }
183 }
184 src++;
185 } else {
186 /* vis(3) requires up to 4 chars */
187 if (dst + 3 < end)
188 dst = vis(dst, c, flag, *++src);
189 else
190 break;
191 }
192 }
193 *dst = '\0';
194 if (dst >= end) {
195 char tbuf[5];
196
197 /* adjust return value for truncation */
198 while ((c = *src))
199 dst += vis(tbuf, c, flag, *++src) - tbuf;
200 }
201 return (dst - start);
202}
203
204int
205strvisx(dst, src, len, flag)
206 register char *dst;
207 register const char *src;
208 register size_t len;
209 int flag;
210{
211 register char c;
212 char *start;
213
214 for (start = dst; len > 1; len--) {
215 c = *src;
216 dst = vis(dst, c, flag, *++src);
217 }
218 if (len)
219 dst = vis(dst, *src, flag, '\0');
220 *dst = '\0';
221 return (dst - start);
222}
223
224/*
225 * unvis - decode characters previously encoded by vis
226 */
227int
228#ifdef __STDC__
229unvis(char *cp, char c, int *astate, int flag)
230#else
231unvis(cp, c, astate, flag)
232 char *cp;
233 char c;
234 int *astate, flag;
235#endif
236{
237
238 if (flag & UNVIS_END) {
239 if (*astate == S_OCTAL2 || *astate == S_OCTAL3) {
240 *astate = S_GROUND;
241 return (UNVIS_VALID);
242 }
243 return (*astate == S_GROUND ? UNVIS_NOCHAR : UNVIS_SYNBAD);
244 }
245
246 switch (*astate) {
247
248 case S_GROUND:
249 *cp = 0;
250 if (c == '\\') {
251 *astate = S_START;
252 return (0);
253 }
254 *cp = c;
255 return (UNVIS_VALID);
256
257 case S_START:
258 switch(c) {
259 case '\\':
260 *cp = c;
261 *astate = S_GROUND;
262 return (UNVIS_VALID);
263 case '0': case '1': case '2': case '3':
264 case '4': case '5': case '6': case '7':
265 *cp = (c - '0');
266 *astate = S_OCTAL2;
267 return (0);
268 case 'M':
269 *cp = (char) 0200;
270 *astate = S_META;
271 return (0);
272 case '^':
273 *astate = S_CTRL;
274 return (0);
275 case 'n':
276 *cp = '\n';
277 *astate = S_GROUND;
278 return (UNVIS_VALID);
279 case 'r':
280 *cp = '\r';
281 *astate = S_GROUND;
282 return (UNVIS_VALID);
283 case 'b':
284 *cp = '\b';
285 *astate = S_GROUND;
286 return (UNVIS_VALID);
287 case 'a':
288 *cp = '\007';
289 *astate = S_GROUND;
290 return (UNVIS_VALID);
291 case 'v':
292 *cp = '\v';
293 *astate = S_GROUND;
294 return (UNVIS_VALID);
295 case 't':
296 *cp = '\t';
297 *astate = S_GROUND;
298 return (UNVIS_VALID);
299 case 'f':
300 *cp = '\f';
301 *astate = S_GROUND;
302 return (UNVIS_VALID);
303 case 's':
304 *cp = ' ';
305 *astate = S_GROUND;
306 return (UNVIS_VALID);
307 case 'E':
308 *cp = '\033';
309 *astate = S_GROUND;
310 return (UNVIS_VALID);
311 case '\n':
312 /*
313 * hidden newline
314 */
315 *astate = S_GROUND;
316 return (UNVIS_NOCHAR);
317 case '$':
318 /*
319 * hidden marker
320 */
321 *astate = S_GROUND;
322 return (UNVIS_NOCHAR);
323 }
324 *astate = S_GROUND;
325 return (UNVIS_SYNBAD);
326
327 case S_META:
328 if (c == '-')
329 *astate = S_META1;
330 else if (c == '^')
331 *astate = S_CTRL;
332 else {
333 *astate = S_GROUND;
334 return (UNVIS_SYNBAD);
335 }
336 return (0);
337
338 case S_META1:
339 *astate = S_GROUND;
340 *cp |= c;
341 return (UNVIS_VALID);
342
343 case S_CTRL:
344 if (c == '?')
345 *cp |= 0177;
346 else
347 *cp |= c & 037;
348 *astate = S_GROUND;
349 return (UNVIS_VALID);
350
351 case S_OCTAL2: /* second possible octal digit */
352 if (isoctal(c)) {
353 /*
354 * yes - and maybe a third
355 */
356 *cp = (*cp << 3) + (c - '0');
357 *astate = S_OCTAL3;
358 return (0);
359 }
360 /*
361 * no - done with current sequence, push back passed char
362 */
363 *astate = S_GROUND;
364 return (UNVIS_VALIDPUSH);
365
366 case S_OCTAL3: /* third possible octal digit */
367 *astate = S_GROUND;
368 if (isoctal(c)) {
369 *cp = (*cp << 3) + (c - '0');
370 return (UNVIS_VALID);
371 }
372 /*
373 * we were done, push back passed char
374 */
375 return (UNVIS_VALIDPUSH);
376
377 default:
378 /*
379 * decoder in unknown state - (probably uninitialized)
380 */
381 *astate = S_GROUND;
382 return (UNVIS_SYNBAD);
383 }
384}
385
386/*
387 * strunvis - decode src into dst
388 *
389 * Number of chars decoded into dst is returned, -1 on error.
390 * Dst is null terminated.
391 */
392
393int
394strunvis(dst, src)
395 register char *dst;
396 register const char *src;
397{
398 register char c;
399 char *start = dst;
400 int state = 0;
401
402 while ((c = *src++)) {
403 again:
404 switch (unvis(dst, c, &state, 0)) {
405 case UNVIS_VALID:
406 dst++;
407 break;
408 case UNVIS_VALIDPUSH:
409 dst++;
410 goto again;
411 case 0:
412 case UNVIS_NOCHAR:
413 break;
414 default:
415 return (-1);
416 }
417 }
418 if (unvis(dst, c, &state, UNVIS_END) == UNVIS_VALID)
419 dst++;
420 *dst = '\0';
421 return (dst - start);
422}
423
424#endif /* HAVE_STRVIS */
This page took 0.13204 seconds and 5 git commands to generate.