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