Annotation of researchv10no/cmd/troff/n4.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * troff4.c
                      3:  *
                      4:  * number registers, conversion, arithmetic
                      5:  */
                      6: 
                      7: #include "tdef.h"
                      8: #include "fns.h"
                      9: #include "ext.h"
                     10: 
                     11: 
                     12: int    regcnt = NNAMES;
                     13: int    falsef  = 0;    /* on if inside false branch of if */
                     14: 
                     15: #define        NHASHSIZE       128     /* must be 2**n */
                     16: #define        NHASH(i)        ((i>>6)^i) & (NHASHSIZE-1)
                     17: Numtab *nhash[NHASHSIZE];
                     18: 
                     19: void setn(void)
                     20: {
                     21:        int i, j, f;
                     22:        Tchar ii;
                     23:        char *p;
                     24:        char buf[NTM];          /* for \n(.S */
                     25: 
                     26:        f = nform = 0;
                     27:        if ((i = cbits(ii = getach())) == '+')
                     28:                f = 1;
                     29:        else if (i == '-')
                     30:                f = -1;
                     31:        else if (ii)    /* don't put it back if it's already back (thanks to jaap) */
                     32:                ch = ii;
                     33:        if (falsef)
                     34:                f = 0;
                     35:        if ((i = getsn()) == 0)
                     36:                return;
                     37:        p = unpair(i);
                     38:        if (p[0] == '.')
                     39:                switch (p[1]) {
                     40:                case 's':
                     41:                        i = pts;
                     42:                        break;
                     43:                case 'v':
                     44:                        i = lss;
                     45:                        break;
                     46:                case 'f':
                     47:                        i = font;
                     48:                        break;
                     49:                case 'p':
                     50:                        i = pl;
                     51:                        break;
                     52:                case 't':
                     53:                        i = findt1();
                     54:                        break;
                     55:                case 'o':
                     56:                        i = po;
                     57:                        break;
                     58:                case 'l':
                     59:                        i = ll;
                     60:                        break;
                     61:                case 'i':
                     62:                        i = in;
                     63:                        break;
                     64:                case '$':
                     65:                        i = frame->nargs;
                     66:                        break;
                     67:                case 'A':
                     68:                        i = ascii;
                     69:                        break;
                     70:                case 'c':
                     71:                        i = numtab[CD].val;
                     72:                        break;
                     73:                case 'n':
                     74:                        i = lastl;
                     75:                        break;
                     76:                case 'a':
                     77:                        i = ralss;
                     78:                        break;
                     79:                case 'h':
                     80:                        i = dip->hnl;
                     81:                        break;
                     82:                case 'd':
                     83:                        if (dip != d)
                     84:                                i = dip->dnl;
                     85:                        else
                     86:                                i = numtab[NL].val;
                     87:                        break;
                     88:                case 'u':
                     89:                        i = fi;
                     90:                        break;
                     91:                case 'j':
                     92:                        i = ad + 2 * admod;
                     93:                        break;
                     94:                case 'w':
                     95:                        i = widthp;
                     96:                        break;
                     97:                case 'x':
                     98:                        i = nel;
                     99:                        break;
                    100:                case 'y':
                    101:                        i = un;
                    102:                        break;
                    103:                case 'T':
                    104:                        i = dotT;
                    105:                        break;   /* -Tterm used in nroff */
                    106:                case 'V':
                    107:                        i = VERT;
                    108:                        break;
                    109:                case 'H':
                    110:                        i = HOR;
                    111:                        break;
                    112:                case 'k':
                    113:                        i = ne;
                    114:                        break;
                    115:                case 'P':
                    116:                        i = print;
                    117:                        break;
                    118:                case 'L':
                    119:                        i = ls;
                    120:                        break;
                    121:                case 'R':
                    122:                        i = NN - regcnt;
                    123:                        break;
                    124:                case 'z':
                    125:                        p = unpair(dip->curd);
                    126:                        *pbp++ = p[1];  /* watch order */
                    127:                        *pbp++ = p[0];
                    128:                        return;
                    129:                case 'b':
                    130:                        i = bdtab[font];
                    131:                        break;
                    132:                case 'F':
                    133:                        cpushback(cfname[ifi]);
                    134:                        return;
                    135:                case 'S':
                    136:                        buf[0] = j = 0; 
                    137:                        for( i = 0; tabtab[i] != 0 && i < NTAB; i++) {
                    138:                                if (i > 0)
                    139:                                        buf[j++] = ' ';
                    140:                                sprintf(&buf[j], "%d", tabtab[i] & TABMASK);
                    141:                                j = strlen(buf);
                    142:                                if ( tabtab[i] & RTAB)
                    143:                                        sprintf(&buf[j], "uR");
                    144:                                else if (tabtab[i] & CTAB)
                    145:                                        sprintf(&buf[j], "uC");
                    146:                                else
                    147:                                        sprintf(&buf[j], "uL");
                    148:                                j += 2;
                    149:                        }
                    150:                        cpushback(buf);
                    151:                        return;
                    152:                default:
                    153:                        goto s0;
                    154:                }
                    155:        else {
                    156: s0:
                    157:                if ((j = findr(i)) == -1)
                    158:                        i = 0;
                    159:                else {
                    160:                        i = numtab[j].val = numtab[j].val + numtab[j].inc * f;
                    161:                        nform = numtab[j].fmt;
                    162:                }
                    163:        }
                    164:        setn1(i, nform, (Tchar) 0);
                    165: }
                    166: 
                    167: Tchar  numbuf[25];
                    168: Tchar  *numbufp;
                    169: 
                    170: int wrc(Tchar i)
                    171: {
                    172:        if (numbufp >= &numbuf[24])
                    173:                return(0);
                    174:        *numbufp++ = i;
                    175:        return(1);
                    176: }
                    177: 
                    178: 
                    179: 
                    180: /* insert into input number i, in format form, with size-font bits bits */
                    181: void setn1(int i, int form, Tchar bits)
                    182: {
                    183:        numbufp = numbuf;
                    184:        nrbits = bits;
                    185:        nform = form;
                    186:        fnumb(i, wrc);
                    187:        *numbufp = 0;
                    188:        pushback(numbuf);
                    189: }
                    190: 
                    191: 
                    192: void nrehash(void)
                    193: {
                    194:        Numtab *p;
                    195:        int i;
                    196: 
                    197:        for (i=0; i<NHASHSIZE; i++)
                    198:                nhash[i] = 0;
                    199:        for (p=numtab; p < &numtab[NN]; p++)
                    200:                p->link = 0;
                    201:        for (p=numtab; p < &numtab[NN]; p++) {
                    202:                if (p->r == 0)
                    203:                        continue;
                    204:                i = NHASH(p->r);
                    205:                p->link = nhash[i];
                    206:                nhash[i] = p;
                    207:        }
                    208: }
                    209: 
                    210: void nunhash(Numtab *rp)
                    211: {
                    212:        Numtab *p;
                    213:        Numtab **lp;
                    214: 
                    215:        if (rp->r == 0)
                    216:                return;
                    217:        lp = &nhash[NHASH(rp->r)];
                    218:        p = *lp;
                    219:        while (p) {
                    220:                if (p == rp) {
                    221:                        *lp = p->link;
                    222:                        p->link = 0;
                    223:                        return;
                    224:                }
                    225:                lp = &p->link;
                    226:                p = p->link;
                    227:        }
                    228: }
                    229: 
                    230: int findr(int i)
                    231: {
                    232:        Numtab *p;
                    233:        int h = NHASH(i);
                    234: 
                    235:        if (i == 0)
                    236:                return(-1);
                    237:        for (p = nhash[h]; p; p = p->link)
                    238:                if (i == p->r)
                    239:                        return(p - numtab);
                    240:        for (p = numtab; p < &numtab[NN]; p++) {
                    241:                if (p->r == 0) {
                    242:                        p->r = i;
                    243:                        p->link = nhash[h];
                    244:                        nhash[h] = p;
                    245:                        regcnt++;
                    246:                        return(p - numtab);
                    247:                }
                    248:        }
                    249:        ERROR "too many number registers (%d).", NN WARN;
                    250:        done2(04);
                    251:        /* NOTREACHED */
                    252:        return -1;
                    253: }
                    254: 
                    255: int usedr(int i)       /* returns -1 if nr i has never been used */
                    256: {
                    257:        Numtab *p;
                    258: 
                    259:        if (i == 0)
                    260:                return(-1);
                    261:        for (p = nhash[NHASH(i)]; p; p = p->link)
                    262:                if (i == p->r)
                    263:                        return(p - numtab);
                    264:        return -1;
                    265: }
                    266: 
                    267: 
                    268: int fnumb(int i, int (*f)(Tchar))
                    269: {
                    270:        int j;
                    271: 
                    272:        j = 0;
                    273:        if (i < 0) {
                    274:                j = (*f)('-' | nrbits);
                    275:                i = -i;
                    276:        }
                    277:        switch (nform) {
                    278:        default:
                    279:        case '1':
                    280:        case 0:
                    281:                return decml(i, f) + j;
                    282:        case 'i':
                    283:        case 'I':
                    284:                return roman(i, f) + j;
                    285:        case 'a':
                    286:        case 'A':
                    287:                return abc(i, f) + j;
                    288:        }
                    289: }
                    290: 
                    291: 
                    292: int decml(int i, int (*f)(Tchar))
                    293: {
                    294:        int j, k;
                    295: 
                    296:        k = 0;
                    297:        nform--;
                    298:        if ((j = i / 10) || (nform > 0))
                    299:                k = decml(j, f);
                    300:        return(k + (*f)((i % 10 + '0') | nrbits));
                    301: }
                    302: 
                    303: 
                    304: int roman(int i, int (*f)(Tchar))
                    305: {
                    306: 
                    307:        if (!i)
                    308:                return((*f)('0' | nrbits));
                    309:        if (nform == 'i')
                    310:                return(roman0(i, f, "ixcmz", "vldw"));
                    311:        else
                    312:                return(roman0(i, f, "IXCMZ", "VLDW"));
                    313: }
                    314: 
                    315: 
                    316: int roman0(int i, int (*f)(Tchar), char *onesp, char *fivesp)
                    317: {
                    318:        int q, rem, k;
                    319: 
                    320:        if (!i)
                    321:                return(0);
                    322:        k = roman0(i / 10, f, onesp + 1, fivesp + 1);
                    323:        q = (i = i % 10) / 5;
                    324:        rem = i % 5;
                    325:        if (rem == 4) {
                    326:                k += (*f)(*onesp | nrbits);
                    327:                if (q)
                    328:                        i = *(onesp + 1);
                    329:                else
                    330:                        i = *fivesp;
                    331:                return(k += (*f)(i | nrbits));
                    332:        }
                    333:        if (q)
                    334:                k += (*f)(*fivesp | nrbits);
                    335:        while (--rem >= 0)
                    336:                k += (*f)(*onesp | nrbits);
                    337:        return(k);
                    338: }
                    339: 
                    340: 
                    341: int abc(int i, int (*f)(Tchar))
                    342: {
                    343:        if (!i)
                    344:                return((*f)('0' | nrbits));
                    345:        else
                    346:                return(abc0(i - 1, f));
                    347: }
                    348: 
                    349: 
                    350: int abc0(int i, int (*f)(Tchar))
                    351: {
                    352:        int j, k;
                    353: 
                    354:        k = 0;
                    355:        if (j = i / 26)
                    356:                k = abc0(j - 1, f);
                    357:        return(k + (*f)((i % 26 + nform) | nrbits));
                    358: }
                    359: 
                    360: long atoi0(void)
                    361: {
                    362:        int c, k, cnt;
                    363:        Tchar ii;
                    364:        long i, acc;
                    365: 
                    366:        acc = 0;
                    367:        nonumb = 0;
                    368:        cnt = -1;
                    369: a0:
                    370:        cnt++;
                    371:        ii = getch();
                    372:        c = cbits(ii);
                    373:        switch (c) {
                    374:        default:
                    375:                ch = ii;
                    376:                if (cnt)
                    377:                        break;
                    378:        case '+':
                    379:                i = ckph();
                    380:                if (nonumb)
                    381:                        break;
                    382:                acc += i;
                    383:                goto a0;
                    384:        case '-':
                    385:                i = ckph();
                    386:                if (nonumb)
                    387:                        break;
                    388:                acc -= i;
                    389:                goto a0;
                    390:        case '*':
                    391:                i = ckph();
                    392:                if (nonumb)
                    393:                        break;
                    394:                acc *= i;
                    395:                goto a0;
                    396:        case '/':
                    397:                i = ckph();
                    398:                if (nonumb)
                    399:                        break;
                    400:                if (i == 0) {
                    401:                        flusho();
                    402:                        ERROR "divide by zero." WARN;
                    403:                        acc = 0;
                    404:                } else
                    405:                        acc /= i;
                    406:                goto a0;
                    407:        case '%':
                    408:                i = ckph();
                    409:                if (nonumb)
                    410:                        break;
                    411:                acc %= i;
                    412:                goto a0;
                    413:        case '&':       /*and*/
                    414:                i = ckph();
                    415:                if (nonumb)
                    416:                        break;
                    417:                if ((acc > 0) && (i > 0))
                    418:                        acc = 1;
                    419:                else
                    420:                        acc = 0;
                    421:                goto a0;
                    422:        case ':':       /*or*/
                    423:                i = ckph();
                    424:                if (nonumb)
                    425:                        break;
                    426:                if ((acc > 0) || (i > 0))
                    427:                        acc = 1;
                    428:                else
                    429:                        acc = 0;
                    430:                goto a0;
                    431:        case '=':
                    432:                if (cbits(ii = getch()) != '=')
                    433:                        ch = ii;
                    434:                i = ckph();
                    435:                if (nonumb) {
                    436:                        acc = 0;
                    437:                        break;
                    438:                }
                    439:                if (i == acc)
                    440:                        acc = 1;
                    441:                else
                    442:                        acc = 0;
                    443:                goto a0;
                    444:        case '>':
                    445:                k = 0;
                    446:                if (cbits(ii = getch()) == '=')
                    447:                        k++;
                    448:                else
                    449:                        ch = ii;
                    450:                i = ckph();
                    451:                if (nonumb) {
                    452:                        acc = 0;
                    453:                        break;
                    454:                }
                    455:                if (acc > (i - k))
                    456:                        acc = 1;
                    457:                else
                    458:                        acc = 0;
                    459:                goto a0;
                    460:        case '<':
                    461:                k = 0;
                    462:                if (cbits(ii = getch()) == '=')
                    463:                        k++;
                    464:                else
                    465:                        ch = ii;
                    466:                i = ckph();
                    467:                if (nonumb) {
                    468:                        acc = 0;
                    469:                        break;
                    470:                }
                    471:                if (acc < (i + k))
                    472:                        acc = 1;
                    473:                else
                    474:                        acc = 0;
                    475:                goto a0;
                    476:        case ')':
                    477:                break;
                    478:        case '(':
                    479:                acc = atoi0();
                    480:                goto a0;
                    481:        }
                    482:        return(acc);
                    483: }
                    484: 
                    485: 
                    486: long ckph(void)
                    487: {
                    488:        Tchar i;
                    489:        long j;
                    490: 
                    491:        if (cbits(i = getch()) == '(')
                    492:                j = atoi0();
                    493:        else {
                    494:                j = atoi1(i);
                    495:        }
                    496:        return(j);
                    497: }
                    498: 
                    499: 
                    500: long atoi1(Tchar ii)
                    501: {
                    502:        int i, j, digits;
                    503:        double acc;     /* this is the only double in troff! */
                    504:        int neg, abs, field;
                    505: 
                    506:        neg = abs = field = digits = 0;
                    507:        acc = 0;
                    508:        for (;;) {
                    509:                i = cbits(ii);
                    510:                switch (i) {
                    511:                default:
                    512:                        break;
                    513:                case '+':
                    514:                        ii = getch();
                    515:                        continue;
                    516:                case '-':
                    517:                        neg = 1;
                    518:                        ii = getch();
                    519:                        continue;
                    520:                case '|':
                    521:                        abs = 1 + neg;
                    522:                        neg = 0;
                    523:                        ii = getch();
                    524:                        continue;
                    525:                }
                    526:                break;
                    527:        }
                    528: a1:
                    529:        while (i >= '0' && i <= '9') {
                    530:                field++;
                    531:                digits++;
                    532:                acc = 10 * acc + i - '0';
                    533:                ii = getch();
                    534:                i = cbits(ii);
                    535:        }
                    536:        if (i == '.') {
                    537:                field++;
                    538:                digits = 0;
                    539:                ii = getch();
                    540:                i = cbits(ii);
                    541:                goto a1;
                    542:        }
                    543:        if (!field) {
                    544:                ch = ii;
                    545:                goto a2;
                    546:        }
                    547:        switch (i) {
                    548:        case 'u':
                    549:                i = j = 1;      /* should this be related to HOR?? */
                    550:                break;
                    551:        case 'v':       /*VSs - vert spacing*/
                    552:                j = lss;
                    553:                i = 1;
                    554:                break;
                    555:        case 'm':       /*Ems*/
                    556:                j = EM;
                    557:                i = 1;
                    558:                break;
                    559:        case 'n':       /*Ens*/
                    560:                j = EM;
                    561:                if (TROFF)
                    562:                        i = 2;
                    563:                else
                    564:                        i = 1;  /*Same as Ems in NROFF*/
                    565:                break;
                    566:        case 'p':       /*Points*/
                    567:                j = INCH;
                    568:                i = 72;
                    569:                break;
                    570:        case 'i':       /*Inches*/
                    571:                j = INCH;
                    572:                i = 1;
                    573:                break;
                    574:        case 'c':       /*Centimeters*/
                    575:                /* if INCH is too big, this will overflow */
                    576:                j = INCH * 50;
                    577:                i = 127;
                    578:                break;
                    579:        case 'P':       /*Picas*/
                    580:                j = INCH;
                    581:                i = 6;
                    582:                break;
                    583:        default:
                    584:                j = dfact;
                    585:                ch = ii;
                    586:                i = dfactd;
                    587:        }
                    588:        if (neg)
                    589:                acc = -acc;
                    590:        if (!noscale) {
                    591:                acc = (acc * j) / i;
                    592:        }
                    593:        if (field != digits && digits > 0)
                    594:                while (digits--)
                    595:                        acc /= 10;
                    596:        if (abs) {
                    597:                if (dip != d)
                    598:                        j = dip->dnl;
                    599:                else
                    600:                        j = numtab[NL].val;
                    601:                if (!vflag) {
                    602:                        j = numtab[HP].val;
                    603:                }
                    604:                if (abs == 2)
                    605:                        j = -j;
                    606:                acc -= j;
                    607:        }
                    608: a2:
                    609:        nonumb = !field;
                    610:        return(acc);
                    611: }
                    612: 
                    613: 
                    614: void caserr(void)
                    615: {
                    616:        int i, j;
                    617:        Numtab *p;
                    618: 
                    619:        lgf++;
                    620:        while (!skip() && (i = getrq()) ) {
                    621:                j = usedr(i);
                    622:                if (j < 0)
                    623:                        continue;
                    624:                p = &numtab[j];
                    625:                nunhash(p);
                    626:                p->r = p->val = p->inc = p->fmt = 0;
                    627:                regcnt--;
                    628:        }
                    629: }
                    630: 
                    631: 
                    632: void casenr(void)
                    633: {
                    634:        int i, j;
                    635: 
                    636:        lgf++;
                    637:        skip();
                    638:        if ((i = findr(getrq())) == -1)
                    639:                goto rtn;
                    640:        skip();
                    641:        j = inumb(&numtab[i].val);
                    642:        if (nonumb)
                    643:                goto rtn;
                    644:        numtab[i].val = j;
                    645:        skip();
                    646:        j = atoi0();            /* BUG??? */
                    647:        if (nonumb)
                    648:                goto rtn;
                    649:        numtab[i].inc = j;
                    650: rtn:
                    651:        return;
                    652: }
                    653: 
                    654: void caseaf(void)
                    655: {
                    656:        int i, k;
                    657:        Tchar j;
                    658: 
                    659:        lgf++;
                    660:        if (skip() || !(i = getrq()) || skip())
                    661:                return;
                    662:        k = 0;
                    663:        j = getch();
                    664:        if (!isalpha(cbits(j))) {
                    665:                ch = j;
                    666:                while ((j = cbits(getch())) >= '0' &&  j <= '9')
                    667:                        k++;
                    668:        }
                    669:        if (!k)
                    670:                k = j;
                    671:        numtab[findr(i)].fmt = k;       /* was k & BYTEMASK */
                    672: }
                    673: 
                    674: void setaf(void)       /* return format of number register */
                    675: {
                    676:        int i, j;
                    677: 
                    678:        i = usedr(getsn());
                    679:        if (i == -1)
                    680:                return;
                    681:        if (numtab[i].fmt > 20) /* it was probably a, A, i or I */
                    682:                *pbp++ = numtab[i].fmt;
                    683:        else
                    684:                for (j = (numtab[i].fmt ? numtab[i].fmt : 1); j; j--)
                    685:                        *pbp++ = '0';
                    686: }
                    687: 
                    688: 
                    689: int vnumb(int *i)
                    690: {
                    691:        vflag++;
                    692:        dfact = lss;
                    693:        res = VERT;
                    694:        return(inumb(i));
                    695: }
                    696: 
                    697: 
                    698: int hnumb(int *i)
                    699: {
                    700:        dfact = EM;
                    701:        res = HOR;
                    702:        return(inumb(i));
                    703: }
                    704: 
                    705: 
                    706: int inumb(int *n)
                    707: {
                    708:        int i, j, f;
                    709:        Tchar ii;
                    710: 
                    711:        f = 0;
                    712:        if (n) {
                    713:                if ((j = cbits(ii = getch())) == '+')
                    714:                        f = 1;
                    715:                else if (j == '-')
                    716:                        f = -1;
                    717:                else
                    718:                        ch = ii;
                    719:        }
                    720:        i = atoi0();
                    721:        if (n && f)
                    722:                i = *n + f * i;
                    723:        i = quant(i, res);
                    724:        vflag = 0;
                    725:        res = dfactd = dfact = 1;
                    726:        if (nonumb)
                    727:                i = 0;
                    728:        return(i);
                    729: }
                    730: 
                    731: 
                    732: int quant(int n, int m)
                    733: {
                    734:        int i, neg;
                    735: 
                    736:        neg = 0;
                    737:        if (n < 0) {
                    738:                neg++;
                    739:                n = -n;
                    740:        }
                    741:        /* better as i = ((n + m/2)/m)*m */
                    742:        i = n / m;
                    743:        if (n - m * i > m / 2)
                    744:                i += 1;
                    745:        i *= m;
                    746:        if (neg)
                    747:                i = -i;
                    748:        return(i);
                    749: }

unix.superglobalmegacorp.com

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