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