Annotation of 3BSD/cmd/deroff.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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