unvis.c revision 72445
172445Sassar/*	$NetBSD: unvis.c,v 1.19 2000/01/22 22:19:13 mycroft Exp $	*/
272445Sassar
372445Sassar/*-
472445Sassar * Copyright (c) 1989, 1993
572445Sassar *	The Regents of the University of California.  All rights reserved.
672445Sassar *
772445Sassar * Redistribution and use in source and binary forms, with or without
872445Sassar * modification, are permitted provided that the following conditions
972445Sassar * are met:
1072445Sassar * 1. Redistributions of source code must retain the above copyright
1172445Sassar *    notice, this list of conditions and the following disclaimer.
1272445Sassar * 2. Redistributions in binary form must reproduce the above copyright
1372445Sassar *    notice, this list of conditions and the following disclaimer in the
1472445Sassar *    documentation and/or other materials provided with the distribution.
1572445Sassar * 3. All advertising materials mentioning features or use of this software
1672445Sassar *    must display the following acknowledgement:
1772445Sassar *	This product includes software developed by the University of
1872445Sassar *	California, Berkeley and its contributors.
1972445Sassar * 4. Neither the name of the University nor the names of its contributors
2072445Sassar *    may be used to endorse or promote products derived from this software
2172445Sassar *    without specific prior written permission.
2272445Sassar *
2372445Sassar * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2472445Sassar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2572445Sassar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2672445Sassar * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2772445Sassar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2872445Sassar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2972445Sassar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3072445Sassar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3172445Sassar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3272445Sassar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3372445Sassar * SUCH DAMAGE.
3472445Sassar */
3572445Sassar
3672445Sassar#if 1
3772445Sassar#ifdef HAVE_CONFIG_H
3872445Sassar#include <config.h>
3972445SassarRCSID("$Id: unvis.c,v 1.2 2000/12/06 21:41:46 joda Exp $");
4072445Sassar#endif
4172445Sassar#include <roken.h>
4272445Sassar#ifndef _DIAGASSERT
4372445Sassar#define _DIAGASSERT(X)
4472445Sassar#endif
4572445Sassar#else
4672445Sassar#include <sys/cdefs.h>
4772445Sassar#if defined(LIBC_SCCS) && !defined(lint)
4872445Sassar#if 0
4972445Sassarstatic char sccsid[] = "@(#)unvis.c	8.1 (Berkeley) 6/4/93";
5072445Sassar#else
5172445Sassar__RCSID("$NetBSD: unvis.c,v 1.19 2000/01/22 22:19:13 mycroft Exp $");
5272445Sassar#endif
5372445Sassar#endif /* LIBC_SCCS and not lint */
5472445Sassar
5572445Sassar#define __LIBC12_SOURCE__
5672445Sassar
5772445Sassar#include "namespace.h"
5872445Sassar#endif
5972445Sassar#include <sys/types.h>
6072445Sassar
6172445Sassar#include <assert.h>
6272445Sassar#include <ctype.h>
6372445Sassar#include <stdio.h>
6472445Sassar#include <vis.h>
6572445Sassar
6672445Sassar#if 0
6772445Sassar#ifdef __weak_alias
6872445Sassar__weak_alias(strunvis,_strunvis)
6972445Sassar__weak_alias(unvis,_unvis)
7072445Sassar#endif
7172445Sassar
7272445Sassar__warn_references(unvis,
7372445Sassar    "warning: reference to compatibility unvis(); include <vis.h> for correct reference")
7472445Sassar#endif
7572445Sassar
7672445Sassar/*
7772445Sassar * decode driven by state machine
7872445Sassar */
7972445Sassar#define	S_GROUND	0	/* haven't seen escape char */
8072445Sassar#define	S_START		1	/* start decoding special sequence */
8172445Sassar#define	S_META		2	/* metachar started (M) */
8272445Sassar#define	S_META1		3	/* metachar more, regular char (-) */
8372445Sassar#define	S_CTRL		4	/* control char started (^) */
8472445Sassar#define	S_OCTAL2	5	/* octal digit 2 */
8572445Sassar#define	S_OCTAL3	6	/* octal digit 3 */
8672445Sassar
8772445Sassar#define	isoctal(c)	(((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
8872445Sassar
8972445Sassar/*
9072445Sassar * unvis - decode characters previously encoded by vis
9172445Sassar */
9272445Sassar#ifndef HAVE_UNVIS
9372445Sassarint
9472445Sassarunvis(char *cp, int c, int *astate, int flag)
9572445Sassar{
9672445Sassar
9772445Sassar	_DIAGASSERT(cp != NULL);
9872445Sassar	_DIAGASSERT(astate != NULL);
9972445Sassar
10072445Sassar	if (flag & UNVIS_END) {
10172445Sassar		if (*astate == S_OCTAL2 || *astate == S_OCTAL3) {
10272445Sassar			*astate = S_GROUND;
10372445Sassar			return (UNVIS_VALID);
10472445Sassar		}
10572445Sassar		return (*astate == S_GROUND ? UNVIS_NOCHAR : UNVIS_SYNBAD);
10672445Sassar	}
10772445Sassar
10872445Sassar	switch (*astate) {
10972445Sassar
11072445Sassar	case S_GROUND:
11172445Sassar		*cp = 0;
11272445Sassar		if (c == '\\') {
11372445Sassar			*astate = S_START;
11472445Sassar			return (0);
11572445Sassar		}
11672445Sassar		*cp = c;
11772445Sassar		return (UNVIS_VALID);
11872445Sassar
11972445Sassar	case S_START:
12072445Sassar		switch(c) {
12172445Sassar		case '\\':
12272445Sassar			*cp = c;
12372445Sassar			*astate = S_GROUND;
12472445Sassar			return (UNVIS_VALID);
12572445Sassar		case '0': case '1': case '2': case '3':
12672445Sassar		case '4': case '5': case '6': case '7':
12772445Sassar			*cp = (c - '0');
12872445Sassar			*astate = S_OCTAL2;
12972445Sassar			return (0);
13072445Sassar		case 'M':
13172445Sassar			*cp = (char)0200;
13272445Sassar			*astate = S_META;
13372445Sassar			return (0);
13472445Sassar		case '^':
13572445Sassar			*astate = S_CTRL;
13672445Sassar			return (0);
13772445Sassar		case 'n':
13872445Sassar			*cp = '\n';
13972445Sassar			*astate = S_GROUND;
14072445Sassar			return (UNVIS_VALID);
14172445Sassar		case 'r':
14272445Sassar			*cp = '\r';
14372445Sassar			*astate = S_GROUND;
14472445Sassar			return (UNVIS_VALID);
14572445Sassar		case 'b':
14672445Sassar			*cp = '\b';
14772445Sassar			*astate = S_GROUND;
14872445Sassar			return (UNVIS_VALID);
14972445Sassar		case 'a':
15072445Sassar			*cp = '\007';
15172445Sassar			*astate = S_GROUND;
15272445Sassar			return (UNVIS_VALID);
15372445Sassar		case 'v':
15472445Sassar			*cp = '\v';
15572445Sassar			*astate = S_GROUND;
15672445Sassar			return (UNVIS_VALID);
15772445Sassar		case 't':
15872445Sassar			*cp = '\t';
15972445Sassar			*astate = S_GROUND;
16072445Sassar			return (UNVIS_VALID);
16172445Sassar		case 'f':
16272445Sassar			*cp = '\f';
16372445Sassar			*astate = S_GROUND;
16472445Sassar			return (UNVIS_VALID);
16572445Sassar		case 's':
16672445Sassar			*cp = ' ';
16772445Sassar			*astate = S_GROUND;
16872445Sassar			return (UNVIS_VALID);
16972445Sassar		case 'E':
17072445Sassar			*cp = '\033';
17172445Sassar			*astate = S_GROUND;
17272445Sassar			return (UNVIS_VALID);
17372445Sassar		case '\n':
17472445Sassar			/*
17572445Sassar			 * hidden newline
17672445Sassar			 */
17772445Sassar			*astate = S_GROUND;
17872445Sassar			return (UNVIS_NOCHAR);
17972445Sassar		case '$':
18072445Sassar			/*
18172445Sassar			 * hidden marker
18272445Sassar			 */
18372445Sassar			*astate = S_GROUND;
18472445Sassar			return (UNVIS_NOCHAR);
18572445Sassar		}
18672445Sassar		*astate = S_GROUND;
18772445Sassar		return (UNVIS_SYNBAD);
18872445Sassar
18972445Sassar	case S_META:
19072445Sassar		if (c == '-')
19172445Sassar			*astate = S_META1;
19272445Sassar		else if (c == '^')
19372445Sassar			*astate = S_CTRL;
19472445Sassar		else {
19572445Sassar			*astate = S_GROUND;
19672445Sassar			return (UNVIS_SYNBAD);
19772445Sassar		}
19872445Sassar		return (0);
19972445Sassar
20072445Sassar	case S_META1:
20172445Sassar		*astate = S_GROUND;
20272445Sassar		*cp |= c;
20372445Sassar		return (UNVIS_VALID);
20472445Sassar
20572445Sassar	case S_CTRL:
20672445Sassar		if (c == '?')
20772445Sassar			*cp |= 0177;
20872445Sassar		else
20972445Sassar			*cp |= c & 037;
21072445Sassar		*astate = S_GROUND;
21172445Sassar		return (UNVIS_VALID);
21272445Sassar
21372445Sassar	case S_OCTAL2:	/* second possible octal digit */
21472445Sassar		if (isoctal(c)) {
21572445Sassar			/*
21672445Sassar			 * yes - and maybe a third
21772445Sassar			 */
21872445Sassar			*cp = (*cp << 3) + (c - '0');
21972445Sassar			*astate = S_OCTAL3;
22072445Sassar			return (0);
22172445Sassar		}
22272445Sassar		/*
22372445Sassar		 * no - done with current sequence, push back passed char
22472445Sassar		 */
22572445Sassar		*astate = S_GROUND;
22672445Sassar		return (UNVIS_VALIDPUSH);
22772445Sassar
22872445Sassar	case S_OCTAL3:	/* third possible octal digit */
22972445Sassar		*astate = S_GROUND;
23072445Sassar		if (isoctal(c)) {
23172445Sassar			*cp = (*cp << 3) + (c - '0');
23272445Sassar			return (UNVIS_VALID);
23372445Sassar		}
23472445Sassar		/*
23572445Sassar		 * we were done, push back passed char
23672445Sassar		 */
23772445Sassar		return (UNVIS_VALIDPUSH);
23872445Sassar
23972445Sassar	default:
24072445Sassar		/*
24172445Sassar		 * decoder in unknown state - (probably uninitialized)
24272445Sassar		 */
24372445Sassar		*astate = S_GROUND;
24472445Sassar		return (UNVIS_SYNBAD);
24572445Sassar	}
24672445Sassar}
24772445Sassar#endif
24872445Sassar
24972445Sassar/*
25072445Sassar * strunvis - decode src into dst
25172445Sassar *
25272445Sassar *	Number of chars decoded into dst is returned, -1 on error.
25372445Sassar *	Dst is null terminated.
25472445Sassar */
25572445Sassar
25672445Sassar#ifndef HAVE_STRUNVIS
25772445Sassarint
25872445Sassarstrunvis(char *dst, const char *src)
25972445Sassar{
26072445Sassar	char c;
26172445Sassar	char *start = dst;
26272445Sassar	int state = 0;
26372445Sassar
26472445Sassar	_DIAGASSERT(src != NULL);
26572445Sassar	_DIAGASSERT(dst != NULL);
26672445Sassar
26772445Sassar	while ((c = *src++) != '\0') {
26872445Sassar	again:
26972445Sassar		switch (unvis(dst, c, &state, 0)) {
27072445Sassar		case UNVIS_VALID:
27172445Sassar			dst++;
27272445Sassar			break;
27372445Sassar		case UNVIS_VALIDPUSH:
27472445Sassar			dst++;
27572445Sassar			goto again;
27672445Sassar		case 0:
27772445Sassar		case UNVIS_NOCHAR:
27872445Sassar			break;
27972445Sassar		default:
28072445Sassar			return (-1);
28172445Sassar		}
28272445Sassar	}
28372445Sassar	if (unvis(dst, c, &state, UNVIS_END) == UNVIS_VALID)
28472445Sassar		dst++;
28572445Sassar	*dst = '\0';
28672445Sassar	return (dst - start);
28772445Sassar}
28872445Sassar#endif
289