[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.5

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