xref: /original-bsd/usr.bin/vis/vis.c (revision 5e1b3b90)
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 #ifndef lint
19 char copyright[] =
20 "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
21  All rights reserved.\n";
22 #endif /* not lint */
23 
24 #ifndef lint
25 static char sccsid[] = "@(#)vis.c	1.1 (Berkeley) 05/15/90";
26 #endif /* not lint */
27 
28 #include <stdio.h>
29 #include <cencode.h>
30 
31 int eflags, dflags, invert, strip, fold, foldwidth=80, none;
32 
33 main(argc, argv)
34 	char *argv[];
35 {
36 	extern char *optarg;
37 	extern int optind;
38 	extern int errno;
39 	FILE *fp;
40 	int ch;
41 
42 	while ((ch = getopt(argc, argv, "nwcgovishfF:")) != EOF)
43 		switch((char)ch) {
44 		case 'n':
45 			none++;
46 			break;
47 		case 'w':
48 			eflags |= CENC_WHITE;
49 			break;
50 		case 'c':
51 			eflags |= CENC_CSTYLE;
52 			break;
53 		case 'g':
54 			eflags |= CENC_GRAPH;
55 			break;
56 		case 'o':
57 			eflags |= CENC_OCTAL;
58 			break;
59 		case 'v':	/* vis -v considered harmful */
60 			eflags |= CENC_GRAPH | CENC_OCTAL;
61 			break;
62 		case 'i':
63 			invert++;
64 			break;
65 		case 'F':
66 			if ((foldwidth = atoi(optarg))<5) {
67 				fprintf(stderr,
68 				 "vis: can't fold lines to less than 2 cols\n");
69 				exit(1);
70 			}
71 			/*FALLTHROUGH*/
72 		case 'f':
73 			fold++;		/* fold output lines to 80 cols */
74 			break;		/* using hidden newline */
75 		case 's':
76 			strip++;
77 			break;
78 		case 'h':
79 			dflags |= CDEC_HAT;
80 			break;
81 		case '?':
82 		default:
83 			fprintf(stderr,
84 		"usage: vis [-nwcgovifsh] [-F foldwidth]\n");
85 			exit(1);
86 		}
87 	argc -= optind;
88 	argv += optind;
89 
90 #define ALL	(CENC_CSTYLE | CENC_GRAPH | CENC_OCTAL)
91 	if (none)
92 		eflags &= ~ALL;
93 	else if (!(eflags&ALL))
94 		eflags |= ALL;
95 	if (*argv)
96 		while (*argv) {
97 			if ((fp=fopen(*argv, "r")) != NULL)
98 				process(fp, *argv);
99 			else
100 				fprintf(stderr, "vis: %s: %s\n", *argv,
101 				    (char *)strerror(errno));
102 			argv++;
103 		}
104 	else
105 		process(stdin, "<stdin>");
106 	exit(0);
107 }
108 
109 process(fp, filename)
110 	FILE *fp;
111 	char *filename;
112 {
113 	static int col = 0;
114 	register char *cp = "X"+1;	/* so *(cp-1) starts out != '\n' */
115 	register int byte = 0;
116 	register int c, rachar;
117 	register char nc;
118 
119 	/*
120 	 * Encode
121 	 */
122 	if (!invert) {
123 		c = getc(fp);
124 		while (c != EOF) {
125 			rachar = getc(fp);
126 			if (strip)
127 				c &= 0177;
128 			cp = cencode((char)c, eflags|CENC_RACHAR, (char)rachar);
129 			if (fold) {
130 				/*
131 				 * Keep track of printables and
132 				 * space chars (like fold(1)).
133 				 */
134 				for (;;) {
135 					switch(*cp) {
136 					case '\n':
137 					case '\r':
138 						col = 0;
139 						break;
140 					case '\t':
141 						col = col + 8 &~ 07;
142 						break;
143 					case '\b':
144 						col = col ? col - 1 : 0;
145 						break;
146 					default:
147 						col += strlen(cp);
148 					}
149 					if (col > (foldwidth-2)) {
150 						printf("\\\n");
151 						col = 0;
152 					} else
153 						break;
154 				}
155 			}
156 			do {
157 				putchar(*cp++);
158 			} while (*cp);
159 			c = rachar;
160 		}
161 		if (fold && *(cp-1) != '\n')
162 			printf("\\\n");
163 	/*
164 	 * Decode
165 	 */
166 	} else {
167 		while ((c = getc(fp)) != EOF) {
168 			byte++;
169 		again:
170 			switch(cdecode((char)c, &nc, dflags)) {
171 			case CDEC_NEEDMORE:
172 			case CDEC_NOCHAR:
173 				break;
174 			case CDEC_OK:
175 				putchar(nc);
176 				break;
177 			case CDEC_OKPUSH:
178 				putchar(nc);
179 				goto again;
180 			case CDEC_SYNBAD:
181 				fprintf(stderr,
182 				    "vis: %s: offset: %d: can't decode\n",
183 				    filename, byte);
184 				break;
185 			default:
186 				fprintf(stderr,
187 				    "vis: bad return value (can't happen)\n");
188 				exit(1);
189 			}
190 		}
191 		if (cdecode((char)0, &nc, CDEC_END) == CDEC_OK)
192 			putchar(nc);
193 	}
194 	exit(0);
195 }
196