Annotation of researchv10no/cmd/tpr.c, revision 1.1.1.1

1.1       root        1: /*
                      2: **     tpr - text formatter
                      3: **             Ken Yap, June 1981
                      4: */
                      5: #include       <stdio.h>
                      6: #include       <ctype.h>
                      7: 
                      8: #define        min(a,b)        (a<b?a:b)
                      9: #define        max(a,b)        (a>b?a:b)
                     10: #define        skipbl(p)       {while(*p == ' ' || *p == '\t')p++;}
                     11: #define        skipnbl(p)      {while(*p != ' ' && *p != '\t' && *p != '\n')p++;}
                     12: #define        CHARNULL        ((char *)NULL)
                     13: #define        NO              0
                     14: #define        YES             1
                     15: #define        COMMAND         '.'
                     16: #define        PAGENUM         '%'
                     17: #define        HUGE            10000
                     18: #define        MAXIN           132
                     19: #define        MAXOUT          132
                     20: #define        MAXCHARS        14
                     21: #define        MAXMAC          50
                     22: #define        MAXPB           50
                     23: #define        MAXTABS         20
                     24: #define        PAGLEN          66
                     25: #define        PAPERSIZE       65
                     26: #define        M1DEF           3
                     27: #define        M2DEF           1
                     28: #define        M3DEF           1
                     29: #define        M4DEF           3
                     30: #define        PAGEWIDTH       60
                     31: #define        ARABIC          0
                     32: #define        ROMAN           1
                     33: 
                     34: struct linelink{
                     35:        char *lineptr;
                     36:        struct linelink *lastline;
                     37:        };
                     38: struct macro{
                     39:        char macnam[3];
                     40:        struct linelink *macend;
                     41:        } macros[MAXMAC];
                     42: short  maccnt = 0;             /* counter for current macro */
                     43: char   *pbptr[MAXMAC];         /* pointers to pushed back lines */
                     44: short  pblev = 0;              /* indicates level of macro nesting during collection */
                     45: 
                     46: char   outbuf[MAXOUT]; /* lines to be filled collect here */
                     47: char   *outp = outbuf; /* last char position in outbuf; init = 0 */
                     48: short  outw = 0;       /* width of text currenty in outbuf; init = 0 */
                     49: short  outwds = 0;     /* number of words in outbuf; init = 0 */
                     50: 
                     51: short curpag   = 0;
                     52: short newpag   = 1;
                     53: short lineno   = 0;
                     54: char blnkhdr[] = "\n";
                     55: struct envir{
                     56:        short plval;
                     57:        short m1val;
                     58:        short m2val;
                     59:        short m3val;
                     60:        short m4val;
                     61:        short bottom;
                     62:        char *evenhdr,*oddhdr;
                     63:        char *evenftr,*oddftr;
                     64:        char comchr;
                     65:        char tabchr;
                     66:        char ubchr;
                     67:        short fill;
                     68:        short adjust;
                     69:        short numtyp;
                     70:        short lsval;
                     71:        short llval;
                     72:        short inval;
                     73:        short tival;
                     74:        short poval;
                     75:        short ceval;
                     76:        short ulval;
                     77:        short litval;
                     78:        short blval;
                     79:        short skpval;
                     80:        short tabpos[MAXTABS];
                     81:        struct envir *lastenv;
                     82:        };
                     83: struct envir env       = {
                     84:        PAGLEN, M1DEF, M2DEF, M3DEF, M4DEF, (PAGLEN-M3DEF-M4DEF),
                     85:        blnkhdr, blnkhdr,
                     86:        blnkhdr, blnkhdr,
                     87:        '.', '\t', ' ',
                     88:        YES, YES, ARABIC, 1, PAGEWIDTH, 0, 0, 0, 0, 0, 0, 0, 0,
                     89:        { 8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,0 },
                     90:        NULL
                     91:        };
                     92: struct envir *curenv   = NULL;
                     93: struct cmdents{
                     94:        char cmdname[3];
                     95:        short notredefd;
                     96:        };
                     97: struct cmdents builtins[] ={
                     98:        { "ad",YES },
                     99:        { "ar",YES },
                    100:        { "bl",YES },
                    101:        { "bp",YES },
                    102:        { "br",YES },
                    103:        { "cc",YES },
                    104:        { "ce",YES },
                    105:        { "de",YES },
                    106:        { "ef",YES },
                    107:        { "eh",YES },
                    108:        { "fi",YES },
                    109:        { "fo",YES },
                    110:        { "he",YES },
                    111:        { "in",YES },
                    112:        { "ix",YES },
                    113:        { "li",YES },
                    114:        { "ll",YES },
                    115:        { "ls",YES },
                    116:        { "m1",YES },
                    117:        { "m2",YES },
                    118:        { "m3",YES },
                    119:        { "m4",YES },
                    120:        { "na",YES },
                    121:        { "ne",YES },
                    122:        { "nf",YES },
                    123:        { "of",YES },
                    124:        { "oh",YES },
                    125:        { "pl",YES },
                    126:        { "po",YES },
                    127:        { "re",YES },
                    128:        { "ro",YES },
                    129:        { "se",YES },
                    130:        { "sk",YES },
                    131:        { "sp",YES },
                    132:        { "ta",YES },
                    133:        { "tc",YES },
                    134:        { "ti",YES },
                    135:        { "ub",YES },
                    136:        { "ul",YES }
                    137:        };
                    138: 
                    139: enum cmdnum    {ADJ, ARA, BLN, BPG, BRE, CMC, CEN, DFN, EFO, EHD, FIL,
                    140:                FOT, HED, IND, INX, LIT, LNL, LNS, M1, M2, M3,
                    141:                M4, NAD, NED, NFL, OFO, OHD, PGL, POF, RNV, ROM, SNV, SKP,
                    142:                SPA, TCL, TCH, TMI, UBC, UDL, MAC, UNKNOWN};
                    143: 
                    144: short echodir  = 0;
                    145: char *filename = "stdin";
                    146: short fileline = 0;
                    147: char *nomem    = "Out of dynamic memory\n";    /* canned message */
                    148: 
                    149: /*
                    150: **     main
                    151: */
                    152: main(argc,argv)
                    153:        short argc;
                    154:        char **argv;{
                    155:        char stdoutbuf[BUFSIZ];
                    156:        FILE *file;
                    157:        
                    158:        for(argc--, argv++; argc > 0 && **argv == '-' && (*argv)[1] != '\0'; argc--, argv++)
                    159:                setoptions(*argv);
                    160:        setbuf(stdout,stdoutbuf);
                    161:        if(argc == 0)
                    162:                tpr(stdin,"stdin");
                    163:        else
                    164:                for( ; argc > 0; argc--, argv++){
                    165:                        if(**argv == '-' && (*argv)[1] == '\0')
                    166:                                tpr(stdin,"stdin");
                    167:                        else{
                    168:                                if((file = fopen(*argv,"r")) == NULL){
                    169:                                        perror(*argv);
                    170:                                        continue;
                    171:                                        }
                    172:                                tpr(file,*argv);
                    173:                                fclose(file);
                    174:                                }
                    175:                        }
                    176:        if(lineno > 0)
                    177:                spc(HUGE);              /* flush last output */
                    178:        fflush(stdout);
                    179: }
                    180: 
                    181: setoptions(arg)
                    182:        char *arg;{
                    183:        register char c;
                    184: 
                    185:        while((c = *++arg) != '\0')
                    186:                switch(c){
                    187:                        case 'd':       /* echo directives */
                    188:                                echodir++;
                    189:                                break;
                    190:                        case 'e':       /* divert errors */
                    191:                                close(2);
                    192:                                if(creat(++arg,0600) < 0){
                    193:                                        open("/dev/tty",1);
                    194:                                        perror(arg);
                    195:                                        exit(1);
                    196:                                        }
                    197:                                return;
                    198:                        default:
                    199:                                fprintf(stderr,"Usage - see manual (ho, ho)\n");
                    200:                                exit(1);
                    201:                        }
                    202: }
                    203: 
                    204: /*
                    205: **     tpr - here is the main routine for each file
                    206: **     the name is passed along so that the 'include' directive
                    207: **     can call 'tpr' recursively
                    208: */
                    209: tpr(file,name)
                    210:        FILE *file;
                    211:        char *name;{
                    212:        register char *savename;
                    213:        register short saveline;
                    214:        char inbuf[MAXIN];
                    215:        char *ngetl();
                    216: 
                    217:        savename = filename;    /* save old name */
                    218:        filename = name;        /* make new one available for error routine */
                    219:        saveline = fileline;    /* and line number */
                    220:        fileline = 0;
                    221:        while(ngetl(inbuf,file) != CHARNULL){
                    222:                ++fileline;
                    223:                if(*inbuf == env.comchr)        /* it's a command */
                    224:                        cmd(inbuf,file);
                    225:                else                    /* it's text */
                    226:                        text(inbuf);
                    227:                }
                    228:        filename = savename;    /* restore name and linenumber */
                    229:        fileline = saveline;
                    230: }
                    231: 
                    232: /*
                    233: **     error - prints filename and linenumber
                    234: */
                    235: error(msg,arg)
                    236:        char *msg,*arg;{
                    237: 
                    238: /*ROB
                    239:        fprintf(stderr,"At line %d in file %s: ",fileline,filename);
                    240:        fprintf(stderr,msg,arg);
                    241: */
                    242: }
                    243: 
                    244: /*
                    245: **     blnk - space n lines (to new page if necessary, cf spc)
                    246: */
                    247: blnk(n)
                    248:        short n;{
                    249:        register short i;
                    250:        
                    251:        linebreak();
                    252:        while(n > 0){
                    253:                if(lineno > env.bottom){
                    254:                        pfoot();
                    255:                        lineno = 0;
                    256:                        }
                    257:                if(lineno == 0)
                    258:                        phead();
                    259:                i = min(n,env.bottom + 1 - lineno);
                    260:                skip(i);
                    261:                n -= i;
                    262:                lineno += i;
                    263:                }
                    264:        if(lineno > env.bottom)
                    265:                pfoot();
                    266: }
                    267: 
                    268: /*
                    269: **     linebreak - end current filled line
                    270: */
                    271: linebreak(){
                    272:        
                    273:        if(outp != outbuf){
                    274:                *outp++ = '\n';
                    275:                *outp = '\0';
                    276:                put(outbuf);
                    277:                }
                    278:        outp = outbuf;
                    279:        outw = 0;
                    280:        outwds = 0;
                    281: }
                    282: 
                    283: /*
                    284: **     centre - centre a line by setting tival
                    285: */
                    286: center(buf)
                    287:        char *buf;{
                    288:        short width();
                    289:        
                    290:        env.tival = max((env.llval + env.tival - width(buf))/2,0);
                    291: }
                    292: 
                    293: /*
                    294: **     cmd - perform formatting command
                    295: */
                    296: cmd(buf,file)
                    297:        char *buf;
                    298:        FILE *file;{
                    299:        enum cmdnum comtyp(),ct;
                    300:        register short spval,val;
                    301:        short macnum;
                    302:        char argtyp;
                    303:        short getval(),set();
                    304:        char *gettl();
                    305:        
                    306:        if(echodir)
                    307:                putdir(buf);
                    308:        ct = comtyp(buf,&macnum);
                    309:        val = 0;
                    310:        val = getval(buf,&argtyp);
                    311:        switch(ct){
                    312:                case SPA:
                    313:                        spval = set(0,val,argtyp,1,0,HUGE);
                    314:                        spc(spval);
                    315:                        break;
                    316:                case IND:
                    317:                case INX:
                    318:                        if(ct == IND)
                    319:                                linebreak();
                    320:                        env.inval = set(env.inval,val,argtyp,0,0,env.llval - 1);
                    321:                        env.tival = env.inval;
                    322:                        break;
                    323:                case TMI:
                    324:                        linebreak();
                    325:                        env.tival = set(env.tival,val,argtyp,0,0,env.llval);
                    326:                        break;
                    327:                case CEN:
                    328:                        linebreak();
                    329:                        env.ceval = set(env.ceval,val,argtyp,1,0,HUGE);
                    330:                        break;
                    331:                case UDL:
                    332:                        env.ulval = set(env.ulval,val,argtyp,0,1,HUGE);
                    333:                        break;
                    334:                case FIL:
                    335:                        linebreak();
                    336:                        env.fill = YES;
                    337:                        break;
                    338:                case NFL:
                    339:                        linebreak();
                    340:                        env.fill = NO;
                    341:                        break;
                    342:                case BRE:
                    343:                        linebreak();
                    344:                        break;
                    345:                case BLN:
                    346:                        env.blval = set(env.blval,val,argtyp,1,0,HUGE);
                    347:                        blnk(env.blval);
                    348:                        env.blval = 0;
                    349:                        break;
                    350:                case NED:
                    351:                        if(val > env.bottom - lineno + 1)
                    352:                                spc(HUGE);
                    353:                        break;
                    354:                case LNS:
                    355:                        env.lsval = set(env.lsval,val,argtyp,1,1,HUGE);
                    356:                        break;
                    357:                case LNL:
                    358:                        env.llval = set(env.llval,val,argtyp,PAGEWIDTH,env.tival + 1,HUGE);
                    359:                        break;
                    360:                case PGL:
                    361:                        env.plval = set(env.plval,val,argtyp,PAGLEN,
                    362:                                env.m1val + env.m2val + env.m3val + env.m4val + 1,HUGE);
                    363:                        env.bottom = env.plval - env.m3val - env.m4val;
                    364:                        break;
                    365:                case BPG:
                    366:                        if(lineno > 0)
                    367:                                spc(HUGE);
                    368:                        curpag = set(curpag,val,argtyp,curpag + 1, - HUGE,HUGE);
                    369:                        newpag = curpag;
                    370:                        break;
                    371:                case HED:
                    372:                        env.evenhdr = env.oddhdr = gettl(buf);
                    373:                        break;
                    374:                case FOT:
                    375:                        env.evenftr = env.oddftr = gettl(buf);
                    376:                        break;
                    377:                case EHD:
                    378:                        env.evenhdr = gettl(buf);
                    379:                        break;
                    380:                case EFO:
                    381:                        env.evenftr = gettl(buf);
                    382:                        break;
                    383:                case OHD:
                    384:                        env.oddhdr = gettl(buf);
                    385:                        break;
                    386:                case OFO:
                    387:                        env.oddftr = gettl(buf);
                    388:                        break;
                    389:                case NAD:
                    390:                        env.adjust = NO;
                    391:                        break;
                    392:                case ADJ:
                    393:                        env.adjust = YES;
                    394:                        break;
                    395:                case ROM:
                    396:                        env.numtyp = ROMAN;
                    397:                        break;
                    398:                case ARA:
                    399:                        env.numtyp = ARABIC;
                    400:                        break;
                    401:                case LIT:
                    402:                        env.litval = set(env.litval,val,argtyp,1,0,HUGE);
                    403:                        break;
                    404:                case M1:
                    405:                        env.m1val = set(env.m1val,val,argtyp,M1DEF,
                    406:                                0,env.plval - (env.m2val + env.m3val + env.m4val + 1));
                    407:                        break;
                    408:                case M2:
                    409:                        env.m2val = set(env.m2val,val,argtyp,M2DEF,
                    410:                                0,env.plval - (env.m1val + env.m3val + env.m4val + 1));
                    411:                        break;
                    412:                case M3:
                    413:                        env.m3val = set(env.m3val,val,argtyp,M3DEF,
                    414:                                0,env.plval - (env.m1val + env.m2val + env.m4val + 1));
                    415:                        env.bottom = env.plval - env.m3val - env.m4val;
                    416:                        break;
                    417:                case M4:
                    418:                        env.m4val = set(env.m4val,val,argtyp,M4DEF,
                    419:                                0,env.plval - (env.m1val + env.m2val + env.m3val + 1));
                    420:                        env.bottom = env.plval - env.m3val - env.m4val;
                    421:                        break;
                    422:                case CMC:
                    423:                        if(argtyp != '\n')
                    424:                                env.comchr = argtyp;
                    425:                        else
                    426:                                env.comchr = COMMAND;
                    427:                        break;
                    428:                case POF:
                    429:                        env.poval = set(env.poval,val,argtyp,0,0,PAPERSIZE);
                    430:                        break;
                    431:                case SKP:
                    432:                        env.skpval = set(env.skpval,val,argtyp,1,0,HUGE);
                    433:                        break;
                    434:                case DFN:
                    435:                        getmac(buf,file);
                    436:                        break;
                    437:                case TCH:
                    438:                        if(argtyp != '\n')
                    439:                                env.tabchr = argtyp;
                    440:                        else
                    441:                                env.tabchr = '\t';
                    442:                        break;
                    443:                case TCL:
                    444:                        tabcol(buf);
                    445:                        break;
                    446:                case UBC:
                    447:                        if(argtyp != '\n')
                    448:                                env.ubchr = argtyp;
                    449:                        else
                    450:                                env.ubchr = ' ';
                    451:                        break;
                    452:                case RNV:
                    453:                        if(val <= 0)
                    454:                                val = 1;
                    455:                        resenv(val);
                    456:                        break;
                    457:                case SNV:
                    458:                        savenv();
                    459:                        break;
                    460:                case MAC:
                    461:                        expand(macnum);
                    462:                        break;
                    463:                case UNKNOWN:
                    464:                        error("Unrecognised directive:\n%s",buf);
                    465:                        return;
                    466:                }
                    467: }
                    468: 
                    469: /*
                    470: **     comtyp - decode command type
                    471: */
                    472: enum cmdnum comtyp(buf,macnum)
                    473:        char *buf;
                    474:        short *macnum;{
                    475:        register char a,b;
                    476:        register struct cmdents *p;
                    477:        register char *q;
                    478:        register short l,h,m;
                    479:        
                    480:        a = buf[1];
                    481:        b = buf[2];
                    482:        for(l = 0, h = (sizeof(builtins)/sizeof(builtins[0])) - 1; l <= h; ){
                    483:                p = &builtins[m = (l + h) / 2];
                    484:                if(a < p->cmdname[0] || a <= p->cmdname[0] && b < p->cmdname[1])
                    485:                        h = m - 1;
                    486:                else if(a > p->cmdname[0] || a <= p->cmdname[0] && b > p->cmdname[1])
                    487:                        l = m + 1;
                    488:                else
                    489:                        break;
                    490:                }
                    491:        if(l <= h && p->notredefd)
                    492:                return((enum cmdnum)m);
                    493:        for(l = maccnt - 1; l >= 0; l--){
                    494:                q = macros[l].macnam;
                    495:                if(a == *q++ && b == *q){
                    496:                        *macnum = l;
                    497:                        return(MAC);
                    498:                        }
                    499:                }
                    500:        return(UNKNOWN);
                    501: }
                    502: 
                    503: /*
                    504: **     expand - pushback macro definition onto input
                    505: */
                    506: expand(macnum)
                    507:        short macnum;{
                    508:        register struct linelink *lp;
                    509:        
                    510:        for(lp = macros[macnum].macend; lp != NULL; lp = lp->lastline){
                    511:                if(pblev > MAXPB){
                    512:                        error("Not enough pushback space\n",CHARNULL);
                    513:                        break;  /* to catch stack overflow */
                    514:                        }
                    515:                pbptr[pblev] = lp->lineptr;
                    516:                pblev++;
                    517:                }
                    518: }
                    519: 
                    520: /*
                    521: **     getmac - collect macro
                    522: */
                    523: getmac(buf,file)
                    524:        char *buf;
                    525:        FILE *file;{
                    526:        register char *p;
                    527:        register struct macro *mp;
                    528:        register struct linelink *lp;
                    529:        register short dotlev;
                    530:        enum cmdnum ct;
                    531:        short macnum;
                    532:        char line[MAXIN];
                    533:        enum cmdnum comtyp();
                    534:        char *strcpy();
                    535:        char *malloc();
                    536:        
                    537:        skipnbl(buf);
                    538:        skipbl(buf);
                    539:        if(*buf == '\n'){
                    540:                error("Missing macro name\n",CHARNULL);
                    541:                return;
                    542:                }
                    543:        if(maccnt >= MAXMAC){
                    544:                error("Too many macro definitions",CHARNULL);
                    545:                return;
                    546:                }
                    547:        mp = &macros[maccnt];
                    548:        p = mp->macnam;
                    549:        if((ct = comtyp(buf - 1,&macnum)) != UNKNOWN && ct != MAC)
                    550:                builtins[(int)ct].notredefd = NO;
                    551:        *p++ = *buf++;  /* record name */
                    552:        *p++ = *buf++;
                    553:        *p = '\0';
                    554:        mp->macend = NULL;
                    555:        dotlev = 1;
                    556:        do{
                    557:                if((p = ngetl(line,file)) == CHARNULL)
                    558:                        break;  /* unexpected EOF */
                    559:                ++fileline;
                    560:                if(*p++ == env.comchr){
                    561:                        if(*p == '.')
                    562:                                dotlev--;
                    563:                        else if(comtyp(line,&macnum) == DFN)
                    564:                                dotlev++;       /* included .de */
                    565:                        }
                    566:                if(dotlev > 0){
                    567:                        if((lp = (struct linelink *)malloc((unsigned)sizeof(*mp->macend))) == NULL){
                    568:                                error(nomem,CHARNULL);
                    569:                                break;
                    570:                                }
                    571:                        lp->lastline = mp->macend;
                    572:                        mp->macend = lp;
                    573:                        if((lp->lineptr = malloc((unsigned)(strlen(line) + 1))) == NULL){
                    574:                                error(nomem,CHARNULL);
                    575:                                break;
                    576:                                }
                    577:                        strcpy(lp->lineptr,line);
                    578:                        }
                    579:                }while(dotlev > 0);
                    580:        maccnt++;
                    581: }
                    582: 
                    583: /*
                    584: **     getseg - puts out part of header
                    585: */
                    586: char *getseg(buf,copy,copyend,term,pageno)
                    587:        char *buf,*copy,*copyend,term;
                    588:        short pageno;{
                    589:        register short i;
                    590:        register char *p;
                    591:        short itorom();
                    592:        
                    593:        p = buf;
                    594:        for( ;copy != copyend && *p != term && *p != '\0' && *p != '\n'; p++){
                    595:                if(*p == PAGENUM){
                    596:                        if(env.numtyp == ARABIC){
                    597:                                sprintf(copy, "%d", pageno);
                    598:                                i=strlen(copy);
                    599:                        }
                    600:                        else
                    601:                                i = itorom(pageno,copy,min(MAXCHARS,(short)(copyend - copy)));
                    602:                        copy += i;
                    603:                        }
                    604:                else
                    605:                        *copy++ = *p;
                    606:                }
                    607:        if(*p == term)
                    608:                p++;
                    609:        *copy = '\0';
                    610:        return(p);
                    611: }
                    612: 
                    613: /*
                    614: **     gettl - copy title from buf to ttl
                    615: */
                    616: char *gettl(buf)
                    617:        char *buf;{
                    618:        register char *p,*q;
                    619:        char *strcpy();
                    620:        char *malloc();
                    621:        
                    622:        p = buf;
                    623:        skipnbl(p);
                    624:        skipbl(p);      /* find argument */
                    625:        if((q = malloc((unsigned)(strlen(p) + 1))) == NULL){
                    626:                error(nomem,CHARNULL);
                    627:                return(q);
                    628:                }
                    629:        strcpy(q,p);
                    630:        return(q);
                    631: }
                    632: 
                    633: /*
                    634: **     getval - evaluate optional numeric argument
                    635: */
                    636: short getval(buf,argtyp)
                    637:        char *buf;
                    638:        char *argtyp;{
                    639:        int atoi();
                    640:        
                    641:        skipnbl(buf);
                    642:        skipbl(buf);    /* find argument */
                    643:        *argtyp = *buf;
                    644:        if(!isdigit(*buf))
                    645:                buf++;
                    646:        return(atoi(buf));
                    647: }
                    648: 
                    649: /*
                    650: **     getwrd - get a non - blank word from instr(i) to out, increment i
                    651: */
                    652: char *getwrd(instr,out)
                    653:        char *instr,*out;{
                    654:        register char c;
                    655:        register char *p,*q;
                    656:        
                    657:        p = instr;
                    658:        q = out;
                    659:        while((*p == ' ' || *p == '\t') && *p != env.tabchr)
                    660:                p++;
                    661:        instr = p;
                    662:        if(*p == env.tabchr)
                    663:                *q++ = *p;
                    664:        else{
                    665:                while((c = *p) != '\0' && c != ' ' && c != '\t'
                    666:                        && c != '\n' && c != env.tabchr){
                    667:                        *q++ = *p++;
                    668:                        }
                    669:                }
                    670:        *q = '\0';
                    671:        return(p == instr ? NULL : p);
                    672: }
                    673: 
                    674: /*
                    675: **     itorom - converts integer to roman numerals
                    676: */
                    677: short itorom(num,str,flen)
                    678:        char *str;
                    679:        short num,flen;{
                    680:        register short i,j;
                    681:        char *p;
                    682:        static short romval[]   = { 1000,500,100,50,10,5,1,0 };
                    683:        static short reltab[]   = { 2,1,2,1,2,1,1,0 };
                    684:        static char romlet[]    = "mdclxvi0";
                    685:        
                    686:        p = str;
                    687:        if(num < 0 && flen > 1){
                    688:                num = -num;
                    689:                *p++ = '-';
                    690:                }
                    691:        for(i = 0; num > 0; i++){
                    692:                while(num >= romval[i]){
                    693:                        num -= romval[i];
                    694:                        *p++ = romlet[i];
                    695:                        }
                    696:                j = i + reltab[i];
                    697:                if(num >= (romval[i] - romval[j])){
                    698:                        num -= (romval[i] - romval[j]);
                    699:                        *p++ = romlet[j];
                    700:                        *p++ = romlet[i];
                    701:                        }
                    702:                }
                    703:        *p = '\0';
                    704:        return((short)(p - str));
                    705: }
                    706: 
                    707: /*
                    708: **     leadbl - delete leading blanks, set tival
                    709: */
                    710: leadbl(buf)
                    711:        char *buf;{
                    712:        register char *p;
                    713:        
                    714:        linebreak();
                    715:        p = buf;
                    716:        skipnbl(buf);
                    717:        if(*buf != '\n')
                    718:                env.tival = (buf - p);
                    719:        while(*buf != '\0')             /* move line to left */
                    720:                *p++ = *buf++;
                    721:        *p = '\0';
                    722: }
                    723: 
                    724: /*
                    725: **     nextab - returns position of next tab stop
                    726: */
                    727: short nextab(pos)
                    728:        short pos;{
                    729:        register short i,k;
                    730:        
                    731:        for(i =  0; i < MAXTABS; i++){
                    732:               if(env.tabpos[i] == 0)
                    733:                        break;
                    734:               if(env.tabpos[i] > pos){
                    735:                       k = env.tabpos[i];
                    736:                       return(k);
                    737:                       }
                    738:               }
                    739:        k = pos + 1;
                    740:        return(k);
                    741: }
                    742: 
                    743: /*
                    744: **     ngetl - gets line from input or pushback buffer
                    745: */
                    746: char *ngetl(buf,file)
                    747:        char *buf;
                    748:        FILE *file;{
                    749:        char *fgets();
                    750:        char *strcpy();
                    751:        
                    752:        if(pblev <= 0)
                    753:                return(fgets(buf,MAXIN,file));
                    754:        else{
                    755:                pblev--;
                    756:                strcpy(buf,pbptr[pblev]);
                    757:                }
                    758:        return(buf);
                    759: }
                    760: 
                    761: /*
                    762: **     pfoot - put out page footer
                    763: */
                    764: pfoot(){
                    765:        
                    766:        skip(env.m3val);
                    767:        if(env.m4val > 0){
                    768:                puttl(curpag % 2 ? env.oddftr : env.evenftr, curpag);
                    769:                skip(env.m4val - 1);
                    770:                }
                    771: }
                    772: 
                    773: /*
                    774: **     phead - put out page header
                    775: */
                    776: phead(){
                    777:        
                    778:        curpag = newpag;
                    779:        newpag++;
                    780:        if(env.m1val > 0){
                    781:                skip(env.m1val - 1);
                    782:                puttl(curpag % 2 ? env.oddhdr : env.evenhdr, curpag);
                    783:                }
                    784:        skip(env.m2val);
                    785:        lineno = env.m1val + env.m2val + 1;
                    786: }
                    787: 
                    788: /*
                    789: **     put - put out line with proper spacing and indenting
                    790: */
                    791: put(buf)
                    792:        char *buf;{
                    793:        short nextab();
                    794:        register char c;
                    795:        register short col,i;
                    796:        
                    797:        if(lineno == 0 || lineno > env.bottom)
                    798:                phead();
                    799:        for(i = (env.tival + env.poval); i--; )
                    800:                putchar(' ');
                    801:        col = env.tival;
                    802:        env.tival = env.inval;
                    803:        for(; (c = *buf) != '\0'; buf++){
                    804:                if(c == env.ubchr)
                    805:                        c = ' ';        /* put blanks instead of blank replacement */
                    806:                if(c == env.tabchr){
                    807:                        i = nextab(col);        /* nextab wants last used column */
                    808:                        for(; col < i; col++)
                    809:                                putchar(' ');
                    810:                        continue;
                    811:                        }
                    812:                else if(c == '\b')
                    813:                        col--;
                    814:                else
                    815:                        col++;
                    816:                putchar(c);
                    817:                }
                    818:        skip(min(env.lsval - 1,env.bottom - lineno));
                    819:        lineno += env.lsval;
                    820:        if(lineno > env.bottom){
                    821:                pfoot();
                    822:                if(env.skpval > 0)
                    823:                        skpage(env.skpval);
                    824:                        env.skpval = 0;
                    825:                }
                    826: }
                    827: 
                    828: /*
                    829: **     putdir - output a directive
                    830: */
                    831: putdir(buf)
                    832:        char *buf;{
                    833: 
                    834:        fprintf(stderr,"%.10s",buf);    /* first 10 chars */
                    835: }
                    836: 
                    837: /*
                    838: **     puttl - put out title line with optional page number
                    839: */
                    840: puttl(buf,pageno)
                    841:        char *buf;
                    842:        short pageno;{
                    843:        char copy[MAXOUT],term;
                    844:        char *getseg();
                    845:        register char *p;
                    846:        register short i,col,newcol;
                    847:        
                    848:        for(i = env.poval; i--; )
                    849:                putchar(' ');
                    850:        term = *buf;
                    851:        if(term == '\n'){
                    852:                putchar('\n');
                    853:                return;
                    854:                }
                    855:        col = 1;
                    856:        p = buf + 1;
                    857:        p = getseg(p,copy,&copy[MAXOUT],term,pageno);
                    858:        printf("%s", copy);
                    859:        col += strlen(copy);
                    860:        buf = p;
                    861:        p = getseg(p,copy,&copy[MAXOUT],term,pageno);
                    862:        newcol = (env.llval - strlen(copy))/2 + 1;      /* start of centre */
                    863:        for(; col < newcol; col++)
                    864:                putchar(' ');
                    865:        printf("%s", copy);
                    866:        col += strlen(copy);
                    867:        p = getseg(p,copy,&copy[MAXOUT],term,pageno);
                    868:        newcol = env.llval - strlen(copy) + 1;  /* start of right */
                    869:        for(; col < newcol; col++)
                    870:                putchar(' ');
                    871:        printf("%s",copy);
                    872:        putchar('\n');
                    873: }
                    874: 
                    875: /*
                    876: **     putwrd - put a word in outbuf; includes margin justification
                    877: */
                    878: putwrd(wrdbuf)
                    879:        char *wrdbuf;{
                    880:        char *strcpy();
                    881:        register short l,w,lnval,nextra;
                    882:        short width(), nextab();
                    883:        int strlen();
                    884:        
                    885:        lnval = env.llval - env.tival;
                    886:        if(*wrdbuf == env.tabchr){
                    887:                outw = nextab(outw + env.tival) - env.tival;
                    888:                /* because outw floats from the indent */
                    889:                /* and nextab is absolute */
                    890:                if(outp  != outbuf && outw > lnval){
                    891:                        linebreak();
                    892:                        outw = nextab(outw + env.tival) - env.tival;
                    893:                        }
                    894:                *++outp = env.tabchr;
                    895:                outwds = 0;             /* adjust from next word */
                    896:                }
                    897:        else{
                    898:                w = width(wrdbuf);
                    899:                l = strlen(wrdbuf);
                    900:                if(outp != outbuf && (outw + w > lnval ||       /* too big */
                    901:                        (char *)(outp + l) >= &outbuf[MAXOUT])){
                    902:                        --outp; /* we put in a blank earlier */
                    903:                        if(env.adjust == YES){
                    904:                                nextra = lnval - outw + 1;
                    905:                                spread(outp,nextra,outwds);
                    906:                                outp += nextra;
                    907:                                }
                    908:                        linebreak();            /* flush previous line */
                    909:                        }
                    910:                strcpy(outp,wrdbuf);
                    911:                outp += l;
                    912:                *outp++ = ' ';          /* blank between words */
                    913:                outw += w + 1;                  /* 1 for blank */
                    914:                outwds++;
                    915:                }
                    916: }
                    917: 
                    918: /*
                    919: **     resenv - restore environment n levels back
                    920: */
                    921: resenv(n)
                    922:        short n;{
                    923:        register struct envir *ep,*tp;
                    924:        
                    925:        linebreak();            /* to flush any latent output */
                    926:        for(ep = curenv; ep != NULL && --n > 0; free(tp))
                    927:                ep = (tp = ep)->lastenv;
                    928:        if(ep != NULL){
                    929:                env = *ep;
                    930:                curenv = ep->lastenv;
                    931:                free(ep);
                    932:                }
                    933: }
                    934: 
                    935: /*
                    936: **     savenv - keep environment for later restoration
                    937: */
                    938: savenv(){
                    939:        register struct envir *ep;
                    940:        
                    941:        if((ep = (struct envir *)malloc((unsigned)sizeof(env))) == NULL){
                    942:                error(nomem,CHARNULL);
                    943:                return;
                    944:                }
                    945:        *ep = env;      /* structure copy */
                    946:        ep->lastenv = curenv;
                    947:        curenv = ep;
                    948: }
                    949: 
                    950: /*
                    951: **     set - set parameter and check range
                    952: */
                    953: short set(param,val,argtyp,defval,minval,maxval)
                    954:        short param,val,defval,minval,maxval;
                    955:        char argtyp;{
                    956:        
                    957:        switch(argtyp){
                    958:                case '\n':
                    959:                        param = defval;
                    960:                        break;
                    961:                case '+':
                    962:                        param = param + val;
                    963:                        break;
                    964:                case '-':
                    965:                        param = param - val;
                    966:                        break;
                    967:                default:
                    968:                        param = val;
                    969:                }
                    970:        param = min(param,maxval);
                    971:        param = max(param,minval);
                    972:        return(param);
                    973: }
                    974: 
                    975: /*
                    976: **     skip - output n blank lines
                    977: */
                    978: skip(n)
                    979:        short n;{
                    980:        
                    981:        while(n-- > 0)
                    982:                putchar('\n');
                    983: }
                    984: 
                    985: /*
                    986: **     skpage - skip n pages
                    987: */
                    988: skpage(n)
                    989:        short n;{
                    990:        
                    991:        while(n-- > 0){
                    992:                phead();
                    993:                skip(env.bottom + 1 - lineno);
                    994:                lineno = env.bottom + 1;
                    995:                pfoot();
                    996:                }
                    997: }
                    998: 
                    999: /*
                   1000: **     spc - space n lines or to bottom of page (cf blnk)
                   1001: */
                   1002: spc(n)
                   1003:        short n;{
                   1004:        
                   1005:        linebreak();
                   1006:        if(lineno > env.bottom)
                   1007:                return;
                   1008:        if(lineno == 0)
                   1009:                phead();
                   1010:        skip(min(n,env.bottom + 1 - lineno));
                   1011:        lineno += n;
                   1012:        if(lineno > env.bottom){
                   1013:                pfoot();
                   1014:                if(env.skpval > 0)
                   1015:                        skpage(env.skpval);
                   1016:                        env.skpval = 0;
                   1017:                }
                   1018: }
                   1019: 
                   1020: /*
                   1021: **     spread - spread words to justify right margin
                   1022: */
                   1023: spread(ptr,nextra,nwrds)
                   1024:        char *ptr;
                   1025:        short nextra,nwrds;{
                   1026:        register char *p,*q;
                   1027:        register short nb,nholes;
                   1028:        static short dir        = 0;
                   1029:        
                   1030:        if(nextra <= 0 || nwrds <= 1)
                   1031:                return;
                   1032:        dir = !dir;             /* reverse previous direction */
                   1033:        nholes = nwrds - 1;
                   1034:        p = ptr - 1;
                   1035:        q = ptr + nextra;
                   1036:        *q-- = '\0';
                   1037:        while(p < q){
                   1038:                if((*q = *p) == ' '){
                   1039:                        nb = dir ? (nextra - 1) / nholes + 1 :
                   1040:                                nextra / nholes;
                   1041:                        nextra -= nb;
                   1042:                        nholes--;
                   1043:                        while(nb-- > 0){
                   1044:                                *--q = ' ';
                   1045:                                }
                   1046:                        }
                   1047:                p--;
                   1048:                q--;
                   1049:                }
                   1050: }
                   1051: 
                   1052: /*
                   1053: **     tabcol - enters pseudotab stops, checking validity
                   1054: */
                   1055: tabcol(buf)
                   1056:        char *buf;{
                   1057:        int atoi();
                   1058:        register short tp,incr,val;
                   1059:        
                   1060:        for(tp = 0; tp < MAXTABS - 1; tp++){
                   1061:                skipnbl(buf);
                   1062:                skipbl(buf);
                   1063:                if(*buf == '\n')
                   1064:                        break;  /* end of list */
                   1065:                incr = *buf++ == '+' ? YES : NO;
                   1066:                val = atoi(buf);
                   1067:                if(incr == YES && tp > 1)       /* relative tab */
                   1068:                        val = env.tabpos[tp - 1] + val;
                   1069:                env.tabpos[tp] = val;
                   1070:                if(val < 0 || (tp > 1 && val < env.tabpos[tp - 1]))
                   1071:                        tp--;
                   1072:                }
                   1073:        env.tabpos[tp] = 0;     /* end of list */
                   1074: }
                   1075: 
                   1076: /*
                   1077: **     text - process text lines
                   1078: */
                   1079: text(inbuf)
                   1080:        char *inbuf;{
                   1081:        register char *p;
                   1082:        char wrdbuf[MAXIN];
                   1083:        char *getwrd();
                   1084:        
                   1085:        if(env.litval > 0){
                   1086:                put(inbuf);
                   1087:                env.litval--;
                   1088:                return;
                   1089:                }
                   1090:        if(*inbuf == ' ' || *inbuf == '\n')
                   1091:                leadbl(inbuf);  /* move left, set tival */
                   1092:        if(env.ulval > 0){                      /* underlining */
                   1093:                underl(inbuf,wrdbuf,&wrdbuf[MAXIN]);
                   1094:                env.ulval--;
                   1095:                }
                   1096:        if(env.ceval > 0){                      /* centering */
                   1097:                center(inbuf);
                   1098:                put(inbuf);
                   1099:                env.ceval--;
                   1100:                }
                   1101:        else if(*inbuf == '\n') /* all blank line */
                   1102:                put(inbuf);
                   1103:        else if(env.fill == NO)         /* unfilled text */
                   1104:                put(inbuf);
                   1105:        else
                   1106:                for(p = inbuf; (p = getwrd(p,wrdbuf)) != NULL;)
                   1107:                        putwrd(wrdbuf);
                   1108: }
                   1109: 
                   1110: /*
                   1111: **     underl - underline a line
                   1112: */
                   1113: underl(buf,tbuf,tend)
                   1114:        char *buf,*tbuf,*tend;{
                   1115:        register char c;
                   1116:        register char *p,*q;
                   1117:        char *strcpy();
                   1118:        
                   1119:        p = buf;
                   1120:        q = tbuf;
                   1121:        while(*p != '\n' && q < tend){
                   1122:                if(isalnum(c = *p++)){
                   1123:                        *q++ = '_';
                   1124:                        *q++ = '\b';
                   1125:                        }
                   1126:                *q++ = c;
                   1127:                }
                   1128:        *q++ = '\n';
                   1129:        *q = '\0';
                   1130:        strcpy(buf,tbuf);       /* copy it back to buf */
                   1131: }
                   1132: 
                   1133: /*
                   1134: **     width - compute width of character string
                   1135: */
                   1136: short width(buf)
                   1137:        char *buf;{
                   1138:        register short i;
                   1139:        register char c;
                   1140:        
                   1141:        for(i = 0; (c = *buf) != '\0'; buf++){
                   1142:                if(c == '\b')
                   1143:                        i--;
                   1144:                else if(c != '\n')
                   1145:                        i++;
                   1146:                }
                   1147:        return(i);
                   1148: }

unix.superglobalmegacorp.com

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