Commit | Line | Data |
---|---|---|
2770968b BJ |
1 | static char *sccsid = "@(#)ul.c 4.1 (Berkeley) %G%"; |
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 | } |