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

Annotation of mandoc/mdoc_man.c, Revision 1.2

1.2     ! schwarze    1: /*     $Id: mdoc_man.c,v 1.1 2011/09/17 15:00:51 schwarze Exp $ */
1.1       schwarze    2: /*
                      3:  * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
                      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 above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  */
                     17: #include <stdio.h>
                     18: #include <string.h>
                     19:
                     20: #include "mandoc.h"
                     21: #include "mdoc.h"
                     22: #include "main.h"
                     23:
                     24: static int       need_space = 0;
                     25: static int       need_nl = 0;
                     26:
                     27: #define        DECL_ARGS const struct mdoc_meta *m, \
                     28:                  const struct mdoc_node *n
                     29:
                     30: struct manact {
                     31:        int             (*cond)(DECL_ARGS);
                     32:        int             (*pre)(DECL_ARGS);
                     33:        void            (*post)(DECL_ARGS);
1.2     ! schwarze   34:        const char       *prefix;
        !            35:        const char       *suffix;
1.1       schwarze   36: };
                     37:
                     38: static void      print_word(const char *);
                     39: static void      print_node(DECL_ARGS);
                     40:
                     41: static int       cond_head(DECL_ARGS);
                     42: static int       cond_body(DECL_ARGS);
                     43: static int       pre_enc(DECL_ARGS);
                     44: static void      post_enc(DECL_ARGS);
                     45: static void      post_percent(DECL_ARGS);
                     46:
                     47: static int       pre_dl(DECL_ARGS);
                     48: static void      post_dl(DECL_ARGS);
                     49: static int       pre_it(DECL_ARGS);
                     50: static int       pre_nm(DECL_ARGS);
                     51: static void      post_nm(DECL_ARGS);
                     52: static int       pre_ns(DECL_ARGS);
                     53: static int       pre_pp(DECL_ARGS);
                     54: static int       pre_sh(DECL_ARGS);
                     55: static void      post_sh(DECL_ARGS);
                     56: static int       pre_xr(DECL_ARGS);
                     57:
                     58:
                     59: static const struct manact manacts[MDOC_MAX] = {
                     60:        { NULL, NULL, NULL, NULL, NULL }, /* _Ap */
                     61:        { NULL, NULL, NULL, NULL, NULL }, /* _Dd */
                     62:        { NULL, NULL, NULL, NULL, NULL }, /* _Dt */
                     63:        { NULL, NULL, NULL, NULL, NULL }, /* _Os */
                     64:        { NULL, pre_sh, post_sh, NULL, NULL }, /* Sh */
                     65:        { NULL, NULL, NULL, NULL, NULL }, /* _Ss */
                     66:        { NULL, pre_pp, NULL, NULL, NULL }, /* Pp */
                     67:        { NULL, NULL, NULL, NULL, NULL }, /* _D1 */
                     68:        { cond_body, pre_dl, post_dl, NULL, NULL }, /* Dl */
                     69:        { NULL, NULL, NULL, NULL, NULL }, /* _Bd */
                     70:        { NULL, NULL, NULL, NULL, NULL }, /* _Ed */
                     71:        { NULL, NULL, NULL, NULL, NULL }, /* _Bl */
                     72:        { NULL, NULL, NULL, NULL, NULL }, /* _El */
                     73:        { NULL, pre_it, NULL, NULL, NULL }, /* _It */
                     74:        { NULL, NULL, NULL, NULL, NULL }, /* _Ad */
                     75:        { NULL, NULL, NULL, NULL, NULL }, /* _An */
                     76:        { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Ar */
                     77:        { NULL, NULL, NULL, NULL, NULL }, /* _Cd */
                     78:        { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Cm */
                     79:        { NULL, NULL, NULL, NULL, NULL }, /* _Dv */
                     80:        { NULL, NULL, NULL, NULL, NULL }, /* _Er */
                     81:        { NULL, NULL, NULL, NULL, NULL }, /* _Ev */
                     82:        { NULL, pre_enc, post_enc, "The \\fB",
                     83:            "\\fP\nutility exits 0 on success, and >0 if an error occurs."
                     84:            }, /* Ex */
                     85:        { NULL, NULL, NULL, NULL, NULL }, /* _Fa */
                     86:        { NULL, NULL, NULL, NULL, NULL }, /* _Fd */
                     87:        { NULL, pre_enc, post_enc, "\\fB-", "\\fP" }, /* Fl */
                     88:        { NULL, NULL, NULL, NULL, NULL }, /* _Fn */
                     89:        { NULL, NULL, NULL, NULL, NULL }, /* _Ft */
                     90:        { NULL, NULL, NULL, NULL, NULL }, /* _Ic */
                     91:        { NULL, NULL, NULL, NULL, NULL }, /* _In */
                     92:        { NULL, NULL, NULL, NULL, NULL }, /* _Li */
                     93:        { cond_head, pre_enc, NULL, "\\- ", NULL }, /* Nd */
                     94:        { NULL, pre_nm, post_nm, NULL, NULL }, /* Nm */
                     95:        { cond_body, pre_enc, post_enc, "[", "]" }, /* Op */
                     96:        { NULL, NULL, NULL, NULL, NULL }, /* _Ot */
                     97:        { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* _Pa */
                     98:        { NULL, NULL, NULL, NULL, NULL }, /* _Rv */
                     99:        { NULL, NULL, NULL, NULL, NULL }, /* _St */
                    100:        { NULL, NULL, NULL, NULL, NULL }, /* _Va */
                    101:        { NULL, NULL, NULL, NULL, NULL }, /* _Vt */
                    102:        { NULL, pre_xr, NULL, NULL, NULL }, /* _Xr */
                    103:        { NULL, NULL, post_percent, NULL, NULL }, /* _%A */
                    104:        { NULL, NULL, NULL, NULL, NULL }, /* _%B */
                    105:        { NULL, NULL, post_percent, NULL, NULL }, /* _%D */
                    106:        { NULL, NULL, NULL, NULL, NULL }, /* _%I */
                    107:        { NULL, pre_enc, post_percent, "\\fI", "\\fP" }, /* %J */
                    108:        { NULL, NULL, NULL, NULL, NULL }, /* _%N */
                    109:        { NULL, NULL, NULL, NULL, NULL }, /* _%O */
                    110:        { NULL, NULL, NULL, NULL, NULL }, /* _%P */
                    111:        { NULL, NULL, NULL, NULL, NULL }, /* _%R */
                    112:        { NULL, pre_enc, post_percent, "\"", "\"" }, /* %T */
                    113:        { NULL, NULL, NULL, NULL, NULL }, /* _%V */
                    114:        { NULL, NULL, NULL, NULL, NULL }, /* _Ac */
                    115:        { NULL, NULL, NULL, NULL, NULL }, /* _Ao */
                    116:        { cond_body, pre_enc, post_enc, "<", ">" }, /* Aq */
                    117:        { NULL, NULL, NULL, NULL, NULL }, /* _At */
                    118:        { NULL, NULL, NULL, NULL, NULL }, /* _Bc */
                    119:        { NULL, NULL, NULL, NULL, NULL }, /* _Bf */
                    120:        { NULL, NULL, NULL, NULL, NULL }, /* _Bo */
                    121:        { NULL, NULL, NULL, NULL, NULL }, /* _Bq */
                    122:        { NULL, NULL, NULL, NULL, NULL }, /* _Bsx */
                    123:        { NULL, NULL, NULL, NULL, NULL }, /* _Bx */
                    124:        { NULL, NULL, NULL, NULL, NULL }, /* _Db */
                    125:        { NULL, NULL, NULL, NULL, NULL }, /* _Dc */
                    126:        { NULL, NULL, NULL, NULL, NULL }, /* _Do */
                    127:        { cond_body, pre_enc, post_enc, "``", "''" }, /* Dq */
                    128:        { NULL, NULL, NULL, NULL, NULL }, /* _Ec */
                    129:        { NULL, NULL, NULL, NULL, NULL }, /* _Ef */
                    130:        { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* _Em */
                    131:        { NULL, NULL, NULL, NULL, NULL }, /* _Eo */
                    132:        { NULL, NULL, NULL, NULL, NULL }, /* _Fx */
                    133:        { NULL, NULL, NULL, NULL, NULL }, /* _Ms */
                    134:        { NULL, NULL, NULL, NULL, NULL }, /* _No */
                    135:        { NULL, pre_ns, NULL, NULL, NULL }, /* Ns */
                    136:        { NULL, NULL, NULL, NULL, NULL }, /* _Nx */
                    137:        { NULL, NULL, NULL, NULL, NULL }, /* _Ox */
                    138:        { NULL, NULL, NULL, NULL, NULL }, /* _Pc */
                    139:        { NULL, NULL, NULL, NULL, NULL }, /* _Pf */
                    140:        { NULL, NULL, NULL, NULL, NULL }, /* _Po */
                    141:        { cond_body, pre_enc, post_enc, "(", ")" }, /* _Pq */
                    142:        { NULL, NULL, NULL, NULL, NULL }, /* _Qc */
                    143:        { cond_body, pre_enc, post_enc, "`", "'" }, /* Ql */
                    144:        { NULL, NULL, NULL, NULL, NULL }, /* _Qo */
                    145:        { NULL, NULL, NULL, NULL, NULL }, /* _Qq */
                    146:        { NULL, NULL, NULL, NULL, NULL }, /* _Re */
                    147:        { cond_body, pre_pp, NULL, NULL, NULL }, /* Rs */
                    148:        { NULL, NULL, NULL, NULL, NULL }, /* _Sc */
                    149:        { NULL, NULL, NULL, NULL, NULL }, /* _So */
                    150:        { cond_body, pre_enc, post_enc, "`", "'" }, /* Sq */
                    151:        { NULL, NULL, NULL, NULL, NULL }, /* _Sm */
                    152:        { NULL, NULL, NULL, NULL, NULL }, /* _Sx */
                    153:        { NULL, NULL, NULL, NULL, NULL }, /* _Sy */
                    154:        { NULL, NULL, NULL, NULL, NULL }, /* _Tn */
                    155:        { NULL, NULL, NULL, NULL, NULL }, /* _Ux */
                    156:        { NULL, NULL, NULL, NULL, NULL }, /* _Xc */
                    157:        { NULL, NULL, NULL, NULL, NULL }, /* _Xo */
                    158:        { NULL, NULL, NULL, NULL, NULL }, /* _Fo */
                    159:        { NULL, NULL, NULL, NULL, NULL }, /* _Fc */
                    160:        { NULL, NULL, NULL, NULL, NULL }, /* _Oo */
                    161:        { NULL, NULL, NULL, NULL, NULL }, /* _Oc */
                    162:        { NULL, NULL, NULL, NULL, NULL }, /* _Bk */
                    163:        { NULL, NULL, NULL, NULL, NULL }, /* _Ek */
                    164:        { NULL, NULL, NULL, NULL, NULL }, /* _Bt */
                    165:        { NULL, NULL, NULL, NULL, NULL }, /* _Hf */
                    166:        { NULL, NULL, NULL, NULL, NULL }, /* _Fr */
                    167:        { NULL, NULL, NULL, NULL, NULL }, /* _Ud */
                    168:        { NULL, NULL, NULL, NULL, NULL }, /* _Lb */
                    169:        { NULL, NULL, NULL, NULL, NULL }, /* _Lp */
                    170:        { NULL, NULL, NULL, NULL, NULL }, /* _Lk */
                    171:        { NULL, NULL, NULL, NULL, NULL }, /* _Mt */
                    172:        { NULL, NULL, NULL, NULL, NULL }, /* _Brq */
                    173:        { NULL, NULL, NULL, NULL, NULL }, /* _Bro */
                    174:        { NULL, NULL, NULL, NULL, NULL }, /* _Brc */
                    175:        { NULL, NULL, NULL, NULL, NULL }, /* _%C */
                    176:        { NULL, NULL, NULL, NULL, NULL }, /* _Es */
                    177:        { NULL, NULL, NULL, NULL, NULL }, /* _En */
                    178:        { NULL, NULL, NULL, NULL, NULL }, /* _Dx */
                    179:        { NULL, NULL, NULL, NULL, NULL }, /* _%Q */
                    180:        { NULL, NULL, NULL, NULL, NULL }, /* _br */
                    181:        { NULL, NULL, NULL, NULL, NULL }, /* _sp */
                    182:        { NULL, NULL, NULL, NULL, NULL }, /* _%U */
                    183:        { NULL, NULL, NULL, NULL, NULL }, /* _Ta */
                    184: };
                    185:
                    186:
                    187: static void
                    188: print_word(const char *s)
                    189: {
                    190:        if (need_nl) {
                    191:                putchar('\n');
                    192:                need_space = 0;
                    193:                need_nl = 0;
                    194:        } else if (need_space &&
                    195:            (NULL == strchr(".,:;)]?!", s[0]) || '\0' != s[1]))
                    196:                putchar(' ');
                    197:        need_space = ('(' != s[0] && '[' != s[0]) || '\0' != s[1];
                    198:        for ( ; *s; s++) {
                    199:                switch (*s) {
                    200:                case (ASCII_NBRSP):
                    201:                        printf("\\~");
                    202:                        break;
                    203:                case (ASCII_HYPH):
                    204:                        putchar('-');
                    205:                        break;
                    206:                default:
                    207:                        putchar(*s);
                    208:                        break;
                    209:                }
                    210:        }
                    211: }
                    212:
                    213: void
                    214: man_mdoc(void *arg, const struct mdoc *mdoc)
                    215: {
                    216:        const struct mdoc_meta *m;
                    217:        const struct mdoc_node *n;
                    218:
                    219:        m = mdoc_meta(mdoc);
                    220:        n = mdoc_node(mdoc);
                    221:
                    222:        printf(".TH \"%s\" \"%s\" \"%s\"", m->title, m->msec, m->date);
                    223:        need_nl = 1;
                    224:        need_space = 0;
                    225:
                    226:        print_node(m, n);
                    227: }
                    228:
                    229: static void
                    230: print_node(DECL_ARGS)
                    231: {
                    232:        const struct mdoc_node  *prev, *sub;
                    233:        const struct manact     *act = NULL;
                    234:        int                      cond, do_sub;
                    235:
                    236:        prev = n->prev ? n->prev : n->parent;
                    237:        if (prev && prev->line < n->line)
                    238:                need_nl = 1;
                    239:
                    240:        cond = 0;
                    241:        do_sub = 1;
                    242:        if (MDOC_TEXT == n->type) {
                    243:                print_word(n->string);
                    244:        } else {
                    245:                act = manacts + n->tok;
                    246:                cond = NULL == act->cond || (*act->cond)(m, n);
                    247:                if (cond && act->pre)
                    248:                        do_sub = (*act->pre)(m, n);
                    249:        }
                    250:
                    251:        if (do_sub)
                    252:                for (sub = n->child; sub; sub = sub->next)
                    253:                        print_node(m, sub);
                    254:
                    255:        if (cond && act->post)
                    256:                (*act->post)(m, n);
                    257: }
                    258:
                    259: static int
                    260: cond_head(DECL_ARGS)
                    261: {
                    262:        return(MDOC_HEAD == n->type);
                    263: }
                    264:
                    265: static int
                    266: cond_body(DECL_ARGS)
                    267: {
                    268:        return(MDOC_BODY == n->type);
                    269: }
                    270:
                    271: static int
                    272: pre_enc(DECL_ARGS)
                    273: {
                    274:        const char *prefix;
                    275:
                    276:        prefix = manacts[n->tok].prefix;
                    277:        if (NULL == prefix)
                    278:                return(1);
                    279:        print_word(prefix);
                    280:        need_space = 0;
                    281:        return(1);
                    282: }
                    283:
                    284: static void
                    285: post_enc(DECL_ARGS)
                    286: {
                    287:        const char *suffix;
                    288:
                    289:        suffix = manacts[n->tok].suffix;
                    290:        if (NULL == suffix)
                    291:                return;
                    292:        need_space = 0;
                    293:        print_word(suffix);
                    294: }
                    295:
                    296: static void
                    297: post_percent(DECL_ARGS)
                    298: {
                    299:
                    300:        post_enc(m, n);
                    301:        if (n->next)
                    302:                print_word(",");
                    303:        else {
                    304:                print_word(".");
                    305:                need_nl = 1;
                    306:        }
                    307: }
                    308:
                    309: static int
                    310: pre_dl(DECL_ARGS)
                    311: {
                    312:
                    313:        need_nl = 1;
                    314:        print_word(".RS 6n");
                    315:        need_nl = 1;
                    316:        return(1);
                    317: }
                    318:
                    319: static void
                    320: post_dl(DECL_ARGS)
                    321: {
                    322:
                    323:        need_nl = 1;
                    324:        print_word(".RE");
                    325:        need_nl = 1;
                    326: }
                    327:
                    328: static int
                    329: pre_it(DECL_ARGS)
                    330: {
                    331:        const struct mdoc_node *bln;
                    332:
                    333:        if (MDOC_HEAD == n->type) {
                    334:                need_nl = 1;
                    335:                print_word(".TP");
                    336:                bln = n->parent->parent->prev;
                    337:                print_word(bln->norm->Bl.width);
                    338:                need_nl = 1;
                    339:        }
                    340:        return(1);
                    341: }
                    342:
                    343: static int
                    344: pre_nm(DECL_ARGS)
                    345: {
                    346:
                    347:        if (MDOC_ELEM != n->type && MDOC_HEAD != n->type)
                    348:                return(1);
                    349:        print_word("\\fB");
                    350:        need_space = 0;
                    351:        if (NULL == n->child)
                    352:                print_word(m->name);
                    353:        return(1);
                    354: }
                    355:
                    356: static void
                    357: post_nm(DECL_ARGS)
                    358: {
                    359:
                    360:        if (MDOC_ELEM != n->type && MDOC_HEAD != n->type)
                    361:                return;
                    362:        need_space = 0;
                    363:        print_word("\\fP");
                    364: }
                    365:
                    366: static int
                    367: pre_ns(DECL_ARGS)
                    368: {
                    369:
                    370:        need_space = 0;
                    371:        return(0);
                    372: }
                    373:
                    374: static int
                    375: pre_pp(DECL_ARGS)
                    376: {
                    377:
                    378:        need_nl = 1;
                    379:        if (MDOC_It == n->parent->tok)
                    380:                print_word(".sp");
                    381:        else
                    382:                print_word(".PP");
                    383:        need_nl = 1;
                    384:        return(1);
                    385: }
                    386:
                    387: static int
                    388: pre_sh(DECL_ARGS)
                    389: {
                    390:
                    391:        if (MDOC_HEAD != n->type)
                    392:                return(1);
                    393:        need_nl = 1;
                    394:        print_word(".SH \"");
                    395:        need_space = 0;
                    396:        return(1);
                    397: }
                    398:
                    399: static void
                    400: post_sh(DECL_ARGS)
                    401: {
                    402:
                    403:        if (MDOC_HEAD != n->type)
                    404:                return;
                    405:        need_space = 0;
                    406:        print_word("\"");
                    407:        need_nl = 1;
                    408: }
                    409:
                    410: static int
                    411: pre_xr(DECL_ARGS)
                    412: {
                    413:
                    414:        n = n->child;
                    415:        if (NULL == n)
                    416:                return(0);
                    417:        print_node(m, n);
                    418:        n = n->next;
                    419:        if (NULL == n)
                    420:                return(0);
                    421:        need_space = 0;
                    422:        print_word("(");
                    423:        print_node(m, n);
                    424:        print_word(")");
                    425:        return(0);
                    426: }

CVSweb