Annotation of 40BSD/cmd/deroff.c, revision 1.1

1.1     ! root        1: static char *sccsid = "@(#)deroff.c    4.1 (Berkeley) 10/1/80";
        !             2: char *xxxvers = "\nDeroff Version 1.02    24 July 1978\n";
        !             3: 
        !             4: 
        !             5: #include <stdio.h>
        !             6: 
        !             7: /* Deroff command -- strip troff, eqn, and Tbl sequences from
        !             8: a file.  Has one flag argument, -w, to cause output one word per line
        !             9: rather than in the original format.
        !            10: Deroff follows .so and .nx commands, removes contents of macro
        !            11: definitions, equations (both .EQ ... .EN and $...$),
        !            12: Tbl command sequences, and Troff backslash constructions.
        !            13: 
        !            14: All input is through the C macro; the most recently read character is in c.
        !            15: */
        !            16: 
        !            17: #define C ( (c=getc(infile)) == EOF ? eof() : ((c==ldelim)&&(filesp==files) ? skeqn() : c) )
        !            18: #define C1 ( (c=getc(infile)) == EOF ? eof() :  c)
        !            19: #define SKIP while(C != '\n') 
        !            20: 
        !            21: #define YES 1
        !            22: #define NO 0
        !            23: 
        !            24: #define NOCHAR -2
        !            25: #define SPECIAL 0
        !            26: #define APOS 1
        !            27: #define DIGIT 2
        !            28: #define LETTER 3
        !            29: 
        !            30: int wordflag = NO;
        !            31: int inmacro = NO;
        !            32: int intable = NO;
        !            33: 
        !            34: char chars[128];  /* SPECIAL, APOS, DIGIT, or LETTER */
        !            35: 
        !            36: char line[BUFSIZ];
        !            37: char *lp;
        !            38: 
        !            39: int c;
        !            40: int ldelim     = NOCHAR;
        !            41: int rdelim     = NOCHAR;
        !            42: 
        !            43: 
        !            44: int argc;
        !            45: char **argv;
        !            46: 
        !            47: char fname[50];
        !            48: FILE *files[15];
        !            49: FILE **filesp;
        !            50: FILE *infile;
        !            51: 
        !            52: char *calloc();
        !            53: 
        !            54: 
        !            55: 
        !            56: main(ac, av)
        !            57: int ac;
        !            58: char **av;
        !            59: {
        !            60: register int i;
        !            61: register char *p;
        !            62: static char onechar[2] = "X";
        !            63: FILE *opn();
        !            64: 
        !            65: argc = ac - 1;
        !            66: argv = av + 1;
        !            67: 
        !            68: while(argc>0 && argv[0][0]=='-' && argv[0][1]!='\0') 
        !            69:        {
        !            70:        for(p=argv[0]+1; *p; ++p) switch(*p)
        !            71:                {
        !            72:                case 'w':
        !            73:                        wordflag = YES;
        !            74:                        break;
        !            75:                default:
        !            76:                        onechar[0] = *p;
        !            77:                        fatal("Invalid flag %s\n", onechar);
        !            78:                }
        !            79:        --argc;
        !            80:        ++argv;
        !            81:        }
        !            82: 
        !            83: if(argc == 0)
        !            84:        infile = stdin;
        !            85: else   {
        !            86:        infile = opn(argv[0]);
        !            87:        --argc;
        !            88:        ++argv;
        !            89:        }
        !            90: 
        !            91: files[0] = infile;
        !            92: filesp = &files[0];
        !            93: 
        !            94: for(i='a'; i<='z' ; ++i)
        !            95:        chars[i] = LETTER;
        !            96: for(i='A'; i<='Z'; ++i)
        !            97:        chars[i] = LETTER;
        !            98: for(i='0'; i<='9'; ++i)
        !            99:        chars[i] = DIGIT;
        !           100: chars['\''] = APOS;
        !           101: chars['&'] = APOS;
        !           102: 
        !           103: work();
        !           104: }
        !           105: 
        !           106: 
        !           107: 
        !           108: skeqn()
        !           109: {
        !           110: while((c = getc(infile)) != rdelim)
        !           111:        if(c == EOF)
        !           112:                c = eof();
        !           113:        else if(c == '"')
        !           114:                while( (c = getc(infile)) != '"')
        !           115:                        if(c == EOF)
        !           116:                                c = eof();
        !           117:                        else if(c == '\\')
        !           118:                                if((c = getc(infile)) == EOF)
        !           119:                                        c = eof();
        !           120: return(C);
        !           121: }
        !           122: 
        !           123: 
        !           124: FILE *opn(p)
        !           125: register char *p;
        !           126: {
        !           127: FILE *fd;
        !           128: 
        !           129: if(p[0]=='-' && p[1]=='\0')
        !           130:        fd = stdin;
        !           131: else if( (fd = fopen(p, "r")) == NULL)
        !           132:        fatal("Cannot open file %s\n", p);
        !           133: 
        !           134: return(fd);
        !           135: }
        !           136: 
        !           137: 
        !           138: 
        !           139: eof()
        !           140: {
        !           141: if(infile != stdin)
        !           142:        fclose(infile);
        !           143: if(filesp > files)
        !           144:        infile = *--filesp;
        !           145: else if(argc > 0)
        !           146:        {
        !           147:        infile = opn(argv[0]);
        !           148:        --argc;
        !           149:        ++argv;
        !           150:        }
        !           151: else
        !           152:        exit(0);
        !           153: 
        !           154: return(C);
        !           155: }
        !           156: 
        !           157: 
        !           158: 
        !           159: getfname()
        !           160: {
        !           161: register char *p;
        !           162: struct chain { struct chain *nextp; char *datap; } *chainblock;
        !           163: register struct chain *q;
        !           164: static struct chain *namechain = NULL;
        !           165: char *copys();
        !           166: 
        !           167: while(C == ' ') ;
        !           168: 
        !           169: for(p = fname ; (*p=c)!= '\n' && c!=' ' && c!='\t' && c!='\\' ; ++p)
        !           170:        C;
        !           171: *p = '\0';
        !           172: while(c != '\n')
        !           173:        C;
        !           174: 
        !           175: /* see if this name has already been used */
        !           176: 
        !           177: for(q = namechain ; q; q = q->nextp)
        !           178:        if( ! strcmp(fname, q->datap))
        !           179:                {
        !           180:                fname[0] = '\0';
        !           181:                return;
        !           182:                }
        !           183: 
        !           184: q = (struct chain *) calloc(1, sizeof(*chainblock));
        !           185: q->nextp = namechain;
        !           186: q->datap = copys(fname);
        !           187: namechain = q;
        !           188: }
        !           189: 
        !           190: 
        !           191: 
        !           192: 
        !           193: fatal(s,p)
        !           194: char *s, *p;
        !           195: {
        !           196: fprintf(stderr, "Deroff: ");
        !           197: fprintf(stderr, s, p);
        !           198: exit(1);
        !           199: }
        !           200: 
        !           201: work()
        !           202: {
        !           203: 
        !           204: for( ;; )
        !           205:        {
        !           206:        if(C == '.'  ||  c == '\'')
        !           207:                comline();
        !           208:        else
        !           209:                regline(NO);
        !           210:        }
        !           211: }
        !           212: 
        !           213: 
        !           214: 
        !           215: 
        !           216: regline(macline)
        !           217: int macline;
        !           218: {
        !           219: line[0] = c;
        !           220: lp = line;
        !           221: for( ; ; )
        !           222:        {
        !           223:        if(c == '\\')
        !           224:                {
        !           225:                *lp = ' ';
        !           226:                backsl();
        !           227:                }
        !           228:        if(c == '\n') break;
        !           229:        if(intable && c=='T')
        !           230:                {
        !           231:                *++lp = C;
        !           232:                if(c=='{' || c=='}')
        !           233:                        {
        !           234:                        lp[-1] = ' ';
        !           235:                        *lp = C;
        !           236:                        }
        !           237:                }
        !           238:        else    *++lp = C;
        !           239:        }
        !           240: 
        !           241: *lp = '\0';
        !           242: 
        !           243: if(line[0] != '\0')
        !           244:        if(wordflag)
        !           245:                putwords(macline);
        !           246:        else if(macline)
        !           247:                putmac(line);
        !           248:        else
        !           249:                puts(line);
        !           250: }
        !           251: 
        !           252: 
        !           253: 
        !           254: 
        !           255: putmac(s)
        !           256: register char *s;
        !           257: {
        !           258: register char *t;
        !           259: 
        !           260: while(*s)
        !           261:        {
        !           262:        while(*s==' ' || *s=='\t')
        !           263:                putchar(*s++);
        !           264:        for(t = s ; *t!=' ' && *t!='\t' && *t!='\0' ; ++t)
        !           265:                ;
        !           266:        if(t>s+2 && chars[ s[0] ]==LETTER && chars[ s[1] ]==LETTER)
        !           267:                while(s < t)
        !           268:                        putchar(*s++);
        !           269:        else
        !           270:                s = t;
        !           271:        }
        !           272: putchar('\n');
        !           273: }
        !           274: 
        !           275: 
        !           276: 
        !           277: putwords(macline)      /* break into words for -w option */
        !           278: int macline;
        !           279: {
        !           280: register char *p, *p1;
        !           281: int i, nlet;
        !           282: 
        !           283: 
        !           284: for(p1 = line ; ;)
        !           285:        {
        !           286:        /* skip initial specials ampersands and apostrophes */
        !           287:        while( chars[*p1] < DIGIT)
        !           288:                if(*p1++ == '\0') return;
        !           289:        nlet = 0;
        !           290:        for(p = p1 ; (i=chars[*p]) != SPECIAL ; ++p)
        !           291:                if(i == LETTER) ++nlet;
        !           292: 
        !           293:        if( (!macline && nlet>1)   /* MDM definition of word */
        !           294:           || (macline && nlet>2 && chars[ p1[0] ]==LETTER && chars[ p1[1] ]==LETTER) )
        !           295:                {
        !           296:                /* delete trailing ampersands and apostrophes */
        !           297:                while(p[-1]=='\'' || p[-1]=='&')
        !           298:                         --p;
        !           299:                while(p1 < p) putchar(*p1++);
        !           300:                putchar('\n');
        !           301:                }
        !           302:        else
        !           303:                p1 = p;
        !           304:        }
        !           305: }
        !           306: 
        !           307: 
        !           308: 
        !           309: comline()
        !           310: {
        !           311: register int c1, c2;
        !           312: 
        !           313: while(C==' ' || c=='\t')
        !           314:        ;
        !           315: if( (c1=c) == '\n')
        !           316:        return;
        !           317: if(c1 == '.')
        !           318:        {
        !           319:        inmacro = NO;
        !           320:        SKIP;
        !           321:        return;
        !           322:        }
        !           323: if( (c2=C) == '\n')
        !           324:        return;
        !           325: 
        !           326: if(c1=='E' && c2=='Q' && filesp==files)
        !           327:        eqn();
        !           328: else if(c1=='T' && (c2=='S' || c2=='C' || c2=='&') && filesp==files)
        !           329:        tbl();
        !           330: else if(c1=='T' && c2=='E')
        !           331:        intable = NO;
        !           332: else if(!inmacro && c1=='d' && c2=='e')
        !           333:        macro();
        !           334: else if(!inmacro && c1=='i' && c2=='g')
        !           335:        macro();
        !           336: else if(!inmacro && c1=='a' && c2 == 'm')
        !           337:        macro();
        !           338: else if(c1=='s' && c2=='o')
        !           339:        {
        !           340:        getfname();
        !           341:        if( fname[0] )
        !           342:                infile = *++filesp = opn( fname );
        !           343:        }
        !           344: else if(c1=='n' && c2=='x')
        !           345:        {
        !           346:        getfname();
        !           347:        if(fname[0] == '\0') exit(0);
        !           348:        if(infile != stdin)
        !           349:                fclose(infile);
        !           350:        infile = *filesp = opn(fname);
        !           351:        }
        !           352: else if(c1=='h' && c2=='w')
        !           353:        { SKIP; }
        !           354: else
        !           355:        {
        !           356:        ++inmacro;
        !           357:        regline(YES);
        !           358:        --inmacro;
        !           359:        }
        !           360: }
        !           361: 
        !           362: 
        !           363: 
        !           364: macro()
        !           365: {
        !           366: /*
        !           367: do { SKIP; }
        !           368:        while(C!='.' || C!='.');        /* look for  .EN */
        !           369: SKIP;
        !           370: inmacro = YES;
        !           371: }
        !           372: 
        !           373: 
        !           374: 
        !           375: 
        !           376: tbl()
        !           377: {
        !           378: while(C != '.');
        !           379: SKIP;
        !           380: intable = YES;
        !           381: }
        !           382: 
        !           383: eqn()
        !           384: {
        !           385: register int c1, c2;
        !           386: 
        !           387: SKIP;
        !           388: 
        !           389: for( ;;)
        !           390:        {
        !           391:        if(C == '.'  || c == '\'')
        !           392:                {
        !           393:                while(C==' ' || c=='\t')
        !           394:                        ;
        !           395:                if(c=='E' && C=='N')
        !           396:                        {
        !           397:                        SKIP;
        !           398:                        return;
        !           399:                        }
        !           400:                }
        !           401:        else if(c == 'd')       /* look for delim */
        !           402:                {
        !           403:                if(C=='e' && C=='l')
        !           404:                    if( C=='i' && C=='m')
        !           405:                        {
        !           406:                        while(C1 == ' ');
        !           407:                        if((c1=c)=='\n' || (c2=C1)=='\n'
        !           408:                            || (c1=='o' && c2=='f' && C1=='f') )
        !           409:                                {
        !           410:                                ldelim = NOCHAR;
        !           411:                                rdelim = NOCHAR;
        !           412:                                }
        !           413:                        else    {
        !           414:                                ldelim = c1;
        !           415:                                rdelim = c2;
        !           416:                                }
        !           417:                        }
        !           418:                }
        !           419: 
        !           420:        if(c != '\n')  SKIP;
        !           421:        }
        !           422: }
        !           423: 
        !           424: 
        !           425: 
        !           426: backsl()       /* skip over a complete backslash construction */
        !           427: {
        !           428: int bdelim;
        !           429: 
        !           430: sw:  switch(C)
        !           431:        {
        !           432:        case '"':
        !           433:                SKIP;
        !           434:                return;
        !           435:        case 's':
        !           436:                if(C == '\\') backsl();
        !           437:                else    {
        !           438:                        while(C>='0' && c<='9') ;
        !           439:                        ungetc(c,infile);
        !           440:                        c = '0';
        !           441:                        }
        !           442:                --lp;
        !           443:                return;
        !           444: 
        !           445:        case 'f':
        !           446:        case 'n':
        !           447:        case '*':
        !           448:                if(C != '(')
        !           449:                        return;
        !           450: 
        !           451:        case '(':
        !           452:                if(C != '\n') C;
        !           453:                return;
        !           454: 
        !           455:        case '$':
        !           456:                C;      /* discard argument number */
        !           457:                return;
        !           458: 
        !           459:        case 'b':
        !           460:        case 'x':
        !           461:        case 'v':
        !           462:        case 'h':
        !           463:        case 'w':
        !           464:        case 'o':
        !           465:        case 'l':
        !           466:        case 'L':
        !           467:                if( (bdelim=C) == '\n')
        !           468:                        return;
        !           469:                while(C!='\n' && c!=bdelim)
        !           470:                        if(c == '\\') backsl();
        !           471:                return;
        !           472: 
        !           473:        case '\\':
        !           474:                if(inmacro)
        !           475:                        goto sw;
        !           476:        default:
        !           477:                return;
        !           478:        }
        !           479: }
        !           480: 
        !           481: 
        !           482: 
        !           483: 
        !           484: char *copys(s)
        !           485: register char *s;
        !           486: {
        !           487: register char *t, *t0;
        !           488: 
        !           489: if( (t0 = t = calloc( strlen(s)+1, sizeof(*t) ) ) == NULL)
        !           490:        fatal("Cannot allocate memory", (char *) NULL);
        !           491: 
        !           492: while( *t++ = *s++ )
        !           493:        ;
        !           494: return(t0);
        !           495: }

unix.superglobalmegacorp.com

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