Annotation of researchv10no/cmd/tabs.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *     tabs [tabspec] [+mn] [-Ttype]
        !             3:  *     set tabs (and margin, if +mn), for terminal type
        !             4:  */
        !             5: 
        !             6: static char tabsvers[] = "@(#)tabs.c   1.1";
        !             7: 
        !             8: #include <stdio.h>
        !             9: #include <signal.h>
        !            10: #include <sys/types.h>
        !            11: #include <sys/stat.h>
        !            12: #include <sys/ttyio.h>
        !            13: #define EQ(a,b)        (strcmp(a, b) == 0)
        !            14: /*     max # columns used (needed for GSI) */
        !            15: #define NCOLS  158
        !            16: #define NTABS  41      /* max # tabs +1 (to be set) */
        !            17: #define        NTABSCL 21      /* max # tabs + 1 that will be cleared */
        !            18: #define ESC    033
        !            19: #define CLEAR  '2'
        !            20: #define SET    '1'
        !            21: #define TAB    '\t'
        !            22: #define CR     '\r'
        !            23: #define NMG    0       /* no margin setting */
        !            24: #define GMG    1       /* DTC300s margin */
        !            25: #define TMG    2       /* TERMINET margin */
        !            26: #define DMG    3       /* DASI450 margin */
        !            27: #define FMG    4       /* TTY 43 margin */
        !            28: #define TRMG   5       /* Trendata 4000a */
        !            29: 
        !            30: #define TCLRLN 0       /* long, repetitive, general tab clear */
        !            31: 
        !            32: char   tclrhp[] = {ESC,'3',CR,0};      /* short for HP44,45,etc */
        !            33: char   tclrsh[] = {ESC,CLEAR,CR,0};    /* short sequence for many terminals */
        !            34: char   tclrgs[] = {ESC,TAB,CR,0};      /* short, for 300s */
        !            35: char   tclr40[] = {ESC,'R',CR,0};      /* TTY 40/2 */
        !            36: 
        !            37: struct ttab {
        !            38:        char *ttype;    /* -Tttype */
        !            39:        char *tclr;     /* char sequence to clear tabs and return carriage */
        !            40:        int tmaxtab;    /* maximum allowed position */
        !            41:        int tmarg;      /* type of margin setting allowed */
        !            42: } *tt;
        !            43: 
        !            44: struct ttab termtab[] = {
        !            45:        "",             tclrsh, 132,    NMG,
        !            46:        "1620",         tclrsh, 132,    DMG,
        !            47:        "1620-12",      tclrsh, 158,    DMG,
        !            48:        "1620-12-8",    tclrsh, 158,    DMG,
        !            49:        "1700",         tclrsh, 132,    DMG,
        !            50:        "1700-12",      tclrsh, 132,    DMG,
        !            51:        "1700-12-8",    tclrsh, 158,    DMG,
        !            52:        "2640",         TCLRLN,  80,    NMG,    /* hp 2640a & b */
        !            53:        "2645",         tclrhp,  80,    NMG,    /* all hp 40 series except 2640's */
        !            54:        "2621",         tclrhp,  80,    NMG,    /*  hp2621a and p */
        !            55:        "hp",           tclrhp,  80,    NMG,    /*  hp default */
        !            56:        "300",          TCLRLN, 132,    NMG,
        !            57:        "300-12",       TCLRLN, 158,    NMG,
        !            58:        "300s",         tclrgs, 132,    GMG,
        !            59:        "300s-12",      tclrgs, 158,    GMG,
        !            60:        "40-2",         tclr40,  80,    NMG,
        !            61:        "4000a",        tclrsh, 132,    TRMG,
        !            62:        "4000a-12",     tclrsh, 158,    TRMG,
        !            63:        "43",           "",     0,      FMG,
        !            64:        "450",          tclrsh, 132,    DMG,
        !            65:        "450-12",       tclrsh, 158,    DMG,
        !            66:        "450-12-8",     tclrsh, 158,    DMG,
        !            67:        "tn1200",       tclrsh, 118,    TMG,
        !            68:        "tn300",        tclrsh, 118,    TMG,
        !            69:        "1520",         "",     0,      NMG,
        !            70:        "3045",         "",     0,      NMG,
        !            71:        0
        !            72: };
        !            73: 
        !            74: 
        !            75: int    maxtab;         /* max tab for repetitive spec */
        !            76: int    margin; 
        !            77: int    margflg;        /* >0 ==> +m option used, 0 ==> not */
        !            78: char   *terminal = "";
        !            79: char   *tabspec = "-8";        /* default tab specification */
        !            80: 
        !            81: struct sgttyb ttyold;  /* tty table */
        !            82: int    ttysave;        /* save for modes */
        !            83: int    istty;          /* 1 ==> is actual tty */
        !            84: 
        !            85: struct stat    statbuf;
        !            86: char   *devtty;
        !            87: 
        !            88: int    endup();
        !            89: char   *getenv();
        !            90: struct ttab *termadj();
        !            91: 
        !            92: main(argc, argv)
        !            93: char **argv;
        !            94: {
        !            95:        int tabvect[NTABS];     /* build tab list here */
        !            96:        char *ttyname();
        !            97:        char *scan;     /* scan pointer to next char */
        !            98:        int endup();
        !            99: 
        !           100:        signal(SIGINT, endup);
        !           101:        if (ioctl(1, TIOCGETP, &ttyold) == 0) {
        !           102:                ttysave = ttyold.sg_flags;
        !           103:                fstat(1, &statbuf);
        !           104:                devtty = ttyname(1);
        !           105:                if (devtty && *devtty)
        !           106:                        chmod(devtty, 0000);    /* nobody, not even us */
        !           107:                istty++;
        !           108:        }
        !           109:        tabvect[0] = 0; /* mark as not yet filled in */
        !           110:        while (--argc > 0) {
        !           111:                scan = *++argv;
        !           112:                if (*scan == '+')
        !           113:                        switch (*++scan) {
        !           114:                        case 'm':
        !           115:                                margflg++;
        !           116:                                if (*++scan)
        !           117:                                        margin = getnum(&scan);
        !           118:                                else
        !           119:                                        margin = 10;
        !           120:                                break;
        !           121:                        }
        !           122:                else if (*scan == '-' && *(scan+1) == 'T')
        !           123:                        terminal = scan+2;
        !           124:                else
        !           125:                        tabspec = scan;         /* save tab specification */
        !           126:        }
        !           127:        if (*terminal == '\0') {
        !           128:                terminal = getenv("TERM");
        !           129:                if (terminal == NULL)
        !           130:                        terminal = "";
        !           131:        }
        !           132:        tt = termadj();
        !           133:        maxtab = tt->tmaxtab;
        !           134:        scantab(tabspec,tabvect,0);
        !           135:        if (!tabvect[0])
        !           136:                repetab("8",tabvect);
        !           137:        settabs(tabvect);
        !           138:        endup();
        !           139:        exit(0);
        !           140: }
        !           141: 
        !           142: /*     scantab: scan 1 tabspec & return tab list for it */
        !           143: 
        !           144: scantab(scan,tabvect,level)
        !           145: char *scan;
        !           146: int tabvect[NTABS], level;
        !           147: {
        !           148:        register char c;
        !           149:        if (*scan == '-')
        !           150:                if ((c = *++scan) == '-')
        !           151:                        filetab(++scan,tabvect,level);
        !           152:                else if (c >= '0' && c <= '9')
        !           153:                        repetab(scan,tabvect);
        !           154:                else if (stdtab(scan,tabvect))
        !           155:                        error("unknown tab code");
        !           156:                else;
        !           157:        else
        !           158:                arbitab(scan,tabvect);
        !           159: }
        !           160: 
        !           161: /*     repetab: scan and set repetitve tabs, 1+n, 1+2*n, etc */
        !           162: 
        !           163: repetab(scan,tabvect)
        !           164: char *scan;
        !           165: int tabvect[NTABS];
        !           166: {
        !           167:        register incr, i, tabn;
        !           168:        int limit;
        !           169:        incr = getnum(&scan);
        !           170:        tabn = 1;
        !           171:        limit = (maxtab-1)/(incr?incr:1)-1; /* # last actual tab */
        !           172:        if (limit>NTABS-2)
        !           173:                limit = NTABS-2;
        !           174:        for (i = 0; i<=limit; i++)
        !           175:                tabvect[i] = tabn += incr;
        !           176:        tabvect[i] = 0;
        !           177: }
        !           178: 
        !           179: /*     arbitab: handle list of arbitrary tabs */
        !           180: 
        !           181: arbitab(scan,tabvect)
        !           182: char *scan;
        !           183: int tabvect[NTABS];
        !           184: {
        !           185:        register i, t, last;
        !           186:        last = 0;
        !           187:        for (i = 0; i<NTABS-1;) {
        !           188:                if (*scan == '+') {
        !           189:                        scan++;         /* +n ==> increment, not absolute */
        !           190:                        if (t = getnum(&scan))
        !           191:                                tabvect[i++] = last += t;
        !           192:                        else error("illegal increment");
        !           193:                }
        !           194:                else {
        !           195:                        if ((t = getnum(&scan)) > last)
        !           196:                                tabvect[i++] = last = t;
        !           197:                        else error("illegal tabs");
        !           198:                }
        !           199:                if (*scan++ != ',') break;
        !           200:        }
        !           201:        if (last > NCOLS)
        !           202:                error("illegal tabs");
        !           203:        tabvect[i] = 0;
        !           204: }
        !           205: 
        !           206: /*     filetab: copy tabspec from existing file */
        !           207: #define CARDSIZ        132
        !           208: filetab(scan,tabvect,level)
        !           209: char *scan;
        !           210: int tabvect[NTABS];
        !           211: {
        !           212:        register length, i;
        !           213:        register char c;
        !           214:        int fildes;
        !           215:        char card[CARDSIZ];     /* buffer area for 1st card in file */
        !           216:        char state, found;
        !           217:        char *temp;
        !           218:        if (level)
        !           219:                error("file indirection");
        !           220:        if ((fildes = open(scan,0)) < 0)
        !           221:                error("can't open");
        !           222:        length = read(fildes,card,CARDSIZ);
        !           223:        close(fildes);
        !           224:        found = state = 0;
        !           225:        scan = 0;
        !           226:        for (i = 0; i<length && (c = card[i]) != '\n'; i++) {
        !           227:                switch (state) {
        !           228:                case 0:
        !           229:                        state = (c == '<'); break;
        !           230:                case 1:
        !           231:                        state = (c == ':')?2:0; break;
        !           232:                case 2:
        !           233:                        if (c == 't')
        !           234:                                state = 3;
        !           235:                        else if (c == ':')
        !           236:                                state = 6;
        !           237:                        else if (c != ' ')
        !           238:                                state = 5;
        !           239:                        break;
        !           240:                case 3:
        !           241:                        if (c == ' ')
        !           242:                                state = 2;
        !           243:                        else {
        !           244:                                scan = &card[i];
        !           245:                                state = 4;
        !           246:                        }
        !           247:                        break;
        !           248:                case 4:
        !           249:                        if (c == ' ') {
        !           250:                                card[i] = '\0';
        !           251:                                state = 5;
        !           252:                        }
        !           253:                        else if (c == ':') {
        !           254:                                card[i] = '\0';
        !           255:                                state = 6;
        !           256:                        }
        !           257:                        break;
        !           258:                case 5:
        !           259:                        if (c == ' ')
        !           260:                                state = 2;
        !           261:                        else if (c == ':')
        !           262:                                state = 6;
        !           263:                        break;
        !           264:                case 6:
        !           265:                        if (c == '>') {
        !           266:                                found = 1;
        !           267:                                goto done;
        !           268:                        }
        !           269:                        else state = 5;
        !           270:                        break;
        !           271:                }
        !           272:        }
        !           273: done:
        !           274:        if (found && scan != 0) {
        !           275:                scantab(scan,tabvect,1);
        !           276:                temp = scan;
        !           277:                while (*++temp);
        !           278:                *temp = '\n';
        !           279:        }
        !           280:        else scantab("-8",tabvect,1);
        !           281: }
        !           282: 
        !           283: struct ttab *
        !           284: termadj()
        !           285: {
        !           286:        register struct ttab *t;
        !           287: 
        !           288:        for (t = termtab; t->ttype; t++) {
        !           289:                if (EQ(terminal, t->ttype))
        !           290:                        return(t);
        !           291:        }
        !           292: /* should have message */
        !           293:        return(termtab);
        !           294: }
        !           295: 
        !           296: char   *cleartabs();
        !           297: /*     settabs: set actual tabs at terminal */
        !           298: /*     note: this code caters to necessities of handling GSI and
        !           299:        other terminals in a consistent way. */
        !           300: 
        !           301: settabs(tabvect)
        !           302: int tabvect[NTABS];
        !           303: {
        !           304:        char setbuf[400];       /* 2+3*NTABS+2+NCOLS+NTABS (+ some extra) */
        !           305:        register char *p;               /* ptr for assembly in setbuf */
        !           306:        register *curtab;               /* ptr to tabvect item */
        !           307:        int i, previous, nblanks;
        !           308:        if (istty) {
        !           309:                ttyold.sg_flags &= ~(CRMOD);
        !           310:                ioctl(1, TIOCSETN, &ttyold);    /* turn off cr-lf map */
        !           311:        }
        !           312:        p = setbuf;
        !           313:        *p++ = CR;
        !           314:        p = cleartabs(p, tt->tclr);
        !           315: 
        !           316:        if (margflg)
        !           317:                switch(tt->tmarg) {
        !           318:                case GMG:       /* GSI300S */
        !           319:                /* NOTE: the 300S appears somewhat odd, in that there is
        !           320:                a column 0, but there is no way to do a direct tab to it.
        !           321:                The sequence ESC 'T' '\0' jumps to column 27 and prints
        !           322:                a '0', without changing the margin. */
        !           323:                        *p++ = ESC;
        !           324:                        *p++ = 'T';     /* setup for direct tab */
        !           325:                        if (margin &= 0177)     /* normal case */
        !           326:                                *p++ = margin;
        !           327:                        else {                  /* +m0 case */
        !           328:                                *p++ = 1;       /* column 1 */
        !           329:                                *p++ = '\b';    /* column 0 */
        !           330:                        }
        !           331:                        *p++ = margin;  /* direct horizontal tab */
        !           332:                        *p++ = ESC;
        !           333:                        *p++ = '0';     /* actual margin set */
        !           334:                        break;
        !           335:                case TMG:       /* TERMINET 300 & 1200 */
        !           336:                        while (margin--)
        !           337:                                *p++ = ' ';
        !           338:                        break;
        !           339:                case DMG:       /* DASI450/DIABLO 1620 */
        !           340:                        *p++ = ESC;     /* direct tab ignores margin */
        !           341:                        *p++ = '\t';
        !           342:                        if (margin == 3){
        !           343:                                *p++ = (margin & 0177);
        !           344:                                *p++ = ' ';
        !           345:                        }
        !           346:                        else
        !           347:                                *p++ = (margin & 0177) + 1;
        !           348:                        *p++ = ESC;
        !           349:                        *p++ = '9';
        !           350:                        break;
        !           351:                case FMG:       /* TTY 43 */
        !           352:                        p--;
        !           353:                        *p++ = ESC;
        !           354:                        *p++ = 'x';
        !           355:                        *p++ = CR;
        !           356:                        while (margin--)
        !           357:                                *p++ = ' ';
        !           358:                        *p++ = ESC;
        !           359:                        *p++ = 'l';
        !           360:                        *p++ = CR;
        !           361:                        write(1, setbuf, p - setbuf);
        !           362:                        return;
        !           363:                case TRMG:
        !           364:                        p--;
        !           365:                        *p++ = ESC;
        !           366:                        *p++ = 'N';
        !           367:                        while (margin--)
        !           368:                                *p++ = ' ';
        !           369:                        *p++ = ESC;
        !           370:                        *p++ = 'F';
        !           371:                        break;
        !           372:                }
        !           373: 
        !           374: /*
        !           375:  *     actual setting: at least terminals do this consistently!
        !           376:  */
        !           377:        previous = 1; curtab = tabvect;
        !           378:        while ((nblanks = *curtab-previous) >= 0 &&
        !           379:                previous + nblanks <= maxtab) {
        !           380:                for (i = 1; i <= nblanks; i++) *p++ = ' ';
        !           381:                previous = *curtab++;
        !           382:                *p++ =ESC;
        !           383:                *p++ = SET;
        !           384:        }
        !           385:        *p++ = CR;
        !           386:        if (tt->tclr && EQ(tt->tclr, tclr40))
        !           387:                *p++ = '\n';    /* TTY40/2 needs LF, not just CR */
        !           388:        write(1, setbuf, p - setbuf);
        !           389: }
        !           390: 
        !           391: /*     cleartabs(pointer to buffer, pointer to clear sequence */
        !           392: char *cleartabs(p, qq)
        !           393: register char *p;
        !           394: char *qq;
        !           395: {
        !           396:        register i;
        !           397:        register char *q;
        !           398:        q = qq;
        !           399:         if (q == TCLRLN) {      /* if repetitive sequence */
        !           400:                *p++ = CR;
        !           401:                for(i = 0; i < NTABSCL - 1; i++) {
        !           402:                        *p++ = TAB;
        !           403:                        *p++ = ESC;
        !           404:                        *p++ = CLEAR;
        !           405:                }
        !           406:                *p++ = CR;
        !           407:        }
        !           408:        else {
        !           409:                while(*p++ = *q++);     /* copy table sequence */
        !           410:                p--;                    /* adjust for null */
        !           411:                if (qq == tclr40) {     /* TTY40 extra delays needed */
        !           412:                        *p++ = '\0';
        !           413:                        *p++ = '\0';
        !           414:                        *p++ = '\0';
        !           415:                        *p++ = '\0';
        !           416:                }
        !           417:        }
        !           418:        return(p);
        !           419: }
        !           420: /*     getnum: scan and convert number, return zero if none found */
        !           421: /*     set scan ptr to addr of ending delimeter */
        !           422: getnum(scan1)
        !           423: char **scan1;
        !           424: {
        !           425:        register n;
        !           426:        register char c, *scan;
        !           427:        n = 0;
        !           428:        scan = *scan1;
        !           429:        while ((c = *scan++) >= '0' && c <= '9') n = n * 10 + c -'0';
        !           430:        *scan1 = --scan;
        !           431:        return(n);
        !           432: }
        !           433: 
        !           434: /*     error: terminate processing with message to terminal */
        !           435: error(arg)
        !           436: char *arg;
        !           437: {
        !           438:        register char *temp;
        !           439:        temp = arg;
        !           440:        while (*++temp);        /* get length */
        !           441:        *temp = '\n';
        !           442:        endup();
        !           443:        write(2, arg, temp+1-arg);
        !           444:        exit(1);
        !           445: }
        !           446: 
        !           447: /*     endup: make sure tty mode reset & exit */
        !           448: endup()
        !           449: {
        !           450:        if (istty) {
        !           451:                ttyold.sg_flags = ttysave;
        !           452:                ioctl(1, TIOCSETN, &ttyold);    /* reset cr-lf to previous */
        !           453:                if (devtty && *devtty)
        !           454:                        chmod(devtty, statbuf.st_mode & 0777);
        !           455:        }
        !           456: }
        !           457: 
        !           458: /*     stdtabs: standard tabs table
        !           459:        format: option code letter(s), null, tabs, null */
        !           460: char stdtabs[] = {
        !           461: 'a',   0,1,10,16,36,72,0,                      /* IBM 370 Assembler */
        !           462: 'a','2',0,1,10,16,40,72,0,                     /* IBM Assembler alternative*/
        !           463: 'c',   0,1,8,12,16,20,55,0,                    /* COBOL, normal */
        !           464: 'c','2',0,1,6,10,14,49,0,                      /* COBOL, crunched*/
        !           465: 'c','3',0,1,6,10,14,18,22,26,30,34,38,42,46,50,54,58,62,67,0,
        !           466:                                                /* crunched COBOL, many tabs */
        !           467: 'f',   0,1,7,11,15,19,23,0,                    /* FORTRAN */
        !           468: 'p',   0,1,5,9,13,17,21,25,29,33,37,41,45,49,53,57,61,0, /* PL/I */
        !           469: 's',   0,1,10,55,0,                            /* SNOBOL */
        !           470: 'u',   0,1,12,20,44,0,                         /* UNIVAC ASM */
        !           471: 0};
        !           472: 
        !           473: /*     stdtab: return tab list for any "canned" tab option.
        !           474:        entry: option points to null-terminated option string
        !           475:                tabvect points to vector to be filled in
        !           476:        exit: return(0) if legal, tabvect filled, ending with zero
        !           477:                return(-1) if unknown option
        !           478: */
        !           479: stdtab(option,tabvect)
        !           480: char option[];
        !           481: int tabvect[];
        !           482: {
        !           483:        register char *sp;
        !           484:        tabvect[0] = 0;
        !           485:        sp = stdtabs;
        !           486:        while (*sp) {
        !           487:                if (EQ(option,sp)) {
        !           488:                        while (*sp++);          /* skip to 1st tab value */
        !           489:                        while (*tabvect++ = *sp++);     /* copy, make int */
        !           490:                        return(0);
        !           491:                }
        !           492:                while(*sp++);   /* skip to 1st tab value */
        !           493:                while(*sp++);           /* skip over tab list */
        !           494:        }
        !           495:        return(-1);
        !           496: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.