xref: /original-bsd/usr.bin/ul/ul.c (revision d25e1985)
1 static char *sccsid = "@(#)ul.c	4.1 (Berkeley) 10/01/80";
2 /*
3  * ul
4  */
5 #include <stdio.h>
6 
7 char	buf[BUFSIZ];
8 char	isul[BUFSIZ];
9 char	termcap[1024];
10 char	ulbuf[BUFSIZ];
11 char	*stul, *endul, *chul;
12 char	*backspace;
13 char	*termtype;
14 int	outc();
15 char	*tgetstr();
16 char	*getenv();
17 
18 main(argc, argv)
19 	int argc;
20 	char **argv;
21 {
22 	register int i;
23 	char *cp;
24 	FILE *f;
25 
26 	argc--, argv++;
27 	termtype = getenv("TERM");
28 	if (termtype == NULL)
29 		termtype = "dumb";
30 	while (argc > 0 && argv[0][0] == '-') {
31 		switch(argv[0][1]) {
32 
33 		case 't':
34 		case 'T': /* for nroff compatibility */
35 			if (argv[0][2])
36 				termtype = &argv[0][2];
37 			else {
38 				termtype = argv[1];
39 				argc--;
40 				argv++;
41 			}
42 			break;
43 		case 'i':
44 			argc--, argv++;
45 			iul(argc, argv);
46 			exit(0);
47 
48 		default:
49 			printf("Usage: ul [ -i ] [ -tTerm ] file...\n");
50 			exit(1);
51 		}
52 	}
53 	switch(tgetent(termcap, termtype)) {
54 
55 	case 1:
56 		if (tgetflag("os"))
57 			execv("/bin/cat",argv);
58 		cp = ulbuf;
59 		if ((backspace = tgetstr("bc",&cp)) == NULL)
60 			backspace = "\b";
61 		/*
62 		 * Handle terminals that have start underline/stop
63 		 * underline sequences, as well as those with
64 		 * underline char sequences (we assume the sequence
65 		 * moves the cursor forward one character).
66 		 * If we can't find underline sequences, we
67 		 * settle for standout sequences.
68 		 */
69 		if ((chul=tgetstr("uc",&cp)) == NULL)
70 			chul = "";
71 		if ((stul=tgetstr("us",&cp)) == NULL && !tgetflag("ul") &&
72 		    (!*chul) && (stul=tgetstr("so",&cp)) == NULL)
73 			stul = "";
74 		if ((endul=tgetstr("ue",&cp)) == NULL && !tgetflag("ul") &&
75 		    (!*chul) && (endul=tgetstr("se",&cp)) == NULL)
76 			endul = "";
77 		if (chul==0&&stul==0&&endul==0&&tgetflag("ul"))
78 			execv("/bin/cat",argv);
79 		break;
80 
81 	default:
82 		fprintf(stderr,"trouble reading termcap");
83 		/* fall through to ... */
84 
85 	case 0:
86 		/* No such terminal type - assume dumb */
87 		stul = endul = chul = "";
88 		break;
89 	}
90 	if (argc == 0)
91 		filter(stdin);
92 	else for (i=0; i<argc; i++) {
93 		f = fopen(argv[i],"r");
94 		if (f == NULL) {
95 			perror(argv[i]);
96 			exit(1);
97 		} else
98 			filter(f);
99 	}
100 	exit(0);
101 }
102 
103 filter(f)
104 FILE *f;
105 {
106 	register int p, n;
107 	register char c;
108 	int state;
109 
110 	n = 0;
111 	for (;;) {
112 		p = 0;
113 		for (p=0; p<n; p++) {
114 			buf[p] = '\0';
115 			isul[p] = 0;
116 		}
117 		p = n = 0;
118 
119 		for (;;) {
120 			c = getc(f);
121 			if (c==EOF)
122 				break;
123 			if (c=='\b') {
124 				if (p > 0) {
125 					p--;
126 				}
127 			} else if (c=='_' && isul[p]==0 && buf[p]) {
128 				isul[p] = 1;
129 				p++;
130 			} else {
131 				if (buf[p] == '_')
132 					isul[p] = 1;
133 				buf[p] = c;
134 				p++;
135 				if (n < p)
136 					n = p;
137 			}
138 			if (c=='\n')
139 				break;
140 		}
141 
142 		state = 0;
143 		for (p=0; p<n; p++) {
144 			if (isul[p] != state)
145 				tputs(isul[p] ? stul : endul, 1, outc);
146 			state = isul[p];
147 			putchar(buf[p]);
148 			if (isul[p] && *chul) {
149 				printf("%s",backspace);
150 				tputs(chul, 1, outc);
151 			}
152 		}
153 		if (c==EOF) break;
154 	}
155 }
156 
157 outc(c)
158 char c;
159 {
160 	putchar(c);
161 }
162 
163 #define BACKSPACE 0
164 #define	QUOTE	0200
165 
166 char	linebuf[BUFSIZ], genbuf[BUFSIZ];
167 char	*strcpy();
168 
169 iul(argc, argv)
170 	int argc;
171 	char *argv[];
172 {
173 	register c;
174 	register char *lp;
175 
176 	do {
177 		if (argc > 0) {
178 			if (freopen(argv[0], "r", stdin) == NULL) {
179 				perror(argv[0]);
180 				exit(1);
181 			}
182 			argc--; argv++;
183 		}
184 		while (fgets(linebuf, sizeof linebuf, stdin) != 0) {
185 			for (lp = linebuf; *lp; lp++)
186 				continue;
187 			*--lp = 0;
188 			doulg();
189 			dographic();
190 			if (genbuf[0])
191 				printf("\n%s", genbuf);
192 			putchar('\n');
193 			fflush(stdout);
194 		}
195 	} while (argc > 0);
196 	exit(0);
197 }
198 
199 dographic()
200 {
201 	register char *lp;
202 	register c;
203 
204 	for (lp = linebuf; c = *lp++;) {
205 		switch (c) {
206 			case '\b':
207 				if (BACKSPACE == 0)
208 					c = '?';
209 				break;
210 			default:
211 				if (c < ' ' || c == 0177)
212 					c = '?';
213 				break;
214 			case '\t':
215 				break;
216 		}
217 		putchar(c);
218 	}
219 }
220 
221 doulg()
222 {
223 	register char *lp, *gp;
224 	char *maxgp;
225 	register c;
226 	char csw;
227 	int col;
228 
229 	gp = genbuf;
230 	*gp = 0;
231 	maxgp = gp;
232 	col = 0;
233 	for (lp = linebuf; c = *lp++;) {
234 		switch (c) {
235 			case '\t':
236 				while ((col & 7) != 7) {
237 					*gp++ = ' ';
238 					if (gp >= &genbuf[BUFSIZ - 2])
239 						goto ovflo;
240 					col++;
241 				}
242 				break;
243 			default:
244 				if (gp >= maxgp)
245 					break;
246 				c |= (*gp & QUOTE);
247 				break;
248 			case '_':
249 				if (gp >= maxgp)
250 					c = QUOTE;
251 				else
252 					c = *gp | QUOTE;
253 				break;
254 			case '\b':
255 				if (gp > genbuf) {
256 					gp--;
257 					col--;
258 				}
259 				continue;
260 		}
261 		if (gp >= &genbuf[BUFSIZ - 2]) {
262 ovflo:
263 			fprintf(stderr, "Line too long\n");
264 			exit(1);
265 		}
266 		*gp++ = c;
267 		if (gp > maxgp)
268 			maxgp = gp;
269 		col++;
270 	}
271 	*maxgp = 0;
272 	strcpy(linebuf, genbuf);
273 	for (lp = linebuf, gp = genbuf; c = *lp; gp++, lp++)
274 		if (c & QUOTE) {
275 			c &= 0177;
276 			if (c == 0)
277 				*lp = '_', *gp = ' ';
278 			else
279 				*lp = c, *gp = '-';
280 		} else
281 			*gp = ' ';
282 	--gp;
283 	while (gp >= genbuf && *gp == ' ')
284 		--gp;
285 	gp[1] = 0;
286 }
287