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

Annotation of mandoc/html.c, Revision 1.16

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

CVSweb