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

1.1       root        1: #ifndef lint
                      2: static char sccsid[] = "@(#)deroff.c   4.5     (Berkeley)      84/12/18";
                      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 (nlet > 1 && chars[p1[0]] == LETTER) {
                    723:                        /*
                    724:                         *      delete trailing ampersands and apostrophes
                    725:                         */
                    726:                        while( (i=chars[p[-1]]) == PUNCT || i == APOS )
                    727:                                --p;
                    728:                        while(p1 < p)
                    729:                                putchar(*p1++);
                    730:                        putchar('\n');
                    731:                } else {
                    732:                        p1 = p;
                    733:                }
                    734:        }
                    735: }
                    736: /*
                    737:  *     put out a macro using the me conventions
                    738:  */
                    739: #define SKIPBLANK(cp)  while(*cp == ' ' || *cp == '\t') { cp++; }
                    740: #define SKIPNONBLANK(cp) while(*cp !=' ' && *cp !='\cp' && *cp !='\0') { cp++; }
                    741: 
                    742: meputmac(cp, const)
                    743:        reg     char    *cp;
                    744:                int     const;
                    745: {
                    746:        reg     char    *np;
                    747:                int     found;
                    748:                int     argno;
                    749:                int     last;
                    750:                int     inquote;
                    751: 
                    752:        if (wordflag) {
                    753:                meputwords(YES);
                    754:                return;
                    755:        }
                    756:        for (argno = 0; *cp; argno++){
                    757:                SKIPBLANK(cp);
                    758:                inquote = (*cp == '"');
                    759:                if (inquote)
                    760:                        cp++;
                    761:                for (np = cp; *np; np++){
                    762:                        switch(*np){
                    763:                        case '\n':
                    764:                        case '\0':      break;
                    765:                        case '\t':
                    766:                        case ' ':       if (inquote) {
                    767:                                                continue;
                    768:                                        } else {
                    769:                                                goto endarg;
                    770:                                        }
                    771:                        case '"':       if(inquote && np[1] == '"'){
                    772:                                                strcpy(np, np + 1);
                    773:                                                np++;
                    774:                                                continue;
                    775:                                        } else {
                    776:                                                *np = ' ';      /* bye bye " */
                    777:                                                goto endarg;
                    778:                                        }
                    779:                        default:        continue;
                    780:                        }
                    781:                }
                    782:                endarg: ;
                    783:                /*
                    784:                 *      cp points at the first char in the arg
                    785:                 *      np points one beyond the last char in the arg
                    786:                 */
                    787:                if ((argconcat == 0) || (argconcat != argno)) {
                    788:                        putchar(' ');
                    789:                }
                    790: #ifdef FULLDEBUG
                    791:                {
                    792:                        char    *p;
                    793:                        printf("[%d,%d: ", argno, np - cp);
                    794:                        for (p = cp; p < np; p++) {
                    795:                                putchar(*p);
                    796:                        }
                    797:                        printf("]");
                    798:                }
                    799: #endif FULLDEBUG
                    800:                /*
                    801:                 *      Determine if the argument merits being printed
                    802:                 *
                    803:                 *      const is the cut off point below which something
                    804:                 *      is not a word.
                    805:                 */
                    806:                if (   ( (np - cp) > const)
                    807:                    && (    inquote
                    808:                         || (chars[cp[0]] == LETTER)) ){
                    809:                        for (cp = cp; cp < np; cp++){
                    810:                                putchar(*cp);
                    811:                        }
                    812:                        last = np[-1];
                    813:                        found++;
                    814:                } else
                    815:                if(found && (np - cp == 1) && chars[*cp] == PUNCT){
                    816:                        putchar(*cp);
                    817:                } else {
                    818:                        last = np[-1];
                    819:                }
                    820:                cp = np;
                    821:        }
                    822:        if(msflag && chars[last] == PUNCT)
                    823:                putchar(last);
                    824:        putchar('\n');
                    825: }
                    826: /*
                    827:  *     put out words (for the -w option) with ms and mm conventions
                    828:  */
                    829: meputwords(macline)
                    830:        int     macline;
                    831: {
                    832:        msputwords(macline);
                    833: }
                    834: /*
                    835:  *
                    836:  *     Skip over a nested set of macros
                    837:  *
                    838:  *     Possible arguments to noblock are:
                    839:  *
                    840:  *     fi      end of unfilled text
                    841:  *     PE      pic ending
                    842:  *     DE      display ending
                    843:  *
                    844:  *     for ms and mm only:
                    845:  *             KE      keep ending
                    846:  *
                    847:  *             NE      undocumented match to NS (for mm?)
                    848:  *             LE      mm only: matches RL or *L (for lists)
                    849:  *
                    850:  *     for me:
                    851:  *             ([lqbzcdf]
                    852:  */
                    853: 
                    854: noblock(a1, a2)
                    855:        char a1, a2;
                    856: {
                    857:        register int c1,c2;
                    858:        register int eqnf;
                    859:        int lct;
                    860:        lct = 0;
                    861:        eqnf = 1;
                    862:        SKIP;
                    863:        while(1){
                    864:                while(C != '.')
                    865:                        if(c == '\n')
                    866:                                continue;
                    867:                        else
                    868:                                SKIP;
                    869:                if((c1=C) == '\n')
                    870:                        continue;
                    871:                if((c2=C) == '\n')
                    872:                        continue;
                    873:                if(c1==a1 && c2 == a2){
                    874:                        SKIP;
                    875:                        if(lct != 0){
                    876:                                lct--;
                    877:                                continue;
                    878:                        }
                    879:                        if(eqnf)
                    880:                                putchar('.');
                    881:                        putchar('\n');
                    882:                        return;
                    883:                } else if(a1 == 'L' && c2 == 'L'){
                    884:                        lct++;
                    885:                        SKIP;
                    886:                }
                    887:                /*
                    888:                 *      equations (EQ) nested within a display
                    889:                 */
                    890:                else if(c1 == 'E' && c2 == 'Q'){
                    891:                        if (   (mac == ME && a1 == ')')
                    892:                            || (mac != ME && a1 == 'D') ) {
                    893:                                eqn(); 
                    894:                                eqnf=0;
                    895:                        }
                    896:                }
                    897:                /*
                    898:                 *      turning on filling is done by the paragraphing
                    899:                 *      macros
                    900:                 */
                    901:                else if(a1 == 'f') {    /* .fi */
                    902:                        if  (  (mac == ME && (c2 == 'h' || c2 == 'p'))
                    903:                             ||(mac != ME && (c1 == 'P' || c2 == 'P')) ) {
                    904:                                SKIP;
                    905:                                return;
                    906:                        }
                    907:                } else {
                    908:                        SKIP;
                    909:                }
                    910:        }
                    911: }
                    912: 
                    913: EQ()
                    914: {
                    915:        eqn();
                    916:        return(0);
                    917: }
                    918: domacro()
                    919: {
                    920:        macro();
                    921:        return(0);
                    922: }
                    923: PS()
                    924: {
                    925:        if (!msflag) {
                    926:                inpic();
                    927:        } else {
                    928:                noblock('P', 'E');
                    929:        }
                    930:        return(0);
                    931: }
                    932: 
                    933: skip()
                    934: {
                    935:        SKIP;
                    936:        return(0);
                    937: }
                    938: 
                    939: intbl()
                    940: {
                    941:        if(msflag){ 
                    942:                stbl(); 
                    943:        }
                    944:        else tbl(); 
                    945:        return(0);
                    946: }
                    947: 
                    948: outtbl(){ intable = NO; }
                    949: 
                    950: so()
                    951: {
                    952:        getfname();
                    953:        if( fname[0] )
                    954:                infile = *++filesp = opn( fname );
                    955:        return(0);
                    956: }
                    957: nx()
                    958: {
                    959:        getfname();
                    960:        if(fname[0] == '\0') exit(0);
                    961:        if(infile != stdin)
                    962:                fclose(infile);
                    963:        infile = *filesp = opn(fname);
                    964:        return(0);
                    965: }
                    966: skiptocom(){ SKIP_TO_COM; return(COMX); }
                    967: 
                    968: PP(c12)
                    969:        pacmac  c12;
                    970: {
                    971:        int     c1, c2;
                    972:        
                    973:        frommac(c12, c1, c2);
                    974:        printf(".%c%c",c1,c2);
                    975:        while(C != '\n')putchar(c);
                    976:        putchar('\n');
                    977:        return(0);
                    978: }
                    979: AU()
                    980: {
                    981:        if(mac==MM) {
                    982:                return(0);
                    983:        } else {
                    984:                SKIP_TO_COM;
                    985:                return(COMX);
                    986:        }
                    987: }
                    988: 
                    989: SH(c12)
                    990:        pacmac  c12;
                    991: {
                    992:        int     c1, c2;
                    993:        
                    994:        frommac(c12, c1, c2);
                    995: 
                    996:        if(parag){
                    997:                printf(".%c%c",c1,c2);
                    998:                while(C != '\n')putchar(c);
                    999:                putchar(c);
                   1000:                putchar('!');
                   1001:                while(1){
                   1002:                        while(C != '\n')putchar(c);
                   1003:                        putchar('\n');
                   1004:                        if(C == '.')
                   1005:                                return(COM);
                   1006:                        putchar('!');
                   1007:                        putchar(c);
                   1008:                }
                   1009:                /*NOTREACHED*/
                   1010:        } else {
                   1011:                SKIP_TO_COM;
                   1012:                return(COMX);
                   1013:        }
                   1014: }
                   1015: 
                   1016: UX()
                   1017: {
                   1018:        if(wordflag)
                   1019:                printf("UNIX\n");
                   1020:        else
                   1021:                printf("UNIX ");
                   1022:        return(0);
                   1023: }
                   1024: 
                   1025: MMHU(c12)
                   1026:        pacmac  c12;
                   1027: {
                   1028:        int     c1, c2;
                   1029:        
                   1030:        frommac(c12, c1, c2);
                   1031:        if(parag){
                   1032:                printf(".%c%c",c1,c2);
                   1033:                while(C != '\n')putchar(c);
                   1034:                putchar('\n');
                   1035:        } else {
                   1036:                SKIP;
                   1037:        }
                   1038:        return(0);
                   1039: }
                   1040: 
                   1041: mesnblock(c12)
                   1042:        pacmac  c12;
                   1043: {
                   1044:        int     c1, c2;
                   1045:        
                   1046:        frommac(c12, c1, c2);
                   1047:        noblock(')',c2);
                   1048:        return(0);
                   1049: }
                   1050: mssnblock(c12)
                   1051:        pacmac  c12;
                   1052: {
                   1053:        int     c1, c2;
                   1054:        
                   1055:        frommac(c12, c1, c2);
                   1056:        noblock(c1,'E');
                   1057:        return(0);
                   1058: }      
                   1059: nf()
                   1060: {
                   1061:        noblock('f','i');
                   1062:        return(0);
                   1063: }
                   1064: 
                   1065: ce()
                   1066: {
                   1067:        sce();
                   1068:        return(0);
                   1069: }
                   1070: 
                   1071: meip(c12)
                   1072:        pacmac  c12;
                   1073: {
                   1074:        if(parag)
                   1075:                mepp(c12);
                   1076:        else if (wordflag)      /* save the tag */
                   1077:                regline(meputmac, ONE);
                   1078:        else {
                   1079:                SKIP;
                   1080:        }
                   1081:        return(0);
                   1082: }
                   1083: /*
                   1084:  *     only called for -me .pp or .sh, when parag is on
                   1085:  */
                   1086: mepp(c12)
                   1087:        pacmac  c12;
                   1088: {
                   1089:        PP(c12);                /* eats the line */
                   1090:        return(0);
                   1091: }
                   1092: /* 
                   1093:  *     Start of a section heading; output the section name if doing words
                   1094:  */
                   1095: mesh(c12)
                   1096:        pacmac  c12;
                   1097: {
                   1098:        if (parag)
                   1099:                mepp(c12);
                   1100:        else if (wordflag)
                   1101:                defcomline(c12);
                   1102:        else {
                   1103:                SKIP;
                   1104:        }
                   1105:        return(0);
                   1106: }
                   1107: /*
                   1108:  *     process a font setting
                   1109:  */
                   1110: mefont(c12)
                   1111:        pacmac  c12;
                   1112: {
                   1113:        argconcat = 1;
                   1114:        defcomline(c12);
                   1115:        argconcat = 0;
                   1116:        return(0);
                   1117: }
                   1118: manfont(c12)
                   1119:        pacmac  c12;
                   1120: {
                   1121:        return(mefont(c12));
                   1122: }
                   1123: manpp(c12)
                   1124:        pacmac  c12;
                   1125: {
                   1126:        return(mepp(c12));
                   1127: }
                   1128: 
                   1129: defcomline(c12)
                   1130:        pacmac  c12;
                   1131: {
                   1132:        int     c1, c2;
                   1133:        
                   1134:        frommac(c12, c1, c2);
                   1135:        if(msflag && mac==MM && c2=='L'){
                   1136:                if(disp || c1 == 'R') {
                   1137:                        noblock('L','E');
                   1138:                } else {
                   1139:                        SKIP;
                   1140:                        putchar('.');
                   1141:                }
                   1142:        }
                   1143:        else if(c1=='.' && c2=='.'){
                   1144:                if(msflag){
                   1145:                        SKIP;
                   1146:                        return;
                   1147:                }
                   1148:                while(C == '.')
                   1149:                        /*VOID*/;
                   1150:        }
                   1151:        ++inmacro;
                   1152:        /*
                   1153:         *      Process the arguments to the macro
                   1154:         */
                   1155:        switch(mac){
                   1156:        default:
                   1157:        case MM:
                   1158:        case MS:
                   1159:                if(c1 <= 'Z' && msflag)
                   1160:                        regline(msputmac, ONE);
                   1161:                else
                   1162:                        regline(msputmac, TWO);
                   1163:                break;
                   1164:        case ME:
                   1165:                regline(meputmac, ONE);
                   1166:                break;
                   1167:        }
                   1168:        --inmacro;
                   1169: }
                   1170: 
                   1171: comline()
                   1172: {
                   1173:        reg     int     c1;
                   1174:        reg     int     c2;
                   1175:                pacmac  c12;
                   1176:        reg     int     mid;
                   1177:                int     lb, ub;
                   1178:                int     hit;
                   1179:        static  int     tabsize = 0;
                   1180:        static  struct  mactab  *mactab = (struct mactab *)0;
                   1181:        reg     struct  mactab  *mp;
                   1182: 
                   1183:        if (mactab == 0){
                   1184:                 buildtab(&mactab, &tabsize);
                   1185:        }
                   1186: com:
                   1187:        while(C==' ' || c=='\t')
                   1188:                ;
                   1189: comx:
                   1190:        if( (c1=c) == '\n')
                   1191:                return;
                   1192:        c2 = C;
                   1193:        if(c1=='.' && c2 !='.')
                   1194:                inmacro = NO;
                   1195:        if(msflag && c1 == '['){
                   1196:                refer(c2);
                   1197:                return;
                   1198:        }
                   1199:        if(parag && mac==MM && c1 == 'P' && c2 == '\n'){
                   1200:                printf(".P\n");
                   1201:                return;
                   1202:        }
                   1203:        if(c2 == '\n')
                   1204:                return;
                   1205:        /*
                   1206:         *      Single letter macro
                   1207:         */
                   1208:        if (mac == ME && (c2 == ' ' || c2 == '\t') )
                   1209:                c2 = ' ';
                   1210:        c12 = tomac(c1, c2);
                   1211:        /*
                   1212:         *      binary search through the table of macros
                   1213:         */
                   1214:        lb = 0;
                   1215:        ub = tabsize - 1;
                   1216:        while(lb <= ub){
                   1217:                mid = (ub + lb) / 2;
                   1218:                mp = &mactab[mid];
                   1219:                if (mp->macname < c12)
                   1220:                        lb = mid + 1;
                   1221:                else if (mp->macname > c12)
                   1222:                        ub = mid - 1;
                   1223:                else {
                   1224:                        hit = 1;
                   1225: #ifdef FULLDEBUG
                   1226:                        printf("preliminary hit macro %c%c ", c1, c2);
                   1227: #endif FULLDEBUG
                   1228:                        switch(mp->condition){
                   1229:                        case NONE:      hit = YES;                      break;
                   1230:                        case FNEST:     hit = (filesp == files);        break;
                   1231:                        case NOMAC:     hit = !inmacro;                 break;
                   1232:                        case MAC:       hit = inmacro;                  break;
                   1233:                        case PARAG:     hit = parag;                    break;
                   1234:                        case NBLK:      hit = !keepblock;               break;
                   1235:                        default:        hit = 0;
                   1236:                        }
                   1237:                        if (hit) {
                   1238: #ifdef FULLDEBUG
                   1239:                                printf("MATCH\n");
                   1240: #endif FULLDEBUG
                   1241:                                switch( (*(mp->func))(c12) ) {
                   1242:                                default:        return;
                   1243:                                case COMX:      goto comx;
                   1244:                                case COM:       goto com;
                   1245:                                }
                   1246:                        }
                   1247: #ifdef FULLDEBUG
                   1248:                        printf("FAIL\n");
                   1249: #endif FULLDEBUG
                   1250:                        break;
                   1251:                }
                   1252:        }
                   1253:        defcomline(c12);
                   1254: }
                   1255: 
                   1256: int macsort(p1, p2)
                   1257:        struct  mactab  *p1, *p2;
                   1258: {
                   1259:        return(p1->macname - p2->macname);
                   1260: }
                   1261: 
                   1262: int sizetab(mp)
                   1263:        reg     struct  mactab  *mp;
                   1264: {
                   1265:        reg     int     i;
                   1266:        i = 0;
                   1267:        if (mp){
                   1268:                for (; mp->macname; mp++, i++)
                   1269:                        /*VOID*/ ;
                   1270:        }
                   1271:        return(i);
                   1272: }
                   1273: 
                   1274: struct mactab *macfill(dst, src)
                   1275:        reg     struct  mactab  *dst;
                   1276:        reg     struct  mactab  *src;
                   1277: {
                   1278:        if (src) {
                   1279:                while(src->macname){
                   1280:                        *dst++ = *src++;
                   1281:                }
                   1282:        }
                   1283:        return(dst);
                   1284: }
                   1285: 
                   1286: buildtab(r_back, r_size)
                   1287:        struct  mactab  **r_back;
                   1288:        int     *r_size;
                   1289: {
                   1290:        int     size;
                   1291: 
                   1292:        struct  mactab  *p, *p1, *p2;
                   1293:        struct  mactab  *back;
                   1294: 
                   1295:        size = sizetab(troffmactab);
                   1296:        size += sizetab(ppmactab);
                   1297:        p1 = p2 = (struct mactab *)0;
                   1298:        if (msflag){
                   1299:                switch(mac){
                   1300:                case ME:        p1 = memactab; break;
                   1301:                case MM:        p1 = msmactab;
                   1302:                                p2 = mmmactab; break;
                   1303: 
                   1304:                case MS:        p1 = msmactab; break;
                   1305:                case MA:        p1 = manmactab; break;
                   1306:                default:        break;
                   1307:                }
                   1308:        }
                   1309:        size += sizetab(p1);
                   1310:        size += sizetab(p2);
                   1311:        back = (struct mactab *)calloc(size+2, sizeof(struct mactab));
                   1312: 
                   1313:        p = macfill(back, troffmactab);
                   1314:        p = macfill(p, ppmactab);
                   1315:        p = macfill(p, p1);
                   1316:        p = macfill(p, p2);
                   1317: 
                   1318:        qsort(back, size, sizeof(struct mactab), macsort);
                   1319:        *r_size = size;
                   1320:        *r_back = back;
                   1321: }
                   1322: 
                   1323: /*
                   1324:  *     troff commands
                   1325:  */
                   1326: struct mactab  troffmactab[] = {
                   1327:        M(NONE,         '\\','"',       skip),  /* comment */
                   1328:        M(NOMAC,        'd','e',        domacro),       /* define */
                   1329:        M(NOMAC,        'i','g',        domacro),       /* ignore till .. */
                   1330:        M(NOMAC,        'a','m',        domacro),       /* append macro */
                   1331:        M(NBLK,         'n','f',        nf),    /* filled */
                   1332:        M(NBLK,         'c','e',        ce),    /* centered */
                   1333: 
                   1334:        M(NONE,         's','o',        so),    /* source a file */
                   1335:        M(NONE,         'n','x',        nx),    /* go to next file */
                   1336: 
                   1337:        M(NONE,         't','m',        skip),  /* print string on tty */
                   1338:        M(NONE,         'h','w',        skip),  /* exception hyphen words */
                   1339:        M(NONE,         0,0,            0)
                   1340: };
                   1341: /*
                   1342:  *     Preprocessor output
                   1343:  */
                   1344: struct mactab  ppmactab[] = {
                   1345:        M(FNEST,        'E','Q',        EQ),    /* equation starting */
                   1346:        M(FNEST,        'T','S',        intbl), /* table starting */
                   1347:        M(FNEST,        'T','C',        intbl), /* alternative table? */
                   1348:        M(FNEST,        'T','&',        intbl), /* table reformatting */
                   1349:        M(NONE,         'T','E',        outtbl),/* table ending */
                   1350:        M(NONE,         'P','S',        PS),    /* picture starting */
                   1351:        M(NONE,         0,0,            0)
                   1352: };
                   1353: /*
                   1354:  *     Particular to ms and mm
                   1355:  */
                   1356: struct mactab  msmactab[] = {
                   1357:        M(NONE,         'T','L',        skiptocom),     /* title follows */
                   1358:        M(NONE,         'F','S',        skiptocom),     /* start footnote */
                   1359:        M(NONE,         'O','K',        skiptocom),     /* Other kws */
                   1360: 
                   1361:        M(NONE,         'N','R',        skip),  /* undocumented */
                   1362:        M(NONE,         'N','D',        skip),  /* use supplied date */
                   1363: 
                   1364:        M(PARAG,        'P','P',        PP),    /* begin parag */
                   1365:        M(PARAG,        'I','P',        PP),    /* begin indent parag, tag x */
                   1366:        M(PARAG,        'L','P',        PP),    /* left blocked parag */
                   1367: 
                   1368:        M(NONE,         'A','U',        AU),    /* author */
                   1369:        M(NONE,         'A','I',        AU),    /* authors institution */
                   1370: 
                   1371:        M(NONE,         'S','H',        SH),    /* section heading */
                   1372:        M(NONE,         'S','N',        SH),    /* undocumented */
                   1373:        M(NONE,         'U','X',        UX),    /* unix */
                   1374: 
                   1375:        M(NBLK,         'D','S',        mssnblock),     /* start display text */
                   1376:        M(NBLK,         'K','S',        mssnblock),     /* start keep */
                   1377:        M(NBLK,         'K','F',        mssnblock),     /* start float keep */
                   1378:        M(NONE,         0,0,            0)
                   1379: };
                   1380: 
                   1381: struct mactab  mmmactab[] = {
                   1382:        M(NONE,         'H',' ',        MMHU),  /* -mm ? */
                   1383:        M(NONE,         'H','U',        MMHU),  /* -mm ? */
                   1384:        M(PARAG,        'P',' ',        PP),    /* paragraph for -mm */
                   1385:        M(NBLK,         'N','S',        mssnblock),     /* undocumented */
                   1386:        M(NONE,         0,0,            0)
                   1387: };
                   1388: 
                   1389: struct mactab  memactab[] = {
                   1390:        M(PARAG,        'p','p',        mepp),
                   1391:        M(PARAG,        'l','p',        mepp),
                   1392:        M(PARAG,        'n','p',        mepp),
                   1393:        M(NONE,         'i','p',        meip),
                   1394: 
                   1395:        M(NONE,         's','h',        mesh),
                   1396:        M(NONE,         'u','h',        mesh),
                   1397: 
                   1398:        M(NBLK,         '(','l',        mesnblock),
                   1399:        M(NBLK,         '(','q',        mesnblock),
                   1400:        M(NBLK,         '(','b',        mesnblock),
                   1401:        M(NBLK,         '(','z',        mesnblock),
                   1402:        M(NBLK,         '(','c',        mesnblock),
                   1403: 
                   1404:        M(NBLK,         '(','d',        mesnblock),
                   1405:        M(NBLK,         '(','f',        mesnblock),
                   1406:        M(NBLK,         '(','x',        mesnblock),
                   1407: 
                   1408:        M(NONE,         'r',' ',        mefont),
                   1409:        M(NONE,         'i',' ',        mefont),
                   1410:        M(NONE,         'b',' ',        mefont),
                   1411:        M(NONE,         'u',' ',        mefont),
                   1412:        M(NONE,         'q',' ',        mefont),
                   1413:        M(NONE,         'r','b',        mefont),
                   1414:        M(NONE,         'b','i',        mefont),
                   1415:        M(NONE,         'b','x',        mefont),
                   1416:        M(NONE,         0,0,            0)
                   1417: };
                   1418: 
                   1419: 
                   1420: struct mactab  manmactab[] = {
                   1421:        M(PARAG,        'B','I',        manfont),
                   1422:        M(PARAG,        'B','R',        manfont),
                   1423:        M(PARAG,        'I','B',        manfont),
                   1424:        M(PARAG,        'I','R',        manfont),
                   1425:        M(PARAG,        'R','B',        manfont),
                   1426:        M(PARAG,        'R','I',        manfont),
                   1427: 
                   1428:        M(PARAG,        'P','P',        manpp),
                   1429:        M(PARAG,        'L','P',        manpp),
                   1430:        M(PARAG,        'H','P',        manpp),
                   1431:        M(NONE,         0,0,            0)
                   1432: };

unix.superglobalmegacorp.com

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