|
|
1.1 ! root 1: /* ! 2: * hp [-e] [-m] ! 3: * convert nroff TTY37 output to right form for HP2640x terminals. ! 4: * -e indicates enhanced terminal with underline, etc. ! 5: * -m requests minimization of output by removing multiple newlines ! 6: */ ! 7: ! 8: char hpvers[] = "@(#)hp.c 1.6"; ! 9: ! 10: #include <stdio.h> ! 11: #include <signal.h> ! 12: #include <sys/types.h> ! 13: #include <sys/stat.h> ! 14: #include <sgtty.h> ! 15: #define ESC 033 /* escape */ ! 16: #define HFWD '9' ! 17: #define HREV '8' ! 18: #define FREV '7' ! 19: #define SO 016 /* shift out - enter greek */ ! 20: #define SI 017 /* shift in */ ! 21: #define LF '\n' ! 22: #define CR 015 ! 23: #define NFLAG 0200 /* hi-bit flag for non-showing chars */ ! 24: #define NMASK 0177 ! 25: #define AMP 046 /* & */ ! 26: #define DEE 0144 /* d */ ! 27: #define BFSIZ 4096 /* size of output buffer */ ! 28: /* (bigger because of tbl weirds */ ! 29: /* and nroff idiosyncracies */ ! 30: ! 31: /* puty adds control char to output, marked by hi-bit */ ! 32: #define puty(c) putx(c|NFLAG) ! 33: #define flg(x) ((char)(x|NFLAG)) /* set hi-bit of x */ ! 34: int nlcnt, /* accumulated newline count */ ! 35: frevcnt, /* accumulated reverse line-feeds */ ! 36: halfpos, /* half-line position: -1 = above, +1 = below */ ! 37: restrict = 1, /* 0==> full terminal, 1==> no display enhancements */ ! 38: minimiz; /* 0==> normal, 1==> remove extra newlines */ ! 39: char *ttydev; ! 40: int svstmode; /* for mesg restore */ ! 41: int restore(); ! 42: char *ttyname(); ! 43: int svsgflgs; ! 44: struct sgttyb sgb; ! 45: int retcode = 2; /* return code */ ! 46: char peekbuf[2]; ! 47: char *peekstr = peekbuf; /* lookahead ptr */ ! 48: ! 49: char outbf[BFSIZ]; /* output assembly buffer */ ! 50: char *bfnext = outbf, /* addr of next empty byte */ ! 51: *bflast = &outbf[BFSIZ-1]; /* addr of last usable byte */ ! 52: ! 53: /* normal display enhancement strings */ ! 54: char *enunder = "\033&dD", /* underline */ ! 55: *ennorml = "\033&d@", /* normal output */ ! 56: *ensuper = "\033&dH", /* superscript (half) */ ! 57: *ensubsc = "\033&dL", /* subscript (half, underlined */ ! 58: *enrestr = "\033&dB"; /* restricted (inverse only) */ ! 59: ! 60: int restore(); ! 61: main(argc, argv) ! 62: char **argv; ! 63: { ! 64: register c; ! 65: scanarg(argc,argv); ! 66: if (((int)signal(SIGINT, SIG_IGN) & 01) == 0) ! 67: signal(SIGINT, restore); ! 68: if (gtty(1, &sgb) == 0) ! 69: fixtty(); ! 70: setbuf(stdin, calloc(BUFSIZ,1)); ! 71: while((c = getchal()) != EOF) { ! 72: if (nlcnt && c != LF) flushnl(); ! 73: if (frevcnt && c != ESC) flushrv(); ! 74: if (c == LF) { ! 75: if (++nlcnt == 1) flushln(); ! 76: continue; ! 77: } ! 78: if (c == ESC) ! 79: escape(); ! 80: else if (c == SO) ! 81: special(); ! 82: else if (c == '\b') ! 83: backsp(); ! 84: else if (c == '_') { /* C nroff */ ! 85: if ((c = getchal()) == '\b') { ! 86: undersc(); ! 87: } else { ! 88: putx('_'); ! 89: peekbuf[0] = c; ! 90: peekstr = peekbuf; ! 91: } ! 92: } ! 93: else ! 94: putx(c); ! 95: } ! 96: flusher(); ! 97: retcode = 0; ! 98: restore(); ! 99: } ! 100: ! 101: getchal() ! 102: { ! 103: if (*peekstr) ! 104: return(*peekstr++); ! 105: return(getchar()); ! 106: } ! 107: ! 108: /* scanarg: scan arguments and set flags; ignore unknown args */ ! 109: scanarg(argc,argv) ! 110: int argc; char **argv; ! 111: { ! 112: register char *p; ! 113: while ( --argc > 0) { ! 114: p = *++argv; ! 115: if (*p == '-') { ! 116: ++p; ! 117: if (*p == 'e') restrict = 0; ! 118: else if (*p == 'm') minimiz = 1; ! 119: } ! 120: } ! 121: if (restrict) ! 122: enunder = ensuper = ensubsc = enrestr; ! 123: } ! 124: ! 125: /* fixtty: get tty status and save; remove delay and CR-LF mapping */ ! 126: fixtty() ! 127: { ! 128: struct stat sb; ! 129: ! 130: svsgflgs = sgb.sg_flags; ! 131: sgb.sg_flags &= ~(ALLDELAY|CRMOD); ! 132: stty(1, &sgb); /* stty nl nl0 cr0 tab0 ff0 */ ! 133: fstat(1, &sb); ! 134: svstmode = sb.st_mode; ! 135: ttydev = ttyname(1); ! 136: if (ttydev && *ttydev) ! 137: chmod(ttydev, 0600); /* mesg n */ ! 138: } ! 139: ! 140: /* flusher: flush accumulated newlines, reverse line feeds, buffer */ ! 141: flusher() ! 142: { ! 143: flushln(); ! 144: if (nlcnt) flushnl(); ! 145: if (frevcnt) flushrv(); ! 146: fflush(stdout); ! 147: } ! 148: ! 149: /* flushrv: flush accumulated reverse line feeds */ ! 150: flushrv() ! 151: { ! 152: while (frevcnt--) ! 153: putstr("\033T"); ! 154: putstr(ennorml); ! 155: frevcnt = 0; ! 156: } ! 157: ! 158: /* flushnl: flush accumulated newlines (count in nlcnt) */ ! 159: flushnl() ! 160: { ! 161: if (minimiz != 0 && nlcnt > 2) nlcnt = 2; ! 162: putchar(CR); ! 163: while (nlcnt--) ! 164: putchar(LF); ! 165: nlcnt = 0; ! 166: } ! 167: ! 168: putstr(p) ! 169: char *p; ! 170: { ! 171: register char *pp; ! 172: pp = p; ! 173: while (*pp) puty(*pp++); ! 174: } ! 175: ! 176: restore(){ ! 177: if (isatty(1)) { ! 178: sgb.sg_flags = svsgflgs; ! 179: stty(1, &sgb); ! 180: if (ttydev && *ttydev) ! 181: chmod(ttydev, svstmode); ! 182: } ! 183: exit(retcode); ! 184: } ! 185: ! 186: char tab[] = { ! 187: 'A','A', /* alpha */ ! 188: 'B','B', /* beta */ ! 189: 'D','W', /* delta */ ! 190: 'W','V', /* DELTA */ ! 191: 'S','E', /* epsilon */ ! 192: 'N','H', /* eta */ ! 193: '\\','Q', /* gamma */ ! 194: 'G','+', /* GAMMA */ ! 195: 'o','<', /* infinity - not in M37 */ ! 196: '^','\'', /* integral */ ! 197: 'L','G', /* lambda */ ! 198: 'E',';', /* LAMBDA */ ! 199: 'M','M', /* mu */ ! 200: '[','$', /* nabla (del) */ ! 201: '_','\\', /* not */ ! 202: '@','N', /* nu */ ! 203: 'C','L', /* omega */ ! 204: 'Z',':', /* OMEGA */ ! 205: ']','F', /* partial */ ! 206: 'U','D', /* phi */ ! 207: 'F','.', /* PHI */ ! 208: 'V','C', /* psi */ ! 209: 'H',',', /* PSI */ ! 210: 'J','P', /* pi */ ! 211: 'P','*', /* PI */ ! 212: 'K','O', /* rho */ ! 213: 'Y','S', /* sigma */ ! 214: 'R','?', /* SIGMA */ ! 215: 'I','T', /* tau */ ! 216: 'T','R', /* theta */ ! 217: 'O','J', /* THETA */ ! 218: 'X','U', /* xi */ ! 219: 'Q','Z', /* zeta */ ! 220: 'v','Y', ! 221: 0 ! 222: }; ! 223: ! 224: char spec1[] = {LF,SO,0}; ! 225: special(){ ! 226: register int c; ! 227: register char *p; ! 228: puty(SO); ! 229: while ((c = getchal()) != EOF) { ! 230: if (c == SI) { ! 231: puty(c); ! 232: return; ! 233: } ! 234: if (c == LF) { ! 235: peekstr = spec1; ! 236: return; ! 237: } ! 238: for (p = tab; *p != 0; p += 2) ! 239: if (c == *p) { ! 240: c = *++p; ! 241: break; ! 242: } ! 243: putx(c); ! 244: } ! 245: } ! 246: ! 247: /* escape: handle escape sequences */ ! 248: escape() ! 249: { ! 250: register int c; ! 251: c = getchal(); ! 252: if (frevcnt && c != FREV) flushrv(); ! 253: switch (c) { ! 254: case FREV: ! 255: frevcnt++; ! 256: break; ! 257: case HREV: ! 258: if (halfpos == 0) { ! 259: putstr(ensuper); ! 260: halfpos--; ! 261: } ! 262: else if (halfpos > 0) { ! 263: putstr(ennorml); ! 264: halfpos--; ! 265: } ! 266: else { ! 267: putstr("\033T"); /* roll back 1 */ ! 268: putstr(ennorml); ! 269: halfpos = 0; ! 270: } ! 271: break; ! 272: case HFWD: ! 273: if (halfpos == 0) { ! 274: putstr(ensubsc); ! 275: halfpos++; ! 276: } ! 277: else if (halfpos < 0) { ! 278: putstr(ennorml); ! 279: halfpos++; ! 280: } ! 281: else { ! 282: putstr("\033S"); /* roll up 1, i.e., LF w/o CR */ ! 283: putstr(ennorml); ! 284: halfpos = 0; ! 285: } ! 286: break; ! 287: case '&': ! 288: putstr("\033&"); ! 289: puty(c = getchal()); ! 290: if (c == 'd') puty(getchal()); ! 291: break; ! 292: case ')': ! 293: putstr("\033)"); ! 294: puty(getchal()); ! 295: break; ! 296: default: ! 297: puty(ESC); ! 298: puty(getchal()); ! 299: break; ! 300: } ! 301: } ! 302: ! 303: char peeku[3]; ! 304: /* backsp: handle backspacing */ ! 305: /* sequences are handled such that : ( \b is backspace ) */ ! 306: /* a\b_ -> a in inverse video */ ! 307: /* _\ba -> a in inverse video */ ! 308: /* c\bd -> c in inverse video */ ! 309: /* if a control char (ESC) precedes or follows '\b' */ ! 310: /* then an actual backspace movement is performed */ ! 311: backsp() ! 312: { ! 313: register char *bftmp; ! 314: register int c; ! 315: char *bfhi; ! 316: int i, j, ncnt, bscnt; ! 317: char *p, *p1; ! 318: p = bfnext-2; ! 319: p1 = bfnext-4; ! 320: /* check if last char put in buffer was escape sequence */ ! 321: /* if so, put backspace control sequence in buffer */ ! 322: /* check against "\033&d" */ ! 323: if ((*p == flg(ESC)) || ! 324: (*p1++ == flg(ESC) && *p1++==flg(AMP) && *p1==flg(DEE))) { ! 325: putstr("\033D"); ! 326: while((c=getchal())=='\b') putstr("\033D"); ! 327: /* put last char back */ ! 328: peeku[0] = c; ! 329: peeku[1] = '\0'; ! 330: peekstr = peeku; ! 331: return; ! 332: } ! 333: bscnt = 1; ! 334: c = getchal(); ! 335: /* count backspaces */ ! 336: while (c == '\b') { ! 337: bscnt++; ! 338: c = getchal(); ! 339: } ! 340: /* read in chars until bscnt have been read */ ! 341: /* or until an ESC is read */ ! 342: ncnt = 0; ! 343: if (c!=ESC) { ! 344: for (ncnt=0; (ncnt<bscnt && c!=ESC); ncnt++) ! 345: c = getchal(); ! 346: /* since there were normal chars with backsp */ ! 347: /* insert inverse video chars in buffer */ ! 348: bftmp = bfhi = bfnext + 4; ! 349: for (i=0; i<bscnt;) ! 350: if (((*--bftmp = *--bfnext) & NFLAG) == 0) i++; ! 351: putstr(enunder); ! 352: bfnext = bfhi; ! 353: } ! 354: /* if number of bcksp is not = to number normal chars */ ! 355: /* then some bcksp chars will be inserted as actual */ ! 356: /* bcksp movement and not inverse video for another char */ ! 357: j = bscnt - ncnt; ! 358: if (j == 0) putstr(ennorml); ! 359: else { ! 360: /* move chars over and insert normal char seq */ ! 361: if (ncnt > 0) { ! 362: bftmp = bfhi = bfnext + 4; ! 363: for (i=0; i<j;) ! 364: if (((*--bftmp = *--bfnext) & NFLAG) == 0) i++; ! 365: putstr(ennorml); ! 366: bfnext = bfhi; ! 367: } ! 368: /* insert backspace movement chars */ ! 369: while (j--) putstr("\033D"); ! 370: } ! 371: /* put last char read back */ ! 372: peeku[0] = c; ! 373: peeku[1] = '\0'; ! 374: peekstr = peeku; ! 375: } ! 376: /* undersc: handle C nroff's (_ BS char)+ sequences ! 377: * assumes _ BS already found ! 378: * if char is a control char, put char back and break. ! 379: */ ! 380: undersc() ! 381: { ! 382: register char c; ! 383: ! 384: putstr(enunder); ! 385: while (1) { ! 386: if ((c=getchal())==ESC) { ! 387: peeku[0] = c; peeku[1] = '\0'; ! 388: peekstr = peeku; ! 389: break; ! 390: } ! 391: else ! 392: putx(c); ! 393: if ((c = getchal()) != '_') { ! 394: peeku[0] = c; peeku[1] = '\0'; ! 395: peekstr = peeku; ! 396: break; ! 397: } ! 398: if ((c = getchal()) != '\b') { ! 399: peeku[0] = '_'; peeku[1] = c; ! 400: peekstr = peeku; ! 401: break; ! 402: } ! 403: } ! 404: putstr(ennorml); ! 405: } ! 406: ! 407: /* flushln: flush out accumulated line */ ! 408: flushln() ! 409: { ! 410: register char c, *p; ! 411: putx('\0'); ! 412: p = outbf; ! 413: while (c = (*p++ & NMASK)) putchar(c); ! 414: bfnext = outbf; ! 415: } ! 416: ! 417: /* putx: add normal (printing) char to output */ ! 418: putx(c) ! 419: char c; ! 420: { ! 421: if (bfnext <= bflast) ! 422: *bfnext++ = c; ! 423: else die("line too long\n"); ! 424: } ! 425: ! 426: die(mesg) ! 427: char *mesg; ! 428: { ! 429: register char *p; ! 430: char *c = "hp: "; ! 431: ! 432: write(2, c, 4); ! 433: p = mesg; ! 434: while (*p) ! 435: write(2, p++, 1); ! 436: restore(); ! 437: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.