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

Annotation of mandoc/html.c, Revision 1.14

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

CVSweb