|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)ul.c 4.5 (Berkeley) 8/11/83"; ! 3: #endif ! 4: ! 5: #include <stdio.h> ! 6: ! 7: #define IESC '\033' ! 8: #define SO '\016' ! 9: #define SI '\017' ! 10: #define HFWD '9' ! 11: #define HREV '8' ! 12: #define FREV '7' ! 13: #define MAXBUF 512 ! 14: ! 15: #define NORMAL 000 ! 16: #define ALTSET 001 /* Reverse */ ! 17: #define SUPERSC 002 /* Dim */ ! 18: #define SUBSC 004 /* Dim | Ul */ ! 19: #define UNDERL 010 /* Ul */ ! 20: #define BOLD 020 /* Bold */ ! 21: ! 22: int must_use_uc, must_overstrike; ! 23: char *CURS_UP, *CURS_RIGHT, *CURS_LEFT, ! 24: *ENTER_STANDOUT, *EXIT_STANDOUT, *ENTER_UNDERLINE, *EXIT_UNDERLINE, ! 25: *ENTER_DIM, *ENTER_BOLD, *ENTER_REVERSE, *UNDER_CHAR, *EXIT_ATTRIBUTES; ! 26: ! 27: struct CHAR { ! 28: char c_mode; ! 29: char c_char; ! 30: } ; ! 31: ! 32: char buf[BUFSIZ]; ! 33: ! 34: struct CHAR obuf[MAXBUF]; ! 35: int col, maxcol; ! 36: int mode; ! 37: int halfpos; ! 38: int upln; ! 39: int iflag; ! 40: ! 41: main(argc, argv) ! 42: int argc; ! 43: char **argv; ! 44: { ! 45: int c; ! 46: char *cp, *termtype; ! 47: FILE *f; ! 48: char termcap[1024]; ! 49: char *getenv(); ! 50: extern int optind; ! 51: extern char *optarg; ! 52: ! 53: termtype = getenv("TERM"); ! 54: if (termtype == NULL || (argv[0][0] == 'c' && !isatty(1))) ! 55: termtype = "lpr"; ! 56: while ((c=getopt(argc, argv, "it:T:")) != EOF) ! 57: switch(c) { ! 58: ! 59: case 't': ! 60: case 'T': /* for nroff compatibility */ ! 61: termtype = optarg; ! 62: break; ! 63: case 'i': ! 64: iflag = 1; ! 65: break; ! 66: ! 67: default: ! 68: fprintf(stderr, ! 69: "Usage: %s [ -i ] [ -tTerm ] file...\n", ! 70: argv[0]); ! 71: exit(1); ! 72: } ! 73: ! 74: switch(tgetent(termcap, termtype)) { ! 75: ! 76: case 1: ! 77: break; ! 78: ! 79: default: ! 80: fprintf(stderr,"trouble reading termcap"); ! 81: /* fall through to ... */ ! 82: ! 83: case 0: ! 84: /* No such terminal type - assume dumb */ ! 85: strcpy(termcap, "dumb:os:col#80:cr=^M:sf=^J:am:"); ! 86: break; ! 87: } ! 88: initcap(); ! 89: if ( (tgetflag("os") && ENTER_BOLD==NULL ) || ! 90: (tgetflag("ul") && ENTER_UNDERLINE==NULL && UNDER_CHAR==NULL)) ! 91: must_overstrike = 1; ! 92: setbuf(stdout, buf); ! 93: initbuf(); ! 94: if (optind == argc) ! 95: filter(stdin); ! 96: else for (; optind<argc; optind++) { ! 97: f = fopen(argv[optind],"r"); ! 98: if (f == NULL) { ! 99: perror(argv[optind]); ! 100: exit(1); ! 101: } else ! 102: filter(f); ! 103: } ! 104: exit(0); ! 105: } ! 106: ! 107: filter(f) ! 108: FILE *f; ! 109: { ! 110: register c; ! 111: ! 112: while((c = getc(f)) != EOF) switch(c) { ! 113: ! 114: case '\b': ! 115: if (col > 0) ! 116: col--; ! 117: continue; ! 118: ! 119: case '\t': ! 120: col = (col+8) & ~07; ! 121: if (col > maxcol) ! 122: maxcol = col; ! 123: continue; ! 124: ! 125: case '\r': ! 126: col = 0; ! 127: continue; ! 128: ! 129: case SO: ! 130: mode |= ALTSET; ! 131: continue; ! 132: ! 133: case SI: ! 134: mode &= ~ALTSET; ! 135: continue; ! 136: ! 137: case IESC: ! 138: switch (c = getc(f)) { ! 139: ! 140: case HREV: ! 141: if (halfpos == 0) { ! 142: mode |= SUPERSC; ! 143: halfpos--; ! 144: } else if (halfpos > 0) { ! 145: mode &= ~SUBSC; ! 146: halfpos--; ! 147: } else { ! 148: halfpos = 0; ! 149: reverse(); ! 150: } ! 151: continue; ! 152: ! 153: case HFWD: ! 154: if (halfpos == 0) { ! 155: mode |= SUBSC; ! 156: halfpos++; ! 157: } else if (halfpos < 0) { ! 158: mode &= ~SUPERSC; ! 159: halfpos++; ! 160: } else { ! 161: halfpos = 0; ! 162: fwd(); ! 163: } ! 164: continue; ! 165: ! 166: case FREV: ! 167: reverse(); ! 168: continue; ! 169: ! 170: default: ! 171: fprintf(stderr, ! 172: "Unknown escape sequence in input: %o, %o\n", ! 173: IESC, c); ! 174: exit(1); ! 175: } ! 176: continue; ! 177: ! 178: case '_': ! 179: if (obuf[col].c_char) ! 180: obuf[col].c_mode |= UNDERL | mode; ! 181: else ! 182: obuf[col].c_char = '_'; ! 183: case ' ': ! 184: col++; ! 185: if (col > maxcol) ! 186: maxcol = col; ! 187: continue; ! 188: ! 189: case '\n': ! 190: flushln(); ! 191: continue; ! 192: ! 193: default: ! 194: if (c < ' ') /* non printing */ ! 195: continue; ! 196: if (obuf[col].c_char == '\0') { ! 197: obuf[col].c_char = c; ! 198: obuf[col].c_mode = mode; ! 199: } else if (obuf[col].c_char == '_') { ! 200: obuf[col].c_char = c; ! 201: obuf[col].c_mode |= UNDERL|mode; ! 202: } else if (obuf[col].c_char == c) ! 203: obuf[col].c_mode |= BOLD|mode; ! 204: else { ! 205: obuf[col].c_mode = c; ! 206: obuf[col].c_mode = mode; ! 207: } ! 208: col++; ! 209: if (col > maxcol) ! 210: maxcol = col; ! 211: continue; ! 212: } ! 213: if (maxcol) ! 214: flushln(); ! 215: } ! 216: ! 217: flushln() ! 218: { ! 219: register lastmode; ! 220: register i; ! 221: int hadmodes = 0; ! 222: ! 223: lastmode = NORMAL; ! 224: for (i=0; i<maxcol; i++) { ! 225: if (obuf[i].c_mode != lastmode) { ! 226: hadmodes++; ! 227: setmode(obuf[i].c_mode); ! 228: lastmode = obuf[i].c_mode; ! 229: } ! 230: if (obuf[i].c_char == '\0') { ! 231: if (upln) { ! 232: puts(CURS_RIGHT); ! 233: } else ! 234: outc(' '); ! 235: } else ! 236: outc(obuf[i].c_char); ! 237: } ! 238: if (lastmode != NORMAL) { ! 239: setmode(0); ! 240: } ! 241: if (must_overstrike && hadmodes) ! 242: overstrike(); ! 243: putchar('\n'); ! 244: if (iflag && hadmodes) ! 245: iattr(); ! 246: fflush(stdout); ! 247: if (upln) ! 248: upln--; ! 249: initbuf(); ! 250: } ! 251: ! 252: /* ! 253: * For terminals that can overstrike, overstrike underlines and bolds. ! 254: * We don't do anything with halfline ups and downs, or Greek. ! 255: */ ! 256: overstrike() ! 257: { ! 258: register int i; ! 259: char lbuf[256]; ! 260: register char *cp = lbuf; ! 261: int hadbold=0; ! 262: ! 263: /* Set up overstrike buffer */ ! 264: for (i=0; i<maxcol; i++) ! 265: switch (obuf[i].c_mode) { ! 266: case NORMAL: ! 267: default: ! 268: *cp++ = ' '; ! 269: break; ! 270: case UNDERL: ! 271: *cp++ = '_'; ! 272: break; ! 273: case BOLD: ! 274: *cp++ = obuf[i].c_char; ! 275: hadbold=1; ! 276: break; ! 277: } ! 278: putchar('\r'); ! 279: for (*cp=' '; *cp==' '; cp--) ! 280: *cp = 0; ! 281: for (cp=lbuf; *cp; cp++) ! 282: putchar(*cp); ! 283: if (hadbold) { ! 284: putchar('\r'); ! 285: for (cp=lbuf; *cp; cp++) ! 286: putchar(*cp=='_' ? ' ' : *cp); ! 287: putchar('\r'); ! 288: for (cp=lbuf; *cp; cp++) ! 289: putchar(*cp=='_' ? ' ' : *cp); ! 290: } ! 291: } ! 292: ! 293: iattr() ! 294: { ! 295: register int i; ! 296: char lbuf[256]; ! 297: register char *cp = lbuf; ! 298: ! 299: for (i=0; i<maxcol; i++) ! 300: switch (obuf[i].c_mode) { ! 301: case NORMAL: *cp++ = ' '; break; ! 302: case ALTSET: *cp++ = 'g'; break; ! 303: case SUPERSC: *cp++ = '^'; break; ! 304: case SUBSC: *cp++ = 'v'; break; ! 305: case UNDERL: *cp++ = '_'; break; ! 306: case BOLD: *cp++ = '!'; break; ! 307: default: *cp++ = 'X'; break; ! 308: } ! 309: for (*cp=' '; *cp==' '; cp--) ! 310: *cp = 0; ! 311: for (cp=lbuf; *cp; cp++) ! 312: putchar(*cp); ! 313: putchar('\n'); ! 314: } ! 315: ! 316: initbuf() ! 317: { ! 318: register i; ! 319: ! 320: for (i=0; i<MAXBUF; i++) { ! 321: obuf[i].c_char = '\0'; ! 322: obuf[i].c_mode = NORMAL; ! 323: } ! 324: col = 0; ! 325: maxcol = 0; ! 326: mode &= ALTSET; ! 327: } ! 328: ! 329: fwd() ! 330: { ! 331: register oldcol, oldmax; ! 332: ! 333: oldcol = col; ! 334: oldmax = maxcol; ! 335: flushln(); ! 336: col = oldcol; ! 337: maxcol = oldmax; ! 338: } ! 339: ! 340: reverse() ! 341: { ! 342: upln++; ! 343: fwd(); ! 344: puts(CURS_UP); ! 345: puts(CURS_UP); ! 346: upln++; ! 347: } ! 348: ! 349: initcap() ! 350: { ! 351: static char tcapbuf[512]; ! 352: char *termtype; ! 353: char *bp = tcapbuf; ! 354: char *getenv(), *tgetstr(); ! 355: ! 356: /* This nonsense attempts to work with both old and new termcap */ ! 357: CURS_UP = tgetstr("up", &bp); ! 358: CURS_RIGHT = tgetstr("ri", &bp); ! 359: if (CURS_RIGHT == NULL) ! 360: CURS_RIGHT = tgetstr("nd", &bp); ! 361: CURS_LEFT = tgetstr("le", &bp); ! 362: if (CURS_LEFT == NULL) ! 363: CURS_LEFT = tgetstr("bc", &bp); ! 364: if (CURS_LEFT == NULL && tgetflag("bs")) ! 365: CURS_LEFT = "\b"; ! 366: ! 367: ENTER_STANDOUT = tgetstr("so", &bp); ! 368: EXIT_STANDOUT = tgetstr("se", &bp); ! 369: ENTER_UNDERLINE = tgetstr("us", &bp); ! 370: EXIT_UNDERLINE = tgetstr("ue", &bp); ! 371: ENTER_DIM = tgetstr("mh", &bp); ! 372: ENTER_BOLD = tgetstr("md", &bp); ! 373: ENTER_REVERSE = tgetstr("mr", &bp); ! 374: EXIT_ATTRIBUTES = tgetstr("me", &bp); ! 375: ! 376: if (!ENTER_BOLD && ENTER_REVERSE) ! 377: ENTER_BOLD = ENTER_REVERSE; ! 378: if (!ENTER_BOLD && ENTER_STANDOUT) ! 379: ENTER_BOLD = ENTER_STANDOUT; ! 380: if (!ENTER_UNDERLINE && ENTER_STANDOUT) { ! 381: ENTER_UNDERLINE = ENTER_STANDOUT; ! 382: EXIT_UNDERLINE = EXIT_STANDOUT; ! 383: } ! 384: if (!ENTER_DIM && ENTER_STANDOUT) ! 385: ENTER_DIM = ENTER_STANDOUT; ! 386: if (!ENTER_REVERSE && ENTER_STANDOUT) ! 387: ENTER_REVERSE = ENTER_STANDOUT; ! 388: if (!EXIT_ATTRIBUTES && EXIT_STANDOUT) ! 389: EXIT_ATTRIBUTES = EXIT_STANDOUT; ! 390: ! 391: /* ! 392: * Note that we use REVERSE for the alternate character set, ! 393: * not the as/ae capabilities. This is because we are modelling ! 394: * the model 37 teletype (since that's what nroff outputs) and ! 395: * the typical as/ae is more of a graphics set, not the greek ! 396: * letters the 37 has. ! 397: */ ! 398: ! 399: #ifdef notdef ! 400: printf("so %s se %s us %s ue %s me %s\n", ! 401: ENTER_STANDOUT, EXIT_STANDOUT, ENTER_UNDERLINE, ! 402: EXIT_UNDERLINE, EXIT_ATTRIBUTES); ! 403: #endif ! 404: UNDER_CHAR = tgetstr("uc", &bp); ! 405: must_use_uc = (UNDER_CHAR && !ENTER_UNDERLINE); ! 406: } ! 407: ! 408: outchar(c) ! 409: char c; ! 410: { ! 411: putchar(c&0177); ! 412: } ! 413: ! 414: puts(str) ! 415: char *str; ! 416: { ! 417: if (str) ! 418: tputs(str, 1, outchar); ! 419: } ! 420: ! 421: static curmode = 0; ! 422: outc(c) ! 423: char c; ! 424: { ! 425: putchar(c); ! 426: if (must_use_uc && (curmode&UNDERL)) { ! 427: puts(CURS_LEFT); ! 428: puts(UNDER_CHAR); ! 429: } ! 430: } ! 431: ! 432: setmode(newmode) ! 433: int newmode; ! 434: { ! 435: if (!iflag) ! 436: { ! 437: if (curmode != NORMAL && newmode != NORMAL) ! 438: setmode(NORMAL); ! 439: switch (newmode) { ! 440: case NORMAL: ! 441: switch(curmode) { ! 442: case NORMAL: ! 443: break; ! 444: case UNDERL: ! 445: puts(EXIT_UNDERLINE); ! 446: break; ! 447: default: ! 448: /* This includes standout */ ! 449: puts(EXIT_ATTRIBUTES); ! 450: break; ! 451: } ! 452: break; ! 453: case ALTSET: ! 454: puts(ENTER_REVERSE); ! 455: break; ! 456: case SUPERSC: ! 457: /* ! 458: * This only works on a few terminals. ! 459: * It should be fixed. ! 460: */ ! 461: puts(ENTER_UNDERLINE); ! 462: puts(ENTER_DIM); ! 463: break; ! 464: case SUBSC: ! 465: puts(ENTER_DIM); ! 466: break; ! 467: case UNDERL: ! 468: puts(ENTER_UNDERLINE); ! 469: break; ! 470: case BOLD: ! 471: puts(ENTER_BOLD); ! 472: break; ! 473: default: ! 474: /* ! 475: * We should have some provision here for multiple modes ! 476: * on at once. This will have to come later. ! 477: */ ! 478: puts(ENTER_STANDOUT); ! 479: break; ! 480: } ! 481: } ! 482: curmode = newmode; ! 483: } ! 484: /* @(#)getopt.c 3.2 */ ! 485: #define ERR(s, c) if(opterr){\ ! 486: fputs(argv[0], stderr);\ ! 487: fputs(s, stderr);\ ! 488: fputc(c, stderr);\ ! 489: fputc('\n', stderr);} ! 490: ! 491: int opterr = 1; ! 492: int optind = 1; ! 493: char *optarg; ! 494: char *index(); ! 495: ! 496: int ! 497: getopt (argc, argv, opts) ! 498: char **argv, *opts; ! 499: { ! 500: static int sp = 1; ! 501: char c; ! 502: char *cp; ! 503: ! 504: if (sp == 1) ! 505: if (optind >= argc || ! 506: argv[optind][0] != '-' || argv[optind][1] == '\0') ! 507: return EOF; ! 508: else if (strcmp(argv[optind], "--") == NULL) { ! 509: optind++; ! 510: return EOF; ! 511: } ! 512: else if (strcmp(argv[optind], "-?") == NULL) { ! 513: optind++; ! 514: return '?'; ! 515: } ! 516: c = argv[optind][sp]; ! 517: if (c == ':' || (cp=index(opts, c)) == NULL) { ! 518: ERR (": illegal option -- ", c); ! 519: if (argv[optind][++sp] == '\0') { ! 520: optind++; ! 521: sp = 1; ! 522: } ! 523: return '?'; ! 524: } ! 525: if (*++cp == ':') { ! 526: if (argv[optind][2] != '\0') ! 527: optarg = &argv[optind++][sp+1]; ! 528: else if (++optind >= argc) { ! 529: ERR (": option requires an argument -- ", c); ! 530: sp = 1; ! 531: return '?'; ! 532: } else ! 533: optarg = argv[optind++]; ! 534: sp = 1; ! 535: } ! 536: else if (argv[optind][++sp] == '\0') { ! 537: sp = 1; ! 538: optind++; ! 539: } ! 540: return c; ! 541: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.