Annotation of 41BSD/cmd/diction/deroff.c, revision 1.1.1.1

1.1       root        1: char *xxxvers = "\nDeroff Version 2.0    29 December 1979\n";
                      2: 
                      3: 
                      4: #include <stdio.h>
                      5: 
                      6: /* Deroff command -- strip troff, eqn, and Tbl sequences from
                      7: a file.  Has two flags argument, -w, to cause output one word per line
                      8: rather than in the original format.
                      9: -ms (or -m) causes -ms macro's to be interpreted so that just
                     10: sentences are output, -mm does same for -mm macro's,
                     11: -ml in addition to interpreting -ms macros also gets rid of
                     12: lists.
                     13: Deroff follows .so and .nx commands, removes contents of macro
                     14: definitions, equations (both .EQ ... .EN and $...$),
                     15: Tbl command sequences, and Troff backslash constructions.
                     16: 
                     17: All input is through the C macro; the most recently read character is in c.
                     18: */
                     19: 
                     20: #define C ( (c=getc(infile)) == EOF ? eof() : ((c==ldelim)&&(filesp==files) ? skeqn() : c) )
                     21: #define C1 ( (c=getc(infile)) == EOF ? eof() :  c)
                     22: #define SKIP while(C != '\n') 
                     23: #define SKIP_TO_COM SKIP; SKIP; pc=c; while(C != '.' || pc != '\n' || C > 'Z')pc=c
                     24: 
                     25: #define YES 1
                     26: #define NO 0
                     27: #define MS 0
                     28: #define MM 1
                     29: #define ONE 1
                     30: #define TWO 2
                     31: 
                     32: #define NOCHAR -2
                     33: #define SPECIAL 0
                     34: #define APOS 1
                     35: #define DIGIT 2
                     36: #define LETTER 3
                     37: 
                     38: int wordflag = NO;
                     39: int msflag = NO;
                     40: int mac = MS;
                     41: int disp = 0;
                     42: int inmacro = NO;
                     43: int intable = NO;
                     44: 
                     45: char chars[128];  /* SPECIAL, APOS, DIGIT, or LETTER */
                     46: 
                     47: char line[512];
                     48: char *lp;
                     49: 
                     50: int c;
                     51: int pc;
                     52: int ldelim     = NOCHAR;
                     53: int rdelim     = NOCHAR;
                     54: 
                     55: 
                     56: int argc;
                     57: char **argv;
                     58: 
                     59: char fname[50];
                     60: FILE *files[15];
                     61: FILE **filesp;
                     62: FILE *infile;
                     63: 
                     64: char *calloc();
                     65: 
                     66: 
                     67: 
                     68: main(ac, av)
                     69: int ac;
                     70: char **av;
                     71: {
                     72: register int i;
                     73: register char *p;
                     74: static char onechar[2] = "X";
                     75: FILE *opn();
                     76: 
                     77: argc = ac - 1;
                     78: argv = av + 1;
                     79: 
                     80: while(argc>0 && argv[0][0]=='-' && argv[0][1]!='\0') 
                     81:        {
                     82:        for(p=argv[0]+1; *p; ++p) switch(*p)
                     83:                {
                     84:                case 'w':
                     85:                        wordflag = YES;
                     86:                        break;
                     87:                case 'm':
                     88:                        msflag = YES;
                     89:                        if(*(p+1) == 'm'){
                     90:                                mac=MM;
                     91:                                p++;
                     92:                        }
                     93:                        else if(*(p+1) == 's')
                     94:                                p++;
                     95:                        else if(*(p+1) == 'l'){
                     96:                                disp=1;
                     97:                                p++;
                     98:                        }
                     99:                        break;
                    100:                default:
                    101:                        onechar[0] = *p;
                    102:                        fatal("Invalid flag %s\n", onechar);
                    103:                }
                    104:        --argc;
                    105:        ++argv;
                    106:        }
                    107: 
                    108: if(argc == 0)
                    109:        infile = stdin;
                    110: else   {
                    111:        infile = opn(argv[0]);
                    112:        --argc;
                    113:        ++argv;
                    114:        }
                    115: 
                    116: files[0] = infile;
                    117: filesp = &files[0];
                    118: 
                    119: for(i='a'; i<='z' ; ++i)
                    120:        chars[i] = LETTER;
                    121: for(i='A'; i<='Z'; ++i)
                    122:        chars[i] = LETTER;
                    123: for(i='0'; i<='9'; ++i)
                    124:        chars[i] = DIGIT;
                    125: chars['\''] = APOS;
                    126: chars['&'] = APOS;
                    127: 
                    128: work();
                    129: }
                    130: 
                    131: 
                    132: 
                    133: skeqn()
                    134: {
                    135: while((c = getc(infile)) != rdelim)
                    136:        if(c == EOF)
                    137:                c = eof();
                    138:        else if(c == '"')
                    139:                while( (c = getc(infile)) != '"')
                    140:                        if(c == EOF)
                    141:                                c = eof();
                    142:                        else if(c == '\\')
                    143:                                if((c = getc(infile)) == EOF)
                    144:                                        c = eof();
                    145: if(msflag)return(c='x');
                    146: return(c = ' ');
                    147: }
                    148: 
                    149: 
                    150: FILE *opn(p)
                    151: register char *p;
                    152: {
                    153: FILE *fd;
                    154: 
                    155: if(p[0]=='-' && p[1]=='\0')
                    156:        fd = stdin;
                    157: else if( (fd = fopen(p, "r")) == NULL)
                    158:        fatal("Cannot open file %s\n", p);
                    159: 
                    160: return(fd);
                    161: }
                    162: 
                    163: 
                    164: 
                    165: eof()
                    166: {
                    167: if(infile != stdin)
                    168:        fclose(infile);
                    169: if(filesp > files)
                    170:        infile = *--filesp;
                    171: else if(argc > 0)
                    172:        {
                    173:        infile = opn(argv[0]);
                    174:        --argc;
                    175:        ++argv;
                    176:        }
                    177: else
                    178:        exit(0);
                    179: 
                    180: return(C);
                    181: }
                    182: 
                    183: 
                    184: 
                    185: getfname()
                    186: {
                    187: register char *p;
                    188: struct chain { struct chain *nextp; char *datap; } *chainblock;
                    189: register struct chain *q;
                    190: static struct chain *namechain = NULL;
                    191: char *copys();
                    192: 
                    193: while(C == ' ') ;
                    194: 
                    195: for(p = fname ; (*p=c)!= '\n' && c!=' ' && c!='\t' && c!='\\' ; ++p)
                    196:        C;
                    197: *p = '\0';
                    198: while(c != '\n')
                    199:        C;
                    200: 
                    201: /* see if this name has already been used */
                    202: 
                    203: for(q = namechain ; q; q = q->nextp)
                    204:        if( ! strcmp(fname, q->datap))
                    205:                {
                    206:                fname[0] = '\0';
                    207:                return;
                    208:                }
                    209: 
                    210: q = (struct chain *) calloc(1, sizeof(*chainblock));
                    211: q->nextp = namechain;
                    212: q->datap = copys(fname);
                    213: namechain = q;
                    214: }
                    215: 
                    216: 
                    217: 
                    218: 
                    219: fatal(s,p)
                    220: char *s, *p;
                    221: {
                    222: fprintf(stderr, "Deroff: ");
                    223: fprintf(stderr, s, p);
                    224: exit(1);
                    225: }
                    226: 
                    227: work()
                    228: {
                    229: 
                    230: for( ;; )
                    231:        {
                    232:        if(C == '.'  ||  c == '\'')
                    233:                comline();
                    234:        else
                    235:                regline(NO,TWO);
                    236:        }
                    237: }
                    238: 
                    239: 
                    240: 
                    241: 
                    242: regline(macline,const)
                    243: int macline;
                    244: int const;
                    245: {
                    246: line[0] = c;
                    247: lp = line;
                    248: for( ; ; )
                    249:        {
                    250:        if(c == '\\')
                    251:                {
                    252:                *lp = ' ';
                    253:                backsl();
                    254:                }
                    255:        if(c == '\n') break;
                    256:        if(intable && c=='T')
                    257:                {
                    258:                *++lp = C;
                    259:                if(c=='{' || c=='}')
                    260:                        {
                    261:                        lp[-1] = ' ';
                    262:                        *lp = C;
                    263:                        }
                    264:                }
                    265:        else    *++lp = C;
                    266:        }
                    267: 
                    268: *lp = '\0';
                    269: 
                    270: if(line[0] != '\0')
                    271:        if(wordflag)
                    272:                putwords(macline);
                    273:        else if(macline)
                    274:                putmac(line,const);
                    275:        else
                    276:                puts(line);
                    277: }
                    278: 
                    279: 
                    280: 
                    281: 
                    282: putmac(s,const)
                    283: register char *s;
                    284: int const;
                    285: {
                    286: register char *t;
                    287: 
                    288: while(*s)
                    289:        {
                    290:        while(*s==' ' || *s=='\t')
                    291:                putchar(*s++);
                    292:        for(t = s ; *t!=' ' && *t!='\t' && *t!='\0' ; ++t)
                    293:                ;
                    294:        if(*s == '\"')s++;
                    295:        if(t>s+const && chars[ s[0] ]==LETTER && chars[ s[1] ]==LETTER)
                    296:                while(s < t)
                    297:                        if(*s == '\"')s++;
                    298:                        else
                    299:                                putchar(*s++);
                    300:        else
                    301:                s = t;
                    302:        }
                    303: putchar('\n');
                    304: }
                    305: 
                    306: 
                    307: 
                    308: putwords(macline)      /* break into words for -w option */
                    309: int macline;
                    310: {
                    311: register char *p, *p1;
                    312: int i, nlet;
                    313: 
                    314: 
                    315: for(p1 = line ; ;)
                    316:        {
                    317:        /* skip initial specials ampersands and apostrophes */
                    318:        while( chars[*p1] < DIGIT)
                    319:                if(*p1++ == '\0') return;
                    320:        nlet = 0;
                    321:        for(p = p1 ; (i=chars[*p]) != SPECIAL ; ++p)
                    322:                if(i == LETTER) ++nlet;
                    323: 
                    324:        if( (!macline && nlet>1)   /* MDM definition of word */
                    325:           || (macline && nlet>2 && chars[ p1[0] ]==LETTER && chars[ p1[1] ]==LETTER) )
                    326:                {
                    327:                /* delete trailing ampersands and apostrophes */
                    328:                while(p[-1]=='\'' || p[-1]=='&')
                    329:                         --p;
                    330:                while(p1 < p) putchar(*p1++);
                    331:                putchar('\n');
                    332:                }
                    333:        else
                    334:                p1 = p;
                    335:        }
                    336: }
                    337: 
                    338: 
                    339: 
                    340: comline()
                    341: {
                    342: register int c1, c2;
                    343: 
                    344: com:
                    345: while(C==' ' || c=='\t')
                    346:        ;
                    347: comx:
                    348: if( (c1=c) == '\n')
                    349:        return;
                    350: c2 = C;
                    351: if(c1=='.' && c2!='.')
                    352:        inmacro = NO;
                    353: if(c2 == '\n')
                    354:        return;
                    355: 
                    356: if(c1=='E' && c2=='Q' && filesp==files)
                    357:        eqn();
                    358: else if(c1=='T' && (c2=='S' || c2=='C' || c2=='&') && filesp==files){
                    359:        if(msflag){ stbl(); }
                    360:        else tbl(); }
                    361: else if(c1=='T' && c2=='E')
                    362:        intable = NO;
                    363: else if(c1=='G' && c2 == 'R')
                    364:                sdis('G','E');
                    365: else if(!inmacro && c1=='d' && c2=='e')
                    366:        macro();
                    367: else if(!inmacro && c1=='i' && c2=='g')
                    368:        macro();
                    369: else if(!inmacro && c1=='a' && c2 == 'm')
                    370:        macro();
                    371: else if(c1=='s' && c2=='o')
                    372:        {
                    373:        getfname();
                    374:        if( fname[0] )
                    375:                infile = *++filesp = opn( fname );
                    376:        }
                    377: else if(c1=='n' && c2=='x')
                    378:        {
                    379:        getfname();
                    380:        if(fname[0] == '\0') exit(0);
                    381:        if(infile != stdin)
                    382:                fclose(infile);
                    383:        infile = *filesp = opn(fname);
                    384:        }
                    385: else if(c1=='h' && c2=='w')
                    386:        { SKIP; }
                    387: else if(msflag && c1 == 'T' && c2 == 'L'){
                    388:        SKIP_TO_COM;
                    389:        goto comx; }
                    390: else if(msflag && c1=='N' && c2 == 'R')SKIP;
                    391: else if(msflag && c1 == 'A' && (c2 == 'U' || c2 == 'I')){
                    392:        if(mac==MM)SKIP;
                    393:        else {
                    394:                SKIP_TO_COM;
                    395:                goto comx; }
                    396:        }
                    397: else if(msflag && c1 == 'F' && c2 == 'S'){
                    398:        SKIP_TO_COM;
                    399:        goto comx; }
                    400: else if(msflag && c1 == 'S' && c2 == 'H'){
                    401:        SKIP_TO_COM;
                    402:        goto comx; }
                    403: else if(msflag && c1 == 'N' && c2 == 'H'){
                    404:        SKIP_TO_COM;
                    405:        goto comx; }
                    406: else if(msflag && c1 == 'O' && c2 == 'K'){
                    407:        SKIP_TO_COM;
                    408:        goto comx; }
                    409: else if(msflag && c1 == 'N' && c2 == 'D')
                    410:        SKIP;
                    411: else if(msflag && mac==MM && c1=='H' && (c2==' '||c2=='U'))
                    412:        SKIP;
                    413: else if(msflag && mac==MM && c2=='L'){
                    414:        if(disp || c1 == 'R')sdis('L','E');
                    415:        else{
                    416:                SKIP;
                    417:                putchar('.');
                    418:                }
                    419:        }
                    420: else if(msflag && (c1 == 'D' || c1 == 'N' || c1 == 'K') && c2 == 'S')
                    421:        { sdis(c1,'E'); }               /* removed RS-RE */
                    422: else if(msflag && c1 == 'n' && c2 == 'f')
                    423:        sdis('f','i');
                    424: else if(msflag && c1 == 'c' && c2 == 'e')
                    425:        sce();
                    426: else
                    427:        {
                    428:        if(c1=='.' && c2=='.')
                    429:                while(C == '.')
                    430:                        ;
                    431:        ++inmacro;
                    432:        if(c1 <= 'Z' && msflag)regline(YES,ONE);
                    433:        else regline(YES,TWO);
                    434:        --inmacro;
                    435:        }
                    436: }
                    437: 
                    438: 
                    439: 
                    440: macro()
                    441: {
                    442: if(msflag){
                    443:        do { SKIP; }
                    444:                while(C!='.' || C!='.' || C=='.');      /* look for  .. */
                    445:        if(c != '\n')SKIP;
                    446:        return;
                    447: }
                    448: SKIP;
                    449: inmacro = YES;
                    450: }
                    451: 
                    452: 
                    453: 
                    454: 
                    455: sdis(a1,a2)
                    456: char a1,a2;
                    457: {
                    458:        register int c1,c2;
                    459:        register int eqnf;
                    460:        eqnf=1;
                    461:        SKIP;
                    462:        while(1){
                    463:                while(C != '.')SKIP;
                    464:                if((c1=C) == '\n')continue;
                    465:                if((c2=C) == '\n')continue;
                    466:                if(c1==a1 && c2 == a2){
                    467:                        SKIP;
                    468:                        if(eqnf)putchar('.');
                    469:                        putchar('\n');
                    470:                        return;
                    471:                }
                    472:                else if(a1 == 'D' && c1 == 'E' && c2 == 'Q'){eqn(); eqnf=0;}
                    473:                else SKIP;
                    474:        }
                    475: }
                    476: tbl()
                    477: {
                    478: while(C != '.');
                    479: SKIP;
                    480: intable = YES;
                    481: }
                    482: stbl()
                    483: {
                    484: while(C != '.');
                    485: SKIP_TO_COM;
                    486: if(c != 'T' || C != 'E'){
                    487:        SKIP;
                    488:        pc=c;
                    489:        while(C != '.' || pc != '\n' || C != 'T' || C != 'E')pc=c;
                    490: }
                    491: }
                    492: 
                    493: eqn()
                    494: {
                    495: register int c1, c2;
                    496: register int dflg;
                    497: int last;
                    498: 
                    499: last=0;
                    500: dflg = 1;
                    501: SKIP;
                    502: 
                    503: for( ;;)
                    504:        {
                    505:        if(C == '.'  || c == '\'')
                    506:                {
                    507:                while(C==' ' || c=='\t')
                    508:                        ;
                    509:                if(c=='E' && C=='N')
                    510:                        {
                    511:                        SKIP;
                    512:                        if(msflag && dflg){
                    513:                                putchar('x');
                    514:                                putchar(' ');
                    515:                                if(last){putchar('.'); putchar(' '); }
                    516:                        }
                    517:                        return;
                    518:                        }
                    519:                }
                    520:        else if(c == 'd')       /* look for delim */
                    521:                {
                    522:                if(C=='e' && C=='l')
                    523:                    if( C=='i' && C=='m')
                    524:                        {
                    525:                        while(C1 == ' ');
                    526:                        if((c1=c)=='\n' || (c2=C1)=='\n'
                    527:                            || (c1=='o' && c2=='f' && C1=='f') )
                    528:                                {
                    529:                                ldelim = NOCHAR;
                    530:                                rdelim = NOCHAR;
                    531:                                }
                    532:                        else    {
                    533:                                ldelim = c1;
                    534:                                rdelim = c2;
                    535:                                }
                    536:                        }
                    537:                        dflg = 0;
                    538:                }
                    539: 
                    540:        if(c != '\n') while(C != '\n'){ if(c == '.')last=1; else last=0; }
                    541:        }
                    542: }
                    543: 
                    544: 
                    545: 
                    546: backsl()       /* skip over a complete backslash construction */
                    547: {
                    548: int bdelim;
                    549: 
                    550: sw:  switch(C)
                    551:        {
                    552:        case '"':
                    553:                SKIP;
                    554:                return;
                    555:        case 's':
                    556:                if(C == '\\') backsl();
                    557:                else    {
                    558:                        while(C>='0' && c<='9') ;
                    559:                        ungetc(c,infile);
                    560:                        c = '0';
                    561:                        }
                    562:                --lp;
                    563:                return;
                    564: 
                    565:        case 'f':
                    566:        case 'n':
                    567:        case '*':
                    568:                if(C != '(')
                    569:                        return;
                    570: 
                    571:        case '(':
                    572:                if(C != '\n') C;
                    573:                return;
                    574: 
                    575:        case '$':
                    576:                C;      /* discard argument number */
                    577:                return;
                    578: 
                    579:        case 'b':
                    580:        case 'x':
                    581:        case 'v':
                    582:        case 'h':
                    583:        case 'w':
                    584:        case 'o':
                    585:        case 'l':
                    586:        case 'L':
                    587:                if( (bdelim=C) == '\n')
                    588:                        return;
                    589:                while(C!='\n' && c!=bdelim)
                    590:                        if(c == '\\') backsl();
                    591:                return;
                    592: 
                    593:        case '\\':
                    594:                if(inmacro)
                    595:                        goto sw;
                    596:        default:
                    597:                return;
                    598:        }
                    599: }
                    600: 
                    601: 
                    602: 
                    603: 
                    604: char *copys(s)
                    605: register char *s;
                    606: {
                    607: register char *t, *t0;
                    608: 
                    609: if( (t0 = t = calloc( strlen(s)+1, sizeof(*t) ) ) == NULL)
                    610:        fatal("Cannot allocate memory", (char *) NULL);
                    611: 
                    612: while( *t++ = *s++ )
                    613:        ;
                    614: return(t0);
                    615: }
                    616: sce(){
                    617: register char *ap;
                    618: register int n, i;
                    619: char a[10];
                    620:        for(ap=a;C != '\n';ap++){
                    621:                *ap = c;
                    622:                if(ap == &a[9]){
                    623:                        SKIP;
                    624:                        ap=a;
                    625:                        break;
                    626:                }
                    627:        }
                    628:        if(ap != a)n = atoi(a);
                    629:        else n = 1;
                    630:        for(i=0;i<n;){
                    631:                if(C == '.'){
                    632:                        if(C == 'c'){
                    633:                                if(C == 'e'){
                    634:                                        while(C == ' ');
                    635:                                        if(c == '0')break;
                    636:                                        else SKIP;
                    637:                                }
                    638:                                else SKIP;
                    639:                        }
                    640:                        else SKIP;
                    641:                }
                    642:                else {
                    643:                        SKIP;
                    644:                        i++;
                    645:                }
                    646:        }
                    647: }

unix.superglobalmegacorp.com

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