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

Annotation of mandoc/html.c, Revision 1.13

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

CVSweb