Annotation of 42BSD/usr.bin/deroff.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char sccsid[] = "@(#)deroff.c   4.4     (Berkeley)      83/04/29";
                      3: #endif not lint
                      4: 
                      5: #include <stdio.h>
                      6: 
                      7: /*
                      8:  *     Deroff command -- strip troff, eqn, and Tbl sequences from
                      9:  *     a file.  Has two flags argument, -w, to cause output one word per line
                     10:  *     rather than in the original format.
                     11:  *     -mm (or -ms) causes the corresponding macro's to be interpreted
                     12:  *     so that just sentences are output
                     13:  *     -ml  also gets rid of lists.
                     14:  *     Deroff follows .so and .nx commands, removes contents of macro
                     15:  *     definitions, equations (both .EQ ... .EN and $...$),
                     16:  *     Tbl command sequences, and Troff backslash constructions.
                     17:  *
                     18:  *     All input is through the Cget macro;
                     19:  *     the most recently read character is in c.
                     20:  *
                     21:  *     Modified by Robert Henry to process -me and -man macros.
                     22:  */
                     23: 
                     24: #define Cget ( (c=getc(infile)) == EOF ? eof() : ((c==ldelim)&&(filesp==files) ? skeqn() : c) )
                     25: #define C1get ( (c=getc(infile)) == EOF ? eof() :  c)
                     26: 
                     27: #ifdef DEBUG
                     28: #  define C    _C()
                     29: #  define C1   _C1()
                     30: #else not DEBUG
                     31: #  define C    Cget
                     32: #  define C1   C1get
                     33: #endif not DEBUG
                     34: 
                     35: #define SKIP while(C != '\n') 
                     36: #define SKIP_TO_COM SKIP; SKIP; pc=c; while(C != '.' || pc != '\n' || C > 'Z')pc=c
                     37: 
                     38: #define        YES 1
                     39: #define        NO 0
                     40: #define        MS 0    /* -ms */
                     41: #define        MM 1    /* -mm */
                     42: #define        ME 2    /* -me */
                     43: #define        MA 3    /* -man */
                     44: 
                     45: #ifdef DEBUG
                     46: char *mactab[] = {"-ms", "-mm", "-me", "-ma"};
                     47: #endif DEBUG
                     48: 
                     49: #define        ONE 1
                     50: #define        TWO 2
                     51: 
                     52: #define NOCHAR -2
                     53: #define SPECIAL 0
                     54: #define APOS 1
                     55: #define PUNCT 2
                     56: #define DIGIT 3
                     57: #define LETTER 4
                     58: 
                     59: int    wordflag;
                     60: int    msflag;         /* processing a source written using a mac package */
                     61: int    mac;            /* which package */
                     62: int    disp;
                     63: int    parag;
                     64: int    inmacro;
                     65: int    intable;
                     66: int    keepblock;      /* keep blocks of text; normally false when msflag */
                     67: 
                     68: char chars[128];  /* SPECIAL, PUNCT, APOS, DIGIT, or LETTER */
                     69: 
                     70: char line[512];
                     71: char *lp;
                     72: 
                     73: int c;
                     74: int pc;
                     75: int ldelim;
                     76: int rdelim;
                     77: 
                     78: 
                     79: int argc;
                     80: char **argv;
                     81: 
                     82: char fname[50];
                     83: FILE *files[15];
                     84: FILE **filesp;
                     85: FILE *infile;
                     86: FILE   *opn();
                     87: /*
                     88:  *     Flags for matching conditions other than
                     89:  *     the macro name
                     90:  */
                     91: #define        NONE            0
                     92: #define        FNEST           1               /* no nested files */
                     93: #define        NOMAC           2               /* no macro */
                     94: #define        MAC             3               /* macro */
                     95: #define        PARAG           4               /* in a paragraph */
                     96: #define        MSF             5               /* msflag is on */
                     97: #define        NBLK            6               /* set if no blocks to be kept */
                     98: 
                     99: /*
                    100:  *     Return codes from macro minions, determine where to jump,
                    101:  *     how to repeat/reprocess text
                    102:  */
                    103: #define        COMX            1               /* goto comx */
                    104: #define        COM             2               /* goto com */
                    105: 
                    106: main(ac, av)
                    107: int ac;
                    108: char **av;
                    109: {
                    110:        register int i;
                    111:        int     errflg = 0;
                    112:        register        optchar;
                    113:        FILE *opn();
                    114:        int     kflag = NO;
                    115:        char    *p;
                    116: 
                    117:        wordflag = NO;
                    118:        msflag = NO;
                    119:        mac = ME;
                    120:        disp = NO;
                    121:        parag = NO;
                    122:        inmacro = NO;
                    123:        intable = NO;
                    124:        ldelim  = NOCHAR;
                    125:        rdelim  = NOCHAR;
                    126:        keepblock = YES;
                    127: 
                    128:        for(argc = ac - 1, argv = av + 1;
                    129:            (   (argc > 0)
                    130:             && (argv[0][0] == '-')
                    131:             && (argv[0][1] != '\0') );
                    132:            --argc, ++argv
                    133:        ){
                    134:                for(p = argv[0]+1; *p; ++p) {
                    135:                        switch(*p) {
                    136:                        case 'p':
                    137:                                parag=YES;
                    138:                                break;
                    139:                        case 'k':
                    140:                                kflag = YES;
                    141:                                break;
                    142:                        case 'w':
                    143:                                wordflag = YES;
                    144:                                kflag = YES;
                    145:                                break;
                    146:                        case 'm':
                    147:                                msflag = YES;
                    148:                                keepblock = NO;
                    149:                                switch(p[1]){
                    150:                                case 'm':       mac = MM; p++; break;
                    151:                                case 's':       mac = MS; p++; break;
                    152:                                case 'e':       mac = ME; p++; break;
                    153:                                case 'a':       mac = MA; p++; break;
                    154:                                case 'l':       disp = YES; p++; break;
                    155:                                default:        errflg++; break;
                    156:                                }
                    157:                                break;
                    158:                        default:
                    159:                                errflg++;
                    160:                        }
                    161:                }
                    162:        }
                    163: 
                    164:        if (kflag)
                    165:                keepblock = YES;
                    166:        if (errflg)
                    167:                fatal("usage: deroff [ -w ] [ -k] [ -m (a e m s l) ] [ file ] ... \n",
                    168:                        (char *) NULL);
                    169: 
                    170: #ifdef DEBUG
                    171:        printf("msflag = %d, mac = %s, keepblock = %d, disp = %d\n",
                    172:                msflag, mactab[mac], keepblock, disp);
                    173: #endif DEBUG
                    174:        if (argc == 0){
                    175:                infile = stdin;
                    176:        } else {
                    177:                infile = opn(argv[0]);
                    178:                --argc;
                    179:                ++argv;
                    180:        }
                    181: 
                    182: 
                    183:        files[0] = infile;
                    184:        filesp = &files[0];
                    185: 
                    186:        for(i='a'; i<='z' ; ++i)
                    187:                chars[i] = LETTER;
                    188:        for(i='A'; i<='Z'; ++i)
                    189:                chars[i] = LETTER;
                    190:        for(i='0'; i<='9'; ++i)
                    191:                chars[i] = DIGIT;
                    192:        chars['\''] = APOS;
                    193:        chars['&'] = APOS;
                    194:        chars['.'] = PUNCT;
                    195:        chars[','] = PUNCT;
                    196:        chars[';'] = PUNCT;
                    197:        chars['?'] = PUNCT;
                    198:        chars[':'] = PUNCT;
                    199:        work();
                    200: }
                    201: char *calloc();
                    202: 
                    203: skeqn()
                    204: {
                    205:        while((c = getc(infile)) != rdelim)
                    206:                if(c == EOF)
                    207:                        c = eof();
                    208:                else if(c == '"')
                    209:                        while( (c = getc(infile)) != '"')
                    210:                                if(c == EOF)
                    211:                                        c = eof();
                    212:                                else if(c == '\\')
                    213:                                        if((c = getc(infile)) == EOF)
                    214:                                                c = eof();
                    215:        if(msflag)return(c='x');
                    216:        return(c = ' ');
                    217: }
                    218: 
                    219: FILE *opn(p)
                    220: register char *p;
                    221: {
                    222:        FILE *fd;
                    223: 
                    224:        if( (fd = fopen(p, "r")) == NULL) {
                    225:                fprintf(stderr, "Deroff: ");
                    226:                perror(p);
                    227:                exit(1);
                    228:        }
                    229: 
                    230:        return(fd);
                    231: }
                    232: 
                    233: eof()
                    234: {
                    235:        if(infile != stdin)
                    236:                fclose(infile);
                    237:        if(filesp > files)
                    238:                infile = *--filesp;
                    239:        else if (argc > 0) {
                    240:                infile = opn(argv[0]);
                    241:                --argc;
                    242:                ++argv;
                    243:        } else
                    244:                exit(0);
                    245:        return(C);
                    246: }
                    247: 
                    248: getfname()
                    249: {
                    250:        register char *p;
                    251:        struct chain { 
                    252:                struct chain *nextp; 
                    253:                char *datap; 
                    254:        } *chainblock;
                    255:        register struct chain *q;
                    256:        static struct chain *namechain  = NULL;
                    257:        char *copys();
                    258: 
                    259:        while(C == ' ') ;
                    260: 
                    261:        for(p = fname ; (*p=c)!= '\n' && c!=' ' && c!='\t' && c!='\\' ; ++p)
                    262:                C;
                    263:        *p = '\0';
                    264:        while(c != '\n')
                    265:                C;
                    266: 
                    267:        /* see if this name has already been used */
                    268: 
                    269:        for(q = namechain ; q; q = q->nextp)
                    270:                if( ! strcmp(fname, q->datap))
                    271:                {
                    272:                        fname[0] = '\0';
                    273:                        return;
                    274:                }
                    275: 
                    276:        q = (struct chain *) calloc(1, sizeof(*chainblock));
                    277:        q->nextp = namechain;
                    278:        q->datap = copys(fname);
                    279:        namechain = q;
                    280: }
                    281: 
                    282: fatal(s,p)
                    283: char *s, *p;
                    284: {
                    285:        fprintf(stderr, "Deroff: ");
                    286:        fprintf(stderr, s, p);
                    287:        exit(1);
                    288: }
                    289: 
                    290: /*ARGSUSED*/
                    291: textline(str, const)
                    292:        char    *str;
                    293:        int     const;
                    294: {
                    295:        if (wordflag) {
                    296:                msputwords(0);
                    297:                return;
                    298:        }
                    299:        puts(str);
                    300: }
                    301: 
                    302: work()
                    303: {
                    304:        for( ;; )
                    305:        {
                    306:                C;
                    307: #ifdef FULLDEBUG
                    308:                printf("Starting work with `%c'\n", c);
                    309: #endif FULLDEBUG
                    310:                if(c == '.'  ||  c == '\'')
                    311:                        comline();
                    312:                else
                    313:                        regline(textline, TWO);
                    314:        }
                    315: }
                    316: 
                    317: regline(pfunc, const)
                    318:        int     (*pfunc)();
                    319:        int     const;
                    320: {
                    321:        line[0] = c;
                    322:        lp = line;
                    323:        for( ; ; )
                    324:        {
                    325:                if(c == '\\') {
                    326:                        *lp = ' ';
                    327:                        backsl();
                    328:                }
                    329:                if(c == '\n')
                    330:                        break;
                    331:                if(intable && c=='T') {
                    332:                        *++lp = C;
                    333:                        if(c=='{' || c=='}') {
                    334:                                lp[-1] = ' ';
                    335:                                *lp = C;
                    336:                        }
                    337:                } else {
                    338:                        *++lp = C;
                    339:                }
                    340:        }
                    341: 
                    342:        *lp = '\0';
                    343: 
                    344:        if(line[0] != '\0')
                    345:                (*pfunc)(line, const);
                    346: }
                    347: 
                    348: macro()
                    349: {
                    350:        if(msflag){
                    351:                do { 
                    352:                        SKIP; 
                    353:                }               while(C!='.' || C!='.' || C=='.');      /* look for  .. */
                    354:                if(c != '\n')SKIP;
                    355:                return;
                    356:        }
                    357:        SKIP;
                    358:        inmacro = YES;
                    359: }
                    360: 
                    361: tbl()
                    362: {
                    363:        while(C != '.');
                    364:        SKIP;
                    365:        intable = YES;
                    366: }
                    367: stbl()
                    368: {
                    369:        while(C != '.');
                    370:        SKIP_TO_COM;
                    371:        if(c != 'T' || C != 'E'){
                    372:                SKIP;
                    373:                pc=c;
                    374:                while(C != '.' || pc != '\n' || C != 'T' || C != 'E')pc=c;
                    375:        }
                    376: }
                    377: 
                    378: eqn()
                    379: {
                    380:        register int c1, c2;
                    381:        register int dflg;
                    382:        char last;
                    383: 
                    384:        last=0;
                    385:        dflg = 1;
                    386:        SKIP;
                    387: 
                    388:        for( ;;)
                    389:        {
                    390:                if(C1 == '.'  || c == '\'')
                    391:                {
                    392:                        while(C1==' ' || c=='\t')
                    393:                                ;
                    394:                        if(c=='E' && C1=='N')
                    395:                        {
                    396:                                SKIP;
                    397:                                if(msflag && dflg){
                    398:                                        putchar('x');
                    399:                                        putchar(' ');
                    400:                                        if(last){
                    401:                                                putchar(last); 
                    402:                                                putchar('\n'); 
                    403:                                        }
                    404:                                }
                    405:                                return;
                    406:                        }
                    407:                }
                    408:                else if(c == 'd')       /* look for delim */
                    409:                {
                    410:                        if(C1=='e' && C1=='l')
                    411:                                if( C1=='i' && C1=='m')
                    412:                                {
                    413:                                        while(C1 == ' ');
                    414:                                        if((c1=c)=='\n' || (c2=C1)=='\n'
                    415:                                            || (c1=='o' && c2=='f' && C1=='f') )
                    416:                                        {
                    417:                                                ldelim = NOCHAR;
                    418:                                                rdelim = NOCHAR;
                    419:                                        }
                    420:                                        else    {
                    421:                                                ldelim = c1;
                    422:                                                rdelim = c2;
                    423:                                        }
                    424:                                }
                    425:                        dflg = 0;
                    426:                }
                    427: 
                    428:                if(c != '\n') while(C1 != '\n'){ 
                    429:                        if(chars[c] == PUNCT)last = c;
                    430:                        else if(c != ' ')last = 0;
                    431:                }
                    432:        }
                    433: }
                    434: 
                    435: backsl()       /* skip over a complete backslash construction */
                    436: {
                    437:        int bdelim;
                    438: 
                    439: sw:  
                    440:        switch(C)
                    441:        {
                    442:        case '"':
                    443:                SKIP;
                    444:                return;
                    445:        case 's':
                    446:                if(C == '\\') backsl();
                    447:                else    {
                    448:                        while(C>='0' && c<='9') ;
                    449:                        ungetc(c,infile);
                    450:                        c = '0';
                    451:                }
                    452:                --lp;
                    453:                return;
                    454: 
                    455:        case 'f':
                    456:        case 'n':
                    457:        case '*':
                    458:                if(C != '(')
                    459:                        return;
                    460: 
                    461:        case '(':
                    462:                if(msflag){
                    463:                        if(C == 'e'){
                    464:                                if(C == 'm'){
                    465:                                        *lp = '-';
                    466:                                        return;
                    467:                                }
                    468:                        }
                    469:                        else if(c != '\n')C;
                    470:                        return;
                    471:                }
                    472:                if(C != '\n') C;
                    473:                return;
                    474: 
                    475:        case '$':
                    476:                C;      /* discard argument number */
                    477:                return;
                    478: 
                    479:        case 'b':
                    480:        case 'x':
                    481:        case 'v':
                    482:        case 'h':
                    483:        case 'w':
                    484:        case 'o':
                    485:        case 'l':
                    486:        case 'L':
                    487:                if( (bdelim=C) == '\n')
                    488:                        return;
                    489:                while(C!='\n' && c!=bdelim)
                    490:                        if(c == '\\') backsl();
                    491:                return;
                    492: 
                    493:        case '\\':
                    494:                if(inmacro)
                    495:                        goto sw;
                    496:        default:
                    497:                return;
                    498:        }
                    499: }
                    500: 
                    501: char *copys(s)
                    502: register char *s;
                    503: {
                    504:        register char *t, *t0;
                    505: 
                    506:        if( (t0 = t = calloc( (unsigned)(strlen(s)+1), sizeof(*t) ) ) == NULL)
                    507:                fatal("Cannot allocate memory", (char *) NULL);
                    508: 
                    509:        while( *t++ = *s++ )
                    510:                ;
                    511:        return(t0);
                    512: }
                    513: 
                    514: sce()
                    515: {
                    516:        register char *ap;
                    517:        register int n, i;
                    518:        char a[10];
                    519:        for(ap=a;C != '\n';ap++){
                    520:                *ap = c;
                    521:                if(ap == &a[9]){
                    522:                        SKIP;
                    523:                        ap=a;
                    524:                        break;
                    525:                }
                    526:        }
                    527:        if(ap != a)n = atoi(a);
                    528:        else n = 1;
                    529:        for(i=0;i<n;){
                    530:                if(C == '.'){
                    531:                        if(C == 'c'){
                    532:                                if(C == 'e'){
                    533:                                        while(C == ' ');
                    534:                                        if(c == '0'){
                    535:                                                SKIP;
                    536:                                                break;
                    537:                                        }
                    538:                                        else SKIP;
                    539:                                }
                    540:                                else SKIP;
                    541:                        }
                    542:                        else if(c == 'P' || C == 'P'){
                    543:                                if(c != '\n')SKIP;
                    544:                                break;
                    545:                        }
                    546:                        else if(c != '\n')SKIP;
                    547:                }
                    548:                else {
                    549:                        SKIP;
                    550:                        i++;
                    551:                }
                    552:        }
                    553: }
                    554: 
                    555: refer(c1)
                    556: {
                    557:        register int c2;
                    558:        if(c1 != '\n')
                    559:                SKIP;
                    560:        while(1){
                    561:                if(C != '.')
                    562:                        SKIP;
                    563:                else {
                    564:                        if(C != ']')
                    565:                                SKIP;
                    566:                        else {
                    567:                                while(C != '\n')
                    568:                                        c2=c;
                    569:                                if(chars[c2] == PUNCT)putchar(c2);
                    570:                                return;
                    571:                        }
                    572:                }
                    573:        }
                    574: }
                    575: 
                    576: inpic()
                    577: {
                    578:        register int c1;
                    579:        register char *p1;
                    580:        SKIP;
                    581:        p1 = line;
                    582:        c = '\n';
                    583:        while(1){
                    584:                c1 = c;
                    585:                if(C == '.' && c1 == '\n'){
                    586:                        if(C != 'P'){
                    587:                                if(c == '\n')continue;
                    588:                                else { SKIP; c='\n'; continue;}
                    589:                        }
                    590:                        if(C != 'E'){
                    591:                                if(c == '\n')continue;
                    592:                                else { SKIP; c='\n';continue; }
                    593:                        }
                    594:                        SKIP;
                    595:                        return;
                    596:                }
                    597:                else if(c == '\"'){
                    598:                        while(C != '\"'){
                    599:                                if(c == '\\'){
                    600:                                        if(C == '\"')continue;
                    601:                                        ungetc(c,infile);
                    602:                                        backsl();
                    603:                                }
                    604:                                else *p1++ = c;
                    605:                        }
                    606:                        *p1++ = ' ';
                    607:                }
                    608:                else if(c == '\n' && p1 != line){
                    609:                        *p1 = '\0';
                    610:                        if(wordflag)msputwords(NO);
                    611:                        else {
                    612:                                puts(line);
                    613:                                putchar('\n');
                    614:                        }
                    615:                        p1 = line;
                    616:                }
                    617:        }
                    618: }
                    619: 
                    620: #ifdef DEBUG
                    621: _C1()
                    622: {
                    623:        return(C1get);
                    624: }
                    625: _C()
                    626: {
                    627:        return(Cget);
                    628: }
                    629: #endif DEBUG
                    630: 
                    631: /*
                    632:  *     Macro processing
                    633:  *
                    634:  *     Macro table definitions
                    635:  */
                    636: #define        reg     register
                    637: typedef        int pacmac;             /* compressed macro name */
                    638: int    argconcat = 0;          /* concat arguments together (-me only) */
                    639: 
                    640: #define        tomac(c1, c2)           ((((c1) & 0xFF) << 8) | ((c2) & 0xFF))
                    641: #define        frommac(src, c1, c2)    (((c1)=((src)>>8)&0xFF),((c2) =(src)&0xFF))
                    642: 
                    643: struct mactab{
                    644:        int     condition;
                    645:        pacmac  macname;
                    646:        int     (*func)();
                    647: };
                    648: struct mactab  troffmactab[];
                    649: struct mactab  ppmactab[];
                    650: struct mactab  msmactab[];
                    651: struct mactab  mmmactab[];
                    652: struct mactab  memactab[];
                    653: struct mactab  manmactab[];
                    654: /*
                    655:  *     macro table initialization
                    656:  */
                    657: #define        M(cond, c1, c2, func) {cond, tomac(c1, c2), func}
                    658: 
                    659: /*
                    660:  *     Put out a macro line, using ms and mm conventions.
                    661:  */
                    662: msputmac(s, const)
                    663:        register char *s;
                    664:        int     const;
                    665: {
                    666:        register char *t;
                    667:        register found;
                    668:        int last;
                    669:        found = 0;
                    670: 
                    671:        if (wordflag) {
                    672:                msputwords(YES);
                    673:                return;
                    674:        }
                    675:        while(*s)
                    676:        {
                    677:                while(*s==' ' || *s=='\t')
                    678:                        putchar(*s++);
                    679:                for(t = s ; *t!=' ' && *t!='\t' && *t!='\0' ; ++t)
                    680:                        ;
                    681:                if(*s == '\"')s++;
                    682:                if(t>s+const && chars[ s[0] ]==LETTER && chars[ s[1] ]==LETTER){
                    683:                        while(s < t)
                    684:                                if(*s == '\"')s++;
                    685:                                else
                    686:                                        putchar(*s++);
                    687:                        last = *(t-1);
                    688:                        found++;
                    689:                }
                    690:                else if(found && chars[ s[0] ] == PUNCT && s[1] == '\0')
                    691:                        putchar(*s++);
                    692:                else{
                    693:                        last = *(t-1);
                    694:                        s = t;
                    695:                }
                    696:        }
                    697:        putchar('\n');
                    698:        if(msflag && chars[last] == PUNCT){
                    699:                putchar(last);
                    700:                putchar('\n');
                    701:        }
                    702: }
                    703: /*
                    704:  *     put out words (for the -w option) with ms and mm conventions
                    705:  */
                    706: msputwords(macline)    
                    707:        int macline;    /* is this is a macro line */
                    708: {
                    709:        register char *p, *p1;
                    710:        int i, nlet;
                    711: 
                    712:        for(p1 = line ; ;) {
                    713:                /*
                    714:                 *      skip initial specials ampersands and apostrophes
                    715:                 */
                    716:                while( chars[*p1] < DIGIT)
                    717:                        if(*p1++ == '\0') return;
                    718:                nlet = 0;
                    719:                for(p = p1 ; (i=chars[*p]) != SPECIAL ; ++p)
                    720:                        if(i == LETTER) ++nlet;
                    721: 
                    722:                if (   (macline && nlet > 1)
                    723:                    || (!macline && nlet > 2 
                    724:                                 && chars[p1[0]] == LETTER
                    725:                                 && chars[p1[1]] == LETTER) )
                    726:                {
                    727:                        /*
                    728:                         *      delete trailing ampersands and apostrophes
                    729:                         */
                    730:                        while(  (p[-1]=='\'')
                    731:                             || (p[-1]=='&')
                    732:                             || (chars[p[-1]] == PUNCT) ){
                    733:                                --p;
                    734:                        }
                    735:                        while(p1 < p)
                    736:                                putchar(*p1++);
                    737:                        putchar('\n');
                    738:                } else {
                    739:                        p1 = p;
                    740:                }
                    741:        }
                    742: }
                    743: /*
                    744:  *     put out a macro using the me conventions
                    745:  */
                    746: #define SKIPBLANK(cp)  while(*cp == ' ' || *cp == '\t') { cp++; }
                    747: #define SKIPNONBLANK(cp) while(*cp !=' ' && *cp !='\cp' && *cp !='\0') { cp++; }
                    748: 
                    749: meputmac(cp, const)
                    750:        reg     char    *cp;
                    751:                int     const;
                    752: {
                    753:        reg     char    *np;
                    754:                int     found;
                    755:                int     argno;
                    756:                int     last;
                    757:                int     inquote;
                    758: 
                    759:        if (wordflag) {
                    760:                meputwords(YES);
                    761:                return;
                    762:        }
                    763:        for (argno = 0; *cp; argno++){
                    764:                SKIPBLANK(cp);
                    765:                inquote = (*cp == '"');
                    766:                if (inquote)
                    767:                        cp++;
                    768:                for (np = cp; *np; np++){
                    769:                        switch(*np){
                    770:                        case '\n':
                    771:                        case '\0':      break;
                    772:                        case '\t':
                    773:                        case ' ':       if (inquote) {
                    774:                                                continue;
                    775:                                        } else {
                    776:                                                goto endarg;
                    777:                                        }
                    778:                        case '"':       if(inquote && np[1] == '"'){
                    779:                                                strcpy(np, np + 1);
                    780:                                                np++;
                    781:                                                continue;
                    782:                                        } else {
                    783:                                                *np = ' ';      /* bye bye " */
                    784:                                                goto endarg;
                    785:                                        }
                    786:                        default:        continue;
                    787:                        }
                    788:                }
                    789:                endarg: ;
                    790:                /*
                    791:                 *      cp points at the first char in the arg
                    792:                 *      np points one beyond the last char in the arg
                    793:                 */
                    794:                if ((argconcat == 0) || (argconcat != argno)) {
                    795:                        putchar(' ');
                    796:                }
                    797: #ifdef FULLDEBUG
                    798:                {
                    799:                        char    *p;
                    800:                        printf("[%d,%d: ", argno, np - cp);
                    801:                        for (p = cp; p < np; p++) {
                    802:                                putchar(*p);
                    803:                        }
                    804:                        printf("]");
                    805:                }
                    806: #endif FULLDEBUG
                    807:                /*
                    808:                 *      Determine if the argument merits being printed
                    809:                 *
                    810:                 *      const is the cut off point below which something
                    811:                 *      is not a word.
                    812:                 */
                    813:                if (   ( (np - cp) > const)
                    814:                    && (    inquote
                    815:                         || (chars[cp[0]] == LETTER)) ){
                    816:                        for (cp = cp; cp < np; cp++){
                    817:                                putchar(*cp);
                    818:                        }
                    819:                        last = np[-1];
                    820:                        found++;
                    821:                } else
                    822:                if(found && (np - cp == 1) && chars[*cp] == PUNCT){
                    823:                        putchar(*cp);
                    824:                } else {
                    825:                        last = np[-1];
                    826:                }
                    827:                cp = np;
                    828:        }
                    829:        if(msflag && chars[last] == PUNCT)
                    830:                putchar(last);
                    831:        putchar('\n');
                    832: }
                    833: /*
                    834:  *     put out words (for the -w option) with ms and mm conventions
                    835:  */
                    836: meputwords(macline)
                    837:        int     macline;
                    838: {
                    839:        msputwords(macline);
                    840: }
                    841: /*
                    842:  *
                    843:  *     Skip over a nested set of macros
                    844:  *
                    845:  *     Possible arguments to noblock are:
                    846:  *
                    847:  *     fi      end of unfilled text
                    848:  *     PE      pic ending
                    849:  *     DE      display ending
                    850:  *
                    851:  *     for ms and mm only:
                    852:  *             KE      keep ending
                    853:  *
                    854:  *             NE      undocumented match to NS (for mm?)
                    855:  *             LE      mm only: matches RL or *L (for lists)
                    856:  *
                    857:  *     for me:
                    858:  *             ([lqbzcdf]
                    859:  */
                    860: 
                    861: noblock(a1, a2)
                    862:        char a1, a2;
                    863: {
                    864:        register int c1,c2;
                    865:        register int eqnf;
                    866:        int lct;
                    867:        lct = 0;
                    868:        eqnf = 1;
                    869:        SKIP;
                    870:        while(1){
                    871:                while(C != '.')
                    872:                        if(c == '\n')
                    873:                                continue;
                    874:                        else
                    875:                                SKIP;
                    876:                if((c1=C) == '\n')
                    877:                        continue;
                    878:                if((c2=C) == '\n')
                    879:                        continue;
                    880:                if(c1==a1 && c2 == a2){
                    881:                        SKIP;
                    882:                        if(lct != 0){
                    883:                                lct--;
                    884:                                continue;
                    885:                        }
                    886:                        if(eqnf)
                    887:                                putchar('.');
                    888:                        putchar('\n');
                    889:                        return;
                    890:                } else if(a1 == 'L' && c2 == 'L'){
                    891:                        lct++;
                    892:                        SKIP;
                    893:                }
                    894:                /*
                    895:                 *      equations (EQ) nested within a display
                    896:                 */
                    897:                else if(c1 == 'E' && c2 == 'Q'){
                    898:                        if (   (mac == ME && a1 == ')')
                    899:                            || (mac != ME && a1 == 'D') ) {
                    900:                                eqn(); 
                    901:                                eqnf=0;
                    902:                        }
                    903:                }
                    904:                /*
                    905:                 *      turning on filling is done by the paragraphing
                    906:                 *      macros
                    907:                 */
                    908:                else if(a1 == 'f') {    /* .fi */
                    909:                        if  (  (mac == ME && (c2 == 'h' || c2 == 'p'))
                    910:                             ||(mac != ME && (c1 == 'P' || c2 == 'P')) ) {
                    911:                                SKIP;
                    912:                                return;
                    913:                        }
                    914:                } else {
                    915:                        SKIP;
                    916:                }
                    917:        }
                    918: }
                    919: 
                    920: EQ()
                    921: {
                    922:        eqn();
                    923:        return(0);
                    924: }
                    925: domacro()
                    926: {
                    927:        macro();
                    928:        return(0);
                    929: }
                    930: PS()
                    931: {
                    932:        if (!msflag) {
                    933:                inpic();
                    934:        } else {
                    935:                noblock('P', 'E');
                    936:        }
                    937:        return(0);
                    938: }
                    939: 
                    940: skip()
                    941: {
                    942:        SKIP;
                    943:        return(0);
                    944: }
                    945: 
                    946: intbl()
                    947: {
                    948:        if(msflag){ 
                    949:                stbl(); 
                    950:        }
                    951:        else tbl(); 
                    952:        return(0);
                    953: }
                    954: 
                    955: outtbl(){ intable = NO; }
                    956: 
                    957: so()
                    958: {
                    959:        getfname();
                    960:        if( fname[0] )
                    961:                infile = *++filesp = opn( fname );
                    962:        return(0);
                    963: }
                    964: nx()
                    965: {
                    966:        getfname();
                    967:        if(fname[0] == '\0') exit(0);
                    968:        if(infile != stdin)
                    969:                fclose(infile);
                    970:        infile = *filesp = opn(fname);
                    971:        return(0);
                    972: }
                    973: skiptocom(){ SKIP_TO_COM; return(COMX); }
                    974: 
                    975: PP(c12)
                    976:        pacmac  c12;
                    977: {
                    978:        int     c1, c2;
                    979:        
                    980:        frommac(c12, c1, c2);
                    981:        printf(".%c%c",c1,c2);
                    982:        while(C != '\n')putchar(c);
                    983:        putchar('\n');
                    984:        return(0);
                    985: }
                    986: AU()
                    987: {
                    988:        if(mac==MM) {
                    989:                return(0);
                    990:        } else {
                    991:                SKIP_TO_COM;
                    992:                return(COMX);
                    993:        }
                    994: }
                    995: 
                    996: SH(c12)
                    997:        pacmac  c12;
                    998: {
                    999:        int     c1, c2;
                   1000:        
                   1001:        frommac(c12, c1, c2);
                   1002: 
                   1003:        if(parag){
                   1004:                printf(".%c%c",c1,c2);
                   1005:                while(C != '\n')putchar(c);
                   1006:                putchar(c);
                   1007:                putchar('!');
                   1008:                while(1){
                   1009:                        while(C != '\n')putchar(c);
                   1010:                        putchar('\n');
                   1011:                        if(C == '.')
                   1012:                                return(COM);
                   1013:                        putchar('!');
                   1014:                        putchar(c);
                   1015:                }
                   1016:                /*NOTREACHED*/
                   1017:        } else {
                   1018:                SKIP_TO_COM;
                   1019:                return(COMX);
                   1020:        }
                   1021: }
                   1022: 
                   1023: UX()
                   1024: {
                   1025:        if(wordflag)
                   1026:                printf("UNIX\n");
                   1027:        else
                   1028:                printf("UNIX ");
                   1029:        return(0);
                   1030: }
                   1031: 
                   1032: MMHU(c12)
                   1033:        pacmac  c12;
                   1034: {
                   1035:        int     c1, c2;
                   1036:        
                   1037:        frommac(c12, c1, c2);
                   1038:        if(parag){
                   1039:                printf(".%c%c",c1,c2);
                   1040:                while(C != '\n')putchar(c);
                   1041:                putchar('\n');
                   1042:        } else {
                   1043:                SKIP;
                   1044:        }
                   1045:        return(0);
                   1046: }
                   1047: 
                   1048: mesnblock(c12)
                   1049:        pacmac  c12;
                   1050: {
                   1051:        int     c1, c2;
                   1052:        
                   1053:        frommac(c12, c1, c2);
                   1054:        noblock(')',c2);
                   1055:        return(0);
                   1056: }
                   1057: mssnblock(c12)
                   1058:        pacmac  c12;
                   1059: {
                   1060:        int     c1, c2;
                   1061:        
                   1062:        frommac(c12, c1, c2);
                   1063:        noblock(c1,'E');
                   1064:        return(0);
                   1065: }      
                   1066: nf()
                   1067: {
                   1068:        noblock('f','i');
                   1069:        return(0);
                   1070: }
                   1071: 
                   1072: ce()
                   1073: {
                   1074:        sce();
                   1075:        return(0);
                   1076: }
                   1077: 
                   1078: meip(c12)
                   1079:        pacmac  c12;
                   1080: {
                   1081:        if(parag)
                   1082:                mepp(c12);
                   1083:        else if (wordflag)      /* save the tag */
                   1084:                regline(meputmac, ONE);
                   1085:        else {
                   1086:                SKIP;
                   1087:        }
                   1088:        return(0);
                   1089: }
                   1090: /*
                   1091:  *     only called for -me .pp or .sh, when parag is on
                   1092:  */
                   1093: mepp(c12)
                   1094:        pacmac  c12;
                   1095: {
                   1096:        PP(c12);                /* eats the line */
                   1097:        return(0);
                   1098: }
                   1099: /* 
                   1100:  *     Start of a section heading; output the section name if doing words
                   1101:  */
                   1102: mesh(c12)
                   1103:        pacmac  c12;
                   1104: {
                   1105:        if (parag)
                   1106:                mepp(c12);
                   1107:        else if (wordflag)
                   1108:                defcomline(c12);
                   1109:        else {
                   1110:                SKIP;
                   1111:        }
                   1112:        return(0);
                   1113: }
                   1114: /*
                   1115:  *     process a font setting
                   1116:  */
                   1117: mefont(c12)
                   1118:        pacmac  c12;
                   1119: {
                   1120:        argconcat = 1;
                   1121:        defcomline(c12);
                   1122:        argconcat = 0;
                   1123:        return(0);
                   1124: }
                   1125: manfont(c12)
                   1126:        pacmac  c12;
                   1127: {
                   1128:        return(mefont(c12));
                   1129: }
                   1130: manpp(c12)
                   1131:        pacmac  c12;
                   1132: {
                   1133:        return(mepp(c12));
                   1134: }
                   1135: 
                   1136: defcomline(c12)
                   1137:        pacmac  c12;
                   1138: {
                   1139:        int     c1, c2;
                   1140:        
                   1141:        frommac(c12, c1, c2);
                   1142:        if(msflag && mac==MM && c2=='L'){
                   1143:                if(disp || c1 == 'R') {
                   1144:                        noblock('L','E');
                   1145:                } else {
                   1146:                        SKIP;
                   1147:                        putchar('.');
                   1148:                }
                   1149:        }
                   1150:        else if(c1=='.' && c2=='.'){
                   1151:                if(msflag){
                   1152:                        SKIP;
                   1153:                        return;
                   1154:                }
                   1155:                while(C == '.')
                   1156:                        /*VOID*/;
                   1157:        }
                   1158:        ++inmacro;
                   1159:        /*
                   1160:         *      Process the arguments to the macro
                   1161:         */
                   1162:        switch(mac){
                   1163:        default:
                   1164:        case MM:
                   1165:        case MS:
                   1166:                if(c1 <= 'Z' && msflag)
                   1167:                        regline(msputmac, ONE);
                   1168:                else
                   1169:                        regline(msputmac, TWO);
                   1170:                break;
                   1171:        case ME:
                   1172:                regline(meputmac, ONE);
                   1173:                break;
                   1174:        }
                   1175:        --inmacro;
                   1176: }
                   1177: 
                   1178: comline()
                   1179: {
                   1180:        reg     int     c1;
                   1181:        reg     int     c2;
                   1182:                pacmac  c12;
                   1183:        reg     int     mid;
                   1184:                int     lb, ub;
                   1185:                int     hit;
                   1186:        static  int     tabsize = 0;
                   1187:        static  struct  mactab  *mactab = (struct mactab *)0;
                   1188:        reg     struct  mactab  *mp;
                   1189: 
                   1190:        if (mactab == 0){
                   1191:                 buildtab(&mactab, &tabsize);
                   1192:        }
                   1193: com:
                   1194:        while(C==' ' || c=='\t')
                   1195:                ;
                   1196: comx:
                   1197:        if( (c1=c) == '\n')
                   1198:                return;
                   1199:        c2 = C;
                   1200:        if(c1=='.' && c2 !='.')
                   1201:                inmacro = NO;
                   1202:        if(msflag && c1 == '['){
                   1203:                refer(c2);
                   1204:                return;
                   1205:        }
                   1206:        if(parag && mac==MM && c1 == 'P' && c2 == '\n'){
                   1207:                printf(".P\n");
                   1208:                return;
                   1209:        }
                   1210:        if(c2 == '\n')
                   1211:                return;
                   1212:        /*
                   1213:         *      Single letter macro
                   1214:         */
                   1215:        if (mac == ME && (c2 == ' ' || c2 == '\t') )
                   1216:                c2 = ' ';
                   1217:        c12 = tomac(c1, c2);
                   1218:        /*
                   1219:         *      binary search through the table of macros
                   1220:         */
                   1221:        lb = 0;
                   1222:        ub = tabsize - 1;
                   1223:        while(lb <= ub){
                   1224:                mid = (ub + lb) / 2;
                   1225:                mp = &mactab[mid];
                   1226:                if (mp->macname < c12)
                   1227:                        lb = mid + 1;
                   1228:                else if (mp->macname > c12)
                   1229:                        ub = mid - 1;
                   1230:                else {
                   1231:                        hit = 1;
                   1232: #ifdef FULLDEBUG
                   1233:                        printf("preliminary hit macro %c%c ", c1, c2);
                   1234: #endif FULLDEBUG
                   1235:                        switch(mp->condition){
                   1236:                        case NONE:      hit = YES;                      break;
                   1237:                        case FNEST:     hit = (filesp == files);        break;
                   1238:                        case NOMAC:     hit = !inmacro;                 break;
                   1239:                        case MAC:       hit = inmacro;                  break;
                   1240:                        case PARAG:     hit = parag;                    break;
                   1241:                        case NBLK:      hit = !keepblock;               break;
                   1242:                        default:        hit = 0;
                   1243:                        }
                   1244:                        if (hit) {
                   1245: #ifdef FULLDEBUG
                   1246:                                printf("MATCH\n");
                   1247: #endif FULLDEBUG
                   1248:                                switch( (*(mp->func))(c12) ) {
                   1249:                                default:        return;
                   1250:                                case COMX:      goto comx;
                   1251:                                case COM:       goto com;
                   1252:                                }
                   1253:                        }
                   1254: #ifdef FULLDEBUG
                   1255:                        printf("FAIL\n");
                   1256: #endif FULLDEBUG
                   1257:                        break;
                   1258:                }
                   1259:        }
                   1260:        defcomline(c12);
                   1261: }
                   1262: 
                   1263: int macsort(p1, p2)
                   1264:        struct  mactab  *p1, *p2;
                   1265: {
                   1266:        return(p1->macname - p2->macname);
                   1267: }
                   1268: 
                   1269: int sizetab(mp)
                   1270:        reg     struct  mactab  *mp;
                   1271: {
                   1272:        reg     int     i;
                   1273:        i = 0;
                   1274:        if (mp){
                   1275:                for (; mp->macname; mp++, i++)
                   1276:                        /*VOID*/ ;
                   1277:        }
                   1278:        return(i);
                   1279: }
                   1280: 
                   1281: struct mactab *macfill(dst, src)
                   1282:        reg     struct  mactab  *dst;
                   1283:        reg     struct  mactab  *src;
                   1284: {
                   1285:        if (src) {
                   1286:                while(src->macname){
                   1287:                        *dst++ = *src++;
                   1288:                }
                   1289:        }
                   1290:        return(dst);
                   1291: }
                   1292: 
                   1293: buildtab(r_back, r_size)
                   1294:        struct  mactab  **r_back;
                   1295:        int     *r_size;
                   1296: {
                   1297:        int     size;
                   1298: 
                   1299:        struct  mactab  *p, *p1, *p2;
                   1300:        struct  mactab  *back;
                   1301: 
                   1302:        size = sizetab(troffmactab);
                   1303:        size += sizetab(ppmactab);
                   1304:        p1 = p2 = (struct mactab *)0;
                   1305:        if (msflag){
                   1306:                switch(mac){
                   1307:                case ME:        p1 = memactab; break;
                   1308:                case MM:        p1 = msmactab;
                   1309:                                p2 = mmmactab; break;
                   1310: 
                   1311:                case MS:        p1 = msmactab; break;
                   1312:                case MA:        p1 = manmactab; break;
                   1313:                default:        break;
                   1314:                }
                   1315:        }
                   1316:        size += sizetab(p1);
                   1317:        size += sizetab(p2);
                   1318:        back = (struct mactab *)calloc(size+2, sizeof(struct mactab));
                   1319: 
                   1320:        p = macfill(back, troffmactab);
                   1321:        p = macfill(p, ppmactab);
                   1322:        p = macfill(p, p1);
                   1323:        p = macfill(p, p2);
                   1324: 
                   1325:        qsort(back, size, sizeof(struct mactab), macsort);
                   1326:        *r_size = size;
                   1327:        *r_back = back;
                   1328: }
                   1329: 
                   1330: /*
                   1331:  *     troff commands
                   1332:  */
                   1333: struct mactab  troffmactab[] = {
                   1334:        M(NONE,         '\\','"',       skip),  /* comment */
                   1335:        M(NOMAC,        'd','e',        domacro),       /* define */
                   1336:        M(NOMAC,        'i','g',        domacro),       /* ignore till .. */
                   1337:        M(NOMAC,        'a','m',        domacro),       /* append macro */
                   1338:        M(NBLK,         'n','f',        nf),    /* filled */
                   1339:        M(NBLK,         'c','e',        ce),    /* centered */
                   1340: 
                   1341:        M(NONE,         's','o',        so),    /* source a file */
                   1342:        M(NONE,         'n','x',        nx),    /* go to next file */
                   1343: 
                   1344:        M(NONE,         't','m',        skip),  /* print string on tty */
                   1345:        M(NONE,         'h','w',        skip),  /* exception hyphen words */
                   1346:        M(NONE,         0,0,            0)
                   1347: };
                   1348: /*
                   1349:  *     Preprocessor output
                   1350:  */
                   1351: struct mactab  ppmactab[] = {
                   1352:        M(FNEST,        'E','Q',        EQ),    /* equation starting */
                   1353:        M(FNEST,        'T','S',        intbl), /* table starting */
                   1354:        M(FNEST,        'T','C',        intbl), /* alternative table? */
                   1355:        M(FNEST,        'T','&',        intbl), /* table reformatting */
                   1356:        M(NONE,         'T','E',        outtbl),/* table ending */
                   1357:        M(NONE,         'P','S',        PS),    /* picture starting */
                   1358:        M(NONE,         0,0,            0)
                   1359: };
                   1360: /*
                   1361:  *     Particular to ms and mm
                   1362:  */
                   1363: struct mactab  msmactab[] = {
                   1364:        M(NONE,         'T','L',        skiptocom),     /* title follows */
                   1365:        M(NONE,         'F','S',        skiptocom),     /* start footnote */
                   1366:        M(NONE,         'O','K',        skiptocom),     /* Other kws */
                   1367: 
                   1368:        M(NONE,         'N','R',        skip),  /* undocumented */
                   1369:        M(NONE,         'N','D',        skip),  /* use supplied date */
                   1370: 
                   1371:        M(PARAG,        'P','P',        PP),    /* begin parag */
                   1372:        M(PARAG,        'I','P',        PP),    /* begin indent parag, tag x */
                   1373:        M(PARAG,        'L','P',        PP),    /* left blocked parag */
                   1374: 
                   1375:        M(NONE,         'A','U',        AU),    /* author */
                   1376:        M(NONE,         'A','I',        AU),    /* authors institution */
                   1377: 
                   1378:        M(NONE,         'S','H',        SH),    /* section heading */
                   1379:        M(NONE,         'S','N',        SH),    /* undocumented */
                   1380:        M(NONE,         'U','X',        UX),    /* unix */
                   1381: 
                   1382:        M(NBLK,         'D','S',        mssnblock),     /* start display text */
                   1383:        M(NBLK,         'K','S',        mssnblock),     /* start keep */
                   1384:        M(NBLK,         'K','F',        mssnblock),     /* start float keep */
                   1385:        M(NONE,         0,0,            0)
                   1386: };
                   1387: 
                   1388: struct mactab  mmmactab[] = {
                   1389:        M(NONE,         'H',' ',        MMHU),  /* -mm ? */
                   1390:        M(NONE,         'H','U',        MMHU),  /* -mm ? */
                   1391:        M(PARAG,        'P',' ',        PP),    /* paragraph for -mm */
                   1392:        M(NBLK,         'N','S',        mssnblock),     /* undocumented */
                   1393:        M(NONE,         0,0,            0)
                   1394: };
                   1395: 
                   1396: struct mactab  memactab[] = {
                   1397:        M(PARAG,        'p','p',        mepp),
                   1398:        M(PARAG,        'l','p',        mepp),
                   1399:        M(PARAG,        'n','p',        mepp),
                   1400:        M(NONE,         'i','p',        meip),
                   1401: 
                   1402:        M(NONE,         's','h',        mesh),
                   1403:        M(NONE,         'u','h',        mesh),
                   1404: 
                   1405:        M(NBLK,         '(','l',        mesnblock),
                   1406:        M(NBLK,         '(','q',        mesnblock),
                   1407:        M(NBLK,         '(','b',        mesnblock),
                   1408:        M(NBLK,         '(','z',        mesnblock),
                   1409:        M(NBLK,         '(','c',        mesnblock),
                   1410: 
                   1411:        M(NBLK,         '(','d',        mesnblock),
                   1412:        M(NBLK,         '(','f',        mesnblock),
                   1413:        M(NBLK,         '(','x',        mesnblock),
                   1414: 
                   1415:        M(NONE,         'r',' ',        mefont),
                   1416:        M(NONE,         'i',' ',        mefont),
                   1417:        M(NONE,         'b',' ',        mefont),
                   1418:        M(NONE,         'u',' ',        mefont),
                   1419:        M(NONE,         'q',' ',        mefont),
                   1420:        M(NONE,         'r','b',        mefont),
                   1421:        M(NONE,         'b','i',        mefont),
                   1422:        M(NONE,         'b','x',        mefont),
                   1423:        M(NONE,         0,0,            0)
                   1424: };
                   1425: 
                   1426: 
                   1427: struct mactab  manmactab[] = {
                   1428:        M(PARAG,        'B','I',        manfont),
                   1429:        M(PARAG,        'B','R',        manfont),
                   1430:        M(PARAG,        'I','B',        manfont),
                   1431:        M(PARAG,        'I','R',        manfont),
                   1432:        M(PARAG,        'R','B',        manfont),
                   1433:        M(PARAG,        'R','I',        manfont),
                   1434: 
                   1435:        M(PARAG,        'P','P',        manpp),
                   1436:        M(PARAG,        'L','P',        manpp),
                   1437:        M(PARAG,        'H','P',        manpp),
                   1438:        M(NONE,         0,0,            0)
                   1439: };

unix.superglobalmegacorp.com

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