Annotation of researchv10no/cmd/tpr.c, revision 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.