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

Annotation of mandoc/html.c, Revision 1.12

1.12    ! kristaps    1: /* $Id: html.c,v 1.11 2008/12/05 22:54:44 kristaps Exp $ */
1.1       kristaps    2: /*
                      3:  * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
                      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:  */
1.4       kristaps   19: #include <sys/param.h>
                     20: #include <sys/stat.h>
                     21:
1.1       kristaps   22: #include <assert.h>
1.4       kristaps   23: #include <err.h>
                     24: #include <fcntl.h>
1.1       kristaps   25: #include <stdlib.h>
1.4       kristaps   26: #include <stdio.h>
1.2       kristaps   27: #include <string.h>
1.4       kristaps   28: #include <unistd.h>
1.1       kristaps   29:
                     30: #include "libmdocml.h"
                     31: #include "private.h"
1.2       kristaps   32: #include "ml.h"
                     33:
                     34:
1.8       kristaps   35: /* TODO: allow head/tail-less invocations (just "div" start). */
                     36:
1.7       kristaps   37: struct htmlnode {
1.8       kristaps   38:        int              tok;
                     39:        enum md_ns       ns;
1.10      kristaps   40:        int              argc[ROFF_MAXLINEARG];
1.7       kristaps   41:        char            *argv[ROFF_MAXLINEARG];
                     42:        struct htmlnode *parent;
                     43: };
                     44:
                     45:
                     46: struct htmlq {
                     47:        struct htmlnode *last;
                     48: };
                     49:
                     50:
1.4       kristaps   51: static int             html_loadcss(struct md_mbuf *, const char *);
                     52:
1.9       kristaps   53: static int             html_alloc(void **);
                     54: static void            html_free(void *);
1.8       kristaps   55: static ssize_t         html_endtag(struct md_mbuf *, void *,
1.2       kristaps   56:                                const struct md_args *,
                     57:                                enum md_ns, int);
1.8       kristaps   58: static ssize_t         html_begintag(struct md_mbuf *, void *,
1.2       kristaps   59:                                const struct md_args *,
                     60:                                enum md_ns, int,
                     61:                                const int *, const char **);
1.4       kristaps   62: static int             html_begin(struct md_mbuf *,
                     63:                                const struct md_args *,
                     64:                                const struct tm *,
                     65:                                const char *, const char *,
                     66:                                const char *, const char *);
1.7       kristaps   67: static int             html_printargs(struct md_mbuf *, int,
                     68:                                const char *, const int *,
                     69:                                const char **, size_t *);
1.2       kristaps   70: static int             html_end(struct md_mbuf *,
                     71:                                const struct md_args *);
1.7       kristaps   72: static int             html_blocktagname(struct md_mbuf *,
1.10      kristaps   73:                                const struct md_args *, int,
                     74:                                struct htmlq *, const int *,
                     75:                                const char **, size_t *);
1.7       kristaps   76: static int             html_blocktagargs(struct md_mbuf *,
1.2       kristaps   77:                                const struct md_args *, int,
1.7       kristaps   78:                                const int *, const char **, size_t *);
1.10      kristaps   79: static int             html_headtagname(struct md_mbuf *,
                     80:                                const struct md_args *, int,
                     81:                                struct htmlq *, const int *,
                     82:                                const char **, size_t *);
                     83: static int             html_headtagargs(struct md_mbuf *,
1.3       kristaps   84:                                const struct md_args *, int,
1.7       kristaps   85:                                const int *, const char **, size_t *);
1.12    ! kristaps   86: static int             html_bodytagname(struct md_mbuf *,
1.10      kristaps   87:                                const struct md_args *,
                     88:                                int, struct htmlq *, const int *,
                     89:                                const char **, size_t *);
1.12    ! kristaps   90: static int             html_bodytagargs(struct md_mbuf *,
1.3       kristaps   91:                                const struct md_args *, int,
1.7       kristaps   92:                                const int *, const char **, size_t *);
                     93: static int             html_inlinetagname(struct md_mbuf *,
                     94:                                const struct md_args *, int, size_t *);
                     95: static int             html_inlinetagargs(struct md_mbuf *,
1.2       kristaps   96:                                const struct md_args *, int,
1.7       kristaps   97:                                const int *, const char **, size_t *);
1.10      kristaps   98: static int             html_Bl_bodytagname(struct md_mbuf *,
                     99:                                struct htmlq *, const int *,
                    100:                                const char **, size_t *);
                    101: static int             html_It_blocktagname(struct md_mbuf *,
                    102:                                struct htmlq *, const int *,
                    103:                                const char **, size_t *);
                    104: static int             html_It_headtagname(struct md_mbuf *,
                    105:                                struct htmlq *, const int *,
                    106:                                const char **, size_t *);
                    107: static int             html_It_bodytagname(struct md_mbuf *,
                    108:                                struct htmlq *, const int *,
                    109:                                const char **, size_t *);
                    110:
                    111:
                    112: /* ARGSUSED */
                    113: static int
                    114: html_It_headtagname(struct md_mbuf *mbuf, struct htmlq *q,
                    115:                const int *argc, const char **argv, size_t *res)
                    116: {
                    117:        struct htmlnode *n;
1.11      kristaps  118:        int              i;
1.10      kristaps  119:
                    120:        for (n = q->last; n; n = n->parent)
                    121:                if (n->tok == ROFF_Bl)
                    122:                        break;
                    123:
                    124:        assert(n);
1.11      kristaps  125:        for (i = 0; ROFF_ARGMAX != n->argc[i] &&
1.10      kristaps  126:                        i < ROFF_MAXLINEARG; i++) {
                    127:                switch (n->argc[i]) {
                    128:                case (ROFF_Tag):
                    129:                        /* FALLTHROUGH */
                    130:                case (ROFF_Column):
                    131:                        return(ml_nputs(mbuf, "td", 2, res));
                    132:                default:
                    133:                        break;
                    134:                }
                    135:        }
                    136:
                    137:        assert(i != ROFF_MAXLINEARG);
                    138:        abort();
                    139:        /* NOTREACHED */
                    140:
                    141:        return(1);
                    142: }
                    143:
                    144:
                    145: /* ARGSUSED */
                    146: static int
                    147: html_It_bodytagname(struct md_mbuf *mbuf, struct htmlq *q,
                    148:                const int *argc, const char **argv, size_t *res)
                    149: {
                    150:        struct htmlnode *n;
1.11      kristaps  151:        int              i;
1.10      kristaps  152:
                    153:        for (n = q->last; n; n = n->parent)
                    154:                if (n->tok == ROFF_Bl)
                    155:                        break;
                    156:
                    157:        assert(n);
1.11      kristaps  158:        for (i = 0; ROFF_ARGMAX != n->argc[i] &&
1.10      kristaps  159:                        i < ROFF_MAXLINEARG; i++) {
                    160:                switch (n->argc[i]) {
                    161:                case (ROFF_Enum):
                    162:                        /* FALLTHROUGH */
                    163:                case (ROFF_Bullet):
                    164:                        /* FALLTHROUGH */
                    165:                case (ROFF_Dash):
                    166:                        /* FALLTHROUGH */
                    167:                case (ROFF_Hyphen):
                    168:                        /* FALLTHROUGH */
                    169:                case (ROFF_Item):
                    170:                        /* FALLTHROUGH */
                    171:                case (ROFF_Diag):
                    172:                        /* FALLTHROUGH */
                    173:                case (ROFF_Hang):
                    174:                        /* FALLTHROUGH */
                    175:                case (ROFF_Ohang):
                    176:                        /* FALLTHROUGH */
                    177:                case (ROFF_Inset):
                    178:                        return(ml_nputs(mbuf, "div", 3, res));
                    179:                case (ROFF_Tag):
                    180:                        /* FALLTHROUGH */
                    181:                case (ROFF_Column):
                    182:                        return(ml_nputs(mbuf, "td", 2, res));
                    183:                default:
                    184:                        break;
                    185:                }
                    186:        }
                    187:
                    188:        assert(i != ROFF_MAXLINEARG);
                    189:        abort();
                    190:        /* NOTREACHED */
                    191:
                    192:        return(1);
                    193: }
                    194:
                    195:
                    196: /* ARGSUSED */
                    197: static int
                    198: html_Bl_bodytagname(struct md_mbuf *mbuf, struct htmlq *q,
                    199:                const int *argc, const char **argv, size_t *res)
                    200: {
1.11      kristaps  201:        int              i;
1.10      kristaps  202:
1.11      kristaps  203:        for (i = 0; ROFF_ARGMAX != argc[i]
1.10      kristaps  204:                        && i < ROFF_MAXLINEARG; i++) {
                    205:                switch (argc[i]) {
                    206:                case (ROFF_Enum):
                    207:                        return(ml_nputs(mbuf, "ol", 2, res));
                    208:                case (ROFF_Bullet):
                    209:                        /* FALLTHROUGH */
                    210:                case (ROFF_Dash):
                    211:                        /* FALLTHROUGH */
                    212:                case (ROFF_Hyphen):
                    213:                        /* FALLTHROUGH */
                    214:                case (ROFF_Item):
                    215:                        /* FALLTHROUGH */
                    216:                case (ROFF_Diag):
                    217:                        /* FALLTHROUGH */
                    218:                case (ROFF_Hang):
                    219:                        /* FALLTHROUGH */
                    220:                case (ROFF_Ohang):
                    221:                        /* FALLTHROUGH */
                    222:                case (ROFF_Inset):
                    223:                        return(ml_nputs(mbuf, "ul", 2, res));
                    224:                case (ROFF_Tag):
                    225:                        /* FALLTHROUGH */
                    226:                case (ROFF_Column):
                    227:                        return(ml_nputs(mbuf, "table", 5, res));
                    228:                default:
                    229:                        break;
                    230:                }
                    231:        }
                    232:
                    233:        assert(i != ROFF_MAXLINEARG);
                    234:        abort();
                    235:        /* NOTREACHED */
                    236: }
                    237:
                    238:
                    239: /* ARGSUSED */
                    240: static int
                    241: html_It_blocktagname(struct md_mbuf *mbuf, struct htmlq *q,
                    242:                const int *argc, const char **argv, size_t *res)
                    243: {
                    244:        struct htmlnode *n;
1.11      kristaps  245:        int              i;
1.10      kristaps  246:
                    247:        for (n = q->last; n; n = n->parent)
                    248:                if (n->tok == ROFF_Bl)
                    249:                        break;
                    250:
                    251:        assert(n);
1.11      kristaps  252:        for (i = 0; ROFF_ARGMAX != n->argc[i] &&
1.10      kristaps  253:                        i < ROFF_MAXLINEARG; i++) {
                    254:                switch (n->argc[i]) {
                    255:                case (ROFF_Enum):
                    256:                        /* FALLTHROUGH */
                    257:                case (ROFF_Bullet):
                    258:                        /* FALLTHROUGH */
                    259:                case (ROFF_Dash):
                    260:                        /* FALLTHROUGH */
                    261:                case (ROFF_Hyphen):
                    262:                        /* FALLTHROUGH */
                    263:                case (ROFF_Item):
                    264:                        /* FALLTHROUGH */
                    265:                case (ROFF_Diag):
                    266:                        /* FALLTHROUGH */
                    267:                case (ROFF_Hang):
                    268:                        /* FALLTHROUGH */
                    269:                case (ROFF_Ohang):
                    270:                        /* FALLTHROUGH */
                    271:                case (ROFF_Inset):
                    272:                        return(ml_nputs(mbuf, "li", 2, res));
                    273:                case (ROFF_Tag):
                    274:                        /* FALLTHROUGH */
                    275:                case (ROFF_Column):
                    276:                        return(ml_nputs(mbuf, "tr", 2, res));
                    277:                default:
                    278:                        break;
                    279:                }
                    280:        }
                    281:
                    282:        assert(i != ROFF_MAXLINEARG);
                    283:        abort();
                    284:        /* NOTREACHED */
                    285: }
1.2       kristaps  286:
                    287:
1.4       kristaps  288: static int
                    289: html_loadcss(struct md_mbuf *mbuf, const char *css)
                    290: {
                    291:        size_t           res, bufsz;
                    292:        char            *buf;
                    293:        struct stat      st;
                    294:        int              fd, c;
                    295:        ssize_t          ssz;
                    296:
                    297:        c = 0;
                    298:        res = 0;
                    299:        buf = NULL;
                    300:
                    301:        if (-1 == (fd = open(css, O_RDONLY, 0))) {
                    302:                warn("%s", css);
                    303:                return(0);
                    304:        }
                    305:
                    306:        if (-1 == fstat(fd, &st)) {
                    307:                warn("%s", css);
                    308:                goto out;
                    309:        }
                    310:
                    311:        bufsz = MAX(st.st_blksize, BUFSIZ);
                    312:        if (NULL == (buf = malloc(bufsz))) {
                    313:                warn("malloc");
                    314:                goto out;
                    315:        }
                    316:
                    317:        for (;;) {
                    318:                if (-1 == (ssz = read(fd, buf, bufsz))) {
                    319:                        warn("%s", css);
                    320:                        goto out;
                    321:                } else if (0 == ssz)
                    322:                        break;
                    323:                if ( ! ml_nputs(mbuf, buf, (size_t)ssz, &res))
                    324:                        goto out;
                    325:        }
                    326:
                    327:        c = 1;
                    328:
                    329: out:
                    330:        if (-1 == close(fd)) {
                    331:                warn("%s", css);
                    332:                c = 0;
                    333:        }
                    334:
                    335:        if (buf)
                    336:                free(buf);
                    337:
                    338:        return(c);
                    339: }
                    340:
                    341:
1.3       kristaps  342: /* ARGSUSED */
1.2       kristaps  343: static int
1.4       kristaps  344: html_begin(struct md_mbuf *mbuf, const struct md_args *args,
                    345:                const struct tm *tm, const char *os,
                    346:                const char *title, const char *section,
                    347:                const char *vol)
1.2       kristaps  348: {
1.4       kristaps  349:        const char      *preamble, *css, *trail;
                    350:        char             buf[512];
1.2       kristaps  351:        size_t           res;
                    352:
1.4       kristaps  353:        preamble =
                    354:        "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n"
                    355:        "    \"http://www.w3.org/TR/html4/strict.dtd\">\n"
                    356:        "<html>\n"
                    357:        "<head>\n"
                    358:        "    <meta http-equiv=\"Content-Type\"\n"
                    359:        "         content=\"text/html;charset=utf-8\">\n"
                    360:        "    <meta name=\"resource-type\" content=\"document\">\n"
                    361:        "    <title>Manual Page for %s(%s)</title>\n";
                    362:
                    363:        css =
                    364:        "    <link rel=\"stylesheet\" type=\"text/css\"\n"
                    365:        "         href=\"%s\">\n";
                    366:        trail =
                    367:        "</head>\n"
                    368:        "<body>\n"
1.10      kristaps  369:        "<div class=\"mdoc\">";
1.4       kristaps  370:
1.2       kristaps  371:        res = 0;
1.4       kristaps  372:
                    373:        (void)snprintf(buf, sizeof(buf) - 1,
                    374:                        preamble, title, section);
                    375:
                    376:        if ( ! ml_puts(mbuf, buf, &res))
1.2       kristaps  377:                return(0);
1.4       kristaps  378:
                    379:        assert(args->params.html.css);
                    380:        if (HTML_CSS_EMBED & args->params.html.flags) {
1.5       kristaps  381:                if ( ! ml_puts(mbuf, "    <style type=\"text/css\"><!--\n", &res))
1.4       kristaps  382:                        return(0);
                    383:                if ( ! html_loadcss(mbuf, args->params.html.css))
                    384:                        return(0);
                    385:                if ( ! ml_puts(mbuf, "    --!></style>\n", &res))
                    386:                        return(0);
                    387:        } else {
                    388:                (void)snprintf(buf, sizeof(buf) - 1, css,
                    389:                                args->params.html.css);
                    390:                if ( ! ml_puts(mbuf, buf, &res))
                    391:                        return(0);
                    392:        }
                    393:
                    394:        if ( ! ml_puts(mbuf, trail, &res))
1.2       kristaps  395:                return(0);
                    396:
                    397:        return(1);
                    398: }
                    399:
                    400:
1.3       kristaps  401: /* ARGSUSED */
1.2       kristaps  402: static int
                    403: html_end(struct md_mbuf *mbuf, const struct md_args *args)
                    404: {
                    405:
1.9       kristaps  406:        return(ml_puts(mbuf, "</div></body>\n</html>", NULL));
1.2       kristaps  407: }
                    408:
                    409:
1.3       kristaps  410: /* ARGSUSED */
1.7       kristaps  411: static int
1.12    ! kristaps  412: html_bodytagname(struct md_mbuf *mbuf,
1.10      kristaps  413:                const struct md_args *args, int tok, struct htmlq *q,
                    414:                const int *argc, const char **argv, size_t *res)
1.2       kristaps  415: {
1.3       kristaps  416:
1.10      kristaps  417:        switch (tok) {
                    418:        case (ROFF_Bl):
                    419:                return(html_Bl_bodytagname(mbuf, q, argc, argv, res));
1.12    ! kristaps  420:        case (ROFF_Fo):
        !           421:                return(ml_nputs(mbuf, "span", 4, res));
1.10      kristaps  422:        case (ROFF_It):
                    423:                return(html_It_bodytagname(mbuf, q, argc, argv, res));
1.12    ! kristaps  424:        case (ROFF_Oo):
        !           425:                return(ml_nputs(mbuf, "span", 4, res));
1.10      kristaps  426:        default:
                    427:                break;
                    428:        }
                    429:
1.7       kristaps  430:        return(ml_puts(mbuf, "div", res));
1.3       kristaps  431: }
                    432:
                    433:
                    434: /* ARGSUSED */
1.7       kristaps  435: static int
1.10      kristaps  436: html_headtagname(struct md_mbuf *mbuf,
                    437:                const struct md_args *args, int tok, struct htmlq *q,
                    438:                const int *argc, const char **argv, size_t *res)
1.3       kristaps  439: {
                    440:
1.10      kristaps  441:        switch (tok) {
                    442:        case (ROFF_It):
                    443:                return(html_It_headtagname(mbuf, q, argc, argv, res));
1.12    ! kristaps  444:        case (ROFF_Fo):
        !           445:                return(ml_nputs(mbuf, "span", 4, res));
        !           446:        case (ROFF_Oo):
        !           447:                return(ml_nputs(mbuf, "span", 4, res));
1.10      kristaps  448:        case (ROFF_Sh):
1.12    ! kristaps  449:                return(ml_nputs(mbuf, "h1", 2, res));
1.10      kristaps  450:        case (ROFF_Ss):
1.12    ! kristaps  451:                return(ml_nputs(mbuf, "h2", 2, res));
1.10      kristaps  452:        default:
                    453:                break;
                    454:        }
                    455:
1.12    ! kristaps  456:        return(ml_nputs(mbuf, "div", 3, res));
1.3       kristaps  457: }
                    458:
                    459:
                    460: /* ARGSUSED */
1.7       kristaps  461: static int
1.10      kristaps  462: html_blocktagname(struct md_mbuf *mbuf, const struct md_args *args,
                    463:                int tok, struct htmlq *q, const int *argc,
                    464:                const char **argv, size_t *res)
1.3       kristaps  465: {
                    466:
1.10      kristaps  467:        switch (tok) {
1.12    ! kristaps  468:        case (ROFF_Fo):
        !           469:                return(ml_nputs(mbuf, "span", 4, res));
        !           470:        case (ROFF_Oo):
        !           471:                return(ml_nputs(mbuf, "span", 4, res));
1.10      kristaps  472:        case (ROFF_It):
                    473:                return(html_It_blocktagname(mbuf, q, argc, argv, res));
                    474:        default:
                    475:                break;
                    476:        }
                    477:
1.7       kristaps  478:        return(ml_puts(mbuf, "div", res));
1.3       kristaps  479: }
                    480:
                    481:
1.9       kristaps  482: /* ARGSUSED */
1.7       kristaps  483: static int
                    484: html_printargs(struct md_mbuf *mbuf, int tok, const char *ns,
                    485:                const int *argc, const char **argv, size_t *res)
1.3       kristaps  486: {
                    487:
1.7       kristaps  488:        if ( ! ml_puts(mbuf, " class=\"", res))
                    489:                return(0);
                    490:        if ( ! ml_puts(mbuf, ns, res))
                    491:                return(0);
                    492:        if ( ! ml_puts(mbuf, "-", res))
1.3       kristaps  493:                return(0);
1.7       kristaps  494:        if ( ! ml_puts(mbuf, toknames[tok], res))
1.3       kristaps  495:                return(0);
1.9       kristaps  496:        return(ml_puts(mbuf, "\"", res));
1.3       kristaps  497: }
                    498:
                    499:
                    500: /* ARGSUSED */
1.7       kristaps  501: static int
1.10      kristaps  502: html_headtagargs(struct md_mbuf *mbuf,
1.7       kristaps  503:                const struct md_args *args, int tok,
                    504:                const int *argc, const char **argv, size_t *res)
1.3       kristaps  505: {
                    506:
1.7       kristaps  507:        return(html_printargs(mbuf, tok, "head", argc, argv, res));
                    508: }
1.3       kristaps  509:
                    510:
1.7       kristaps  511: /* ARGSUSED */
                    512: static int
1.12    ! kristaps  513: html_bodytagargs(struct md_mbuf *mbuf,
1.7       kristaps  514:                const struct md_args *args, int tok,
                    515:                const int *argc, const char **argv, size_t *res)
                    516: {
1.3       kristaps  517:
1.7       kristaps  518:        return(html_printargs(mbuf, tok, "body", argc, argv, res));
1.2       kristaps  519: }
                    520:
                    521:
                    522: /* ARGSUSED */
1.7       kristaps  523: static int
                    524: html_blocktagargs(struct md_mbuf *mbuf,
                    525:                const struct md_args *args, int tok,
                    526:                const int *argc, const char **argv, size_t *res)
1.2       kristaps  527: {
1.3       kristaps  528:
1.7       kristaps  529:        return(html_printargs(mbuf, tok, "block", argc, argv, res));
1.2       kristaps  530: }
1.1       kristaps  531:
                    532:
                    533: /* ARGSUSED */
1.7       kristaps  534: static int
                    535: html_inlinetagargs(struct md_mbuf *mbuf,
                    536:                const struct md_args *args, int tok,
                    537:                const int *argc, const char **argv, size_t *res)
1.2       kristaps  538: {
                    539:
1.12    ! kristaps  540:        if ( ! html_printargs(mbuf, tok, "inline", argc, argv, res))
        !           541:                return(0);
        !           542:
        !           543:        switch (tok) {
        !           544:        case (ROFF_Sx):
        !           545:                assert(*argv);
        !           546:                if ( ! ml_nputs(mbuf, " href=\"#", 8, res))
        !           547:                        return(0);
        !           548:                if ( ! ml_putstring(mbuf, *argv, res))
        !           549:                        return(0);
        !           550:                if ( ! ml_nputs(mbuf, "\"", 1, res))
        !           551:                        return(0);
        !           552:        default:
        !           553:                break;
        !           554:        }
        !           555:
        !           556:        return(1);
1.2       kristaps  557: }
                    558:
                    559:
1.3       kristaps  560: /* ARGSUSED */
1.7       kristaps  561: static int
1.2       kristaps  562: html_inlinetagname(struct md_mbuf *mbuf,
1.7       kristaps  563:                const struct md_args *args, int tok, size_t *res)
1.2       kristaps  564: {
                    565:
                    566:        switch (tok) {
1.4       kristaps  567:        case (ROFF_Pp):
1.12    ! kristaps  568:                return(ml_nputs(mbuf, "div", 3, res));
        !           569:        case (ROFF_Sx):
        !           570:                return(ml_nputs(mbuf, "a", 1, res));
1.2       kristaps  571:        default:
1.9       kristaps  572:                break;
1.2       kristaps  573:        }
1.9       kristaps  574:
                    575:        return(ml_puts(mbuf, "span", res));
1.2       kristaps  576: }
                    577:
                    578:
                    579: static ssize_t
1.8       kristaps  580: html_begintag(struct md_mbuf *mbuf, void *data,
                    581:                const struct md_args *args, enum md_ns ns,
                    582:                int tok, const int *argc, const char **argv)
1.2       kristaps  583: {
1.7       kristaps  584:        size_t           res;
1.8       kristaps  585:        struct htmlq    *q;
                    586:        struct htmlnode *node;
1.11      kristaps  587:        int              i;
1.2       kristaps  588:
                    589:        assert(ns != MD_NS_DEFAULT);
1.7       kristaps  590:        res = 0;
                    591:
1.8       kristaps  592:        assert(data);
                    593:        q = (struct htmlq *)data;
                    594:
                    595:        if (NULL == (node = calloc(1, sizeof(struct htmlnode)))) {
                    596:                warn("calloc");
                    597:                return(-1);
                    598:        }
                    599:
                    600:        node->parent = q->last;
                    601:        node->tok = tok;
                    602:        node->ns = ns;
                    603:
1.10      kristaps  604:        if (argc)  {
                    605:                /* TODO: argv. */
                    606:
                    607:                assert(argv);
1.11      kristaps  608:                for (i = 0; ROFF_ARGMAX != argc[i]
1.10      kristaps  609:                                && i < ROFF_MAXLINEARG; i++)
                    610:                        node->argc[i] = argc[i];
                    611:                assert(i != ROFF_MAXLINEARG);
1.12    ! kristaps  612:        }
1.10      kristaps  613:
                    614:
1.8       kristaps  615:        q->last = node;
                    616:
1.3       kristaps  617:        switch (ns) {
                    618:        case (MD_NS_BLOCK):
1.10      kristaps  619:                if ( ! html_blocktagname(mbuf, args, tok,
                    620:                                        q, argc, argv, &res))
1.7       kristaps  621:                        return(-1);
                    622:                if ( ! html_blocktagargs(mbuf, args, tok,
                    623:                                        argc, argv, &res))
                    624:                        return(-1);
                    625:                break;
1.3       kristaps  626:        case (MD_NS_BODY):
1.12    ! kristaps  627:                if ( ! html_bodytagname(mbuf, args, tok,
1.10      kristaps  628:                                        q, argc, argv, &res))
1.7       kristaps  629:                        return(-1);
1.12    ! kristaps  630:                if ( ! html_bodytagargs(mbuf, args, tok,
1.7       kristaps  631:                                        argc, argv, &res))
                    632:                        return(-1);
                    633:                break;
1.3       kristaps  634:        case (MD_NS_HEAD):
1.10      kristaps  635:                if ( ! html_headtagname(mbuf, args, tok, q,
                    636:                                        argc, argv, &res))
1.7       kristaps  637:                        return(-1);
1.10      kristaps  638:                if ( ! html_headtagargs(mbuf, args, tok,
1.7       kristaps  639:                                        argc, argv, &res))
                    640:                        return(-1);
                    641:                break;
1.3       kristaps  642:        default:
1.7       kristaps  643:                if ( ! html_inlinetagname(mbuf, args, tok, &res))
                    644:                        return(-1);
                    645:                if ( ! html_inlinetagargs(mbuf, args, tok,
                    646:                                        argc, argv, &res))
                    647:                        return(-1);
1.3       kristaps  648:                break;
1.2       kristaps  649:        }
                    650:
1.7       kristaps  651:        return((ssize_t)res);
1.2       kristaps  652: }
                    653:
                    654:
                    655: static ssize_t
1.8       kristaps  656: html_endtag(struct md_mbuf *mbuf, void *data,
                    657:                const struct md_args *args, enum md_ns ns, int tok)
1.2       kristaps  658: {
1.7       kristaps  659:        size_t           res;
1.8       kristaps  660:        struct htmlq    *q;
                    661:        struct htmlnode *node;
1.2       kristaps  662:
                    663:        assert(ns != MD_NS_DEFAULT);
1.7       kristaps  664:        res = 0;
                    665:
1.8       kristaps  666:        assert(data);
                    667:        q = (struct htmlq *)data;
1.10      kristaps  668:        node = q->last;
1.8       kristaps  669:
1.3       kristaps  670:        switch (ns) {
                    671:        case (MD_NS_BLOCK):
1.10      kristaps  672:                if ( ! html_blocktagname(mbuf, args, tok,
                    673:                                        q, node->argc,
                    674:                                        (const char **)node->argv, &res))
1.7       kristaps  675:                        return(-1);
                    676:                break;
1.3       kristaps  677:        case (MD_NS_BODY):
1.12    ! kristaps  678:                if ( ! html_bodytagname(mbuf, args, tok,
1.10      kristaps  679:                                        q, node->argc,
                    680:                                        (const char **)node->argv, &res))
1.7       kristaps  681:                        return(-1);
                    682:                break;
1.3       kristaps  683:        case (MD_NS_HEAD):
1.10      kristaps  684:                if ( ! html_headtagname(mbuf, args, tok,
                    685:                                        q, node->argc,
                    686:                                        (const char **)node->argv, &res))
1.7       kristaps  687:                        return(-1);
                    688:                break;
1.3       kristaps  689:        default:
1.7       kristaps  690:                if ( ! html_inlinetagname(mbuf, args, tok, &res))
                    691:                        return(-1);
1.3       kristaps  692:                break;
                    693:        }
1.2       kristaps  694:
1.8       kristaps  695:        q->last = node->parent;
                    696:
1.9       kristaps  697:        free(node);
1.8       kristaps  698:
1.7       kristaps  699:        return((ssize_t)res);
1.2       kristaps  700: }
                    701:
                    702:
1.9       kristaps  703: static int
                    704: html_alloc(void **p)
                    705: {
                    706:
                    707:        if (NULL == (*p = calloc(1, sizeof(struct htmlq)))) {
                    708:                warn("calloc");
                    709:                return(0);
                    710:        }
                    711:        return(1);
                    712: }
                    713:
                    714:
                    715: static void
                    716: html_free(void *p)
                    717: {
                    718:        struct htmlq    *q;
                    719:        struct htmlnode *n;
                    720:
                    721:        assert(p);
                    722:        q = (struct htmlq *)p;
                    723:
                    724:        while ((n = q->last)) {
                    725:                q->last = n->parent;
                    726:                free(n);
                    727:        }
                    728:
                    729:        free(q);
                    730: }
                    731:
                    732:
1.1       kristaps  733: int
                    734: md_line_html(void *data, char *buf)
                    735: {
                    736:
1.2       kristaps  737:        return(mlg_line((struct md_mlg *)data, buf));
1.1       kristaps  738: }
                    739:
                    740:
                    741: int
                    742: md_exit_html(void *data, int flush)
                    743: {
                    744:
1.2       kristaps  745:        return(mlg_exit((struct md_mlg *)data, flush));
1.1       kristaps  746: }
                    747:
                    748:
                    749: void *
                    750: md_init_html(const struct md_args *args,
                    751:                struct md_mbuf *mbuf, const struct md_rbuf *rbuf)
                    752: {
1.9       kristaps  753:        struct ml_cbs    cbs;
1.8       kristaps  754:
1.9       kristaps  755:        cbs.ml_alloc = html_alloc;
                    756:        cbs.ml_free = html_free;
                    757:        cbs.ml_begintag = html_begintag;
                    758:        cbs.ml_endtag = html_endtag;
                    759:        cbs.ml_begin = html_begin;
                    760:        cbs.ml_end = html_end;
1.1       kristaps  761:
1.9       kristaps  762:        return(mlg_alloc(args, rbuf, mbuf, &cbs));
1.1       kristaps  763: }
1.2       kristaps  764:

CVSweb