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