Annotation of 41BSD/cmd/diction/deroff.c, revision 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.