1: /*
   2:  * Copyright (c) 1980 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  */
   6: 
   7: #ifndef lint
   8: char copyright[] =
   9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
  10:  All rights reserved.\n";
  11: #endif not lint
  12: 
  13: #ifndef lint
  14: static char sccsid[] = "@(#)ul.c	5.1 (Berkeley) 5/31/85";
  15: #endif not lint
  16: 
  17: #include <stdio.h>
  18: 
  19: #define IESC    '\033'
  20: #define SO  '\016'
  21: #define SI  '\017'
  22: #define HFWD    '9'
  23: #define HREV    '8'
  24: #define FREV    '7'
  25: #define MAXBUF  512
  26: 
  27: #define NORMAL  000
  28: #define ALTSET  001 /* Reverse */
  29: #define SUPERSC 002 /* Dim */
  30: #define SUBSC   004 /* Dim | Ul */
  31: #define UNDERL  010 /* Ul */
  32: #define BOLD    020 /* Bold */
  33: 
  34: int must_use_uc, must_overstrike;
  35: char    *CURS_UP, *CURS_RIGHT, *CURS_LEFT,
  36:     *ENTER_STANDOUT, *EXIT_STANDOUT, *ENTER_UNDERLINE, *EXIT_UNDERLINE,
  37:     *ENTER_DIM, *ENTER_BOLD, *ENTER_REVERSE, *UNDER_CHAR, *EXIT_ATTRIBUTES;
  38: 
  39: struct  CHAR    {
  40:     char    c_mode;
  41:     char    c_char;
  42: } ;
  43: 
  44: struct  CHAR    obuf[MAXBUF];
  45: int col, maxcol;
  46: int mode;
  47: int halfpos;
  48: int upln;
  49: int iflag;
  50: 
  51: main(argc, argv)
  52:     int argc;
  53:     char **argv;
  54: {
  55:     int c;
  56:     char *cp, *termtype;
  57:     FILE *f;
  58:     char termcap[1024];
  59:     char *getenv();
  60:     extern int optind;
  61:     extern char *optarg;
  62: 
  63:     termtype = getenv("TERM");
  64:     if (termtype == NULL || (argv[0][0] == 'c' && !isatty(1)))
  65:         termtype = "lpr";
  66:     while ((c=getopt(argc, argv, "it:T:")) != EOF)
  67:         switch(c) {
  68: 
  69:         case 't':
  70:         case 'T': /* for nroff compatibility */
  71:                 termtype = optarg;
  72:             break;
  73:         case 'i':
  74:             iflag = 1;
  75:             break;
  76: 
  77:         default:
  78:             fprintf(stderr,
  79:                 "Usage: %s [ -i ] [ -tTerm ] file...\n",
  80:                 argv[0]);
  81:             exit(1);
  82:         }
  83: 
  84:     switch(tgetent(termcap, termtype)) {
  85: 
  86:     case 1:
  87:         break;
  88: 
  89:     default:
  90:         fprintf(stderr,"trouble reading termcap");
  91:         /* fall through to ... */
  92: 
  93:     case 0:
  94:         /* No such terminal type - assume dumb */
  95:         strcpy(termcap, "dumb:os:col#80:cr=^M:sf=^J:am:");
  96:         break;
  97:     }
  98:     initcap();
  99:     if (    (tgetflag("os") && ENTER_BOLD==NULL ) ||
 100:         (tgetflag("ul") && ENTER_UNDERLINE==NULL && UNDER_CHAR==NULL))
 101:             must_overstrike = 1;
 102:     initbuf();
 103:     if (optind == argc)
 104:         filter(stdin);
 105:     else for (; optind<argc; optind++) {
 106:         f = fopen(argv[optind],"r");
 107:         if (f == NULL) {
 108:             perror(argv[optind]);
 109:             exit(1);
 110:         } else
 111:             filter(f);
 112:     }
 113:     exit(0);
 114: }
 115: 
 116: filter(f)
 117: FILE *f;
 118: {
 119:     register c;
 120: 
 121:     while((c = getc(f)) != EOF) switch(c) {
 122: 
 123:     case '\b':
 124:         if (col > 0)
 125:             col--;
 126:         continue;
 127: 
 128:     case '\t':
 129:         col = (col+8) & ~07;
 130:         if (col > maxcol)
 131:             maxcol = col;
 132:         continue;
 133: 
 134:     case '\r':
 135:         col = 0;
 136:         continue;
 137: 
 138:     case SO:
 139:         mode |= ALTSET;
 140:         continue;
 141: 
 142:     case SI:
 143:         mode &= ~ALTSET;
 144:         continue;
 145: 
 146:     case IESC:
 147:         switch (c = getc(f)) {
 148: 
 149:         case HREV:
 150:             if (halfpos == 0) {
 151:                 mode |= SUPERSC;
 152:                 halfpos--;
 153:             } else if (halfpos > 0) {
 154:                 mode &= ~SUBSC;
 155:                 halfpos--;
 156:             } else {
 157:                 halfpos = 0;
 158:                 reverse();
 159:             }
 160:             continue;
 161: 
 162:         case HFWD:
 163:             if (halfpos == 0) {
 164:                 mode |= SUBSC;
 165:                 halfpos++;
 166:             } else if (halfpos < 0) {
 167:                 mode &= ~SUPERSC;
 168:                 halfpos++;
 169:             } else {
 170:                 halfpos = 0;
 171:                 fwd();
 172:             }
 173:             continue;
 174: 
 175:         case FREV:
 176:             reverse();
 177:             continue;
 178: 
 179:         default:
 180:             fprintf(stderr,
 181:                 "Unknown escape sequence in input: %o, %o\n",
 182:                 IESC, c);
 183:             exit(1);
 184:         }
 185:         continue;
 186: 
 187:     case '_':
 188:         if (obuf[col].c_char)
 189:             obuf[col].c_mode |= UNDERL | mode;
 190:         else
 191:             obuf[col].c_char = '_';
 192:     case ' ':
 193:         col++;
 194:         if (col > maxcol)
 195:             maxcol = col;
 196:         continue;
 197: 
 198:     case '\n':
 199:         flushln();
 200:         continue;
 201: 
 202:     default:
 203:         if (c < ' ')    /* non printing */
 204:             continue;
 205:         if (obuf[col].c_char == '\0') {
 206:             obuf[col].c_char = c;
 207:             obuf[col].c_mode = mode;
 208:         } else if (obuf[col].c_char == '_') {
 209:             obuf[col].c_char = c;
 210:             obuf[col].c_mode |= UNDERL|mode;
 211:         } else if (obuf[col].c_char == c)
 212:             obuf[col].c_mode |= BOLD|mode;
 213:         else {
 214:             obuf[col].c_mode = c;
 215:             obuf[col].c_mode = mode;
 216:         }
 217:         col++;
 218:         if (col > maxcol)
 219:             maxcol = col;
 220:         continue;
 221:     }
 222:     if (maxcol)
 223:         flushln();
 224: }
 225: 
 226: flushln()
 227: {
 228:     register lastmode;
 229:     register i;
 230:     int hadmodes = 0;
 231: 
 232:     lastmode = NORMAL;
 233:     for (i=0; i<maxcol; i++) {
 234:         if (obuf[i].c_mode != lastmode) {
 235:             hadmodes++;
 236:             setmode(obuf[i].c_mode);
 237:             lastmode = obuf[i].c_mode;
 238:         }
 239:         if (obuf[i].c_char == '\0') {
 240:             if (upln) {
 241:                 puts(CURS_RIGHT);
 242:             } else
 243:                 outc(' ');
 244:         } else
 245:             outc(obuf[i].c_char);
 246:     }
 247:     if (lastmode != NORMAL) {
 248:         setmode(0);
 249:     }
 250:     if (must_overstrike && hadmodes)
 251:         overstrike();
 252:     putchar('\n');
 253:     if (iflag && hadmodes)
 254:         iattr();
 255:     fflush(stdout);
 256:     if (upln)
 257:         upln--;
 258:     initbuf();
 259: }
 260: 
 261: /*
 262:  * For terminals that can overstrike, overstrike underlines and bolds.
 263:  * We don't do anything with halfline ups and downs, or Greek.
 264:  */
 265: overstrike()
 266: {
 267:     register int i;
 268:     char lbuf[256];
 269:     register char *cp = lbuf;
 270:     int hadbold=0;
 271: 
 272:     /* Set up overstrike buffer */
 273:     for (i=0; i<maxcol; i++)
 274:         switch (obuf[i].c_mode) {
 275:         case NORMAL:
 276:         default:
 277:             *cp++ = ' ';
 278:             break;
 279:         case UNDERL:
 280:             *cp++ = '_';
 281:             break;
 282:         case BOLD:
 283:             *cp++ = obuf[i].c_char;
 284:             hadbold=1;
 285:             break;
 286:         }
 287:     putchar('\r');
 288:     for (*cp=' '; *cp==' '; cp--)
 289:         *cp = 0;
 290:     for (cp=lbuf; *cp; cp++)
 291:         putchar(*cp);
 292:     if (hadbold) {
 293:         putchar('\r');
 294:         for (cp=lbuf; *cp; cp++)
 295:             putchar(*cp=='_' ? ' ' : *cp);
 296:         putchar('\r');
 297:         for (cp=lbuf; *cp; cp++)
 298:             putchar(*cp=='_' ? ' ' : *cp);
 299:     }
 300: }
 301: 
 302: iattr()
 303: {
 304:     register int i;
 305:     char lbuf[256];
 306:     register char *cp = lbuf;
 307: 
 308:     for (i=0; i<maxcol; i++)
 309:         switch (obuf[i].c_mode) {
 310:         case NORMAL:    *cp++ = ' '; break;
 311:         case ALTSET:    *cp++ = 'g'; break;
 312:         case SUPERSC:   *cp++ = '^'; break;
 313:         case SUBSC: *cp++ = 'v'; break;
 314:         case UNDERL:    *cp++ = '_'; break;
 315:         case BOLD:  *cp++ = '!'; break;
 316:         default:    *cp++ = 'X'; break;
 317:         }
 318:     for (*cp=' '; *cp==' '; cp--)
 319:         *cp = 0;
 320:     for (cp=lbuf; *cp; cp++)
 321:         putchar(*cp);
 322:     putchar('\n');
 323: }
 324: 
 325: initbuf()
 326: {
 327: 
 328:     bzero(obuf, sizeof (obuf));     /* depends on NORMAL == 0 */
 329:     col = 0;
 330:     maxcol = 0;
 331:     mode &= ALTSET;
 332: }
 333: 
 334: fwd()
 335: {
 336:     register oldcol, oldmax;
 337: 
 338:     oldcol = col;
 339:     oldmax = maxcol;
 340:     flushln();
 341:     col = oldcol;
 342:     maxcol = oldmax;
 343: }
 344: 
 345: reverse()
 346: {
 347:     upln++;
 348:     fwd();
 349:     puts(CURS_UP);
 350:     puts(CURS_UP);
 351:     upln++;
 352: }
 353: 
 354: initcap()
 355: {
 356:     static char tcapbuf[512];
 357:     char *termtype;
 358:     char *bp = tcapbuf;
 359:     char *getenv(), *tgetstr();
 360: 
 361:     /* This nonsense attempts to work with both old and new termcap */
 362:     CURS_UP =       tgetstr("up", &bp);
 363:     CURS_RIGHT =        tgetstr("ri", &bp);
 364:     if (CURS_RIGHT == NULL)
 365:         CURS_RIGHT =    tgetstr("nd", &bp);
 366:     CURS_LEFT =     tgetstr("le", &bp);
 367:     if (CURS_LEFT == NULL)
 368:         CURS_LEFT = tgetstr("bc", &bp);
 369:     if (CURS_LEFT == NULL && tgetflag("bs"))
 370:         CURS_LEFT = "\b";
 371: 
 372:     ENTER_STANDOUT =    tgetstr("so", &bp);
 373:     EXIT_STANDOUT =     tgetstr("se", &bp);
 374:     ENTER_UNDERLINE =   tgetstr("us", &bp);
 375:     EXIT_UNDERLINE =    tgetstr("ue", &bp);
 376:     ENTER_DIM =     tgetstr("mh", &bp);
 377:     ENTER_BOLD =        tgetstr("md", &bp);
 378:     ENTER_REVERSE =     tgetstr("mr", &bp);
 379:     EXIT_ATTRIBUTES =   tgetstr("me", &bp);
 380: 
 381:     if (!ENTER_BOLD && ENTER_REVERSE)
 382:         ENTER_BOLD = ENTER_REVERSE;
 383:     if (!ENTER_BOLD && ENTER_STANDOUT)
 384:         ENTER_BOLD = ENTER_STANDOUT;
 385:     if (!ENTER_UNDERLINE && ENTER_STANDOUT) {
 386:         ENTER_UNDERLINE = ENTER_STANDOUT;
 387:         EXIT_UNDERLINE = EXIT_STANDOUT;
 388:     }
 389:     if (!ENTER_DIM && ENTER_STANDOUT)
 390:         ENTER_DIM = ENTER_STANDOUT;
 391:     if (!ENTER_REVERSE && ENTER_STANDOUT)
 392:         ENTER_REVERSE = ENTER_STANDOUT;
 393:     if (!EXIT_ATTRIBUTES && EXIT_STANDOUT)
 394:         EXIT_ATTRIBUTES = EXIT_STANDOUT;
 395: 
 396:     /*
 397: 	 * Note that we use REVERSE for the alternate character set,
 398: 	 * not the as/ae capabilities.  This is because we are modelling
 399: 	 * the model 37 teletype (since that's what nroff outputs) and
 400: 	 * the typical as/ae is more of a graphics set, not the greek
 401: 	 * letters the 37 has.
 402: 	 */
 403: 
 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: }

Defined functions

filter defined in line 116; used 2 times
flushln defined in line 226; used 3 times
fwd defined in line 334; used 2 times
getopt defined in line 496; used 1 times
  • in line 66
iattr defined in line 302; used 1 times
initbuf defined in line 325; used 2 times
initcap defined in line 354; used 1 times
  • in line 98
main defined in line 51; never used
outc defined in line 422; used 2 times
outchar defined in line 408; used 1 times
overstrike defined in line 265; used 1 times
puts defined in line 414; used 14 times
reverse defined in line 345; used 2 times
setmode defined in line 432; used 3 times

Defined variables

CURS_LEFT defined in line 35; used 6 times
CURS_RIGHT defined in line 35; used 4 times
CURS_UP defined in line 35; used 3 times
ENTER_BOLD defined in line 37; used 7 times
ENTER_DIM defined in line 37; used 5 times
ENTER_REVERSE defined in line 37; used 6 times
ENTER_STANDOUT defined in line 36; used 10 times
ENTER_UNDERLINE defined in line 36; used 7 times
EXIT_ATTRIBUTES defined in line 37; used 4 times
EXIT_STANDOUT defined in line 36; used 4 times
EXIT_UNDERLINE defined in line 36; used 3 times
UNDER_CHAR defined in line 37; used 4 times
col defined in line 45; used 29 times
copyright defined in line 8; never used
halfpos defined in line 47; used 10 times
iflag defined in line 49; used 3 times
maxcol defined in line 45; used 13 times
mode defined in line 46; used 12 times
must_overstrike defined in line 34; used 2 times
must_use_uc defined in line 34; used 2 times
obuf defined in line 44; used 23 times
optarg defined in line 493; used 4 times
opterr defined in line 491; used 1 times
optind defined in line 492; used 22 times
sccsid defined in line 14; never used
upln defined in line 48; used 5 times

Defined struct's

CHAR defined in line 39; used 2 times
  • in line 44(2)

Defined macros

ALTSET defined in line 28; used 3 times
BOLD defined in line 32; used 1 times
ERR defined in line 485; used 2 times
FREV defined in line 24; never used
HFWD defined in line 22; never used
HREV defined in line 23; never used
IESC defined in line 19; used 1 times
MAXBUF defined in line 25; used 1 times
  • in line 44
NORMAL defined in line 27; used 5 times
SI defined in line 21; never used
SO defined in line 20; never used
SUBSC defined in line 30; used 2 times
SUPERSC defined in line 29; used 2 times
UNDERL defined in line 31; used 3 times
Last modified: 1985-05-31
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1963
Valid CSS Valid XHTML 1.0 Strict