[BACK]Return to deroff.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / deroff

Annotation of src/usr.bin/deroff/deroff.c, Revision 1.4

1.4     ! danh        1: /*     $OpenBSD: deroff.c,v 1.3 2002/02/28 08:57:37 millert Exp $      */
1.1       millert     2:
                      3: /*-
                      4:  * Copyright (c) 1988, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *     This product includes software developed by the University of
                     18:  *     California, Berkeley and its contributors.
                     19:  * 4. Neither the name of the University nor the names of its contributors
                     20:  *    may be used to endorse or promote products derived from this software
                     21:  *    without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     33:  * SUCH DAMAGE.
                     34:  */
                     35: /*
                     36:  * Copyright (C) Caldera International Inc.  2001-2002.
                     37:  * All rights reserved.
                     38:  *
                     39:  * Redistribution and use in source and binary forms, with or without
                     40:  * modification, are permitted provided that the following conditions
                     41:  * are met:
                     42:  * 1. Redistributions of source code and documentation must retain the above
                     43:  *    copyright notice, this list of conditions and the following disclaimer.
                     44:  * 2. Redistributions in binary form must reproduce the above copyright
                     45:  *    notice, this list of conditions and the following disclaimer in the
                     46:  *    documentation and/or other materials provided with the distribution.
                     47:  * 3. All advertising materials mentioning features or use of this software
                     48:  *    must display the following acknowledgement:
                     49:  *     This product includes software developed or owned by Caldera
                     50:  *     International, Inc.
                     51:  * 4. Neither the name of Caldera International, Inc. nor the names of other
                     52:  *    contributors may be used to endorse or promote products derived from
                     53:  *    this software without specific prior written permission.
                     54:  *
                     55:  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
                     56:  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
                     57:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     58:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     59:  * IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE FOR ANY DIRECT,
                     60:  * INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     61:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     62:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     63:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     64:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
                     65:  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     66:  * POSSIBILITY OF SUCH DAMAGE.
                     67:  */
                     68:
                     69: #ifndef lint
                     70: static const char copyright[] =
                     71: "@(#) Copyright (c) 1988, 1993\n\
                     72:        The Regents of the University of California.  All rights reserved.\n";
                     73: #endif /* not lint */
                     74:
                     75: #ifndef lint
                     76: #if 0
                     77: static const char sccsid[] = "@(#)deroff.c     8.1 (Berkeley) 6/6/93";
                     78: #else
1.4     ! danh       79: static const char rcsid[] = "$OpenBSD: deroff.c,v 1.3 2002/02/28 08:57:37 millert Exp $";
1.1       millert    80: #endif
                     81: #endif /* not lint */
                     82:
                     83: #include <err.h>
                     84: #include <limits.h>
                     85: #include <stdio.h>
                     86: #include <stdlib.h>
                     87: #include <string.h>
                     88: #include <unistd.h>
                     89:
                     90: /*
                     91:  *     Deroff command -- strip troff, eqn, and Tbl sequences from
                     92:  *     a file.  Has two flags argument, -w, to cause output one word per line
                     93:  *     rather than in the original format.
                     94:  *     -mm (or -ms) causes the corresponding macro's to be interpreted
                     95:  *     so that just sentences are output
                     96:  *     -ml  also gets rid of lists.
                     97:  *     Deroff follows .so and .nx commands, removes contents of macro
                     98:  *     definitions, equations (both .EQ ... .EN and $...$),
                     99:  *     Tbl command sequences, and Troff backslash constructions.
                    100:  *
                    101:  *     All input is through the Cget macro;
                    102:  *     the most recently read character is in c.
                    103:  *
                    104:  *     Modified by Robert Henry to process -me and -man macros.
                    105:  */
                    106:
                    107: #define Cget ( (c=getc(infile)) == EOF ? eof() : ((c==ldelim)&&(filesp==files) ? skeqn() : c) )
                    108: #define C1get ( (c=getc(infile)) == EOF ? eof() :  c)
                    109:
                    110: #ifdef DEBUG
                    111: #  define C    _C()
                    112: #  define C1   _C1()
1.4     ! danh      113: #else /* not DEBUG */
1.1       millert   114: #  define C    Cget
                    115: #  define C1   C1get
1.4     ! danh      116: #endif /* not DEBUG */
1.1       millert   117:
                    118: #define SKIP while (C != '\n')
                    119: #define SKIP_TO_COM SKIP; SKIP; pc=c; while (C != '.' || pc != '\n' || C > 'Z')pc=c
                    120:
                    121: #define        YES 1
                    122: #define        NO 0
                    123: #define        MS 0    /* -ms */
                    124: #define        MM 1    /* -mm */
                    125: #define        ME 2    /* -me */
                    126: #define        MA 3    /* -man */
                    127:
                    128: #ifdef DEBUG
                    129: char *mactab[] = { "-ms", "-mm", "-me", "-ma" };
1.4     ! danh      130: #endif /* DEBUG */
1.1       millert   131:
                    132: #define        ONE 1
                    133: #define        TWO 2
                    134:
                    135: #define NOCHAR -2
                    136: #define SPECIAL 0
                    137: #define APOS 1
                    138: #define PUNCT 2
                    139: #define DIGIT 3
                    140: #define LETTER 4
                    141:
                    142: #define MAXFILES 20
                    143:
                    144: int    iflag;
                    145: int    wordflag;
                    146: int    msflag;         /* processing a source written using a mac package */
                    147: int    mac;            /* which package */
                    148: int    disp;
                    149: int    parag;
                    150: int    inmacro;
                    151: int    intable;
                    152: int    keepblock;      /* keep blocks of text; normally false when msflag */
                    153:
                    154: char chars[128];  /* SPECIAL, PUNCT, APOS, DIGIT, or LETTER */
                    155:
                    156: char line[LINE_MAX];
                    157: char *lp;
                    158:
                    159: int c;
                    160: int pc;
                    161: int ldelim;
                    162: int rdelim;
                    163:
                    164: char fname[PATH_MAX];
                    165: FILE *files[MAXFILES];
                    166: FILE **filesp;
                    167: FILE *infile;
                    168:
                    169: int argc;
                    170: char **argv;
                    171:
                    172: /*
                    173:  *     Macro processing
                    174:  *
                    175:  *     Macro table definitions
                    176:  */
                    177: typedef        int pacmac;             /* compressed macro name */
                    178: int    argconcat = 0;          /* concat arguments together (-me only) */
                    179:
                    180: #define        tomac(c1, c2)           ((((c1) & 0xFF) << 8) | ((c2) & 0xFF))
                    181: #define        frommac(src, c1, c2)    (((c1)=((src)>>8)&0xFF),((c2) =(src)&0xFF))
                    182:
                    183: struct mactab{
                    184:        int     condition;
                    185:        pacmac  macname;
                    186:        int     (*func)();      /* XXX - args */
                    187: };
                    188:
                    189: struct mactab  troffmactab[];
                    190: struct mactab  ppmactab[];
                    191: struct mactab  msmactab[];
                    192: struct mactab  mmmactab[];
                    193: struct mactab  memactab[];
                    194: struct mactab  manmactab[];
                    195:
                    196: /*
                    197:  *     Macro table initialization
                    198:  */
                    199: #define        M(cond, c1, c2, func) {cond, tomac(c1, c2), func}
                    200:
                    201: /*
                    202:  *     Flags for matching conditions other than
                    203:  *     the macro name
                    204:  */
                    205: #define        NONE            0
                    206: #define        FNEST           1               /* no nested files */
                    207: #define        NOMAC           2               /* no macro */
                    208: #define        MAC             3               /* macro */
                    209: #define        PARAG           4               /* in a paragraph */
                    210: #define        MSF             5               /* msflag is on */
                    211: #define        NBLK            6               /* set if no blocks to be kept */
                    212:
                    213: /*
                    214:  *     Return codes from macro minions, determine where to jump,
                    215:  *     how to repeat/reprocess text
                    216:  */
                    217: #define        COMX            1               /* goto comx */
                    218: #define        COM             2               /* goto com */
                    219:
                    220: int     skeqn(void);
                    221: int     eof(void);
                    222: int     _C1(void);
                    223: int     _C(void);
                    224: int     EQ(void);
                    225: int     domacro(void);
                    226: int     PS(void);
                    227: int     skip(void);
                    228: int     intbl(void);
                    229: int     outtbl(void);
                    230: int     so(void);
                    231: int     nx(void);
                    232: int     skiptocom(void);
                    233: int     PP(pacmac);
                    234: int     AU(void);
                    235: int     SH(pacmac);
                    236: int     UX(void);
                    237: int     MMHU(pacmac);
                    238: int     mesnblock(pacmac);
                    239: int     mssnblock(pacmac);
                    240: int     nf(void);
                    241: int     ce(void);
                    242: int     meip(pacmac);
                    243: int     mepp(pacmac);
                    244: int     mesh(pacmac);
                    245: int     mefont(pacmac);
                    246: int     manfont(pacmac);
                    247: int     manpp(pacmac);
                    248: int     macsort(const void *, const void *);
                    249: int     sizetab(struct mactab *);
                    250: void    getfname(void);
                    251: void    textline(char *, int);
                    252: void    work(void);
                    253: void    regline(void (*)(char *, int), int);
                    254: void    macro(void);
                    255: void    tbl(void);
                    256: void    stbl(void);
                    257: void    eqn(void);
                    258: void    backsl(void);
                    259: void    sce(void);
                    260: void    refer(int);
                    261: void    inpic(void);
                    262: void    msputmac(char *, int);
                    263: void    msputwords(int);
                    264: void    meputmac(char *, int);
                    265: void    meputwords(int);
                    266: void    noblock(char, char);
                    267: void    defcomline(pacmac);
                    268: void    comline(void);
                    269: void    buildtab(struct mactab **, int *);
                    270: FILE   *opn(char *);
                    271: struct mactab *macfill(struct mactab *, struct mactab *);
                    272: __dead void usage(void);
                    273:
                    274: int
                    275: main(int ac, char **av)
                    276: {
                    277:        int     i, ch;
                    278:        int     errflg = 0;
                    279:        int     kflag = NO;
                    280:
                    281:        iflag = NO;
                    282:        wordflag = NO;
                    283:        msflag = NO;
                    284:        mac = ME;
                    285:        disp = NO;
                    286:        parag = NO;
                    287:        inmacro = NO;
                    288:        intable = NO;
                    289:        ldelim  = NOCHAR;
                    290:        rdelim  = NOCHAR;
                    291:        keepblock = YES;
                    292:
                    293:        while ((ch = getopt(ac, av, "ikpwm:")) != -1) {
                    294:                switch (ch) {
                    295:                case 'i':
                    296:                        iflag = YES;
                    297:                        break;
                    298:                case 'k':
                    299:                        kflag = YES;
                    300:                        break;
                    301:                case 'm':
                    302:                        msflag = YES;
                    303:                        keepblock = NO;
                    304:                        switch (optarg[0]) {
                    305:                        case 'm':
                    306:                                mac = MM;
                    307:                                break;
                    308:                        case 's':
                    309:                                mac = MS;
                    310:                                break;
                    311:                        case 'e':
                    312:                                mac = ME;
                    313:                                break;
                    314:                        case 'a':
                    315:                                mac = MA;
                    316:                                break;
                    317:                        case 'l':
                    318:                                disp = YES;
                    319:                                break;
                    320:                        default:
                    321:                                errflg++;
                    322:                                break;
                    323:                        }
                    324:                        if (errflg == 0 && optarg[1] != '\0')
                    325:                                errflg++;
                    326:                        break;
                    327:                case 'p':
                    328:                        parag = YES;
                    329:                        break;
                    330:                case 'w':
                    331:                        wordflag = YES;
                    332:                        kflag = YES;
                    333:                        break;
                    334:                default:
                    335:                        errflg++;
                    336:                }
                    337:        }
                    338:        argc = ac - optind;
                    339:        argv = av + optind;
                    340:
                    341:        if (kflag)
                    342:                keepblock = YES;
                    343:        if (errflg)
                    344:                usage();
                    345:
                    346: #ifdef DEBUG
                    347:        printf("msflag = %d, mac = %s, keepblock = %d, disp = %d\n",
                    348:                msflag, mactab[mac], keepblock, disp);
1.4     ! danh      349: #endif /* DEBUG */
1.1       millert   350:        if (argc == 0) {
                    351:                infile = stdin;
                    352:        } else {
                    353:                infile = opn(argv[0]);
                    354:                --argc;
                    355:                ++argv;
                    356:        }
                    357:        files[0] = infile;
                    358:        filesp = &files[0];
                    359:
                    360:        for (i = 'a'; i <= 'z' ; ++i)
                    361:                chars[i] = LETTER;
                    362:        for (i = 'A'; i <= 'Z'; ++i)
                    363:                chars[i] = LETTER;
                    364:        for (i = '0'; i <= '9'; ++i)
                    365:                chars[i] = DIGIT;
                    366:        chars['\''] = APOS;
                    367:        chars['&'] = APOS;
                    368:        chars['.'] = PUNCT;
                    369:        chars[','] = PUNCT;
                    370:        chars[';'] = PUNCT;
                    371:        chars['?'] = PUNCT;
                    372:        chars[':'] = PUNCT;
                    373:        work();
                    374:        exit(0);
                    375: }
                    376:
                    377: int
                    378: skeqn(void)
                    379: {
                    380:
                    381:        while ((c = getc(infile)) != rdelim) {
                    382:                if (c == EOF)
                    383:                        c = eof();
                    384:                else if (c == '"') {
                    385:                        while ((c = getc(infile)) != '"') {
                    386:                                if (c == EOF ||
                    387:                                    (c == '\\' && (c = getc(infile)) == EOF))
                    388:                                        c = eof();
                    389:                        }
                    390:                }
                    391:        }
                    392:        if (msflag)
                    393:                return((c = 'x'));
                    394:        return((c = ' '));
                    395: }
                    396:
                    397: FILE *
                    398: opn(char *p)
                    399: {
                    400:        FILE *fd;
                    401:
                    402:        if ((fd = fopen(p, "r")) == NULL)
                    403:                err(1, "fopen %s", p);
                    404:
                    405:        return(fd);
                    406: }
                    407:
                    408: int
                    409: eof(void)
                    410: {
                    411:
                    412:        if (infile != stdin)
                    413:                fclose(infile);
                    414:        if (filesp > files)
                    415:                infile = *--filesp;
                    416:        else if (argc > 0) {
                    417:                infile = opn(argv[0]);
                    418:                --argc;
                    419:                ++argv;
                    420:        } else
                    421:                exit(0);
                    422:        return(C);
                    423: }
                    424:
                    425: void
                    426: getfname(void)
                    427: {
                    428:        char *p;
                    429:        struct chain {
                    430:                struct chain *nextp;
                    431:                char *datap;
                    432:        } *q;
                    433:        static struct chain *namechain= NULL;
                    434:
                    435:        while (C == ' ')
                    436:                ;       /* nothing */
                    437:
                    438:        for (p = fname ; p - fname < sizeof(fname) && (*p = c) != '\n' &&
                    439:            c != ' ' && c != '\t' && c != '\\'; ++p)
                    440:                C;
                    441:        *p = '\0';
                    442:        while (c != '\n')
                    443:                C;
                    444:
                    445:        /* see if this name has already been used */
                    446:        for (q = namechain ; q; q = q->nextp)
                    447:                if (strcmp(fname, q->datap) == 0) {
                    448:                        fname[0] = '\0';
                    449:                        return;
                    450:                }
                    451:
                    452:        q = (struct chain *) malloc(sizeof(struct chain));
                    453:        if (q == NULL)
                    454:                err(1, "malloc");
                    455:        q->nextp = namechain;
                    456:        q->datap = strdup(fname);
                    457:        if (q->datap == NULL)
                    458:                err(1, "strdup");
                    459:        namechain = q;
                    460: }
                    461:
                    462: /*ARGSUSED*/
                    463: void
                    464: textline(char *str, int constant)
                    465: {
                    466:
                    467:        if (wordflag) {
                    468:                msputwords(0);
                    469:                return;
                    470:        }
                    471:        puts(str);
                    472: }
                    473:
                    474: void
                    475: work(void)
                    476: {
                    477:
                    478:        for (;;) {
                    479:                C;
                    480: #ifdef FULLDEBUG
                    481:                printf("Starting work with `%c'\n", c);
1.4     ! danh      482: #endif /* FULLDEBUG */
1.1       millert   483:                if (c == '.' || c == '\'')
                    484:                        comline();
                    485:                else
                    486:                        regline(textline, TWO);
                    487:        }
                    488: }
                    489:
                    490: void
                    491: regline(void (*pfunc)(char *, int), int constant)
                    492: {
                    493:
                    494:        line[0] = c;
                    495:        lp = line;
                    496:        while (lp - line < sizeof(line)) {
                    497:                if (c == '\\') {
                    498:                        *lp = ' ';
                    499:                        backsl();
                    500:                }
                    501:                if (c == '\n')
                    502:                        break;
                    503:                if (intable && c == 'T') {
                    504:                        *++lp = C;
                    505:                        if (c == '{' || c == '}') {
                    506:                                lp[-1] = ' ';
                    507:                                *lp = C;
                    508:                        }
                    509:                } else {
                    510:                        *++lp = C;
                    511:                }
                    512:        }
                    513:        *lp = '\0';
                    514:
                    515:        if (line[0] != '\0')
                    516:                (*pfunc)(line, constant);
                    517: }
                    518:
                    519: void
                    520: macro(void)
                    521: {
                    522:
                    523:        if (msflag) {
                    524:                do {
                    525:                        SKIP;
                    526:                } while (C!='.' || C!='.' || C=='.');   /* look for  .. */
                    527:                if (c != '\n')
                    528:                        SKIP;
                    529:                return;
                    530:        }
                    531:        SKIP;
                    532:        inmacro = YES;
                    533: }
                    534:
                    535: void
                    536: tbl(void)
                    537: {
                    538:
                    539:        while (C != '.')
                    540:                ;       /* nothing */
                    541:        SKIP;
                    542:        intable = YES;
                    543: }
                    544:
                    545: void
                    546: stbl(void)
                    547: {
                    548:
                    549:        while (C != '.')
                    550:                ;       /* nothing */
                    551:        SKIP_TO_COM;
                    552:        if (c != 'T' || C != 'E') {
                    553:                SKIP;
                    554:                pc = c;
                    555:                while (C != '.' || pc != '\n' || C != 'T' || C != 'E')
                    556:                        pc = c;
                    557:        }
                    558: }
                    559:
                    560: void
                    561: eqn(void)
                    562: {
                    563:        int c1, c2;
                    564:        int dflg;
                    565:        char last;
                    566:
                    567:        last=0;
                    568:        dflg = 1;
                    569:        SKIP;
                    570:
                    571:        for (;;) {
                    572:                if (C1 == '.'  || c == '\'') {
                    573:                        while (C1 == ' ' || c == '\t')
                    574:                                ;
                    575:                        if (c == 'E' && C1 == 'N') {
                    576:                                SKIP;
                    577:                                if (msflag && dflg) {
                    578:                                        putchar('x');
                    579:                                        putchar(' ');
                    580:                                        if (last) {
                    581:                                                putchar(last);
                    582:                                                putchar('\n');
                    583:                                        }
                    584:                                }
                    585:                                return;
                    586:                        }
                    587:                } else if (c == 'd') {
                    588:                        /* look for delim */
                    589:                        if (C1 == 'e' && C1 == 'l')
                    590:                                if (C1 == 'i' && C1 == 'm') {
                    591:                                        while (C1 == ' ')
                    592:                                                ;       /* nothing */
                    593:
                    594:                                        if ((c1 = c) == '\n' ||
                    595:                                            (c2 = C1) == '\n' ||
                    596:                                            (c1 == 'o' && c2 == 'f' && C1=='f')) {
                    597:                                                ldelim = NOCHAR;
                    598:                                                rdelim = NOCHAR;
                    599:                                        } else {
                    600:                                                ldelim = c1;
                    601:                                                rdelim = c2;
                    602:                                        }
                    603:                                }
                    604:                        dflg = 0;
                    605:                }
                    606:
                    607:                if (c != '\n')
                    608:                        while (C1 != '\n') {
                    609:                                if (chars[c] == PUNCT)
                    610:                                        last = c;
                    611:                                else if (c != ' ')
                    612:                                        last = 0;
                    613:                        }
                    614:        }
                    615: }
                    616:
                    617: /* skip over a complete backslash construction */
                    618: void
                    619: backsl(void)
                    620: {
                    621:        int bdelim;
                    622:
                    623: sw:
                    624:        switch (C) {
                    625:        case '"':
                    626:                SKIP;
                    627:                return;
                    628:
                    629:        case 's':
                    630:                if (C == '\\')
                    631:                        backsl();
                    632:                else {
                    633:                        while (C >= '0' && c <= '9')
                    634:                                ;       /* nothing */
                    635:                        ungetc(c, infile);
                    636:                        c = '0';
                    637:                }
                    638:                --lp;
                    639:                return;
                    640:
                    641:        case 'f':
                    642:        case 'n':
                    643:        case '*':
                    644:                if (C != '(')
                    645:                        return;
                    646:
                    647:        case '(':
                    648:                if (msflag) {
                    649:                        if (C == 'e') {
                    650:                                if (C == 'm') {
                    651:                                        *lp = '-';
                    652:                                        return;
                    653:                                }
                    654:                        }
                    655:                        else if (c != '\n')
                    656:                                C;
                    657:                        return;
                    658:                }
                    659:                if (C != '\n')
                    660:                        C;
                    661:                return;
                    662:
                    663:        case '$':
                    664:                C;      /* discard argument number */
                    665:                return;
                    666:
                    667:        case 'b':
                    668:        case 'x':
                    669:        case 'v':
                    670:        case 'h':
                    671:        case 'w':
                    672:        case 'o':
                    673:        case 'l':
                    674:        case 'L':
                    675:                if ((bdelim = C) == '\n')
                    676:                        return;
                    677:                while (C != '\n' && c != bdelim)
                    678:                        if (c == '\\')
                    679:                                backsl();
                    680:                return;
                    681:
                    682:        case '\\':
                    683:                if (inmacro)
                    684:                        goto sw;
                    685:
                    686:        default:
                    687:                return;
                    688:        }
                    689: }
                    690:
                    691: void
                    692: sce(void)
                    693: {
                    694:        char *ap;
                    695:        int n, i;
                    696:        char a[10];
                    697:
                    698:        for (ap = a; C != '\n'; ap++) {
                    699:                *ap = c;
                    700:                if (ap == &a[9]) {
                    701:                        SKIP;
                    702:                        ap = a;
                    703:                        break;
                    704:                }
                    705:        }
                    706:        if (ap != a)
                    707:                n = atoi(a);
                    708:        else
                    709:                n = 1;
                    710:        for (i = 0; i < n;) {
                    711:                if (C == '.') {
                    712:                        if (C == 'c') {
                    713:                                if (C == 'e') {
                    714:                                        while (C == ' ')
                    715:                                                ;       /* nothing */
                    716:                                        if (c == '0') {
                    717:                                                SKIP;
                    718:                                                break;
                    719:                                        } else
                    720:                                                SKIP;
                    721:                                }
                    722:                                else
                    723:                                        SKIP;
                    724:                        } else if (c == 'P' || C == 'P') {
                    725:                                if (c != '\n')
                    726:                                        SKIP;
                    727:                                break;
                    728:                        } else if (c != '\n')
                    729:                                SKIP;
                    730:                } else {
                    731:                        SKIP;
                    732:                        i++;
                    733:                }
                    734:        }
                    735: }
                    736:
                    737: void
                    738: refer(int c1)
                    739: {
                    740:        int c2;
                    741:
                    742:        if (c1 != '\n')
                    743:                SKIP;
                    744:
                    745:        for (c2 = -1;;) {
                    746:                if (C != '.')
                    747:                        SKIP;
                    748:                else {
                    749:                        if (C != ']')
                    750:                                SKIP;
                    751:                        else {
                    752:                                while (C != '\n')
                    753:                                        c2 = c;
                    754:                                if (c2 != -1 && chars[c2] == PUNCT)
                    755:                                        putchar(c2);
                    756:                                return;
                    757:                        }
                    758:                }
                    759:        }
                    760: }
                    761:
                    762: void
                    763: inpic(void)
                    764: {
                    765:        int c1;
                    766:        char *p1;
                    767:
                    768:        SKIP;
                    769:        p1 = line;
                    770:        c = '\n';
                    771:        for (;;) {
                    772:                c1 = c;
                    773:                if (C == '.' && c1 == '\n') {
                    774:                        if (C != 'P') {
                    775:                                if (c == '\n')
                    776:                                        continue;
                    777:                                else {
                    778:                                        SKIP;
                    779:                                        c = '\n';
                    780:                                        continue;
                    781:                                }
                    782:                        }
                    783:                        if (C != 'E') {
                    784:                                if (c == '\n')
                    785:                                        continue;
                    786:                                else {
                    787:                                        SKIP;
                    788:                                        c = '\n';
                    789:                                        continue;
                    790:                                }
                    791:                        }
                    792:                        SKIP;
                    793:                        return;
                    794:                }
                    795:                else if (c == '\"') {
                    796:                        while (C != '\"') {
                    797:                                if (c == '\\') {
                    798:                                        if (C == '\"')
                    799:                                                continue;
                    800:                                        ungetc(c, infile);
                    801:                                        backsl();
                    802:                                } else
                    803:                                        *p1++ = c;
                    804:                        }
                    805:                        *p1++ = ' ';
                    806:                }
                    807:                else if (c == '\n' && p1 != line) {
                    808:                        *p1 = '\0';
                    809:                        if (wordflag)
                    810:                                msputwords(NO);
                    811:                        else {
                    812:                                puts(line);
                    813:                                putchar('\n');
                    814:                        }
                    815:                        p1 = line;
                    816:                }
                    817:        }
                    818: }
                    819:
                    820: #ifdef DEBUG
                    821: int
                    822: _C1(void)
                    823: {
                    824:
                    825:        return(C1get);
                    826: }
                    827:
                    828: int
                    829: _C(void)
                    830: {
                    831:
                    832:        return(Cget);
                    833: }
1.4     ! danh      834: #endif /* DEBUG */
1.1       millert   835:
                    836: /*
                    837:  *     Put out a macro line, using ms and mm conventions.
                    838:  */
                    839: void
                    840: msputmac(char *s, int constant)
                    841: {
                    842:        char *t;
                    843:        int found;
                    844:        int last;
                    845:
                    846:        last = 0;
                    847:        found = 0;
                    848:        if (wordflag) {
                    849:                msputwords(YES);
                    850:                return;
                    851:        }
                    852:        while (*s) {
                    853:                while (*s == ' ' || *s == '\t')
                    854:                        putchar(*s++);
                    855:                for (t = s ; *t != ' ' && *t != '\t' && *t != '\0' ; ++t)
                    856:                        ;       /* nothing */
                    857:                if (*s == '\"')
                    858:                        s++;
                    859:                if (t > s + constant && chars[(unsigned char)s[0]] == LETTER &&
                    860:                    chars[(unsigned char)s[1]] == LETTER) {
                    861:                        while (s < t)
                    862:                                if (*s == '\"')
                    863:                                        s++;
                    864:                                else
                    865:                                        putchar(*s++);
                    866:                        last = *(t-1);
                    867:                        found++;
                    868:                } else if (found && chars[(unsigned char)s[0]] == PUNCT &&
                    869:                    s[1] == '\0') {
                    870:                        putchar(*s++);
                    871:                } else {
                    872:                        last = *(t - 1);
                    873:                        s = t;
                    874:                }
                    875:        }
                    876:        putchar('\n');
                    877:        if (msflag && chars[last] == PUNCT) {
                    878:                putchar(last);
                    879:                putchar('\n');
                    880:        }
                    881: }
                    882:
                    883: /*
                    884:  *     put out words (for the -w option) with ms and mm conventions
                    885:  */
                    886: void
                    887: msputwords(int macline)
                    888: {
                    889:        char *p, *p1;
                    890:        int i, nlet;
                    891:
                    892:        for (p1 = line;;) {
                    893:                /*
                    894:                 *      skip initial specials ampersands and apostrophes
                    895:                 */
                    896:                while (chars[(unsigned char)*p1] < DIGIT)
                    897:                        if (*p1++ == '\0')
                    898:                                return;
                    899:                nlet = 0;
                    900:                for (p = p1 ; (i = chars[(unsigned char)*p]) != SPECIAL ; ++p)
                    901:                        if (i == LETTER)
                    902:                                ++nlet;
                    903:
                    904:                if (nlet > 1 && chars[(unsigned char)p1[0]] == LETTER) {
                    905:                        /*
                    906:                         *      delete trailing ampersands and apostrophes
                    907:                         */
                    908:                        while ((i = chars[(unsigned char)p[-1]]) == PUNCT ||
                    909:                            i == APOS )
                    910:                                --p;
                    911:                        while (p1 < p)
                    912:                                putchar(*p1++);
                    913:                        putchar('\n');
                    914:                } else {
                    915:                        p1 = p;
                    916:                }
                    917:        }
                    918: }
                    919:
                    920: /*
                    921:  *     put out a macro using the me conventions
                    922:  */
                    923: #define SKIPBLANK(cp)  while (*cp == ' ' || *cp == '\t') { cp++; }
                    924: #define SKIPNONBLANK(cp) while (*cp !=' ' && *cp !='\cp' && *cp !='\0') { cp++; }
                    925:
                    926: void
                    927: meputmac(char *cp, int constant)
                    928: {
                    929:        char    *np;
                    930:        int     found;
                    931:        int     argno;
                    932:        int     last;
                    933:        int     inquote;
                    934:
                    935:        last = 0;
                    936:        found = 0;
                    937:        if (wordflag) {
                    938:                meputwords(YES);
                    939:                return;
                    940:        }
                    941:        for (argno = 0; *cp; argno++) {
                    942:                SKIPBLANK(cp);
                    943:                inquote = (*cp == '"');
                    944:                if (inquote)
                    945:                        cp++;
                    946:                for (np = cp; *np; np++) {
                    947:                        switch (*np) {
                    948:                        case '\n':
                    949:                        case '\0':
                    950:                                break;
                    951:
                    952:                        case '\t':
                    953:                        case ' ':
                    954:                                if (inquote)
                    955:                                        continue;
                    956:                                else
                    957:                                        goto endarg;
                    958:
                    959:                        case '"':
                    960:                                if (inquote && np[1] == '"') {
1.3       millert   961:                                        memmove(np, np + 1, strlen(np));
1.1       millert   962:                                        np++;
                    963:                                        continue;
                    964:                                } else {
                    965:                                        *np = ' ';      /* bye bye " */
                    966:                                        goto endarg;
                    967:                                }
                    968:
                    969:                        default:
                    970:                                continue;
                    971:                        }
                    972:                }
                    973:                endarg: ;
                    974:                /*
                    975:                 *      cp points at the first char in the arg
                    976:                 *      np points one beyond the last char in the arg
                    977:                 */
                    978:                if ((argconcat == 0) || (argconcat != argno))
                    979:                        putchar(' ');
                    980: #ifdef FULLDEBUG
                    981:                {
                    982:                        char    *p;
                    983:                        printf("[%d,%d: ", argno, np - cp);
                    984:                        for (p = cp; p < np; p++) {
                    985:                                putchar(*p);
                    986:                        }
                    987:                        printf("]");
                    988:                }
1.4     ! danh      989: #endif /* FULLDEBUG */
1.1       millert   990:                /*
                    991:                 *      Determine if the argument merits being printed
                    992:                 *
                    993:                 *      constant is the cut off point below which something
                    994:                 *      is not a word.
                    995:                 */
                    996:                if (((np - cp) > constant) &&
                    997:                    (inquote || (chars[(unsigned char)cp[0]] == LETTER))) {
                    998:                        for (cp = cp; cp < np; cp++)
                    999:                                putchar(*cp);
                   1000:                        last = np[-1];
                   1001:                        found++;
                   1002:                } else if (found && (np - cp == 1) &&
                   1003:                    chars[(unsigned char)*cp] == PUNCT) {
                   1004:                        putchar(*cp);
                   1005:                } else {
                   1006:                        last = np[-1];
                   1007:                }
                   1008:                cp = np;
                   1009:        }
                   1010:        if (msflag && chars[last] == PUNCT)
                   1011:                putchar(last);
                   1012:        putchar('\n');
                   1013: }
                   1014:
                   1015: /*
                   1016:  *     put out words (for the -w option) with ms and mm conventions
                   1017:  */
                   1018: void
                   1019: meputwords(int macline)
                   1020: {
                   1021:
                   1022:        msputwords(macline);
                   1023: }
                   1024:
                   1025: /*
                   1026:  *
                   1027:  *     Skip over a nested set of macros
                   1028:  *
                   1029:  *     Possible arguments to noblock are:
                   1030:  *
                   1031:  *     fi      end of unfilled text
                   1032:  *     PE      pic ending
                   1033:  *     DE      display ending
                   1034:  *
                   1035:  *     for ms and mm only:
                   1036:  *             KE      keep ending
                   1037:  *
                   1038:  *             NE      undocumented match to NS (for mm?)
                   1039:  *             LE      mm only: matches RL or *L (for lists)
                   1040:  *
                   1041:  *     for me:
                   1042:  *             ([lqbzcdf]
                   1043:  */
                   1044: void
                   1045: noblock(char a1, char a2)
                   1046: {
                   1047:        int c1,c2;
                   1048:        int eqnf;
                   1049:        int lct;
                   1050:
                   1051:        lct = 0;
                   1052:        eqnf = 1;
                   1053:        SKIP;
                   1054:        for (;;) {
                   1055:                while (C != '.')
                   1056:                        if (c == '\n')
                   1057:                                continue;
                   1058:                        else
                   1059:                                SKIP;
                   1060:                if ((c1 = C) == '\n')
                   1061:                        continue;
                   1062:                if ((c2 = C) == '\n')
                   1063:                        continue;
                   1064:                if (c1 == a1 && c2 == a2) {
                   1065:                        SKIP;
                   1066:                        if (lct != 0) {
                   1067:                                lct--;
                   1068:                                continue;
                   1069:                        }
                   1070:                        if (eqnf)
                   1071:                                putchar('.');
                   1072:                        putchar('\n');
                   1073:                        return;
                   1074:                } else if (a1 == 'L' && c2 == 'L') {
                   1075:                        lct++;
                   1076:                        SKIP;
                   1077:                }
                   1078:                /*
                   1079:                 *      equations (EQ) nested within a display
                   1080:                 */
                   1081:                else if (c1 == 'E' && c2 == 'Q') {
                   1082:                        if ((mac == ME && a1 == ')')
                   1083:                            || (mac != ME && a1 == 'D')) {
                   1084:                                eqn();
                   1085:                                eqnf=0;
                   1086:                        }
                   1087:                }
                   1088:                /*
                   1089:                 *      turning on filling is done by the paragraphing
                   1090:                 *      macros
                   1091:                 */
                   1092:                else if (a1 == 'f') {   /* .fi */
                   1093:                        if  ((mac == ME && (c2 == 'h' || c2 == 'p'))
                   1094:                            || (mac != ME && (c1 == 'P' || c2 == 'P'))) {
                   1095:                                SKIP;
                   1096:                                return;
                   1097:                        }
                   1098:                } else {
                   1099:                        SKIP;
                   1100:                }
                   1101:        }
                   1102: }
                   1103:
                   1104: int
                   1105: EQ(void)
                   1106: {
                   1107:
                   1108:        eqn();
                   1109:        return(0);
                   1110: }
                   1111:
                   1112: int
                   1113: domacro(void)
                   1114: {
                   1115:
                   1116:        macro();
                   1117:        return(0);
                   1118: }
                   1119:
                   1120: int
                   1121: PS(void)
                   1122: {
                   1123:
                   1124:        for (C; c == ' ' || c == '\t'; C)
                   1125:                ;       /* nothing */
                   1126:
                   1127:        if (c == '<') {         /* ".PS < file" -- don't expect a .PE */
                   1128:                SKIP;
                   1129:                return(0);
                   1130:        }
                   1131:        if (!msflag)
                   1132:                inpic();
                   1133:        else
                   1134:                noblock('P', 'E');
                   1135:        return(0);
                   1136: }
                   1137:
                   1138: int
                   1139: skip(void)
                   1140: {
                   1141:
                   1142:        SKIP;
                   1143:        return(0);
                   1144: }
                   1145:
                   1146: int
                   1147: intbl(void)
                   1148: {
                   1149:
                   1150:        if (msflag)
                   1151:                stbl();
                   1152:        else
                   1153:                tbl();
                   1154:        return(0);
                   1155: }
                   1156:
                   1157: int
                   1158: outtbl(void)
                   1159: {
                   1160:
                   1161:        intable = NO;
                   1162:        return(0);
                   1163: }
                   1164:
                   1165: int
                   1166: so(void)
                   1167: {
                   1168:
                   1169:        if (!iflag) {
                   1170:                getfname();
                   1171:                if (fname[0]) {
                   1172:                        if (++filesp - &files[0] > MAXFILES)
                   1173:                                err(1, "too many nested files (max %d)",
                   1174:                                    MAXFILES);
                   1175:                        infile = *filesp = opn(fname);
                   1176:                }
                   1177:        }
                   1178:        return(0);
                   1179: }
                   1180:
                   1181: int
                   1182: nx(void)
                   1183: {
                   1184:
                   1185:        if (!iflag) {
                   1186:                getfname();
                   1187:                if (fname[0] == '\0')
                   1188:                        exit(0);
                   1189:                if (infile != stdin)
                   1190:                        fclose(infile);
                   1191:                infile = *filesp = opn(fname);
                   1192:        }
                   1193:        return(0);
                   1194: }
                   1195:
                   1196: int
                   1197: skiptocom(void)
                   1198: {
                   1199:
                   1200:        SKIP_TO_COM;
                   1201:        return(COMX);
                   1202: }
                   1203:
                   1204: int
                   1205: PP(pacmac c12)
                   1206: {
                   1207:        int c1, c2;
                   1208:
                   1209:        frommac(c12, c1, c2);
                   1210:        printf(".%c%c", c1, c2);
                   1211:        while (C != '\n')
                   1212:                putchar(c);
                   1213:        putchar('\n');
                   1214:        return(0);
                   1215: }
                   1216:
                   1217: int
                   1218: AU(void)
                   1219: {
                   1220:
                   1221:        if (mac == MM)
                   1222:                return(0);
                   1223:        SKIP_TO_COM;
                   1224:        return(COMX);
                   1225: }
                   1226:
                   1227: int
                   1228: SH(pacmac c12)
                   1229: {
                   1230:        int c1, c2;
                   1231:
                   1232:        frommac(c12, c1, c2);
                   1233:
                   1234:        if (parag) {
                   1235:                printf(".%c%c", c1, c2);
                   1236:                while (C != '\n')
                   1237:                        putchar(c);
                   1238:                putchar(c);
                   1239:                putchar('!');
                   1240:                for (;;) {
                   1241:                        while (C != '\n')
                   1242:                                putchar(c);
                   1243:                        putchar('\n');
                   1244:                        if (C == '.')
                   1245:                                return(COM);
                   1246:                        putchar('!');
                   1247:                        putchar(c);
                   1248:                }
                   1249:                /*NOTREACHED*/
                   1250:        } else {
                   1251:                SKIP_TO_COM;
                   1252:                return(COMX);
                   1253:        }
                   1254: }
                   1255:
                   1256: int
                   1257: UX(void)
                   1258: {
                   1259:
                   1260:        if (wordflag)
                   1261:                printf("UNIX\n");
                   1262:        else
                   1263:                printf("UNIX ");
                   1264:        return(0);
                   1265: }
                   1266:
                   1267: int
                   1268: MMHU(pacmac c12)
                   1269: {
                   1270:        int c1, c2;
                   1271:
                   1272:        frommac(c12, c1, c2);
                   1273:        if (parag) {
                   1274:                printf(".%c%c", c1, c2);
                   1275:                while (C != '\n')
                   1276:                        putchar(c);
                   1277:                putchar('\n');
                   1278:        } else {
                   1279:                SKIP;
                   1280:        }
                   1281:        return(0);
                   1282: }
                   1283:
                   1284: int
                   1285: mesnblock(pacmac c12)
                   1286: {
                   1287:        int c1, c2;
                   1288:
                   1289:        frommac(c12, c1, c2);
                   1290:        noblock(')', c2);
                   1291:        return(0);
                   1292: }
                   1293:
                   1294: int
                   1295: mssnblock(pacmac c12)
                   1296: {
                   1297:        int c1, c2;
                   1298:
                   1299:        frommac(c12, c1, c2);
                   1300:        noblock(c1, 'E');
                   1301:        return(0);
                   1302: }
                   1303:
                   1304: int
                   1305: nf(void)
                   1306: {
                   1307:
                   1308:        noblock('f', 'i');
                   1309:        return(0);
                   1310: }
                   1311:
                   1312: int
                   1313: ce(void)
                   1314: {
                   1315:
                   1316:        sce();
                   1317:        return(0);
                   1318: }
                   1319:
                   1320: int
                   1321: meip(pacmac c12)
                   1322: {
                   1323:
                   1324:        if (parag)
                   1325:                mepp(c12);
                   1326:        else if (wordflag)      /* save the tag */
                   1327:                regline(meputmac, ONE);
                   1328:        else
                   1329:                SKIP;
                   1330:        return(0);
                   1331: }
                   1332:
                   1333: /*
                   1334:  *     only called for -me .pp or .sh, when parag is on
                   1335:  */
                   1336: int
                   1337: mepp(pacmac c12)
                   1338: {
                   1339:
                   1340:        PP(c12);                /* eats the line */
                   1341:        return(0);
                   1342: }
                   1343:
                   1344: /*
                   1345:  *     Start of a section heading; output the section name if doing words
                   1346:  */
                   1347: int
                   1348: mesh(pacmac c12)
                   1349: {
                   1350:
                   1351:        if (parag)
                   1352:                mepp(c12);
                   1353:        else if (wordflag)
                   1354:                defcomline(c12);
                   1355:        else
                   1356:                SKIP;
                   1357:        return(0);
                   1358: }
                   1359:
                   1360: /*
                   1361:  *     process a font setting
                   1362:  */
                   1363: int
                   1364: mefont(pacmac c12)
                   1365: {
                   1366:
                   1367:        argconcat = 1;
                   1368:        defcomline(c12);
                   1369:        argconcat = 0;
                   1370:        return(0);
                   1371: }
                   1372:
                   1373: int
                   1374: manfont(pacmac c12)
                   1375: {
                   1376:
                   1377:        return(mefont(c12));
                   1378: }
                   1379:
                   1380: int
                   1381: manpp(pacmac c12)
                   1382: {
                   1383:
                   1384:        return(mepp(c12));
                   1385: }
                   1386:
                   1387: void
                   1388: defcomline(pacmac c12)
                   1389: {
                   1390:        int c1, c2;
                   1391:
                   1392:        frommac(c12, c1, c2);
                   1393:        if (msflag && mac == MM && c2 == 'L') {
                   1394:                if (disp || c1 == 'R') {
                   1395:                        noblock('L', 'E');
                   1396:                } else {
                   1397:                        SKIP;
                   1398:                        putchar('.');
                   1399:                }
                   1400:        }
                   1401:        else if (c1 == '.' && c2 == '.') {
                   1402:                if (msflag) {
                   1403:                        SKIP;
                   1404:                        return;
                   1405:                }
                   1406:                while (C == '.')
                   1407:                        /*VOID*/;
                   1408:        }
                   1409:        ++inmacro;
                   1410:        /*
                   1411:         *      Process the arguments to the macro
                   1412:         */
                   1413:        switch (mac) {
                   1414:        default:
                   1415:        case MM:
                   1416:        case MS:
                   1417:                if (c1 <= 'Z' && msflag)
                   1418:                        regline(msputmac, ONE);
                   1419:                else
                   1420:                        regline(msputmac, TWO);
                   1421:                break;
                   1422:        case ME:
                   1423:                regline(meputmac, ONE);
                   1424:                break;
                   1425:        }
                   1426:        --inmacro;
                   1427: }
                   1428:
                   1429: void
                   1430: comline(void)
                   1431: {
                   1432:        int     c1;
                   1433:        int     c2;
                   1434:        pacmac  c12;
                   1435:        int     mid;
                   1436:        int     lb, ub;
                   1437:        int     hit;
                   1438:        static  int     tabsize = 0;
                   1439:        static  struct  mactab  *mactab = (struct mactab *)0;
                   1440:        struct  mactab  *mp;
                   1441:
                   1442:        if (mactab == 0)
                   1443:                 buildtab(&mactab, &tabsize);
                   1444: com:
                   1445:        while (C == ' ' || c == '\t')
                   1446:                ;
                   1447: comx:
                   1448:        if ((c1 = c) == '\n')
                   1449:                return;
                   1450:        c2 = C;
                   1451:        if (c1 == '.' && c2 != '.')
                   1452:                inmacro = NO;
                   1453:        if (msflag && c1 == '[') {
                   1454:                refer(c2);
                   1455:                return;
                   1456:        }
                   1457:        if (parag && mac==MM && c1 == 'P' && c2 == '\n') {
                   1458:                printf(".P\n");
                   1459:                return;
                   1460:        }
                   1461:        if (c2 == '\n')
                   1462:                return;
                   1463:        /*
                   1464:         *      Single letter macro
                   1465:         */
                   1466:        if (mac == ME && (c2 == ' ' || c2 == '\t') )
                   1467:                c2 = ' ';
                   1468:        c12 = tomac(c1, c2);
                   1469:        /*
                   1470:         *      binary search through the table of macros
                   1471:         */
                   1472:        lb = 0;
                   1473:        ub = tabsize - 1;
                   1474:        while (lb <= ub) {
                   1475:                mid = (ub + lb) / 2;
                   1476:                mp = &mactab[mid];
                   1477:                if (mp->macname < c12)
                   1478:                        lb = mid + 1;
                   1479:                else if (mp->macname > c12)
                   1480:                        ub = mid - 1;
                   1481:                else {
                   1482:                        hit = 1;
                   1483: #ifdef FULLDEBUG
                   1484:                        printf("preliminary hit macro %c%c ", c1, c2);
1.4     ! danh     1485: #endif /* FULLDEBUG */
1.1       millert  1486:                        switch (mp->condition) {
                   1487:                        case NONE:
                   1488:                                hit = YES;
                   1489:                                break;
                   1490:                        case FNEST:
                   1491:                                hit = (filesp == files);
                   1492:                                break;
                   1493:                        case NOMAC:
                   1494:                                hit = !inmacro;
                   1495:                                break;
                   1496:                        case MAC:
                   1497:                                hit = inmacro;
                   1498:                                break;
                   1499:                        case PARAG:
                   1500:                                hit = parag;
                   1501:                                break;
                   1502:                        case NBLK:
                   1503:                                hit = !keepblock;
                   1504:                                break;
                   1505:                        default:
                   1506:                                hit = 0;
                   1507:                        }
                   1508:
                   1509:                        if (hit) {
                   1510: #ifdef FULLDEBUG
                   1511:                                printf("MATCH\n");
1.4     ! danh     1512: #endif /* FULLDEBUG */
1.1       millert  1513:                                switch ((*(mp->func))(c12)) {
                   1514:                                default:
                   1515:                                        return;
                   1516:                                case COMX:
                   1517:                                        goto comx;
                   1518:                                case COM:
                   1519:                                        goto com;
                   1520:                                }
                   1521:                        }
                   1522: #ifdef FULLDEBUG
                   1523:                        printf("FAIL\n");
1.4     ! danh     1524: #endif /* FULLDEBUG */
1.1       millert  1525:                        break;
                   1526:                }
                   1527:        }
                   1528:        defcomline(c12);
                   1529: }
                   1530:
                   1531: int
                   1532: macsort(const void *p1, const void *p2)
                   1533: {
                   1534:        struct mactab *t1 = (struct mactab *)p1;
                   1535:        struct mactab *t2 = (struct mactab *)p2;
                   1536:
                   1537:        return(t1->macname - t2->macname);
                   1538: }
                   1539:
                   1540: int
                   1541: sizetab(struct mactab *mp)
                   1542: {
                   1543:        int i;
                   1544:
                   1545:        i = 0;
                   1546:        if (mp) {
                   1547:                for (; mp->macname; mp++, i++)
                   1548:                        /*VOID*/ ;
                   1549:        }
                   1550:        return(i);
                   1551: }
                   1552:
                   1553: struct mactab *
                   1554: macfill(struct mactab *dst, struct mactab *src)
                   1555: {
                   1556:
                   1557:        if (src) {
                   1558:                while (src->macname)
                   1559:                        *dst++ = *src++;
                   1560:        }
                   1561:        return(dst);
                   1562: }
                   1563:
                   1564: __dead void
                   1565: usage(void)
                   1566: {
                   1567:        extern char *__progname;
                   1568:
                   1569:        fprintf(stderr, "usage: %s [-ikpw ] [ -m ( a | e | m | s | l ) ] [ filename ] ... \n", __progname);
                   1570:        exit(1);
                   1571: }
                   1572:
                   1573: void
                   1574: buildtab(struct mactab **r_back, int *r_size)
                   1575: {
                   1576:        int     size;
                   1577:        struct  mactab  *p, *p1, *p2;
                   1578:        struct  mactab  *back;
                   1579:
                   1580:        size = sizetab(troffmactab) + sizetab(ppmactab);
                   1581:        p1 = p2 = NULL;
                   1582:        if (msflag) {
                   1583:                switch (mac) {
                   1584:                case ME:
                   1585:                        p1 = memactab;
                   1586:                        break;
                   1587:                case MM:
                   1588:                        p1 = msmactab;
                   1589:                        p2 = mmmactab;
                   1590:                        break;
                   1591:                case MS:
                   1592:                        p1 = msmactab;
                   1593:                        break;
                   1594:                case MA:
                   1595:                        p1 = manmactab;
                   1596:                        break;
                   1597:                default:
                   1598:                        break;
                   1599:                }
                   1600:        }
                   1601:        size += sizetab(p1);
                   1602:        size += sizetab(p2);
                   1603:        back = (struct mactab *)calloc(size+2, sizeof(struct mactab));
                   1604:        if (back == NULL)
                   1605:                err(1, "calloc");
                   1606:
                   1607:        p = macfill(back, troffmactab);
                   1608:        p = macfill(p, ppmactab);
                   1609:        p = macfill(p, p1);
                   1610:        p = macfill(p, p2);
                   1611:
                   1612:        qsort(back, size, sizeof(struct mactab), macsort);
                   1613:        *r_size = size;
                   1614:        *r_back = back;
                   1615: }
                   1616:
                   1617: /*
                   1618:  *     troff commands
                   1619:  */
                   1620: struct mactab  troffmactab[] = {
                   1621:        M(NONE,         '\\','"',       skip),  /* comment */
                   1622:        M(NOMAC,        'd','e',        domacro),       /* define */
                   1623:        M(NOMAC,        'i','g',        domacro),       /* ignore till .. */
                   1624:        M(NOMAC,        'a','m',        domacro),       /* append macro */
                   1625:        M(NBLK,         'n','f',        nf),    /* filled */
                   1626:        M(NBLK,         'c','e',        ce),    /* centered */
                   1627:
                   1628:        M(NONE,         's','o',        so),    /* source a file */
                   1629:        M(NONE,         'n','x',        nx),    /* go to next file */
                   1630:
                   1631:        M(NONE,         't','m',        skip),  /* print string on tty */
                   1632:        M(NONE,         'h','w',        skip),  /* exception hyphen words */
                   1633:        M(NONE,         0,0,            0)
                   1634: };
                   1635:
                   1636: /*
                   1637:  *     Preprocessor output
                   1638:  */
                   1639: struct mactab  ppmactab[] = {
                   1640:        M(FNEST,        'E','Q',        EQ),    /* equation starting */
                   1641:        M(FNEST,        'T','S',        intbl), /* table starting */
                   1642:        M(FNEST,        'T','C',        intbl), /* alternative table? */
                   1643:        M(FNEST,        'T','&',        intbl), /* table reformatting */
                   1644:        M(NONE,         'T','E',        outtbl),/* table ending */
                   1645:        M(NONE,         'P','S',        PS),    /* picture starting */
                   1646:        M(NONE,         0,0,            0)
                   1647: };
                   1648:
                   1649: /*
                   1650:  *     Particular to ms and mm
                   1651:  */
                   1652: struct mactab  msmactab[] = {
                   1653:        M(NONE,         'T','L',        skiptocom),     /* title follows */
                   1654:        M(NONE,         'F','S',        skiptocom),     /* start footnote */
                   1655:        M(NONE,         'O','K',        skiptocom),     /* Other kws */
                   1656:
                   1657:        M(NONE,         'N','R',        skip),  /* undocumented */
                   1658:        M(NONE,         'N','D',        skip),  /* use supplied date */
                   1659:
                   1660:        M(PARAG,        'P','P',        PP),    /* begin parag */
                   1661:        M(PARAG,        'I','P',        PP),    /* begin indent parag, tag x */
                   1662:        M(PARAG,        'L','P',        PP),    /* left blocked parag */
                   1663:
                   1664:        M(NONE,         'A','U',        AU),    /* author */
                   1665:        M(NONE,         'A','I',        AU),    /* authors institution */
                   1666:
                   1667:        M(NONE,         'S','H',        SH),    /* section heading */
                   1668:        M(NONE,         'S','N',        SH),    /* undocumented */
                   1669:        M(NONE,         'U','X',        UX),    /* unix */
                   1670:
                   1671:        M(NBLK,         'D','S',        mssnblock),     /* start display text */
                   1672:        M(NBLK,         'K','S',        mssnblock),     /* start keep */
                   1673:        M(NBLK,         'K','F',        mssnblock),     /* start float keep */
                   1674:        M(NONE,         0,0,            0)
                   1675: };
                   1676:
                   1677: struct mactab  mmmactab[] = {
                   1678:        M(NONE,         'H',' ',        MMHU),  /* -mm ? */
                   1679:        M(NONE,         'H','U',        MMHU),  /* -mm ? */
                   1680:        M(PARAG,        'P',' ',        PP),    /* paragraph for -mm */
                   1681:        M(NBLK,         'N','S',        mssnblock),     /* undocumented */
                   1682:        M(NONE,         0,0,            0)
                   1683: };
                   1684:
                   1685: struct mactab  memactab[] = {
                   1686:        M(PARAG,        'p','p',        mepp),
                   1687:        M(PARAG,        'l','p',        mepp),
                   1688:        M(PARAG,        'n','p',        mepp),
                   1689:        M(NONE,         'i','p',        meip),
                   1690:
                   1691:        M(NONE,         's','h',        mesh),
                   1692:        M(NONE,         'u','h',        mesh),
                   1693:
                   1694:        M(NBLK,         '(','l',        mesnblock),
                   1695:        M(NBLK,         '(','q',        mesnblock),
                   1696:        M(NBLK,         '(','b',        mesnblock),
                   1697:        M(NBLK,         '(','z',        mesnblock),
                   1698:        M(NBLK,         '(','c',        mesnblock),
                   1699:
                   1700:        M(NBLK,         '(','d',        mesnblock),
                   1701:        M(NBLK,         '(','f',        mesnblock),
                   1702:        M(NBLK,         '(','x',        mesnblock),
                   1703:
                   1704:        M(NONE,         'r',' ',        mefont),
                   1705:        M(NONE,         'i',' ',        mefont),
                   1706:        M(NONE,         'b',' ',        mefont),
                   1707:        M(NONE,         'u',' ',        mefont),
                   1708:        M(NONE,         'q',' ',        mefont),
                   1709:        M(NONE,         'r','b',        mefont),
                   1710:        M(NONE,         'b','i',        mefont),
                   1711:        M(NONE,         'b','x',        mefont),
                   1712:        M(NONE,         0,0,            0)
                   1713: };
                   1714:
                   1715: struct mactab  manmactab[] = {
                   1716:        M(PARAG,        'B','I',        manfont),
                   1717:        M(PARAG,        'B','R',        manfont),
                   1718:        M(PARAG,        'I','B',        manfont),
                   1719:        M(PARAG,        'I','R',        manfont),
                   1720:        M(PARAG,        'R','B',        manfont),
                   1721:        M(PARAG,        'R','I',        manfont),
                   1722:
                   1723:        M(PARAG,        'P','P',        manpp),
                   1724:        M(PARAG,        'L','P',        manpp),
                   1725:        M(PARAG,        'H','P',        manpp),
                   1726:        M(NONE,         0,0,            0)
                   1727: };