date and time created 80/10/30 00:36:13 by mckusick
[unix-history] / usr / src / usr.bin / ul / ul.c
CommitLineData
2770968b
BJ
1static char *sccsid = "@(#)ul.c 4.1 (Berkeley) %G%";
2/*
3 * ul
4 */
5#include <stdio.h>
6
7char buf[BUFSIZ];
8char isul[BUFSIZ];
9char termcap[1024];
10char ulbuf[BUFSIZ];
11char *stul, *endul, *chul;
12char *backspace;
13char *termtype;
14int outc();
15char *tgetstr();
16char *getenv();
17
18main(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
103filter(f)
104FILE *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
157outc(c)
158char c;
159{
160 putchar(c);
161}
162
163#define BACKSPACE 0
164#define QUOTE 0200
165
166char linebuf[BUFSIZ], genbuf[BUFSIZ];
167char *strcpy();
168
169iul(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
199dographic()
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
221doulg()
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]) {
262ovflo:
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}