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

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