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

Annotation of mandoc/html.c, Revision 1.31

1.31    ! kristaps    1: /*     $Id: html.c,v 1.30 2009/09/16 22:17:27 kristaps Exp $ */
1.1       kristaps    2: /*
1.29      kristaps    3:  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
1.1       kristaps    4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
1.29      kristaps    6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
1.1       kristaps    8:  *
1.29      kristaps    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.
1.1       kristaps   16:  */
1.30      kristaps   17: #include <sys/queue.h>
                     18:
1.1       kristaps   19: #include <assert.h>
1.4       kristaps   20: #include <err.h>
1.29      kristaps   21: #include <stdio.h>
1.1       kristaps   22: #include <stdlib.h>
                     23:
1.29      kristaps   24: #include "mdoc.h"
                     25: #include "man.h"
1.2       kristaps   26:
1.29      kristaps   27: #define        DOCTYPE         "-//W3C//DTD HTML 4.01//EN"
                     28: #define        DTD             "http://www.w3.org/TR/html4/strict.dtd"
1.8       kristaps   29:
1.29      kristaps   30: enum   htmltag {
                     31:        TAG_HTML,
                     32:        TAG_HEAD,
                     33:        TAG_BODY,
                     34:        TAG_META,
                     35:        TAG_TITLE,
                     36:        TAG_DIV,
                     37:        TAG_H1,
                     38:        TAG_H2,
                     39:        TAG_P,
                     40:        TAG_SPAN,
                     41:        TAG_LINK,
1.30      kristaps   42:        TAG_BR,
                     43:        TAG_A,
1.29      kristaps   44:        TAG_MAX
1.7       kristaps   45: };
                     46:
1.29      kristaps   47: enum   htmlattr {
                     48:        ATTR_HTTPEQUIV,
                     49:        ATTR_CONTENT,
                     50:        ATTR_NAME,
                     51:        ATTR_REL,
                     52:        ATTR_HREF,
                     53:        ATTR_TYPE,
                     54:        ATTR_MEDIA,
                     55:        ATTR_CLASS,
                     56:        ATTR_MAX
1.7       kristaps   57: };
                     58:
1.29      kristaps   59: struct htmldata {
                     60:        char             *name;
                     61:        int               flags;
1.30      kristaps   62: #define        HTML_CLRLINE     (1 << 0)
                     63: #define        HTML_NOSTACK     (1 << 1)
1.29      kristaps   64: };
1.7       kristaps   65:
1.29      kristaps   66: static const struct htmldata htmltags[TAG_MAX] = {
1.30      kristaps   67:        {"html",        HTML_CLRLINE}, /* TAG_HTML */
                     68:        {"head",        HTML_CLRLINE}, /* TAG_HEAD */
                     69:        {"body",        HTML_CLRLINE}, /* TAG_BODY */
                     70:        {"meta",        HTML_CLRLINE | HTML_NOSTACK}, /* TAG_META */
                     71:        {"title",       HTML_CLRLINE | HTML_NOSTACK}, /* TAG_TITLE */
                     72:        {"div",         HTML_CLRLINE}, /* TAG_DIV */
1.29      kristaps   73:        {"h1",          0}, /* TAG_H1 */
                     74:        {"h2",          0}, /* TAG_H2 */
1.30      kristaps   75:        {"p",           HTML_CLRLINE}, /* TAG_P */
1.29      kristaps   76:        {"span",        0}, /* TAG_SPAN */
1.30      kristaps   77:        {"link",        HTML_CLRLINE | HTML_NOSTACK}, /* TAG_LINK */
                     78:        {"br",          HTML_CLRLINE | HTML_NOSTACK}, /* TAG_LINK */
                     79:        {"a",           0}, /* TAG_A */
1.29      kristaps   80: };
1.10      kristaps   81:
1.29      kristaps   82: static const char       *const htmlattrs[ATTR_MAX] = {
                     83:        "http-equiv",
                     84:        "content",
                     85:        "name",
                     86:        "rel",
                     87:        "href",
                     88:        "type",
                     89:        "media",
                     90:        "class"
                     91: };
1.10      kristaps   92:
1.29      kristaps   93: struct htmlpair {
                     94:        enum htmlattr     key;
                     95:        char             *val;
                     96: };
1.10      kristaps   97:
1.30      kristaps   98: struct tag {
                     99:        enum htmltag      tag;
                    100:        SLIST_ENTRY(tag)  entry;
                    101: };
                    102:
                    103: SLIST_HEAD(tagq, tag);
                    104:
1.29      kristaps  105: struct html {
                    106:        int               flags;
                    107: #define        HTML_NOSPACE     (1 << 0)
1.30      kristaps  108: #define        HTML_NEWLINE     (1 << 1)
                    109:        struct tagq       stack;
1.29      kristaps  110: };
1.10      kristaps  111:
1.29      kristaps  112: #define        MDOC_ARGS         const struct mdoc_meta *m, \
                    113:                          const struct mdoc_node *n, \
                    114:                          struct html *h
                    115: #define        MAN_ARGS          const struct man_meta *m, \
                    116:                          const struct man_node *n, \
                    117:                          struct html *h
                    118: struct htmlmdoc {
                    119:        int             (*pre)(MDOC_ARGS);
                    120:        void            (*post)(MDOC_ARGS);
                    121: };
1.13      kristaps  122:
1.29      kristaps  123: static void              print_gen_doctype(struct html *);
                    124: static void              print_gen_head(struct html *);
                    125: static void              print_mdoc(MDOC_ARGS);
                    126: static void              print_mdoc_head(MDOC_ARGS);
1.30      kristaps  127: static void              print_mdoc_title(MDOC_ARGS);
1.29      kristaps  128: static void              print_mdoc_node(MDOC_ARGS);
                    129: static void              print_man(MAN_ARGS);
                    130: static void              print_man_head(MAN_ARGS);
                    131: static void              print_man_body(MAN_ARGS);
1.30      kristaps  132: static struct tag       *print_otag(struct html *, enum htmltag,
1.29      kristaps  133:                                int, const struct htmlpair *);
1.30      kristaps  134: static void              print_tagq(struct html *, const struct tag *);
                    135: static void              print_stagq(struct html *, const struct tag *);
1.29      kristaps  136: static void              print_ctag(struct html *, enum htmltag);
                    137: static void              print_encode(const char *);
                    138: static void              print_text(struct html *, const char *);
                    139: static int               mdoc_root_pre(MDOC_ARGS);
                    140:
1.31    ! kristaps  141: static int               mdoc_ar_pre(MDOC_ARGS);
1.30      kristaps  142: static int               mdoc_fl_pre(MDOC_ARGS);
1.29      kristaps  143: static int               mdoc_nd_pre(MDOC_ARGS);
                    144: static int               mdoc_nm_pre(MDOC_ARGS);
1.31    ! kristaps  145: static int               mdoc_ns_pre(MDOC_ARGS);
1.30      kristaps  146: static int               mdoc_op_pre(MDOC_ARGS);
                    147: static void              mdoc_op_post(MDOC_ARGS);
1.29      kristaps  148: static int               mdoc_pp_pre(MDOC_ARGS);
                    149: static int               mdoc_sh_pre(MDOC_ARGS);
                    150: static int               mdoc_ss_pre(MDOC_ARGS);
1.30      kristaps  151: static int               mdoc_xr_pre(MDOC_ARGS);
1.29      kristaps  152:
                    153: static const struct htmlmdoc mdocs[MDOC_MAX] = {
                    154:        {NULL, NULL}, /* Ap */
                    155:        {NULL, NULL}, /* Dd */
                    156:        {NULL, NULL}, /* Dt */
                    157:        {NULL, NULL}, /* Os */
1.30      kristaps  158:        {mdoc_sh_pre, NULL }, /* Sh */
                    159:        {mdoc_ss_pre, NULL }, /* Ss */
1.29      kristaps  160:        {mdoc_pp_pre, NULL}, /* Pp */
                    161:        {NULL, NULL}, /* D1 */
                    162:        {NULL, NULL}, /* Dl */
                    163:        {NULL, NULL}, /* Bd */
                    164:        {NULL, NULL}, /* Ed */
                    165:        {NULL, NULL}, /* Bl */
                    166:        {NULL, NULL}, /* El */
                    167:        {NULL, NULL}, /* It */
                    168:        {NULL, NULL}, /* Ad */
                    169:        {NULL, NULL}, /* An */
1.31    ! kristaps  170:        {mdoc_ar_pre, NULL}, /* Ar */
1.29      kristaps  171:        {NULL, NULL}, /* Cd */
                    172:        {NULL, NULL}, /* Cm */
                    173:        {NULL, NULL}, /* Dv */
                    174:        {NULL, NULL}, /* Er */
                    175:        {NULL, NULL}, /* Ev */
                    176:        {NULL, NULL}, /* Ex */
                    177:        {NULL, NULL}, /* Fa */
                    178:        {NULL, NULL}, /* Fd */
1.30      kristaps  179:        {mdoc_fl_pre, NULL}, /* Fl */
1.29      kristaps  180:        {NULL, NULL}, /* Fn */
                    181:        {NULL, NULL}, /* Ft */
                    182:        {NULL, NULL}, /* Ic */
                    183:        {NULL, NULL}, /* In */
                    184:        {NULL, NULL}, /* Li */
                    185:        {mdoc_nd_pre, NULL}, /* Nd */
1.30      kristaps  186:        {mdoc_nm_pre, NULL}, /* Nm */
                    187:        {mdoc_op_pre, mdoc_op_post}, /* Op */
1.29      kristaps  188:        {NULL, NULL}, /* Ot */
                    189:        {NULL, NULL}, /* Pa */
                    190:        {NULL, NULL}, /* Rv */
                    191:        {NULL, NULL}, /* St */
                    192:        {NULL, NULL}, /* Va */
                    193:        {NULL, NULL}, /* Vt */
1.30      kristaps  194:        {mdoc_xr_pre, NULL}, /* Xr */
1.29      kristaps  195:        {NULL, NULL}, /* %A */
                    196:        {NULL, NULL}, /* %B */
                    197:        {NULL, NULL}, /* %D */
                    198:        {NULL, NULL}, /* %I */
                    199:        {NULL, NULL}, /* %J */
                    200:        {NULL, NULL}, /* %N */
                    201:        {NULL, NULL}, /* %O */
                    202:        {NULL, NULL}, /* %P */
                    203:        {NULL, NULL}, /* %R */
                    204:        {NULL, NULL}, /* %T */
                    205:        {NULL, NULL}, /* %V */
                    206:        {NULL, NULL}, /* Ac */
                    207:        {NULL, NULL}, /* Ao */
                    208:        {NULL, NULL}, /* Aq */
                    209:        {NULL, NULL}, /* At */
                    210:        {NULL, NULL}, /* Bc */
                    211:        {NULL, NULL}, /* Bf */
                    212:        {NULL, NULL}, /* Bo */
                    213:        {NULL, NULL}, /* Bq */
                    214:        {NULL, NULL}, /* Bsx */
                    215:        {NULL, NULL}, /* Bx */
                    216:        {NULL, NULL}, /* Db */
                    217:        {NULL, NULL}, /* Dc */
                    218:        {NULL, NULL}, /* Do */
                    219:        {NULL, NULL}, /* Dq */
                    220:        {NULL, NULL}, /* Ec */
                    221:        {NULL, NULL}, /* Ef */
                    222:        {NULL, NULL}, /* Em */
                    223:        {NULL, NULL}, /* Eo */
                    224:        {NULL, NULL}, /* Fx */
                    225:        {NULL, NULL}, /* Ms */
                    226:        {NULL, NULL}, /* No */
1.31    ! kristaps  227:        {mdoc_ns_pre, NULL}, /* Ns */
1.29      kristaps  228:        {NULL, NULL}, /* Nx */
                    229:        {NULL, NULL}, /* Ox */
                    230:        {NULL, NULL}, /* Pc */
                    231:        {NULL, NULL}, /* Pf */
                    232:        {NULL, NULL}, /* Po */
                    233:        {NULL, NULL}, /* Pq */
                    234:        {NULL, NULL}, /* Qc */
                    235:        {NULL, NULL}, /* Ql */
                    236:        {NULL, NULL}, /* Qo */
                    237:        {NULL, NULL}, /* Qq */
                    238:        {NULL, NULL}, /* Re */
                    239:        {NULL, NULL}, /* Rs */
                    240:        {NULL, NULL}, /* Sc */
                    241:        {NULL, NULL}, /* So */
                    242:        {NULL, NULL}, /* Sq */
                    243:        {NULL, NULL}, /* Sm */
                    244:        {NULL, NULL}, /* Sx */
                    245:        {NULL, NULL}, /* Sy */
                    246:        {NULL, NULL}, /* Tn */
                    247:        {NULL, NULL}, /* Ux */
                    248:        {NULL, NULL}, /* Xc */
                    249:        {NULL, NULL}, /* Xo */
                    250:        {NULL, NULL}, /* Fo */
                    251:        {NULL, NULL}, /* Fc */
                    252:        {NULL, NULL}, /* Oo */
                    253:        {NULL, NULL}, /* Oc */
                    254:        {NULL, NULL}, /* Bk */
                    255:        {NULL, NULL}, /* Ek */
                    256:        {NULL, NULL}, /* Bt */
                    257:        {NULL, NULL}, /* Hf */
                    258:        {NULL, NULL}, /* Fr */
                    259:        {NULL, NULL}, /* Ud */
                    260:        {NULL, NULL}, /* Lb */
                    261:        {NULL, NULL}, /* Lp */
                    262:        {NULL, NULL}, /* Lk */
                    263:        {NULL, NULL}, /* Mt */
                    264:        {NULL, NULL}, /* Brq */
                    265:        {NULL, NULL}, /* Bro */
                    266:        {NULL, NULL}, /* Brc */
                    267:        {NULL, NULL}, /* %C */
                    268:        {NULL, NULL}, /* Es */
                    269:        {NULL, NULL}, /* En */
                    270:        {NULL, NULL}, /* Dx */
                    271:        {NULL, NULL}, /* %Q */
                    272:        {NULL, NULL}, /* br */
                    273:        {NULL, NULL}, /* sp */
                    274: };
1.10      kristaps  275:
                    276:
1.30      kristaps  277: void
1.29      kristaps  278: html_mdoc(void *arg, const struct mdoc *m)
1.10      kristaps  279: {
1.29      kristaps  280:        struct html     *h;
1.30      kristaps  281:        struct tag      *t;
1.10      kristaps  282:
1.29      kristaps  283:        h = (struct html *)arg;
1.10      kristaps  284:
1.29      kristaps  285:        print_gen_doctype(h);
1.30      kristaps  286:        t = print_otag(h, TAG_HTML, 0, NULL);
1.29      kristaps  287:        print_mdoc(mdoc_meta(m), mdoc_node(m), h);
1.30      kristaps  288:        print_tagq(h, t);
                    289:
1.29      kristaps  290:        printf("\n");
1.10      kristaps  291: }
                    292:
                    293:
1.30      kristaps  294: void
1.29      kristaps  295: html_man(void *arg, const struct man *m)
1.10      kristaps  296: {
1.29      kristaps  297:        struct html     *h;
1.30      kristaps  298:        struct tag      *t;
1.10      kristaps  299:
1.29      kristaps  300:        h = (struct html *)arg;
1.10      kristaps  301:
1.29      kristaps  302:        print_gen_doctype(h);
1.30      kristaps  303:        t = print_otag(h, TAG_HTML, 0, NULL);
1.29      kristaps  304:        print_man(man_meta(m), man_node(m), h);
1.30      kristaps  305:        print_tagq(h, t);
                    306:
1.29      kristaps  307:        printf("\n");
1.10      kristaps  308: }
                    309:
                    310:
1.29      kristaps  311: void *
                    312: html_alloc(void)
1.10      kristaps  313: {
1.30      kristaps  314:        struct html     *h;
                    315:
                    316:        if (NULL == (h = calloc(1, sizeof(struct html))))
                    317:                return(NULL);
1.10      kristaps  318:
1.30      kristaps  319:        SLIST_INIT(&h->stack);
                    320:        return(h);
1.29      kristaps  321: }
1.10      kristaps  322:
1.13      kristaps  323:
1.29      kristaps  324: void
                    325: html_free(void *p)
                    326: {
1.30      kristaps  327:        struct tag      *tag;
                    328:        struct html     *h;
                    329:
                    330:        h = (struct html *)p;
1.10      kristaps  331:
1.30      kristaps  332:        while ( ! SLIST_EMPTY(&h->stack)) {
                    333:                tag = SLIST_FIRST(&h->stack);
                    334:                SLIST_REMOVE_HEAD(&h->stack, entry);
                    335:                free(tag);
                    336:        }
                    337:        free(h);
1.10      kristaps  338: }
1.2       kristaps  339:
                    340:
1.29      kristaps  341: static void
                    342: print_mdoc(MDOC_ARGS)
1.4       kristaps  343: {
1.30      kristaps  344:        struct tag      *t;
1.4       kristaps  345:
1.30      kristaps  346:        t = print_otag(h, TAG_HEAD, 0, NULL);
1.29      kristaps  347:        print_mdoc_head(m, n, h);
1.30      kristaps  348:        print_tagq(h, t);
                    349:
                    350:        t = print_otag(h, TAG_BODY, 0, NULL);
                    351:        print_mdoc_title(m, n, h);
1.29      kristaps  352:        print_mdoc_node(m, n, h);
1.30      kristaps  353:        print_tagq(h, t);
1.29      kristaps  354: }
1.4       kristaps  355:
                    356:
1.29      kristaps  357: static void
                    358: print_gen_head(struct html *h)
                    359: {
                    360:        struct htmlpair  meta0[2];
                    361:        struct htmlpair  meta1[2];
                    362:        struct htmlpair  link[4];
                    363:
                    364:        meta0[0].key = ATTR_HTTPEQUIV;
                    365:        meta0[0].val = "Content-Type";
                    366:        meta0[1].key = ATTR_CONTENT;
                    367:        meta0[1].val = "text/html; charest-utf-8";
                    368:
                    369:        meta1[0].key = ATTR_NAME;
                    370:        meta1[0].val = "resource-type";
                    371:        meta1[1].key = ATTR_CONTENT;
                    372:        meta1[1].val = "document";
                    373:
                    374:        link[0].key = ATTR_REL;
                    375:        link[0].val = "stylesheet";
                    376:        link[1].key = ATTR_HREF;
1.30      kristaps  377:        link[1].val = "style.css"; /* XXX */
1.29      kristaps  378:        link[2].key = ATTR_TYPE;
                    379:        link[2].val = "text/css";
                    380:        link[3].key = ATTR_MEDIA;
                    381:        link[3].val = "all";
                    382:
                    383:        print_otag(h, TAG_META, 2, meta0);
                    384:        print_otag(h, TAG_META, 2, meta1);
                    385:        print_otag(h, TAG_LINK, 4, link);
1.4       kristaps  386: }
                    387:
                    388:
1.30      kristaps  389: /* ARGSUSED */
1.29      kristaps  390: static void
                    391: print_mdoc_head(MDOC_ARGS)
1.18      kristaps  392: {
                    393:
1.29      kristaps  394:        print_gen_head(h);
                    395:        print_otag(h, TAG_TITLE, 0, NULL);
                    396:        print_encode(m->title);
1.2       kristaps  397: }
                    398:
                    399:
1.30      kristaps  400: /* ARGSUSED */
1.29      kristaps  401: static void
1.30      kristaps  402: print_mdoc_title(MDOC_ARGS)
1.2       kristaps  403: {
                    404:
1.30      kristaps  405:        /* TODO */
1.2       kristaps  406: }
                    407:
                    408:
1.29      kristaps  409: static void
                    410: print_mdoc_node(MDOC_ARGS)
1.2       kristaps  411: {
1.29      kristaps  412:        int              child;
1.30      kristaps  413:        struct tag      *t;
1.8       kristaps  414:
1.29      kristaps  415:        child = 1;
1.30      kristaps  416:        t = SLIST_FIRST(&h->stack);
1.8       kristaps  417:
1.29      kristaps  418:        switch (n->type) {
                    419:        case (MDOC_ROOT):
                    420:                child = mdoc_root_pre(m, n, h);
1.7       kristaps  421:                break;
1.29      kristaps  422:        case (MDOC_TEXT):
                    423:                print_text(h, n->string);
1.7       kristaps  424:                break;
1.3       kristaps  425:        default:
1.29      kristaps  426:                if (mdocs[n->tok].pre)
                    427:                        child = (*mdocs[n->tok].pre)(m, n, h);
1.3       kristaps  428:                break;
1.2       kristaps  429:        }
                    430:
1.29      kristaps  431:        if (child && n->child)
                    432:                print_mdoc_node(m, n->child, h);
1.8       kristaps  433:
1.30      kristaps  434:        print_stagq(h, t);
                    435:
1.29      kristaps  436:        switch (n->type) {
                    437:        case (MDOC_ROOT):
1.7       kristaps  438:                break;
1.29      kristaps  439:        case (MDOC_TEXT):
1.7       kristaps  440:                break;
1.3       kristaps  441:        default:
1.29      kristaps  442:                if (mdocs[n->tok].post)
                    443:                        (*mdocs[n->tok].post)(m, n, h);
1.3       kristaps  444:                break;
                    445:        }
1.2       kristaps  446:
1.29      kristaps  447:        if (n->next)
                    448:                print_mdoc_node(m, n->next, h);
1.2       kristaps  449: }
                    450:
                    451:
1.29      kristaps  452: static void
                    453: print_man(MAN_ARGS)
1.9       kristaps  454: {
1.30      kristaps  455:        struct tag      *t;
1.9       kristaps  456:
1.30      kristaps  457:        t = print_otag(h, TAG_HEAD, 0, NULL);
1.29      kristaps  458:        print_man_head(m, n, h);
1.30      kristaps  459:        print_tagq(h, t);
                    460:
                    461:        t = print_otag(h, TAG_BODY, 0, NULL);
1.29      kristaps  462:        print_man_body(m, n, h);
1.30      kristaps  463:        print_tagq(h, t);
1.9       kristaps  464: }
                    465:
                    466:
1.30      kristaps  467: /* ARGSUSED */
1.9       kristaps  468: static void
1.29      kristaps  469: print_man_head(MAN_ARGS)
1.9       kristaps  470: {
                    471:
1.29      kristaps  472:        print_gen_head(h);
                    473:        print_otag(h, TAG_TITLE, 0, NULL);
                    474:        print_encode(m->title);
                    475: }
1.9       kristaps  476:
                    477:
1.30      kristaps  478: /* ARGSUSED */
1.29      kristaps  479: static void
                    480: print_man_body(MAN_ARGS)
                    481: {
1.30      kristaps  482:
                    483:        /* TODO */
1.9       kristaps  484: }
                    485:
                    486:
1.29      kristaps  487: static void
                    488: print_encode(const char *p)
                    489: {
1.14      kristaps  490:
1.29      kristaps  491:        printf("%s", p); /* XXX */
1.14      kristaps  492: }
                    493:
                    494:
1.30      kristaps  495: static struct tag *
1.29      kristaps  496: print_otag(struct html *h, enum htmltag tag,
                    497:                int sz, const struct htmlpair *p)
1.14      kristaps  498: {
1.29      kristaps  499:        int              i;
1.30      kristaps  500:        struct tag      *t;
                    501:
                    502:        if ( ! (HTML_NOSTACK & htmltags[tag].flags)) {
                    503:                if (NULL == (t = malloc(sizeof(struct tag))))
                    504:                        err(EXIT_FAILURE, "malloc");
                    505:                t->tag = tag;
                    506:                SLIST_INSERT_HEAD(&h->stack, t, entry);
                    507:        } else
                    508:                t = NULL;
1.29      kristaps  509:
                    510:        if ( ! (HTML_NOSPACE & h->flags))
1.30      kristaps  511:                if ( ! (HTML_CLRLINE & htmltags[tag].flags))
1.29      kristaps  512:                        printf(" ");
                    513:
                    514:        printf("<%s", htmltags[tag].name);
                    515:        for (i = 0; i < sz; i++) {
                    516:                printf(" %s=\"", htmlattrs[p[i].key]);
                    517:                assert(p->val);
                    518:                print_encode(p[i].val);
                    519:                printf("\"");
                    520:        }
                    521:        printf(">");
1.14      kristaps  522:
1.29      kristaps  523:        h->flags |= HTML_NOSPACE;
1.30      kristaps  524:        if (HTML_CLRLINE & htmltags[tag].flags)
                    525:                h->flags |= HTML_NEWLINE;
                    526:        else
                    527:                h->flags &= ~HTML_NEWLINE;
1.14      kristaps  528:
1.30      kristaps  529:        return(t);
1.14      kristaps  530: }
                    531:
                    532:
                    533: /* ARGSUSED */
1.29      kristaps  534: static void
                    535: print_ctag(struct html *h, enum htmltag tag)
1.14      kristaps  536: {
                    537:
1.29      kristaps  538:        printf("</%s>", htmltags[tag].name);
1.30      kristaps  539:        if (HTML_CLRLINE & htmltags[tag].flags)
1.29      kristaps  540:                h->flags |= HTML_NOSPACE;
1.30      kristaps  541:        if (HTML_CLRLINE & htmltags[tag].flags)
                    542:                h->flags |= HTML_NEWLINE;
                    543:        else
                    544:                h->flags &= ~HTML_NEWLINE;
1.14      kristaps  545: }
                    546:
                    547:
1.29      kristaps  548: /* ARGSUSED */
                    549: static void
                    550: print_gen_doctype(struct html *h)
1.1       kristaps  551: {
1.29      kristaps  552:
                    553:        printf("<!DOCTYPE HTML PUBLIC \"%s\" \"%s\">\n", DOCTYPE, DTD);
1.1       kristaps  554: }
                    555:
                    556:
1.29      kristaps  557: static void
                    558: print_text(struct html *h, const char *p)
1.1       kristaps  559: {
                    560:
1.29      kristaps  561:        if (*p && 0 == *(p + 1))
                    562:                switch (*p) {
                    563:                case('.'):
                    564:                        /* FALLTHROUGH */
                    565:                case(','):
                    566:                        /* FALLTHROUGH */
                    567:                case(';'):
                    568:                        /* FALLTHROUGH */
                    569:                case(':'):
                    570:                        /* FALLTHROUGH */
                    571:                case('?'):
                    572:                        /* FALLTHROUGH */
                    573:                case('!'):
                    574:                        /* FALLTHROUGH */
                    575:                case(')'):
                    576:                        /* FALLTHROUGH */
                    577:                case(']'):
                    578:                        /* FALLTHROUGH */
                    579:                case('}'):
                    580:                        h->flags |= HTML_NOSPACE;
1.30      kristaps  581:                        break;
1.29      kristaps  582:                default:
                    583:                        break;
                    584:                }
1.1       kristaps  585:
1.29      kristaps  586:        if ( ! (h->flags & HTML_NOSPACE))
                    587:                printf(" ");
1.30      kristaps  588:
1.29      kristaps  589:        h->flags &= ~HTML_NOSPACE;
1.30      kristaps  590:        h->flags &= ~HTML_NEWLINE;
1.1       kristaps  591:
1.29      kristaps  592:        if (p)
                    593:                print_encode(p);
1.8       kristaps  594:
1.29      kristaps  595:        if (*p && 0 == *(p + 1))
                    596:                switch (*p) {
                    597:                case('('):
                    598:                        /* FALLTHROUGH */
                    599:                case('['):
                    600:                        /* FALLTHROUGH */
                    601:                case('{'):
                    602:                        h->flags |= HTML_NOSPACE;
1.30      kristaps  603:                        break;
1.29      kristaps  604:                default:
                    605:                        break;
                    606:                }
1.1       kristaps  607: }
1.30      kristaps  608:
                    609:
                    610: static void
                    611: print_tagq(struct html *h, const struct tag *until)
                    612: {
                    613:        struct tag      *tag;
                    614:
                    615:        while ( ! SLIST_EMPTY(&h->stack)) {
                    616:                tag = SLIST_FIRST(&h->stack);
                    617:                print_ctag(h, tag->tag);
                    618:                SLIST_REMOVE_HEAD(&h->stack, entry);
                    619:                free(tag);
                    620:                if (until && tag == until)
                    621:                        return;
                    622:        }
                    623: }
                    624:
                    625:
                    626: static void
                    627: print_stagq(struct html *h, const struct tag *suntil)
                    628: {
                    629:        struct tag      *tag;
                    630:
                    631:        while ( ! SLIST_EMPTY(&h->stack)) {
                    632:                tag = SLIST_FIRST(&h->stack);
                    633:                if (suntil && tag == suntil)
                    634:                        return;
                    635:                print_ctag(h, tag->tag);
                    636:                SLIST_REMOVE_HEAD(&h->stack, entry);
                    637:                free(tag);
                    638:        }
                    639: }
                    640:
                    641:
                    642: /* ARGSUSED */
                    643: static int
                    644: mdoc_root_pre(MDOC_ARGS)
                    645: {
                    646:        struct htmlpair  tag;
                    647:
                    648:        tag.key = ATTR_CLASS;
                    649:        tag.val = "body";
                    650:
                    651:        print_otag(h, TAG_DIV, 1, &tag);
                    652:        return(1);
                    653: }
                    654:
                    655:
                    656: /* ARGSUSED */
                    657: static int
                    658: mdoc_ss_pre(MDOC_ARGS)
                    659: {
                    660:
                    661:        if (MDOC_BODY == n->type)
                    662:                print_otag(h, TAG_P, 0, NULL);
                    663:        if (MDOC_HEAD == n->type)
                    664:                print_otag(h, TAG_H2, 0, NULL);
                    665:        return(1);
                    666: }
                    667:
                    668:
                    669: /* ARGSUSED */
                    670: static int
                    671: mdoc_fl_pre(MDOC_ARGS)
                    672: {
                    673:        struct htmlpair  tag;
                    674:
                    675:        tag.key = ATTR_CLASS;
                    676:        tag.val = "flag";
                    677:
                    678:        print_otag(h, TAG_SPAN, 1, &tag);
                    679:        print_text(h, "\\-");
                    680:        h->flags |= HTML_NOSPACE;
                    681:        return(1);
                    682: }
                    683:
                    684:
                    685: /* ARGSUSED */
                    686: static int
                    687: mdoc_pp_pre(MDOC_ARGS)
                    688: {
                    689:
                    690:        print_otag(h, TAG_BR, 0, NULL);
                    691:        print_otag(h, TAG_BR, 0, NULL);
                    692:        return(0);
                    693: }
                    694:
                    695:
                    696: /* ARGSUSED */
                    697: static int
                    698: mdoc_nd_pre(MDOC_ARGS)
                    699: {
                    700:
                    701:        if (MDOC_BODY == n->type)
1.31    ! kristaps  702:                print_text(h, "\\(en");
1.30      kristaps  703:        return(1);
                    704: }
                    705:
                    706:
                    707: /* ARGSUSED */
                    708: static int
                    709: mdoc_op_pre(MDOC_ARGS)
                    710: {
                    711:
                    712:        if (MDOC_BODY == n->type) {
                    713:                print_text(h, "\\(lB");
                    714:                h->flags |= HTML_NOSPACE;
                    715:        }
                    716:        return(1);
                    717: }
                    718:
                    719:
                    720: /* ARGSUSED */
                    721: static void
                    722: mdoc_op_post(MDOC_ARGS)
                    723: {
                    724:
                    725:        if (MDOC_BODY != n->type)
                    726:                return;
                    727:        h->flags |= HTML_NOSPACE;
                    728:        print_text(h, "\\(rB");
                    729: }
                    730:
                    731:
                    732: static int
                    733: mdoc_nm_pre(MDOC_ARGS)
                    734: {
                    735:        struct htmlpair class;
                    736:
                    737:        if ( ! (HTML_NEWLINE & h->flags))
                    738:                if (SEC_SYNOPSIS == n->sec)
                    739:                        print_otag(h, TAG_BR, 0, NULL);
                    740:
                    741:        class.key = ATTR_CLASS;
                    742:        class.val = "name";
                    743:
                    744:        print_otag(h, TAG_SPAN, 1, &class);
                    745:        if (NULL == n->child)
                    746:                print_text(h, m->name);
                    747:
                    748:        return(1);
                    749: }
                    750:
                    751:
                    752: /* ARGSUSED */
                    753: static int
                    754: mdoc_sh_pre(MDOC_ARGS)
                    755: {
                    756:
                    757:        if (MDOC_BODY == n->type)
                    758:                print_otag(h, TAG_P, 0, NULL);
                    759:        if (MDOC_HEAD == n->type)
                    760:                print_otag(h, TAG_H1, 0, NULL);
                    761:        return(1);
                    762: }
                    763:
                    764:
                    765: /* ARGSUSED */
                    766: static int
                    767: mdoc_xr_pre(MDOC_ARGS)
                    768: {
                    769:        struct htmlpair tag;
                    770:
                    771:        tag.key = ATTR_HREF;
                    772:        tag.val = "#"; /* TODO */
                    773:
                    774:        print_otag(h, TAG_A, 1, &tag);
                    775:
                    776:        n = n->child;
                    777:        print_text(h, n->string);
                    778:        if (NULL == (n = n->next))
                    779:                return(0);
                    780:
                    781:        h->flags |= HTML_NOSPACE;
                    782:        print_text(h, "(");
                    783:        h->flags |= HTML_NOSPACE;
                    784:        print_text(h, n->string);
                    785:        h->flags |= HTML_NOSPACE;
                    786:        print_text(h, ")");
                    787:
                    788:        return(0);
                    789: }
1.31    ! kristaps  790:
        !           791:
        !           792: /* ARGSUSED */
        !           793: static int
        !           794: mdoc_ns_pre(MDOC_ARGS)
        !           795: {
        !           796:
        !           797:        h->flags |= HTML_NOSPACE;
        !           798:        return(1);
        !           799: }
        !           800:
        !           801:
        !           802: /* ARGSUSED */
        !           803: static int
        !           804: mdoc_ar_pre(MDOC_ARGS)
        !           805: {
        !           806:        struct htmlpair tag;
        !           807:
        !           808:        tag.key = ATTR_CLASS;
        !           809:        tag.val = "arg";
        !           810:
        !           811:        print_otag(h, TAG_SPAN, 1, &tag);
        !           812:        return(1);
        !           813: }

CVSweb