[BACK]Return to term.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Annotation of mandoc/term.c, Revision 1.20

1.20    ! kristaps    1: /* $Id: term.c,v 1.19 2009/02/25 12:27:37 kristaps Exp $ */
1.1       kristaps    2: /*
1.10      kristaps    3:  * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
1.1       kristaps    4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the
                      7:  * above copyright notice and this permission notice appear in all
                      8:  * copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
                     11:  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
                     12:  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
                     13:  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
                     14:  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
                     15:  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
                     16:  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
                     17:  * PERFORMANCE OF THIS SOFTWARE.
                     18:  */
                     19: #include <assert.h>
                     20: #include <stdlib.h>
                     21: #include <string.h>
                     22:
1.10      kristaps   23: #include "term.h"
                     24:
                     25: #define        INDENT            4
                     26:
                     27: /*
                     28:  * Performs actions on nodes of the abstract syntax tree.  Both pre- and
                     29:  * post-fix operations are defined here.
                     30:  */
                     31:
                     32: /* FIXME: indent/tab. */
1.12      kristaps   33: /* FIXME: handle nested lists. */
1.10      kristaps   34:
                     35: #define        TTYPE_PROG        0
                     36: #define        TTYPE_CMD_FLAG    1
                     37: #define        TTYPE_CMD_ARG     2
                     38: #define        TTYPE_SECTION     3
                     39: #define        TTYPE_FUNC_DECL   4
                     40: #define        TTYPE_VAR_DECL    5
                     41: #define        TTYPE_FUNC_TYPE   6
                     42: #define        TTYPE_FUNC_NAME   7
                     43: #define        TTYPE_FUNC_ARG    8
                     44: #define        TTYPE_LINK        9
                     45: #define        TTYPE_SSECTION    10
                     46: #define        TTYPE_FILE        11
1.11      kristaps   47: #define        TTYPE_EMPH        12
1.14      kristaps   48: #define        TTYPE_CONFIG      13
                     49: #define        TTYPE_CMD         14
                     50: #define        TTYPE_INCLUDE     15
1.17      kristaps   51: #define        TTYPE_SYMB        16
                     52: #define        TTYPE_SYMBOL      17
                     53: #define        TTYPE_NMAX        18
1.10      kristaps   54:
                     55: /*
                     56:  * These define "styles" for element types, like command arguments or
                     57:  * executable names.  This is useful when multiple macros must decorate
                     58:  * the same thing (like .Ex -std cmd and .Nm cmd).
                     59:  */
                     60:
                     61: const  int ttypes[TTYPE_NMAX] = {
                     62:        TERMP_BOLD,             /* TTYPE_PROG */
                     63:        TERMP_BOLD,             /* TTYPE_CMD_FLAG */
                     64:        TERMP_UNDERLINE,        /* TTYPE_CMD_ARG */
                     65:        TERMP_BOLD,             /* TTYPE_SECTION */
                     66:        TERMP_BOLD,             /* TTYPE_FUNC_DECL */
                     67:        TERMP_UNDERLINE,        /* TTYPE_VAR_DECL */
                     68:        TERMP_UNDERLINE,        /* TTYPE_FUNC_TYPE */
                     69:        TERMP_BOLD,             /* TTYPE_FUNC_NAME */
                     70:        TERMP_UNDERLINE,        /* TTYPE_FUNC_ARG */
                     71:        TERMP_UNDERLINE,        /* TTYPE_LINK */
                     72:        TERMP_BOLD,             /* TTYPE_SSECTION */
1.11      kristaps   73:        TERMP_UNDERLINE,        /* TTYPE_FILE */
1.14      kristaps   74:        TERMP_UNDERLINE,        /* TTYPE_EMPH */
                     75:        TERMP_BOLD,             /* TTYPE_CONFIG */
                     76:        TERMP_BOLD,             /* TTYPE_CMD */
1.17      kristaps   77:        TERMP_BOLD,             /* TTYPE_INCLUDE */
                     78:        TERMP_BOLD,             /* TTYPE_SYMB */
                     79:        TERMP_BOLD              /* TTYPE_SYMBOL */
1.10      kristaps   80: };
1.7       kristaps   81:
1.10      kristaps   82: static int               arg_hasattr(int, size_t,
                     83:                                const struct mdoc_arg *);
                     84: static int               arg_getattr(int, size_t,
                     85:                                const struct mdoc_arg *);
1.12      kristaps   86: static size_t            arg_offset(const struct mdoc_arg *);
                     87: static size_t            arg_width(const struct mdoc_arg *);
1.10      kristaps   88:
                     89: /*
                     90:  * What follows describes prefix and postfix operations for the abstract
                     91:  * syntax tree descent.
                     92:  */
1.1       kristaps   93:
1.10      kristaps   94: #define        DECL_ARGS \
                     95:        struct termp *p, \
1.18      kristaps   96:        struct termpair *pair, \
1.10      kristaps   97:        const struct mdoc_meta *meta, \
                     98:        const struct mdoc_node *node
                     99:
                    100: #define        DECL_PRE(name) \
                    101: static int               name##_pre(DECL_ARGS)
                    102: #define        DECL_POST(name) \
                    103: static void              name##_post(DECL_ARGS)
                    104: #define        DECL_PREPOST(name) \
                    105: DECL_PRE(name); \
                    106: DECL_POST(name);
                    107:
                    108: DECL_PREPOST(termp_aq);
1.12      kristaps  109: DECL_PREPOST(termp_bd);
1.15      kristaps  110: DECL_PREPOST(termp_bq);
1.10      kristaps  111: DECL_PREPOST(termp_d1);
                    112: DECL_PREPOST(termp_dq);
                    113: DECL_PREPOST(termp_fd);
                    114: DECL_PREPOST(termp_fn);
1.16      kristaps  115: DECL_PREPOST(termp_fo);
1.10      kristaps  116: DECL_PREPOST(termp_ft);
                    117: DECL_PREPOST(termp_it);
                    118: DECL_PREPOST(termp_op);
                    119: DECL_PREPOST(termp_pf);
1.15      kristaps  120: DECL_PREPOST(termp_pq);
1.10      kristaps  121: DECL_PREPOST(termp_qq);
                    122: DECL_PREPOST(termp_sh);
                    123: DECL_PREPOST(termp_ss);
                    124: DECL_PREPOST(termp_sq);
                    125: DECL_PREPOST(termp_vt);
                    126:
1.18      kristaps  127: DECL_PRE(termp_ar);
1.14      kristaps  128: DECL_PRE(termp_at);
1.18      kristaps  129: DECL_PRE(termp_bf);
1.15      kristaps  130: DECL_PRE(termp_bsx);
1.17      kristaps  131: DECL_PRE(termp_bt);
1.10      kristaps  132: DECL_PRE(termp_bx);
1.18      kristaps  133: DECL_PRE(termp_cd);
                    134: DECL_PRE(termp_cm);
                    135: DECL_PRE(termp_em);
1.10      kristaps  136: DECL_PRE(termp_ex);
1.18      kristaps  137: DECL_PRE(termp_fa);
                    138: DECL_PRE(termp_fl);
1.16      kristaps  139: DECL_PRE(termp_fx);
1.18      kristaps  140: DECL_PRE(termp_ic);
                    141: DECL_PRE(termp_in);
                    142: DECL_PRE(termp_ms);
1.10      kristaps  143: DECL_PRE(termp_nd);
1.18      kristaps  144: DECL_PRE(termp_nm);
1.10      kristaps  145: DECL_PRE(termp_ns);
                    146: DECL_PRE(termp_nx);
                    147: DECL_PRE(termp_ox);
1.18      kristaps  148: DECL_PRE(termp_pa);
1.10      kristaps  149: DECL_PRE(termp_pp);
1.14      kristaps  150: DECL_PRE(termp_rv);
                    151: DECL_PRE(termp_st);
1.18      kristaps  152: DECL_PRE(termp_sx);
                    153: DECL_PRE(termp_sy);
1.10      kristaps  154: DECL_PRE(termp_ud);
1.16      kristaps  155: DECL_PRE(termp_ux);
1.18      kristaps  156: DECL_PRE(termp_va);
1.10      kristaps  157: DECL_PRE(termp_xr);
                    158:
                    159: DECL_POST(termp_bl);
                    160:
                    161: const  struct termact __termacts[MDOC_MAX] = {
                    162:        { NULL, NULL }, /* \" */
                    163:        { NULL, NULL }, /* Dd */
                    164:        { NULL, NULL }, /* Dt */
                    165:        { NULL, NULL }, /* Os */
                    166:        { termp_sh_pre, termp_sh_post }, /* Sh */
                    167:        { termp_ss_pre, termp_ss_post }, /* Ss */
                    168:        { termp_pp_pre, NULL }, /* Pp */
                    169:        { termp_d1_pre, termp_d1_post }, /* D1 */
                    170:        { NULL, NULL }, /* Dl */
1.12      kristaps  171:        { termp_bd_pre, termp_bd_post }, /* Bd */
1.10      kristaps  172:        { NULL, NULL }, /* Ed */
                    173:        { NULL, termp_bl_post }, /* Bl */
                    174:        { NULL, NULL }, /* El */
                    175:        { termp_it_pre, termp_it_post }, /* It */
                    176:        { NULL, NULL }, /* Ad */
                    177:        { NULL, NULL }, /* An */
1.18      kristaps  178:        { termp_ar_pre, NULL }, /* Ar */
                    179:        { termp_cd_pre, NULL }, /* Cd */
                    180:        { termp_cm_pre, NULL }, /* Cm */
1.10      kristaps  181:        { NULL, NULL }, /* Dv */
                    182:        { NULL, NULL }, /* Er */
                    183:        { NULL, NULL }, /* Ev */
                    184:        { termp_ex_pre, NULL }, /* Ex */
1.18      kristaps  185:        { termp_fa_pre, NULL }, /* Fa */
1.10      kristaps  186:        { termp_fd_pre, termp_fd_post }, /* Fd */
1.18      kristaps  187:        { termp_fl_pre, NULL }, /* Fl */
1.10      kristaps  188:        { termp_fn_pre, termp_fn_post }, /* Fn */
                    189:        { termp_ft_pre, termp_ft_post }, /* Ft */
1.18      kristaps  190:        { termp_ic_pre, NULL }, /* Ic */
                    191:        { termp_in_pre, NULL }, /* In */
1.10      kristaps  192:        { NULL, NULL }, /* Li */
                    193:        { termp_nd_pre, NULL }, /* Nd */
1.18      kristaps  194:        { termp_nm_pre, NULL }, /* Nm */
1.10      kristaps  195:        { termp_op_pre, termp_op_post }, /* Op */
                    196:        { NULL, NULL }, /* Ot */
1.18      kristaps  197:        { termp_pa_pre, NULL }, /* Pa */
1.14      kristaps  198:        { termp_rv_pre, NULL }, /* Rv */
                    199:        { termp_st_pre, NULL }, /* St */
1.18      kristaps  200:        { termp_va_pre, NULL }, /* Va */
1.10      kristaps  201:        { termp_vt_pre, termp_vt_post }, /* Vt */
                    202:        { termp_xr_pre, NULL }, /* Xr */
                    203:        { NULL, NULL }, /* %A */
                    204:        { NULL, NULL }, /* %B */
                    205:        { NULL, NULL }, /* %D */
                    206:        { NULL, NULL }, /* %I */
                    207:        { NULL, NULL }, /* %J */
                    208:        { NULL, NULL }, /* %N */
                    209:        { NULL, NULL }, /* %O */
                    210:        { NULL, NULL }, /* %P */
                    211:        { NULL, NULL }, /* %R */
                    212:        { NULL, NULL }, /* %T */
                    213:        { NULL, NULL }, /* %V */
                    214:        { NULL, NULL }, /* Ac */
1.14      kristaps  215:        { termp_aq_pre, termp_aq_post }, /* Ao */
1.10      kristaps  216:        { termp_aq_pre, termp_aq_post }, /* Aq */
1.14      kristaps  217:        { termp_at_pre, NULL }, /* At */
1.10      kristaps  218:        { NULL, NULL }, /* Bc */
1.18      kristaps  219:        { termp_bf_pre, NULL }, /* Bf */
1.15      kristaps  220:        { termp_bq_pre, termp_bq_post }, /* Bo */
                    221:        { termp_bq_pre, termp_bq_post }, /* Bq */
                    222:        { termp_bsx_pre, NULL }, /* Bsx */
1.10      kristaps  223:        { termp_bx_pre, NULL }, /* Bx */
                    224:        { NULL, NULL }, /* Db */
                    225:        { NULL, NULL }, /* Dc */
1.15      kristaps  226:        { termp_dq_pre, termp_dq_post }, /* Do */
1.10      kristaps  227:        { termp_dq_pre, termp_dq_post }, /* Dq */
                    228:        { NULL, NULL }, /* Ec */
                    229:        { NULL, NULL }, /* Ef */
1.18      kristaps  230:        { termp_em_pre, NULL }, /* Em */
1.10      kristaps  231:        { NULL, NULL }, /* Eo */
1.16      kristaps  232:        { termp_fx_pre, NULL }, /* Fx */
1.18      kristaps  233:        { termp_ms_pre, NULL }, /* Ms */
1.10      kristaps  234:        { NULL, NULL }, /* No */
                    235:        { termp_ns_pre, NULL }, /* Ns */
                    236:        { termp_nx_pre, NULL }, /* Nx */
                    237:        { termp_ox_pre, NULL }, /* Ox */
                    238:        { NULL, NULL }, /* Pc */
                    239:        { termp_pf_pre, termp_pf_post }, /* Pf */
1.15      kristaps  240:        { termp_pq_pre, termp_pq_post }, /* Po */
                    241:        { termp_pq_pre, termp_pq_post }, /* Pq */
1.10      kristaps  242:        { NULL, NULL }, /* Qc */
1.16      kristaps  243:        { termp_sq_pre, termp_sq_post }, /* Ql */
1.15      kristaps  244:        { termp_qq_pre, termp_qq_post }, /* Qo */
1.10      kristaps  245:        { termp_qq_pre, termp_qq_post }, /* Qq */
                    246:        { NULL, NULL }, /* Re */
                    247:        { NULL, NULL }, /* Rs */
                    248:        { NULL, NULL }, /* Sc */
1.15      kristaps  249:        { termp_sq_pre, termp_sq_post }, /* So */
1.10      kristaps  250:        { termp_sq_pre, termp_sq_post }, /* Sq */
                    251:        { NULL, NULL }, /* Sm */
1.18      kristaps  252:        { termp_sx_pre, NULL }, /* Sx */
                    253:        { termp_sy_pre, NULL }, /* Sy */
1.10      kristaps  254:        { NULL, NULL }, /* Tn */
1.16      kristaps  255:        { termp_ux_pre, NULL }, /* Ux */
1.10      kristaps  256:        { NULL, NULL }, /* Xc */
                    257:        { NULL, NULL }, /* Xo */
1.16      kristaps  258:        { termp_fo_pre, termp_fo_post }, /* Fo */
1.10      kristaps  259:        { NULL, NULL }, /* Fc */
1.16      kristaps  260:        { termp_op_pre, termp_op_post }, /* Oo */
1.10      kristaps  261:        { NULL, NULL }, /* Oc */
                    262:        { NULL, NULL }, /* Bk */
                    263:        { NULL, NULL }, /* Ek */
1.17      kristaps  264:        { termp_bt_pre, NULL }, /* Bt */
1.10      kristaps  265:        { NULL, NULL }, /* Hf */
                    266:        { NULL, NULL }, /* Fr */
                    267:        { termp_ud_pre, NULL }, /* Ud */
1.2       kristaps  268: };
                    269:
1.10      kristaps  270: const struct termact *termacts = __termacts;
                    271:
                    272:
                    273: static size_t
1.12      kristaps  274: arg_width(const struct mdoc_arg *arg)
1.10      kristaps  275: {
1.12      kristaps  276:
                    277:        /* TODO */
                    278:        assert(*arg->value);
                    279:        return(strlen(*arg->value));
                    280: }
                    281:
                    282:
                    283: static size_t
                    284: arg_offset(const struct mdoc_arg *arg)
                    285: {
                    286:
                    287:        /* TODO */
                    288:        assert(*arg->value);
                    289:        if (0 == strcmp(*arg->value, "indent"))
1.10      kristaps  290:                return(INDENT);
1.12      kristaps  291:        if (0 == strcmp(*arg->value, "indent-two"))
1.10      kristaps  292:                return(INDENT * 2);
                    293:
1.12      kristaps  294:        return(strlen(*arg->value));
1.10      kristaps  295: }
                    296:
1.3       kristaps  297:
1.10      kristaps  298: static int
                    299: arg_hasattr(int arg, size_t argc, const struct mdoc_arg *argv)
1.2       kristaps  300: {
                    301:
1.10      kristaps  302:        return(-1 != arg_getattr(arg, argc, argv));
                    303: }
                    304:
                    305:
                    306: static int
                    307: arg_getattr(int arg, size_t argc, const struct mdoc_arg *argv)
                    308: {
                    309:        int              i;
                    310:
                    311:        for (i = 0; i < (int)argc; i++)
                    312:                if (argv[i].arg == arg)
                    313:                        return(i);
                    314:        return(-1);
                    315: }
                    316:
                    317:
                    318: /* ARGSUSED */
                    319: static int
                    320: termp_dq_pre(DECL_ARGS)
                    321: {
                    322:
                    323:        if (MDOC_BODY != node->type)
                    324:                return(1);
                    325:
                    326:        word(p, "``");
                    327:        p->flags |= TERMP_NOSPACE;
                    328:        return(1);
                    329: }
                    330:
                    331:
                    332: /* ARGSUSED */
                    333: static void
                    334: termp_dq_post(DECL_ARGS)
                    335: {
                    336:
                    337:        if (MDOC_BODY != node->type)
                    338:                return;
1.3       kristaps  339:
1.10      kristaps  340:        p->flags |= TERMP_NOSPACE;
                    341:        word(p, "''");
                    342: }
1.2       kristaps  343:
1.3       kristaps  344:
1.10      kristaps  345: /* ARGSUSED */
1.20    ! kristaps  346: static int
        !           347: termp_it_pre(DECL_ARGS)
1.10      kristaps  348: {
                    349:        const struct mdoc_node *n, *it;
                    350:        const struct mdoc_block *bl;
                    351:        int              i;
1.12      kristaps  352:        size_t           width, offset;
1.2       kristaps  353:
1.10      kristaps  354:        switch (node->type) {
                    355:        case (MDOC_BODY):
                    356:                /* FALLTHROUGH */
                    357:        case (MDOC_HEAD):
1.20    ! kristaps  358:                it = node->parent;
        !           359:                break;
        !           360:        case (MDOC_BLOCK):
        !           361:                it = node;
1.10      kristaps  362:                break;
                    363:        default:
1.20    ! kristaps  364:                return(1);
1.8       kristaps  365:        }
                    366:
1.10      kristaps  367:        assert(MDOC_BLOCK == it->type);
                    368:        assert(MDOC_It == it->tok);
                    369:
                    370:        n = it->parent;
                    371:        assert(MDOC_BODY == n->type);
                    372:        assert(MDOC_Bl == n->tok);
                    373:        n = n->parent;
                    374:        bl = &n->data.block;
                    375:
1.20    ! kristaps  376:        /* If `-compact', don't assert vertical space. */
        !           377:
        !           378:        if (MDOC_BLOCK == node->type) {
        !           379:                if (arg_hasattr(MDOC_Compact, bl->argc, bl->argv))
        !           380:                        newln(p);
        !           381:                else
        !           382:                        vspace(p);
        !           383:                return(1);
        !           384:        }
        !           385:
        !           386:        pair->offset = p->offset;
        !           387:        pair->rmargin = p->rmargin;
        !           388:
        !           389:        /* FIXME: auto-size. */
        !           390:        i = arg_getattr(MDOC_Width, bl->argc, bl->argv);
        !           391:        width = i >= 0 ? arg_width(&bl->argv[i]) : 10;
        !           392:
        !           393:        i = arg_getattr(MDOC_Offset, bl->argc, bl->argv);
        !           394:        offset = i >= 0 ? arg_offset(&bl->argv[i]) : 0;
        !           395:
        !           396:        assert(MDOC_HEAD == node->type ||
        !           397:                        MDOC_BODY == node->type);
1.10      kristaps  398:
                    399:        if (arg_hasattr(MDOC_Tag, bl->argc, bl->argv)) {
1.20    ! kristaps  400:                p->flags |= TERMP_NOSPACE;
1.10      kristaps  401:
                    402:                if (MDOC_HEAD == node->type) {
1.20    ! kristaps  403:                        p->flags |= TERMP_NOBREAK;
        !           404:                        p->offset += offset;
        !           405:                        p->rmargin = p->offset + width;
1.10      kristaps  406:                } else {
1.20    ! kristaps  407:                        p->flags |= TERMP_NOLPAD;
        !           408:                        p->offset += width;
1.2       kristaps  409:                }
1.20    ! kristaps  410:
        !           411:        } else if (arg_hasattr(MDOC_Ohang, bl->argc, bl->argv)) {
        !           412:                p->flags |= TERMP_NOSPACE;
        !           413:                p->offset += offset;
1.10      kristaps  414:        }
1.2       kristaps  415:
1.20    ! kristaps  416:        return(1);
1.10      kristaps  417: }
                    418:
                    419:
                    420: /* ARGSUSED */
1.20    ! kristaps  421: static void
        !           422: termp_it_post(DECL_ARGS)
1.10      kristaps  423: {
                    424:        const struct mdoc_node *n, *it;
                    425:        const struct mdoc_block *bl;
1.3       kristaps  426:
1.10      kristaps  427:        switch (node->type) {
                    428:        case (MDOC_BODY):
                    429:                /* FALLTHROUGH */
                    430:        case (MDOC_HEAD):
                    431:                break;
                    432:        default:
1.20    ! kristaps  433:                return;
1.10      kristaps  434:        }
                    435:
1.20    ! kristaps  436:        it = node->parent;
1.10      kristaps  437:        assert(MDOC_BLOCK == it->type);
                    438:        assert(MDOC_It == it->tok);
                    439:
                    440:        n = it->parent;
                    441:        assert(MDOC_BODY == n->type);
                    442:        assert(MDOC_Bl == n->tok);
                    443:        n = n->parent;
                    444:        bl = &n->data.block;
                    445:
                    446:        /* If `-tag', adjust our margins accordingly. */
                    447:
                    448:        if (arg_hasattr(MDOC_Tag, bl->argc, bl->argv)) {
1.20    ! kristaps  449:                flushln(p);
1.10      kristaps  450:
                    451:                if (MDOC_HEAD == node->type) {
1.20    ! kristaps  452:                        p->rmargin = pair->rmargin;
        !           453:                        p->offset = pair->offset;
        !           454:                        p->flags &= ~TERMP_NOBREAK;
1.10      kristaps  455:                } else {
1.20    ! kristaps  456:                        p->offset = pair->offset;
        !           457:                        p->flags &= ~TERMP_NOLPAD;
1.10      kristaps  458:                }
                    459:
1.20    ! kristaps  460:        } else if (arg_hasattr(MDOC_Ohang, bl->argc, bl->argv)) {
        !           461:                flushln(p);
        !           462:                p->offset = pair->offset;
1.10      kristaps  463:        }
1.2       kristaps  464: }
                    465:
                    466:
1.10      kristaps  467: /* ARGSUSED */
1.18      kristaps  468: static int
                    469: termp_nm_pre(DECL_ARGS)
1.10      kristaps  470: {
                    471:
1.18      kristaps  472:        TERMPAIR_SETFLAG(pair, ttypes[TTYPE_PROG]);
                    473:        if (NULL == node->child)
                    474:                word(p, meta->name);
                    475:        return(1);
1.10      kristaps  476: }
                    477:
                    478:
                    479: /* ARGSUSED */
1.18      kristaps  480: static int
                    481: termp_fl_pre(DECL_ARGS)
1.10      kristaps  482: {
                    483:
1.18      kristaps  484:        TERMPAIR_SETFLAG(pair, ttypes[TTYPE_CMD_FLAG]);
                    485:        word(p, "\\-");
                    486:        p->flags |= TERMP_NOSPACE;
                    487:        return(1);
1.10      kristaps  488: }
                    489:
                    490:
                    491: /* ARGSUSED */
                    492: static int
                    493: termp_ar_pre(DECL_ARGS)
                    494: {
                    495:
1.18      kristaps  496:        TERMPAIR_SETFLAG(pair, ttypes[TTYPE_CMD_ARG]);
1.10      kristaps  497:        if (NULL == node->child)
                    498:                word(p, "...");
                    499:        return(1);
                    500: }
                    501:
                    502:
                    503: /* ARGSUSED */
                    504: static int
                    505: termp_ns_pre(DECL_ARGS)
1.2       kristaps  506: {
                    507:
                    508:        p->flags |= TERMP_NOSPACE;
1.10      kristaps  509:        return(1);
                    510: }
                    511:
                    512:
                    513: /* ARGSUSED */
                    514: static int
                    515: termp_pp_pre(DECL_ARGS)
                    516: {
                    517:
                    518:        vspace(p);
                    519:        return(1);
                    520: }
                    521:
                    522:
                    523: /* ARGSUSED */
                    524: static int
1.14      kristaps  525: termp_st_pre(DECL_ARGS)
                    526: {
                    527:        const char      *tp;
                    528:
                    529:        assert(1 == node->data.elem.argc);
                    530:
                    531:        tp = mdoc_st2a(node->data.elem.argv[0].arg);
                    532:        word(p, tp);
                    533:
                    534:        return(1);
                    535: }
                    536:
                    537:
                    538: /* ARGSUSED */
                    539: static int
                    540: termp_rv_pre(DECL_ARGS)
                    541: {
                    542:        int              i;
                    543:
                    544:        i = arg_getattr(MDOC_Std, node->data.elem.argc,
                    545:                        node->data.elem.argv);
                    546:        assert(i >= 0);
                    547:
                    548:        newln(p);
                    549:        word(p, "The");
                    550:
                    551:        p->flags |= ttypes[TTYPE_FUNC_NAME];
                    552:        word(p, *node->data.elem.argv[i].value);
                    553:        p->flags &= ~ttypes[TTYPE_FUNC_NAME];
                    554:
                    555:                word(p, "() function returns the value 0 if successful;");
                    556:                word(p, "otherwise the value -1 is returned and the");
                    557:                word(p, "global variable");
                    558:
                    559:        p->flags |= ttypes[TTYPE_VAR_DECL];
                    560:        word(p, "errno");
                    561:        p->flags &= ~ttypes[TTYPE_VAR_DECL];
                    562:
                    563:                word(p, "is set to indicate the error.");
                    564:
                    565:        return(1);
                    566: }
                    567:
                    568:
                    569: /* ARGSUSED */
                    570: static int
1.10      kristaps  571: termp_ex_pre(DECL_ARGS)
                    572: {
                    573:        int              i;
                    574:
                    575:        i = arg_getattr(MDOC_Std, node->data.elem.argc,
                    576:                        node->data.elem.argv);
                    577:        assert(i >= 0);
                    578:
                    579:        word(p, "The");
                    580:        p->flags |= ttypes[TTYPE_PROG];
                    581:        word(p, *node->data.elem.argv[i].value);
                    582:        p->flags &= ~ttypes[TTYPE_PROG];
                    583:                word(p, "utility exits 0 on success, and >0 if an error occurs.");
                    584:
                    585:        return(1);
                    586: }
                    587:
                    588:
                    589: /* ARGSUSED */
                    590: static int
                    591: termp_nd_pre(DECL_ARGS)
                    592: {
                    593:
                    594:        word(p, "\\-");
                    595:        return(1);
                    596: }
                    597:
                    598:
                    599: /* ARGSUSED */
                    600: static void
                    601: termp_bl_post(DECL_ARGS)
                    602: {
                    603:
                    604:        if (MDOC_BLOCK == node->type)
                    605:                newln(p);
                    606: }
                    607:
                    608:
                    609: /* ARGSUSED */
                    610: static void
                    611: termp_op_post(DECL_ARGS)
                    612: {
                    613:
                    614:        if (MDOC_BODY != node->type)
1.2       kristaps  615:                return;
1.10      kristaps  616:        p->flags |= TERMP_NOSPACE;
                    617:        word(p, "\\(rB");
                    618: }
                    619:
                    620:
                    621: /* ARGSUSED */
                    622: static int
                    623: termp_xr_pre(DECL_ARGS)
                    624: {
                    625:        const struct mdoc_node *n;
                    626:
                    627:        n = node->child;
                    628:        assert(n);
                    629:
                    630:        assert(MDOC_TEXT == n->type);
                    631:        word(p, n->data.text.string);
                    632:
                    633:        if (NULL == (n = n->next))
                    634:                return(0);
                    635:
                    636:        assert(MDOC_TEXT == n->type);
                    637:        p->flags |= TERMP_NOSPACE;
                    638:        word(p, "(");
                    639:        p->flags |= TERMP_NOSPACE;
                    640:        word(p, n->data.text.string);
                    641:        p->flags |= TERMP_NOSPACE;
                    642:        word(p, ")");
                    643:
                    644:        return(0);
1.2       kristaps  645: }
                    646:
                    647:
1.10      kristaps  648: /* ARGSUSED */
                    649: static int
                    650: termp_vt_pre(DECL_ARGS)
1.2       kristaps  651: {
                    652:
1.10      kristaps  653:        /* FIXME: this can be "type name". */
1.18      kristaps  654:        TERMPAIR_SETFLAG(pair, ttypes[TTYPE_VAR_DECL]);
1.10      kristaps  655:        return(1);
1.2       kristaps  656: }
                    657:
                    658:
1.10      kristaps  659: /* ARGSUSED */
1.2       kristaps  660: static void
1.10      kristaps  661: termp_vt_post(DECL_ARGS)
                    662: {
                    663:
                    664:        if (node->sec == SEC_SYNOPSIS)
                    665:                vspace(p);
                    666: }
                    667:
                    668:
                    669: /* ARGSUSED */
                    670: static int
                    671: termp_fd_pre(DECL_ARGS)
1.2       kristaps  672: {
                    673:
1.10      kristaps  674:        /*
                    675:         * FIXME: this naming is bad.  This value is used, in general,
                    676:         * for the #include header or other preprocessor statement.
                    677:         */
1.18      kristaps  678:        TERMPAIR_SETFLAG(pair, ttypes[TTYPE_FUNC_DECL]);
1.10      kristaps  679:        return(1);
1.2       kristaps  680: }
                    681:
                    682:
1.10      kristaps  683: /* ARGSUSED */
1.2       kristaps  684: static void
1.10      kristaps  685: termp_fd_post(DECL_ARGS)
1.2       kristaps  686: {
                    687:
1.10      kristaps  688:        if (node->sec == SEC_SYNOPSIS)
                    689:                vspace(p);
                    690: }
                    691:
                    692:
                    693: /* ARGSUSED */
                    694: static int
                    695: termp_sh_pre(DECL_ARGS)
                    696: {
1.2       kristaps  697:
1.10      kristaps  698:        switch (node->type) {
                    699:        case (MDOC_HEAD):
                    700:                vspace(p);
1.18      kristaps  701:                TERMPAIR_SETFLAG(pair, ttypes[TTYPE_SECTION]);
1.2       kristaps  702:                break;
1.10      kristaps  703:        case (MDOC_BODY):
                    704:                p->offset = INDENT;
1.2       kristaps  705:                break;
1.10      kristaps  706:        default:
                    707:                break;
                    708:        }
                    709:        return(1);
                    710: }
                    711:
                    712:
                    713: /* ARGSUSED */
1.19      kristaps  714: static void
                    715: termp_sh_post(DECL_ARGS)
                    716: {
                    717:
                    718:        switch (node->type) {
                    719:        case (MDOC_HEAD):
                    720:                newln(p);
                    721:                break;
                    722:        case (MDOC_BODY):
                    723:                newln(p);
                    724:                p->offset = 0;
                    725:                break;
                    726:        default:
                    727:                break;
                    728:        }
                    729: }
                    730:
                    731:
                    732: /* ARGSUSED */
1.10      kristaps  733: static int
                    734: termp_op_pre(DECL_ARGS)
                    735: {
                    736:
                    737:        switch (node->type) {
                    738:        case (MDOC_BODY):
                    739:                word(p, "\\(lB");
                    740:                p->flags |= TERMP_NOSPACE;
1.2       kristaps  741:                break;
                    742:        default:
1.10      kristaps  743:                break;
1.2       kristaps  744:        }
1.10      kristaps  745:        return(1);
                    746: }
                    747:
                    748:
                    749: /* ARGSUSED */
                    750: static int
1.17      kristaps  751: termp_bt_pre(DECL_ARGS)
                    752: {
                    753:
                    754:        word(p, "is currently in beta test.");
                    755:        return(1);
                    756: }
                    757:
                    758:
                    759: /* ARGSUSED */
                    760: static int
1.10      kristaps  761: termp_ud_pre(DECL_ARGS)
                    762: {
                    763:
                    764:        word(p, "currently under development.");
                    765:        return(1);
                    766: }
                    767:
                    768:
                    769: /* ARGSUSED */
                    770: static int
                    771: termp_d1_pre(DECL_ARGS)
                    772: {
                    773:
                    774:        if (MDOC_BODY != node->type)
                    775:                return(1);
                    776:        newln(p);
1.19      kristaps  777:        p->offset += (pair->offset = INDENT);
1.10      kristaps  778:        return(1);
1.2       kristaps  779: }
                    780:
                    781:
1.10      kristaps  782: /* ARGSUSED */
1.2       kristaps  783: static void
1.10      kristaps  784: termp_d1_post(DECL_ARGS)
                    785: {
                    786:
                    787:        if (MDOC_BODY != node->type)
                    788:                return;
                    789:        newln(p);
1.19      kristaps  790:        p->offset -= pair->offset;
1.10      kristaps  791: }
                    792:
                    793:
                    794: /* ARGSUSED */
                    795: static int
                    796: termp_aq_pre(DECL_ARGS)
1.6       kristaps  797: {
                    798:
1.10      kristaps  799:        if (MDOC_BODY != node->type)
                    800:                return(1);
                    801:        word(p, "<");
                    802:        p->flags |= TERMP_NOSPACE;
                    803:        return(1);
                    804: }
1.6       kristaps  805:
                    806:
1.10      kristaps  807: /* ARGSUSED */
                    808: static void
                    809: termp_aq_post(DECL_ARGS)
                    810: {
1.6       kristaps  811:
1.10      kristaps  812:        if (MDOC_BODY != node->type)
1.6       kristaps  813:                return;
1.10      kristaps  814:        p->flags |= TERMP_NOSPACE;
                    815:        word(p, ">");
                    816: }
1.6       kristaps  817:
1.10      kristaps  818:
                    819: /* ARGSUSED */
                    820: static int
                    821: termp_ft_pre(DECL_ARGS)
                    822: {
                    823:
1.18      kristaps  824:        TERMPAIR_SETFLAG(pair, ttypes[TTYPE_FUNC_TYPE]);
1.10      kristaps  825:        return(1);
1.6       kristaps  826: }
                    827:
                    828:
1.10      kristaps  829: /* ARGSUSED */
1.6       kristaps  830: static void
1.10      kristaps  831: termp_ft_post(DECL_ARGS)
1.2       kristaps  832: {
                    833:
1.10      kristaps  834:        if (node->sec == SEC_SYNOPSIS)
                    835:                newln(p);
                    836: }
1.2       kristaps  837:
                    838:
1.10      kristaps  839: /* ARGSUSED */
                    840: static int
                    841: termp_fn_pre(DECL_ARGS)
                    842: {
                    843:        const struct mdoc_node *n;
                    844:
                    845:        assert(node->child);
                    846:        assert(MDOC_TEXT == node->child->type);
1.2       kristaps  847:
1.10      kristaps  848:        /* FIXME: can be "type funcname" "type varname"... */
1.2       kristaps  849:
1.10      kristaps  850:        p->flags |= ttypes[TTYPE_FUNC_NAME];
                    851:        word(p, node->child->data.text.string);
                    852:        p->flags &= ~ttypes[TTYPE_FUNC_NAME];
                    853:
                    854:        word(p, "(");
                    855:
                    856:        p->flags |= TERMP_NOSPACE;
                    857:        for (n = node->child->next; n; n = n->next) {
                    858:                assert(MDOC_TEXT == n->type);
                    859:                p->flags |= ttypes[TTYPE_FUNC_ARG];
                    860:                word(p, n->data.text.string);
                    861:                p->flags &= ~ttypes[TTYPE_FUNC_ARG];
1.16      kristaps  862:                if (n->next)
1.10      kristaps  863:                        word(p, ",");
1.6       kristaps  864:        }
1.2       kristaps  865:
1.10      kristaps  866:        word(p, ")");
                    867:
                    868:        if (SEC_SYNOPSIS == node->sec)
                    869:                word(p, ";");
                    870:
                    871:        return(0);
1.2       kristaps  872: }
                    873:
                    874:
1.10      kristaps  875: /* ARGSUSED */
                    876: static void
                    877: termp_fn_post(DECL_ARGS)
1.2       kristaps  878: {
                    879:
1.10      kristaps  880:        if (node->sec == SEC_SYNOPSIS)
                    881:                vspace(p);
                    882:
                    883: }
1.2       kristaps  884:
                    885:
1.10      kristaps  886: /* ARGSUSED */
                    887: static int
                    888: termp_sx_pre(DECL_ARGS)
                    889: {
1.8       kristaps  890:
1.18      kristaps  891:        TERMPAIR_SETFLAG(pair, ttypes[TTYPE_LINK]);
1.10      kristaps  892:        return(1);
1.2       kristaps  893: }
                    894:
                    895:
1.10      kristaps  896: /* ARGSUSED */
                    897: static int
                    898: termp_fa_pre(DECL_ARGS)
                    899: {
1.16      kristaps  900:        struct mdoc_node *n;
                    901:
                    902:        if (node->parent->tok != MDOC_Fo) {
1.18      kristaps  903:                TERMPAIR_SETFLAG(pair, ttypes[TTYPE_FUNC_ARG]);
1.16      kristaps  904:                return(1);
                    905:        }
                    906:
                    907:        for (n = node->child; n; n = n->next) {
                    908:                assert(MDOC_TEXT == n->type);
                    909:
                    910:                p->flags |= ttypes[TTYPE_FUNC_ARG];
                    911:                word(p, n->data.text.string);
                    912:                p->flags &= ~ttypes[TTYPE_FUNC_ARG];
                    913:
                    914:                if (n->next)
                    915:                        word(p, ",");
                    916:        }
                    917:
                    918:        if (node->next && node->next->tok == MDOC_Fa)
                    919:                word(p, ",");
1.2       kristaps  920:
1.16      kristaps  921:        return(0);
1.10      kristaps  922: }
1.2       kristaps  923:
                    924:
1.10      kristaps  925: /* ARGSUSED */
                    926: static int
                    927: termp_va_pre(DECL_ARGS)
                    928: {
1.2       kristaps  929:
1.18      kristaps  930:        TERMPAIR_SETFLAG(pair, ttypes[TTYPE_VAR_DECL]);
1.10      kristaps  931:        return(1);
1.2       kristaps  932: }
                    933:
                    934:
1.10      kristaps  935: /* ARGSUSED */
                    936: static int
                    937: termp_bd_pre(DECL_ARGS)
                    938: {
                    939:        const struct mdoc_block *bl;
                    940:        const struct mdoc_node *n;
1.12      kristaps  941:        int              i;
1.1       kristaps  942:
1.10      kristaps  943:        if (MDOC_BLOCK == node->type) {
                    944:                vspace(p);
                    945:                return(1);
                    946:        } else if (MDOC_BODY != node->type)
                    947:                return(1);
                    948:
                    949:        assert(MDOC_BLOCK == node->parent->type);
1.20    ! kristaps  950:        pair->offset = p->offset;
1.10      kristaps  951:
                    952:        bl = &node->parent->data.block;
1.12      kristaps  953:
1.20    ! kristaps  954:
1.12      kristaps  955:        i = arg_getattr(MDOC_Offset, bl->argc, bl->argv);
                    956:        if (-1 != i) {
                    957:                assert(1 == bl->argv[i].sz);
1.20    ! kristaps  958:                p->offset += arg_offset(&bl->argv[i]);
1.12      kristaps  959:        }
                    960:
1.10      kristaps  961:        if ( ! arg_hasattr(MDOC_Literal, bl->argc, bl->argv))
                    962:                return(1);
                    963:
                    964:        p->flags |= TERMP_LITERAL;
                    965:
                    966:        for (n = node->child; n; n = n->next) {
                    967:                assert(MDOC_TEXT == n->type); /* FIXME */
                    968:                if ((*n->data.text.string)) {
                    969:                        word(p, n->data.text.string);
                    970:                        flushln(p);
                    971:                } else
                    972:                        vspace(p);
1.1       kristaps  973:
1.10      kristaps  974:        }
1.1       kristaps  975:
1.10      kristaps  976:        p->flags &= ~TERMP_LITERAL;
                    977:        return(0);
                    978: }
1.1       kristaps  979:
                    980:
1.10      kristaps  981: /* ARGSUSED */
1.12      kristaps  982: static void
                    983: termp_bd_post(DECL_ARGS)
                    984: {
                    985:
1.20    ! kristaps  986:        if (MDOC_BODY != node->type)
        !           987:                return;
        !           988:        newln(p);
        !           989:        p->offset = pair->offset;
1.12      kristaps  990: }
                    991:
                    992:
                    993: /* ARGSUSED */
1.10      kristaps  994: static int
                    995: termp_qq_pre(DECL_ARGS)
                    996: {
1.1       kristaps  997:
1.10      kristaps  998:        if (MDOC_BODY != node->type)
                    999:                return(1);
                   1000:        word(p, "\"");
                   1001:        p->flags |= TERMP_NOSPACE;
                   1002:        return(1);
1.1       kristaps 1003: }
                   1004:
                   1005:
1.10      kristaps 1006: /* ARGSUSED */
1.1       kristaps 1007: static void
1.10      kristaps 1008: termp_qq_post(DECL_ARGS)
1.1       kristaps 1009: {
                   1010:
1.10      kristaps 1011:        if (MDOC_BODY != node->type)
                   1012:                return;
                   1013:        p->flags |= TERMP_NOSPACE;
                   1014:        word(p, "\"");
                   1015: }
                   1016:
                   1017:
                   1018: /* ARGSUSED */
                   1019: static int
1.15      kristaps 1020: termp_bsx_pre(DECL_ARGS)
                   1021: {
                   1022:
                   1023:        word(p, "BSDI BSD/OS");
                   1024:        return(1);
                   1025: }
                   1026:
                   1027:
                   1028: /* ARGSUSED */
                   1029: static int
1.10      kristaps 1030: termp_bx_pre(DECL_ARGS)
                   1031: {
1.1       kristaps 1032:
1.10      kristaps 1033:        word(p, "BSD");
                   1034:        return(1);
                   1035: }
                   1036:
                   1037:
                   1038: /* ARGSUSED */
                   1039: static int
                   1040: termp_ox_pre(DECL_ARGS)
                   1041: {
                   1042:
                   1043:        word(p, "OpenBSD");
                   1044:        return(1);
                   1045: }
                   1046:
                   1047:
                   1048: /* ARGSUSED */
                   1049: static int
1.16      kristaps 1050: termp_ux_pre(DECL_ARGS)
                   1051: {
                   1052:
                   1053:        word(p, "UNIX");
                   1054:        return(1);
                   1055: }
                   1056:
                   1057:
                   1058: /* ARGSUSED */
                   1059: static int
                   1060: termp_fx_pre(DECL_ARGS)
                   1061: {
                   1062:
                   1063:        word(p, "FreeBSD");
                   1064:        return(1);
                   1065: }
                   1066:
                   1067:
                   1068: /* ARGSUSED */
                   1069: static int
1.10      kristaps 1070: termp_nx_pre(DECL_ARGS)
                   1071: {
                   1072:
                   1073:        word(p, "NetBSD");
                   1074:        return(1);
                   1075: }
                   1076:
                   1077:
                   1078: /* ARGSUSED */
                   1079: static int
                   1080: termp_sq_pre(DECL_ARGS)
                   1081: {
                   1082:
                   1083:        if (MDOC_BODY != node->type)
                   1084:                return(1);
1.13      kristaps 1085:        word(p, "\'");
1.10      kristaps 1086:        p->flags |= TERMP_NOSPACE;
                   1087:        return(1);
                   1088: }
1.1       kristaps 1089:
                   1090:
1.10      kristaps 1091: /* ARGSUSED */
                   1092: static void
                   1093: termp_sq_post(DECL_ARGS)
                   1094: {
                   1095:
                   1096:        if (MDOC_BODY != node->type)
                   1097:                return;
                   1098:        p->flags |= TERMP_NOSPACE;
                   1099:        word(p, "\'");
                   1100: }
1.2       kristaps 1101:
                   1102:
1.10      kristaps 1103: /* ARGSUSED */
                   1104: static int
                   1105: termp_pf_pre(DECL_ARGS)
                   1106: {
1.1       kristaps 1107:
1.10      kristaps 1108:        p->flags |= TERMP_IGNDELIM;
                   1109:        return(1);
                   1110: }
1.1       kristaps 1111:
                   1112:
1.10      kristaps 1113: /* ARGSUSED */
                   1114: static void
                   1115: termp_pf_post(DECL_ARGS)
                   1116: {
1.1       kristaps 1117:
1.10      kristaps 1118:        p->flags &= ~TERMP_IGNDELIM;
                   1119:        p->flags |= TERMP_NOSPACE;
                   1120: }
1.1       kristaps 1121:
                   1122:
1.10      kristaps 1123: /* ARGSUSED */
                   1124: static int
                   1125: termp_ss_pre(DECL_ARGS)
                   1126: {
1.1       kristaps 1127:
1.10      kristaps 1128:        switch (node->type) {
                   1129:        case (MDOC_HEAD):
                   1130:                vspace(p);
1.18      kristaps 1131:                TERMPAIR_SETFLAG(pair, ttypes[TTYPE_SSECTION]);
1.10      kristaps 1132:                p->offset = INDENT / 2;
                   1133:                break;
                   1134:        default:
                   1135:                break;
                   1136:        }
1.1       kristaps 1137:
1.10      kristaps 1138:        return(1);
1.1       kristaps 1139: }
                   1140:
                   1141:
1.10      kristaps 1142: /* ARGSUSED */
                   1143: static void
                   1144: termp_ss_post(DECL_ARGS)
1.1       kristaps 1145: {
                   1146:
1.10      kristaps 1147:        switch (node->type) {
                   1148:        case (MDOC_HEAD):
                   1149:                newln(p);
                   1150:                p->offset = INDENT;
                   1151:                break;
                   1152:        default:
                   1153:                break;
                   1154:        }
                   1155: }
1.2       kristaps 1156:
                   1157:
1.10      kristaps 1158: /* ARGSUSED */
                   1159: static int
                   1160: termp_pa_pre(DECL_ARGS)
                   1161: {
1.2       kristaps 1162:
1.18      kristaps 1163:        TERMPAIR_SETFLAG(pair, ttypes[TTYPE_FILE]);
1.10      kristaps 1164:        return(1);
1.1       kristaps 1165: }
                   1166:
                   1167:
1.10      kristaps 1168: /* ARGSUSED */
1.11      kristaps 1169: static int
                   1170: termp_em_pre(DECL_ARGS)
                   1171: {
                   1172:
1.18      kristaps 1173:        TERMPAIR_SETFLAG(pair, ttypes[TTYPE_EMPH]);
1.11      kristaps 1174:        return(1);
                   1175: }
                   1176:
                   1177:
                   1178: /* ARGSUSED */
1.14      kristaps 1179: static int
                   1180: termp_cd_pre(DECL_ARGS)
                   1181: {
                   1182:
1.18      kristaps 1183:        TERMPAIR_SETFLAG(pair, ttypes[TTYPE_CONFIG]);
1.14      kristaps 1184:        return(1);
                   1185: }
                   1186:
                   1187:
                   1188: /* ARGSUSED */
                   1189: static int
                   1190: termp_cm_pre(DECL_ARGS)
                   1191: {
                   1192:
1.18      kristaps 1193:        TERMPAIR_SETFLAG(pair, ttypes[TTYPE_CMD_FLAG]);
1.14      kristaps 1194:        return(1);
                   1195: }
                   1196:
                   1197:
                   1198: /* ARGSUSED */
                   1199: static int
                   1200: termp_ic_pre(DECL_ARGS)
                   1201: {
                   1202:
1.18      kristaps 1203:        TERMPAIR_SETFLAG(pair, ttypes[TTYPE_CMD]);
1.14      kristaps 1204:        return(1);
                   1205: }
                   1206:
                   1207:
                   1208: /* ARGSUSED */
                   1209: static int
                   1210: termp_in_pre(DECL_ARGS)
                   1211: {
                   1212:
1.18      kristaps 1213:        TERMPAIR_SETFLAG(pair, ttypes[TTYPE_INCLUDE]);
1.14      kristaps 1214:        return(1);
                   1215: }
                   1216:
                   1217:
                   1218: /* ARGSUSED */
                   1219: static int
                   1220: termp_at_pre(DECL_ARGS)
                   1221: {
                   1222:        enum mdoc_att    c;
                   1223:
                   1224:        c = ATT_DEFAULT;
                   1225:        if (node->child) {
                   1226:                assert(MDOC_TEXT == node->child->type);
                   1227:                c = mdoc_atoatt(node->child->data.text.string);
                   1228:        }
                   1229:
                   1230:        word(p, mdoc_att2a(c));
                   1231:        return(0);
                   1232: }
1.15      kristaps 1233:
                   1234:
                   1235: /* ARGSUSED */
                   1236: static int
                   1237: termp_bq_pre(DECL_ARGS)
                   1238: {
                   1239:
                   1240:        if (MDOC_BODY != node->type)
                   1241:                return(1);
                   1242:        word(p, "[");
                   1243:        p->flags |= TERMP_NOSPACE;
                   1244:        return(1);
                   1245: }
                   1246:
                   1247:
                   1248: /* ARGSUSED */
                   1249: static void
                   1250: termp_bq_post(DECL_ARGS)
                   1251: {
                   1252:
                   1253:        if (MDOC_BODY != node->type)
                   1254:                return;
                   1255:        word(p, "]");
                   1256: }
                   1257:
                   1258:
                   1259: /* ARGSUSED */
                   1260: static int
                   1261: termp_pq_pre(DECL_ARGS)
                   1262: {
                   1263:
                   1264:        if (MDOC_BODY != node->type)
                   1265:                return(1);
                   1266:        word(p, "(");
                   1267:        p->flags |= TERMP_NOSPACE;
                   1268:        return(1);
                   1269: }
                   1270:
                   1271:
                   1272: /* ARGSUSED */
                   1273: static void
                   1274: termp_pq_post(DECL_ARGS)
                   1275: {
                   1276:
                   1277:        if (MDOC_BODY != node->type)
                   1278:                return;
                   1279:        word(p, ")");
                   1280: }
                   1281:
                   1282:
1.16      kristaps 1283: /* ARGSUSED */
                   1284: static int
                   1285: termp_fo_pre(DECL_ARGS)
                   1286: {
                   1287:        const struct mdoc_node *n;
                   1288:
                   1289:        if (MDOC_BODY == node->type) {
                   1290:                word(p, "(");
                   1291:                p->flags |= TERMP_NOSPACE;
                   1292:                return(1);
                   1293:        } else if (MDOC_HEAD != node->type)
                   1294:                return(1);
                   1295:
1.17      kristaps 1296:        /* XXX - groff shows only first parameter */
                   1297:
1.16      kristaps 1298:        p->flags |= ttypes[TTYPE_FUNC_NAME];
                   1299:        for (n = node->child; n; n = n->next) {
                   1300:                assert(MDOC_TEXT == n->type);
                   1301:                word(p, n->data.text.string);
                   1302:        }
                   1303:        p->flags &= ~ttypes[TTYPE_FUNC_NAME];
                   1304:
                   1305:        return(0);
                   1306: }
                   1307:
                   1308:
                   1309: /* ARGSUSED */
                   1310: static void
                   1311: termp_fo_post(DECL_ARGS)
                   1312: {
                   1313:
                   1314:        if (MDOC_BODY != node->type)
                   1315:                return;
                   1316:        word(p, ")");
                   1317:        word(p, ";");
                   1318:        newln(p);
                   1319: }
                   1320:
                   1321:
1.17      kristaps 1322: /* ARGSUSED */
                   1323: static int
                   1324: termp_bf_pre(DECL_ARGS)
                   1325: {
                   1326:        const struct mdoc_node  *n;
                   1327:        const struct mdoc_block *b;
                   1328:
                   1329:        /* XXX - we skip over possible trailing HEAD tokens. */
                   1330:
                   1331:        if (MDOC_HEAD == node->type)
                   1332:                return(0);
                   1333:        else if (MDOC_BLOCK != node->type)
                   1334:                return(1);
                   1335:
                   1336:        b = &node->data.block;
                   1337:
                   1338:        if (NULL == (n = b->head->child)) {
                   1339:                if (arg_hasattr(MDOC_Emphasis, b->argc, b->argv))
1.18      kristaps 1340:                        TERMPAIR_SETFLAG(pair, ttypes[TTYPE_EMPH]);
1.17      kristaps 1341:                else if (arg_hasattr(MDOC_Symbolic, b->argc, b->argv))
1.18      kristaps 1342:                        TERMPAIR_SETFLAG(pair, ttypes[TTYPE_SYMB]);
1.17      kristaps 1343:
                   1344:                return(1);
                   1345:        }
                   1346:
                   1347:        assert(MDOC_TEXT == n->type);
                   1348:
                   1349:        if (0 == strcmp("Em", n->data.text.string))
1.18      kristaps 1350:                TERMPAIR_SETFLAG(pair, ttypes[TTYPE_EMPH]);
1.17      kristaps 1351:        else if (0 == strcmp("Sy", n->data.text.string))
1.18      kristaps 1352:                TERMPAIR_SETFLAG(pair, ttypes[TTYPE_EMPH]);
1.17      kristaps 1353:
                   1354:        return(1);
                   1355: }
                   1356:
                   1357:
                   1358: /* ARGSUSED */
                   1359: static int
                   1360: termp_sy_pre(DECL_ARGS)
                   1361: {
                   1362:
1.18      kristaps 1363:        TERMPAIR_SETFLAG(pair, ttypes[TTYPE_SYMB]);
1.17      kristaps 1364:        return(1);
                   1365: }
                   1366:
                   1367:
                   1368: /* ARGSUSED */
                   1369: static int
                   1370: termp_ms_pre(DECL_ARGS)
                   1371: {
                   1372:
1.18      kristaps 1373:        TERMPAIR_SETFLAG(pair, ttypes[TTYPE_SYMBOL]);
1.17      kristaps 1374:        return(1);
                   1375: }
                   1376:

CVSweb