source: trunk/third/moira/afssync/vis.c @ 24319

Revision 24319, 13.3 KB checked in by broder, 14 years ago (diff)
New Moira snapshot from SVN.
Line 
1/* $Id: vis.c 3956 2010-01-05 20:56:56Z zacheiss $
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 */
Note: See TracBrowser for help on using the repository browser.