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

Annotation of mandoc/html.c, Revision 1.25

1.25    ! kristaps    1: /* $Id: html.c,v 1.24 2008/12/10 13:41:58 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:
1.19      kristaps   30: #include "html.h"
1.2       kristaps   31: #include "ml.h"
                     32:
1.8       kristaps   33: /* TODO: allow head/tail-less invocations (just "div" start). */
                     34:
1.7       kristaps   35: struct htmlnode {
1.8       kristaps   36:        int              tok;
                     37:        enum md_ns       ns;
1.10      kristaps   38:        int              argc[ROFF_MAXLINEARG];
1.7       kristaps   39:        char            *argv[ROFF_MAXLINEARG];
                     40:        struct htmlnode *parent;
                     41: };
                     42:
                     43: struct htmlq {
                     44:        struct htmlnode *last;
                     45: };
                     46:
                     47:
1.19      kristaps   48: static int             html_loadcss(struct md_mbuf *,
                     49:                                const char *);
1.9       kristaps   50: static int             html_alloc(void **);
                     51: static void            html_free(void *);
1.25    ! kristaps   52: static ssize_t         html_endtag(struct ml_args *,
1.2       kristaps   53:                                enum md_ns, int);
1.25    ! kristaps   54: static ssize_t         html_beginstring(struct ml_args *,
1.14      kristaps   55:                                const char *, size_t);
1.25    ! kristaps   56: static ssize_t         html_endstring(struct ml_args *,
1.14      kristaps   57:                                const char *, size_t);
1.25    ! kristaps   58: static ssize_t         html_begintag(struct ml_args *,
        !            59:                                enum md_ns, int,
1.2       kristaps   60:                                const int *, const char **);
1.25    ! kristaps   61: static int             html_begin(struct ml_args *,
        !            62:                                const struct tm *,
        !            63:                                const char *, const char *,
        !            64:                                enum roffmsec, enum roffvol);
        !            65: static int             html_end(struct ml_args *,
1.4       kristaps   66:                                const struct tm *,
                     67:                                const char *, const char *,
1.21      kristaps   68:                                enum roffmsec, enum roffvol);
1.7       kristaps   69: static int             html_printargs(struct md_mbuf *, int,
                     70:                                const char *, const int *,
                     71:                                const char **, size_t *);
1.25    ! kristaps   72: static ssize_t         html_beginhttp(struct md_mbuf *,
        !            73:                                const struct md_args *,
        !            74:                                const char *, size_t);
        !            75: static ssize_t         html_endhttp(struct md_mbuf *,
        !            76:                                const struct md_args *,
        !            77:                                const char *, size_t);
1.7       kristaps   78: static int             html_blocktagname(struct md_mbuf *,
1.10      kristaps   79:                                const struct md_args *, int,
                     80:                                struct htmlq *, const int *,
                     81:                                const char **, size_t *);
1.7       kristaps   82: static int             html_blocktagargs(struct md_mbuf *,
1.2       kristaps   83:                                const struct md_args *, int,
1.7       kristaps   84:                                const int *, const char **, size_t *);
1.10      kristaps   85: static int             html_headtagname(struct md_mbuf *,
                     86:                                const struct md_args *, int,
                     87:                                struct htmlq *, const int *,
                     88:                                const char **, size_t *);
                     89: static int             html_headtagargs(struct md_mbuf *,
1.3       kristaps   90:                                const struct md_args *, int,
1.7       kristaps   91:                                const int *, const char **, size_t *);
1.12      kristaps   92: static int             html_bodytagname(struct md_mbuf *,
1.10      kristaps   93:                                const struct md_args *,
                     94:                                int, struct htmlq *, const int *,
                     95:                                const char **, size_t *);
1.12      kristaps   96: static int             html_bodytagargs(struct md_mbuf *,
1.3       kristaps   97:                                const struct md_args *, int,
1.7       kristaps   98:                                const int *, const char **, size_t *);
                     99: static int             html_inlinetagname(struct md_mbuf *,
                    100:                                const struct md_args *, int, size_t *);
                    101: static int             html_inlinetagargs(struct md_mbuf *,
1.2       kristaps  102:                                const struct md_args *, int,
1.7       kristaps  103:                                const int *, const char **, size_t *);
1.10      kristaps  104: static int             html_Bl_bodytagname(struct md_mbuf *,
                    105:                                struct htmlq *, const int *,
                    106:                                const char **, size_t *);
                    107: static int             html_It_blocktagname(struct md_mbuf *,
                    108:                                struct htmlq *, const int *,
                    109:                                const char **, size_t *);
                    110: static int             html_It_headtagname(struct md_mbuf *,
                    111:                                struct htmlq *, const int *,
                    112:                                const char **, size_t *);
                    113: static int             html_It_bodytagname(struct md_mbuf *,
                    114:                                struct htmlq *, const int *,
                    115:                                const char **, size_t *);
1.19      kristaps  116: static int             html_tputln(struct md_mbuf *,
                    117:                                enum ml_scope, int, enum html_tag);
                    118: static int             html_aputln(struct md_mbuf *, enum ml_scope,
                    119:                                int, enum html_tag,
                    120:                                int, const struct html_pair *);
1.10      kristaps  121:
                    122:
                    123: /* ARGSUSED */
                    124: static int
                    125: html_It_headtagname(struct md_mbuf *mbuf, struct htmlq *q,
                    126:                const int *argc, const char **argv, size_t *res)
                    127: {
                    128:        struct htmlnode *n;
1.11      kristaps  129:        int              i;
1.10      kristaps  130:
                    131:        for (n = q->last; n; n = n->parent)
                    132:                if (n->tok == ROFF_Bl)
                    133:                        break;
                    134:
                    135:        assert(n);
1.13      kristaps  136:
                    137:        /* LINTED */
1.11      kristaps  138:        for (i = 0; ROFF_ARGMAX != n->argc[i] &&
1.10      kristaps  139:                        i < ROFF_MAXLINEARG; i++) {
                    140:                switch (n->argc[i]) {
1.14      kristaps  141:                case (ROFF_Ohang):
1.19      kristaps  142:                        return(html_stput(mbuf, HTML_TAG_DIV, res));
1.10      kristaps  143:                case (ROFF_Tag):
                    144:                        /* FALLTHROUGH */
                    145:                case (ROFF_Column):
1.19      kristaps  146:                        return(html_stput(mbuf, HTML_TAG_TD, res));
1.10      kristaps  147:                default:
                    148:                        break;
                    149:                }
                    150:        }
                    151:
1.16      kristaps  152:        return(0);
1.10      kristaps  153: }
                    154:
                    155:
                    156: /* ARGSUSED */
                    157: static int
                    158: html_It_bodytagname(struct md_mbuf *mbuf, struct htmlq *q,
                    159:                const int *argc, const char **argv, size_t *res)
                    160: {
                    161:        struct htmlnode *n;
1.11      kristaps  162:        int              i;
1.10      kristaps  163:
                    164:        for (n = q->last; n; n = n->parent)
                    165:                if (n->tok == ROFF_Bl)
                    166:                        break;
                    167:
                    168:        assert(n);
1.13      kristaps  169:
                    170:        /* LINTED */
1.11      kristaps  171:        for (i = 0; ROFF_ARGMAX != n->argc[i] &&
1.10      kristaps  172:                        i < ROFF_MAXLINEARG; i++) {
                    173:                switch (n->argc[i]) {
                    174:                case (ROFF_Enum):
                    175:                        /* FALLTHROUGH */
                    176:                case (ROFF_Bullet):
                    177:                        /* FALLTHROUGH */
                    178:                case (ROFF_Dash):
                    179:                        /* FALLTHROUGH */
                    180:                case (ROFF_Hyphen):
                    181:                        /* FALLTHROUGH */
                    182:                case (ROFF_Item):
                    183:                        /* FALLTHROUGH */
                    184:                case (ROFF_Diag):
                    185:                        /* FALLTHROUGH */
                    186:                case (ROFF_Hang):
                    187:                        /* FALLTHROUGH */
                    188:                case (ROFF_Ohang):
                    189:                        /* FALLTHROUGH */
                    190:                case (ROFF_Inset):
1.19      kristaps  191:                        return(html_stput(mbuf, HTML_TAG_DIV, res));
1.10      kristaps  192:                case (ROFF_Tag):
                    193:                        /* FALLTHROUGH */
                    194:                case (ROFF_Column):
1.19      kristaps  195:                        return(html_stput(mbuf, HTML_TAG_TD, res));
1.10      kristaps  196:                default:
                    197:                        break;
                    198:                }
                    199:        }
                    200:
                    201:        assert(i != ROFF_MAXLINEARG);
1.16      kristaps  202:        return(0);
1.10      kristaps  203: }
                    204:
                    205:
                    206: /* ARGSUSED */
                    207: static int
                    208: html_Bl_bodytagname(struct md_mbuf *mbuf, struct htmlq *q,
                    209:                const int *argc, const char **argv, size_t *res)
                    210: {
1.11      kristaps  211:        int              i;
1.10      kristaps  212:
1.11      kristaps  213:        for (i = 0; ROFF_ARGMAX != argc[i]
1.10      kristaps  214:                        && i < ROFF_MAXLINEARG; i++) {
                    215:                switch (argc[i]) {
                    216:                case (ROFF_Enum):
1.19      kristaps  217:                        return(html_stput(mbuf, HTML_TAG_OL, res));
1.10      kristaps  218:                case (ROFF_Bullet):
                    219:                        /* FALLTHROUGH */
                    220:                case (ROFF_Dash):
                    221:                        /* FALLTHROUGH */
                    222:                case (ROFF_Hyphen):
                    223:                        /* FALLTHROUGH */
                    224:                case (ROFF_Item):
                    225:                        /* FALLTHROUGH */
                    226:                case (ROFF_Diag):
                    227:                        /* FALLTHROUGH */
                    228:                case (ROFF_Hang):
                    229:                        /* FALLTHROUGH */
                    230:                case (ROFF_Ohang):
                    231:                        /* FALLTHROUGH */
                    232:                case (ROFF_Inset):
1.19      kristaps  233:                        return(html_stput(mbuf, HTML_TAG_UL, res));
1.10      kristaps  234:                case (ROFF_Tag):
                    235:                        /* FALLTHROUGH */
                    236:                case (ROFF_Column):
1.19      kristaps  237:                        return(html_stput(mbuf, HTML_TAG_TABLE, res));
1.10      kristaps  238:                default:
                    239:                        break;
                    240:                }
                    241:        }
                    242:
                    243:        assert(i != ROFF_MAXLINEARG);
1.16      kristaps  244:        return(0);
1.10      kristaps  245: }
                    246:
                    247:
                    248: /* ARGSUSED */
                    249: static int
                    250: html_It_blocktagname(struct md_mbuf *mbuf, struct htmlq *q,
                    251:                const int *argc, const char **argv, size_t *res)
                    252: {
                    253:        struct htmlnode *n;
1.11      kristaps  254:        int              i;
1.10      kristaps  255:
                    256:        for (n = q->last; n; n = n->parent)
                    257:                if (n->tok == ROFF_Bl)
                    258:                        break;
                    259:
                    260:        assert(n);
1.13      kristaps  261:
                    262:        /* LINTED */
1.11      kristaps  263:        for (i = 0; ROFF_ARGMAX != n->argc[i] &&
1.10      kristaps  264:                        i < ROFF_MAXLINEARG; i++) {
                    265:                switch (n->argc[i]) {
                    266:                case (ROFF_Enum):
                    267:                        /* FALLTHROUGH */
                    268:                case (ROFF_Bullet):
                    269:                        /* FALLTHROUGH */
                    270:                case (ROFF_Dash):
                    271:                        /* FALLTHROUGH */
                    272:                case (ROFF_Hyphen):
                    273:                        /* FALLTHROUGH */
                    274:                case (ROFF_Item):
                    275:                        /* FALLTHROUGH */
                    276:                case (ROFF_Diag):
                    277:                        /* FALLTHROUGH */
                    278:                case (ROFF_Hang):
                    279:                        /* FALLTHROUGH */
                    280:                case (ROFF_Ohang):
                    281:                        /* FALLTHROUGH */
                    282:                case (ROFF_Inset):
1.19      kristaps  283:                        return(html_stput(mbuf, HTML_TAG_LI, res));
1.10      kristaps  284:                case (ROFF_Tag):
                    285:                        /* FALLTHROUGH */
                    286:                case (ROFF_Column):
1.19      kristaps  287:                        return(html_stput(mbuf, HTML_TAG_TR, res));
1.10      kristaps  288:                default:
                    289:                        break;
                    290:                }
                    291:        }
                    292:
                    293:        assert(i != ROFF_MAXLINEARG);
1.16      kristaps  294:        return(0);
1.10      kristaps  295: }
1.2       kristaps  296:
                    297:
1.4       kristaps  298: static int
                    299: html_loadcss(struct md_mbuf *mbuf, const char *css)
                    300: {
                    301:        size_t           res, bufsz;
                    302:        char            *buf;
                    303:        struct stat      st;
                    304:        int              fd, c;
                    305:        ssize_t          ssz;
                    306:
                    307:        c = 0;
                    308:        res = 0;
                    309:        buf = NULL;
                    310:
                    311:        if (-1 == (fd = open(css, O_RDONLY, 0))) {
                    312:                warn("%s", css);
                    313:                return(0);
                    314:        }
                    315:
                    316:        if (-1 == fstat(fd, &st)) {
                    317:                warn("%s", css);
                    318:                goto out;
                    319:        }
                    320:
                    321:        bufsz = MAX(st.st_blksize, BUFSIZ);
                    322:        if (NULL == (buf = malloc(bufsz))) {
                    323:                warn("malloc");
                    324:                goto out;
                    325:        }
                    326:
                    327:        for (;;) {
                    328:                if (-1 == (ssz = read(fd, buf, bufsz))) {
                    329:                        warn("%s", css);
                    330:                        goto out;
                    331:                } else if (0 == ssz)
                    332:                        break;
                    333:                if ( ! ml_nputs(mbuf, buf, (size_t)ssz, &res))
                    334:                        goto out;
                    335:        }
                    336:
                    337:        c = 1;
                    338:
                    339: out:
                    340:        if (-1 == close(fd)) {
                    341:                warn("%s", css);
                    342:                c = 0;
                    343:        }
                    344:
                    345:        if (buf)
                    346:                free(buf);
                    347:
                    348:        return(c);
                    349: }
                    350:
                    351:
1.18      kristaps  352: static int
1.19      kristaps  353: html_tputln(struct md_mbuf *mbuf, enum ml_scope scope,
                    354:                int i, enum html_tag tag)
1.18      kristaps  355: {
                    356:
1.19      kristaps  357:        if ( ! ml_putchars(mbuf, ' ', INDENT(i) * INDENT_SZ, NULL))
1.18      kristaps  358:                return(0);
1.19      kristaps  359:        if ( ! html_tput(mbuf, scope, tag, NULL))
1.18      kristaps  360:                return(0);
1.19      kristaps  361:        return(ml_nputs(mbuf, "\n", 1, NULL));
1.18      kristaps  362: }
                    363:
                    364:
                    365: static int
1.19      kristaps  366: html_aputln(struct md_mbuf *mbuf, enum ml_scope scope, int i,
                    367:                enum html_tag tag, int sz, const struct html_pair *p)
1.18      kristaps  368: {
                    369:
1.19      kristaps  370:        if ( ! ml_putchars(mbuf, ' ', INDENT(i) * INDENT_SZ, NULL))
1.18      kristaps  371:                return(0);
1.19      kristaps  372:        if ( ! html_aput(mbuf, scope, tag, NULL, sz, p))
                    373:                return(0);
                    374:        return(ml_nputs(mbuf, "\n", 1, NULL));
1.18      kristaps  375: }
                    376:
                    377:
1.3       kristaps  378: /* ARGSUSED */
1.2       kristaps  379: static int
1.25    ! kristaps  380: html_begin(struct ml_args *p, const struct tm *tm, const char *os,
1.21      kristaps  381:                const char *name, enum roffmsec msec, enum roffvol vol)
1.2       kristaps  382: {
1.22      kristaps  383:        enum roffvol     bvol;
1.19      kristaps  384:        struct html_pair attr[4];
1.21      kristaps  385:        char             ts[32], title[64];
1.19      kristaps  386:        int              i;
1.2       kristaps  387:
1.19      kristaps  388:        (void)snprintf(ts, sizeof(ts), "%s(%s)",
                    389:                        name, roff_msecname(msec));
1.4       kristaps  390:
1.21      kristaps  391:        if (vol >= ROFF_ARCH_START) {
1.22      kristaps  392:                switch (msec) {
                    393:                case(ROFF_MSEC_1):
                    394:                        /* FALLTHROUGH */
                    395:                case(ROFF_MSEC_6):
                    396:                        /* FALLTHROUGH */
                    397:                case(ROFF_MSEC_7):
                    398:                        bvol = ROFF_VOL_URM;
                    399:                        break;
                    400:                case(ROFF_MSEC_2):
                    401:                        /* FALLTHROUGH */
                    402:                case(ROFF_MSEC_3):
                    403:                        /* FALLTHROUGH */
                    404:                case(ROFF_MSEC_3p):
                    405:                        /* FALLTHROUGH */
                    406:                case(ROFF_MSEC_4):
                    407:                        /* FALLTHROUGH */
                    408:                case(ROFF_MSEC_5):
                    409:                        bvol = ROFF_VOL_PRM;
                    410:                        break;
                    411:                case(ROFF_MSEC_8):
                    412:                        bvol = ROFF_VOL_PRM;
                    413:                        break;
                    414:                case(ROFF_MSEC_9):
                    415:                        bvol = ROFF_VOL_KM;
                    416:                        break;
                    417:                case(ROFF_MSEC_UNASS):
                    418:                        /* FALLTHROUGH */
                    419:                case(ROFF_MSEC_DRAFT):
                    420:                        /* FALLTHROUGH */
                    421:                case(ROFF_MSEC_PAPER):
                    422:                        bvol = ROFF_VOL_NONE;
                    423:                        break;
                    424:                default:
                    425:                        abort();
                    426:                        /* NOTREACHED */
                    427:                }
1.21      kristaps  428:
1.22      kristaps  429:                (void)snprintf(title, sizeof(title), "%s (%s)",
                    430:                                roff_volname(bvol), roff_volname(vol));
                    431:        } else
                    432:                (void)snprintf(title, sizeof(title), "%s", roff_volname(vol));
1.21      kristaps  433:
                    434:
1.18      kristaps  435:        i = 0;
1.4       kristaps  436:
1.25    ! kristaps  437:        if ( ! html_typeput(p->mbuf, HTML_TYPE_4_01_STRICT, NULL))
1.17      kristaps  438:                return(0);
1.25    ! kristaps  439:        if ( ! html_tputln(p->mbuf, ML_OPEN, i, HTML_TAG_HTML))
1.17      kristaps  440:                return(0);
1.25    ! kristaps  441:        if ( ! html_tputln(p->mbuf, ML_OPEN, i++, HTML_TAG_HEAD))
1.17      kristaps  442:                return(0);
1.19      kristaps  443:
                    444:        attr[0].attr = HTML_ATTR_HTTP_EQUIV;
                    445:        attr[0].val = "content-type";
                    446:        attr[1].attr = HTML_ATTR_CONTENT;
                    447:        attr[1].val = "text/html;charset=utf-8";
                    448:
1.25    ! kristaps  449:        if ( ! html_aputln(p->mbuf, ML_OPEN, i, HTML_TAG_META, 2, attr))
1.17      kristaps  450:                return(0);
1.19      kristaps  451:
                    452:        attr[0].attr = HTML_ATTR_NAME;
                    453:        attr[0].val = "resource-type";
                    454:        attr[1].attr = HTML_ATTR_CONTENT;
                    455:        attr[1].val = "document";
                    456:
1.25    ! kristaps  457:        if ( ! html_aputln(p->mbuf, ML_OPEN, i, HTML_TAG_META, 2, attr))
1.17      kristaps  458:                return(0);
1.19      kristaps  459:
1.25    ! kristaps  460:        if ( ! html_tputln(p->mbuf, ML_OPEN, i, HTML_TAG_TITLE))
1.17      kristaps  461:                return(0);
1.25    ! kristaps  462:        if ( ! ml_putstring(p->mbuf, ts, NULL))
1.17      kristaps  463:                return(0);
1.25    ! kristaps  464:        if ( ! html_tputln(p->mbuf, ML_CLOSE, i, HTML_TAG_TITLE))
1.2       kristaps  465:                return(0);
1.4       kristaps  466:
1.25    ! kristaps  467:        if (HTML_CSS_EMBED & p->args->params.html.flags) {
1.19      kristaps  468:                attr[0].attr = HTML_ATTR_TYPE;
                    469:                attr[0].val = "text/css";
                    470:
1.25    ! kristaps  471:                if ( ! html_aputln(p->mbuf, ML_OPEN, i,
1.19      kristaps  472:                                        HTML_TAG_STYLE, 1, attr))
1.4       kristaps  473:                        return(0);
1.25    ! kristaps  474:                if ( ! html_commentput(p->mbuf, ML_OPEN, NULL))
1.22      kristaps  475:                        return(0);
1.19      kristaps  476:
1.25    ! kristaps  477:                if ( ! html_loadcss(p->mbuf, p->args->params.html.css))
1.4       kristaps  478:                        return(0);
1.19      kristaps  479:
1.25    ! kristaps  480:                if ( ! html_commentput(p->mbuf, ML_CLOSE, NULL))
1.22      kristaps  481:                        return(0);
1.25    ! kristaps  482:                if ( ! html_tputln(p->mbuf, ML_CLOSE, i, HTML_TAG_STYLE))
1.4       kristaps  483:                        return(0);
1.19      kristaps  484:        } else {
                    485:                attr[0].attr = HTML_ATTR_REL;
                    486:                attr[0].val = "stylesheet";
                    487:                attr[1].attr = HTML_ATTR_TYPE;
                    488:                attr[1].val = "text/css";
                    489:                attr[2].attr = HTML_ATTR_HREF;
1.25    ! kristaps  490:                attr[2].val = p->args->params.html.css;
1.19      kristaps  491:
1.25    ! kristaps  492:                if ( ! html_aputln(p->mbuf, ML_OPEN, i,
1.19      kristaps  493:                                        HTML_TAG_LINK, 3, attr))
                    494:                        return(0);
                    495:        }
1.4       kristaps  496:
1.25    ! kristaps  497:        if ( ! html_tputln(p->mbuf, ML_CLOSE, --i, HTML_TAG_HEAD))
1.18      kristaps  498:                return(0);
1.25    ! kristaps  499:        if ( ! html_tputln(p->mbuf, ML_OPEN, i, HTML_TAG_BODY))
1.18      kristaps  500:                return(0);
1.19      kristaps  501:
                    502:        attr[0].attr = HTML_ATTR_CLASS;
                    503:        attr[0].val = "mdoc";
                    504:
1.25    ! kristaps  505:        if ( ! html_aputln(p->mbuf, ML_OPEN, i, HTML_TAG_DIV, 1, attr))
1.18      kristaps  506:                return(0);
1.19      kristaps  507:
                    508:        attr[0].attr = HTML_ATTR_WIDTH;
                    509:        attr[0].val = "100%";
1.22      kristaps  510:        attr[1].attr = HTML_ATTR_CLASS;
                    511:        attr[1].val = "header-table";
1.19      kristaps  512:
1.25    ! kristaps  513:        if ( ! html_aputln(p->mbuf, ML_OPEN, i++, HTML_TAG_TABLE, 2, attr))
1.18      kristaps  514:                return(0);
1.25    ! kristaps  515:        if ( ! html_tputln(p->mbuf, ML_OPEN, i++, HTML_TAG_TR))
1.18      kristaps  516:                return(0);
1.19      kristaps  517:
1.22      kristaps  518:        attr[0].attr = HTML_ATTR_ALIGN;
                    519:        attr[0].val = "left";
                    520:        attr[1].attr = HTML_ATTR_CLASS;
                    521:        attr[1].val = "header-section";
                    522:
1.25    ! kristaps  523:        if ( ! html_aputln(p->mbuf, ML_OPEN, i, HTML_TAG_TD, 2, attr))
1.2       kristaps  524:                return(0);
1.25    ! kristaps  525:        if ( ! ml_putstring(p->mbuf, ts, NULL))
1.18      kristaps  526:                return(0);
1.25    ! kristaps  527:        if ( ! html_tputln(p->mbuf, ML_CLOSE, i, HTML_TAG_TD))
1.18      kristaps  528:                return(0);
1.19      kristaps  529:
1.22      kristaps  530:        attr[0].attr = HTML_ATTR_ALIGN;
                    531:        attr[0].val = "center";
                    532:        attr[1].attr = HTML_ATTR_CLASS;
                    533:        attr[1].val = "header-volume";
                    534:
1.25    ! kristaps  535:        if ( ! html_aputln(p->mbuf, ML_OPEN, i, HTML_TAG_TD, 2, attr))
1.22      kristaps  536:                return(0);
1.25    ! kristaps  537:        if ( ! ml_putstring(p->mbuf, title, NULL))
1.18      kristaps  538:                return(0);
1.25    ! kristaps  539:        if ( ! html_tputln(p->mbuf, ML_CLOSE, i, HTML_TAG_TD))
1.18      kristaps  540:                return(0);
1.19      kristaps  541:
1.20      kristaps  542:        attr[0].attr = HTML_ATTR_ALIGN;
                    543:        attr[0].val = "right";
1.22      kristaps  544:        attr[1].attr = HTML_ATTR_CLASS;
                    545:        attr[1].val = "header-section";
1.20      kristaps  546:
1.25    ! kristaps  547:        if ( ! html_aputln(p->mbuf, ML_OPEN, i, HTML_TAG_TD, 2, attr))
1.18      kristaps  548:                return(0);
1.25    ! kristaps  549:        if ( ! ml_putstring(p->mbuf, ts, NULL))
1.17      kristaps  550:                return(0);
1.25    ! kristaps  551:        if ( ! html_tputln(p->mbuf, ML_CLOSE, i, HTML_TAG_TD))
1.17      kristaps  552:                return(0);
1.19      kristaps  553:
1.25    ! kristaps  554:        if ( ! html_tputln(p->mbuf, ML_CLOSE, --i, HTML_TAG_TR))
1.17      kristaps  555:                return(0);
1.25    ! kristaps  556:        return(html_tputln(p->mbuf, ML_CLOSE, --i, HTML_TAG_TABLE));
1.2       kristaps  557: }
                    558:
                    559:
1.3       kristaps  560: /* ARGSUSED */
1.2       kristaps  561: static int
1.25    ! kristaps  562: html_end(struct ml_args *p, const struct tm *tm, const char *os,
1.22      kristaps  563:                const char *name, enum roffmsec msec, enum roffvol vol)
1.2       kristaps  564: {
1.22      kristaps  565:        struct html_pair attr[4];
                    566:        int              i;
                    567:        char             ts[64];
                    568:
                    569:        if (0 == strftime(ts, sizeof(ts), "%B %d, %Y", tm)) {
                    570:                warn("strftime");
                    571:                return(0);
                    572:        }
                    573:
                    574:        i = 0;
                    575:
                    576:        attr[0].attr = HTML_ATTR_WIDTH;
                    577:        attr[0].val = "100%";
                    578:        attr[1].attr = HTML_ATTR_CLASS;
                    579:        attr[1].val = "header-footer";
                    580:
1.25    ! kristaps  581:        if ( ! html_aputln(p->mbuf, ML_OPEN, i++, HTML_TAG_TABLE, 2, attr))
1.22      kristaps  582:                return(0);
1.25    ! kristaps  583:        if ( ! html_tputln(p->mbuf, ML_OPEN, i++, HTML_TAG_TR))
1.22      kristaps  584:                return(0);
                    585:
                    586:        attr[0].attr = HTML_ATTR_ALIGN;
                    587:        attr[0].val = "left";
                    588:        attr[1].attr = HTML_ATTR_CLASS;
                    589:        attr[1].val = "footer-os";
                    590:
1.25    ! kristaps  591:        if ( ! html_aputln(p->mbuf, ML_OPEN, i, HTML_TAG_TD, 2, attr))
1.22      kristaps  592:                return(0);
1.25    ! kristaps  593:        if ( ! ml_putstring(p->mbuf, os, NULL))
1.22      kristaps  594:                return(0);
1.25    ! kristaps  595:        if ( ! html_tputln(p->mbuf, ML_CLOSE, i, HTML_TAG_TD))
1.22      kristaps  596:                return(0);
                    597:
                    598:        attr[0].attr = HTML_ATTR_ALIGN;
                    599:        attr[0].val = "right";
                    600:        attr[1].attr = HTML_ATTR_CLASS;
                    601:        attr[1].val = "footer-date";
                    602:
1.25    ! kristaps  603:        if ( ! html_aputln(p->mbuf, ML_OPEN, i, HTML_TAG_TD, 2, attr))
1.22      kristaps  604:                return(0);
1.25    ! kristaps  605:        if ( ! ml_putstring(p->mbuf, ts, NULL))
1.22      kristaps  606:                return(0);
1.25    ! kristaps  607:        if ( ! html_tputln(p->mbuf, ML_CLOSE, i, HTML_TAG_TD))
1.22      kristaps  608:                return(0);
                    609:
1.25    ! kristaps  610:        if ( ! html_tputln(p->mbuf, ML_CLOSE, --i, HTML_TAG_TR))
1.22      kristaps  611:                return(0);
1.25    ! kristaps  612:        if ( ! html_tputln(p->mbuf, ML_CLOSE, --i, HTML_TAG_TABLE))
1.22      kristaps  613:                return(0);
1.2       kristaps  614:
1.25    ! kristaps  615:        if ( ! html_tputln(p->mbuf, ML_CLOSE, 0, HTML_TAG_DIV))
1.18      kristaps  616:                return(0);
1.25    ! kristaps  617:        if ( ! html_tputln(p->mbuf, ML_CLOSE, 0, HTML_TAG_BODY))
1.18      kristaps  618:                return(0);
1.25    ! kristaps  619:        return(html_tputln(p->mbuf, ML_CLOSE, 0, HTML_TAG_HTML));
1.2       kristaps  620: }
                    621:
                    622:
1.3       kristaps  623: /* ARGSUSED */
1.7       kristaps  624: static int
1.12      kristaps  625: html_bodytagname(struct md_mbuf *mbuf,
1.10      kristaps  626:                const struct md_args *args, int tok, struct htmlq *q,
                    627:                const int *argc, const char **argv, size_t *res)
1.2       kristaps  628: {
1.3       kristaps  629:
1.10      kristaps  630:        switch (tok) {
                    631:        case (ROFF_Bl):
                    632:                return(html_Bl_bodytagname(mbuf, q, argc, argv, res));
1.12      kristaps  633:        case (ROFF_Fo):
1.19      kristaps  634:                return(html_stput(mbuf, HTML_TAG_SPAN, res));
1.10      kristaps  635:        case (ROFF_It):
                    636:                return(html_It_bodytagname(mbuf, q, argc, argv, res));
1.12      kristaps  637:        case (ROFF_Oo):
1.19      kristaps  638:                return(html_stput(mbuf, HTML_TAG_SPAN, res));
1.10      kristaps  639:        default:
                    640:                break;
                    641:        }
                    642:
1.19      kristaps  643:        return(html_stput(mbuf, HTML_TAG_DIV, res));
1.3       kristaps  644: }
                    645:
                    646:
                    647: /* ARGSUSED */
1.7       kristaps  648: static int
1.10      kristaps  649: html_headtagname(struct md_mbuf *mbuf,
                    650:                const struct md_args *args, int tok, struct htmlq *q,
                    651:                const int *argc, const char **argv, size_t *res)
1.3       kristaps  652: {
                    653:
1.10      kristaps  654:        switch (tok) {
                    655:        case (ROFF_It):
                    656:                return(html_It_headtagname(mbuf, q, argc, argv, res));
1.12      kristaps  657:        case (ROFF_Fo):
1.19      kristaps  658:                /* FALLTHROUGH */
1.12      kristaps  659:        case (ROFF_Oo):
1.19      kristaps  660:                return(html_stput(mbuf, HTML_TAG_SPAN, res));
1.10      kristaps  661:        case (ROFF_Sh):
1.19      kristaps  662:                return(html_stput(mbuf, HTML_TAG_H1, res));
1.10      kristaps  663:        case (ROFF_Ss):
1.19      kristaps  664:                return(html_stput(mbuf, HTML_TAG_H2, res));
1.10      kristaps  665:        default:
                    666:                break;
                    667:        }
                    668:
1.19      kristaps  669:        return(html_stput(mbuf, HTML_TAG_DIV, res));
1.3       kristaps  670: }
                    671:
                    672:
                    673: /* ARGSUSED */
1.7       kristaps  674: static int
1.10      kristaps  675: html_blocktagname(struct md_mbuf *mbuf, const struct md_args *args,
                    676:                int tok, struct htmlq *q, const int *argc,
                    677:                const char **argv, size_t *res)
1.3       kristaps  678: {
                    679:
1.10      kristaps  680:        switch (tok) {
1.12      kristaps  681:        case (ROFF_Fo):
1.19      kristaps  682:                /* FALLTHROUGH */
1.12      kristaps  683:        case (ROFF_Oo):
1.19      kristaps  684:                return(html_stput(mbuf, HTML_TAG_SPAN, res));
1.10      kristaps  685:        case (ROFF_It):
                    686:                return(html_It_blocktagname(mbuf, q, argc, argv, res));
                    687:        default:
                    688:                break;
                    689:        }
                    690:
1.19      kristaps  691:        return(html_stput(mbuf, HTML_TAG_DIV, res));
1.3       kristaps  692: }
                    693:
                    694:
1.9       kristaps  695: /* ARGSUSED */
1.7       kristaps  696: static int
                    697: html_printargs(struct md_mbuf *mbuf, int tok, const char *ns,
                    698:                const int *argc, const char **argv, size_t *res)
1.3       kristaps  699: {
                    700:
1.19      kristaps  701:        /* FIXME: use API in ml.h. */
                    702:
1.7       kristaps  703:        if ( ! ml_puts(mbuf, " class=\"", res))
                    704:                return(0);
                    705:        if ( ! ml_puts(mbuf, ns, res))
                    706:                return(0);
                    707:        if ( ! ml_puts(mbuf, "-", res))
1.3       kristaps  708:                return(0);
1.7       kristaps  709:        if ( ! ml_puts(mbuf, toknames[tok], res))
1.3       kristaps  710:                return(0);
1.9       kristaps  711:        return(ml_puts(mbuf, "\"", res));
1.3       kristaps  712: }
                    713:
                    714:
                    715: /* ARGSUSED */
1.7       kristaps  716: static int
1.10      kristaps  717: html_headtagargs(struct md_mbuf *mbuf,
1.7       kristaps  718:                const struct md_args *args, int tok,
                    719:                const int *argc, const char **argv, size_t *res)
1.3       kristaps  720: {
                    721:
1.7       kristaps  722:        return(html_printargs(mbuf, tok, "head", argc, argv, res));
                    723: }
1.3       kristaps  724:
                    725:
1.7       kristaps  726: /* ARGSUSED */
                    727: static int
1.12      kristaps  728: html_bodytagargs(struct md_mbuf *mbuf,
1.7       kristaps  729:                const struct md_args *args, int tok,
                    730:                const int *argc, const char **argv, size_t *res)
                    731: {
1.3       kristaps  732:
1.7       kristaps  733:        return(html_printargs(mbuf, tok, "body", argc, argv, res));
1.2       kristaps  734: }
                    735:
                    736:
                    737: /* ARGSUSED */
1.7       kristaps  738: static int
                    739: html_blocktagargs(struct md_mbuf *mbuf,
                    740:                const struct md_args *args, int tok,
                    741:                const int *argc, const char **argv, size_t *res)
1.2       kristaps  742: {
1.3       kristaps  743:
1.7       kristaps  744:        return(html_printargs(mbuf, tok, "block", argc, argv, res));
1.2       kristaps  745: }
1.1       kristaps  746:
                    747:
                    748: /* ARGSUSED */
1.7       kristaps  749: static int
                    750: html_inlinetagargs(struct md_mbuf *mbuf,
                    751:                const struct md_args *args, int tok,
                    752:                const int *argc, const char **argv, size_t *res)
1.2       kristaps  753: {
                    754:
1.12      kristaps  755:        if ( ! html_printargs(mbuf, tok, "inline", argc, argv, res))
                    756:                return(0);
                    757:
                    758:        switch (tok) {
1.24      kristaps  759:        case (ROFF_Sh):
                    760:
                    761:                /* FIXME: use API in ml.h. */
                    762:
                    763:                assert(*argv);
                    764:                if ( ! ml_nputs(mbuf, " name=\"", 7, res))
                    765:                        return(0);
                    766:                if ( ! ml_putstring(mbuf, *argv++, res))
                    767:                        return(0);
                    768:                while (*argv) {
                    769:                        if ( ! ml_putstring(mbuf, "_", res))
                    770:                                return(0);
                    771:                        if ( ! ml_putstring(mbuf, *argv++, res))
                    772:                                return(0);
                    773:                }
                    774:                if ( ! ml_nputs(mbuf, "\"", 1, res))
                    775:                        return(0);
                    776:                break;
                    777:
1.12      kristaps  778:        case (ROFF_Sx):
1.19      kristaps  779:
                    780:                /* FIXME: use API in ml.h. */
                    781:
1.12      kristaps  782:                assert(*argv);
                    783:                if ( ! ml_nputs(mbuf, " href=\"#", 8, res))
                    784:                        return(0);
1.24      kristaps  785:                if ( ! ml_putstring(mbuf, *argv++, res))
1.12      kristaps  786:                        return(0);
1.24      kristaps  787:                while (*argv) {
                    788:                        if ( ! ml_putstring(mbuf, "_", res))
                    789:                                return(0);
                    790:                        if ( ! ml_putstring(mbuf, *argv++, res))
                    791:                                return(0);
                    792:                }
1.12      kristaps  793:                if ( ! ml_nputs(mbuf, "\"", 1, res))
                    794:                        return(0);
1.24      kristaps  795:
1.13      kristaps  796:                break;
1.12      kristaps  797:        default:
                    798:                break;
                    799:        }
                    800:
                    801:        return(1);
1.2       kristaps  802: }
                    803:
                    804:
1.3       kristaps  805: /* ARGSUSED */
1.7       kristaps  806: static int
1.2       kristaps  807: html_inlinetagname(struct md_mbuf *mbuf,
1.7       kristaps  808:                const struct md_args *args, int tok, size_t *res)
1.2       kristaps  809: {
                    810:
                    811:        switch (tok) {
1.24      kristaps  812:        case (ROFF_Sh):
                    813:                return(html_stput(mbuf, HTML_TAG_A, res));
1.4       kristaps  814:        case (ROFF_Pp):
1.19      kristaps  815:                return(html_stput(mbuf, HTML_TAG_DIV, res));
1.12      kristaps  816:        case (ROFF_Sx):
1.19      kristaps  817:                return(html_stput(mbuf, HTML_TAG_A, res));
1.2       kristaps  818:        default:
1.9       kristaps  819:                break;
1.2       kristaps  820:        }
1.9       kristaps  821:
1.19      kristaps  822:        return(html_stput(mbuf, HTML_TAG_SPAN, res));
1.2       kristaps  823: }
                    824:
                    825:
                    826: static ssize_t
1.25    ! kristaps  827: html_begintag(struct ml_args *p, enum md_ns ns,
1.8       kristaps  828:                int tok, const int *argc, const char **argv)
1.2       kristaps  829: {
1.7       kristaps  830:        size_t           res;
1.8       kristaps  831:        struct htmlq    *q;
                    832:        struct htmlnode *node;
1.11      kristaps  833:        int              i;
1.2       kristaps  834:
                    835:        assert(ns != MD_NS_DEFAULT);
1.7       kristaps  836:        res = 0;
                    837:
1.25    ! kristaps  838:        q = (struct htmlq *)p->data;
1.8       kristaps  839:
                    840:        if (NULL == (node = calloc(1, sizeof(struct htmlnode)))) {
                    841:                warn("calloc");
                    842:                return(-1);
                    843:        }
                    844:
                    845:        node->parent = q->last;
                    846:        node->tok = tok;
                    847:        node->ns = ns;
                    848:
1.10      kristaps  849:        if (argc)  {
                    850:                /* TODO: argv. */
                    851:
                    852:                assert(argv);
1.13      kristaps  853:                /* LINTED */
1.11      kristaps  854:                for (i = 0; ROFF_ARGMAX != argc[i]
1.10      kristaps  855:                                && i < ROFF_MAXLINEARG; i++)
                    856:                        node->argc[i] = argc[i];
                    857:                assert(i != ROFF_MAXLINEARG);
1.12      kristaps  858:        }
1.10      kristaps  859:
                    860:
1.8       kristaps  861:        q->last = node;
                    862:
1.3       kristaps  863:        switch (ns) {
                    864:        case (MD_NS_BLOCK):
1.25    ! kristaps  865:                if ( ! html_blocktagname(p->mbuf, p->args, tok,
1.10      kristaps  866:                                        q, argc, argv, &res))
1.7       kristaps  867:                        return(-1);
1.25    ! kristaps  868:                if ( ! html_blocktagargs(p->mbuf, p->args, tok,
1.7       kristaps  869:                                        argc, argv, &res))
                    870:                        return(-1);
                    871:                break;
1.3       kristaps  872:        case (MD_NS_BODY):
1.25    ! kristaps  873:                if ( ! html_bodytagname(p->mbuf, p->args, tok,
1.10      kristaps  874:                                        q, argc, argv, &res))
1.7       kristaps  875:                        return(-1);
1.25    ! kristaps  876:                if ( ! html_bodytagargs(p->mbuf, p->args, tok,
1.7       kristaps  877:                                        argc, argv, &res))
                    878:                        return(-1);
                    879:                break;
1.3       kristaps  880:        case (MD_NS_HEAD):
1.25    ! kristaps  881:                if ( ! html_headtagname(p->mbuf, p->args, tok, q,
1.10      kristaps  882:                                        argc, argv, &res))
1.7       kristaps  883:                        return(-1);
1.25    ! kristaps  884:                if ( ! html_headtagargs(p->mbuf, p->args, tok,
1.7       kristaps  885:                                        argc, argv, &res))
                    886:                        return(-1);
                    887:                break;
1.3       kristaps  888:        default:
1.25    ! kristaps  889:                if ( ! html_inlinetagname(p->mbuf, p->args, tok, &res))
1.7       kristaps  890:                        return(-1);
1.25    ! kristaps  891:                if ( ! html_inlinetagargs(p->mbuf, p->args, tok,
1.7       kristaps  892:                                        argc, argv, &res))
                    893:                        return(-1);
1.3       kristaps  894:                break;
1.2       kristaps  895:        }
                    896:
1.7       kristaps  897:        return((ssize_t)res);
1.2       kristaps  898: }
                    899:
                    900:
                    901: static ssize_t
1.25    ! kristaps  902: html_endtag(struct ml_args *p, enum md_ns ns, int tok)
1.2       kristaps  903: {
1.7       kristaps  904:        size_t           res;
1.8       kristaps  905:        struct htmlq    *q;
                    906:        struct htmlnode *node;
1.2       kristaps  907:
                    908:        assert(ns != MD_NS_DEFAULT);
1.7       kristaps  909:        res = 0;
                    910:
1.25    ! kristaps  911:        q = (struct htmlq *)p->data;
1.10      kristaps  912:        node = q->last;
1.8       kristaps  913:
1.3       kristaps  914:        switch (ns) {
                    915:        case (MD_NS_BLOCK):
1.25    ! kristaps  916:                if ( ! html_blocktagname(p->mbuf, p->args, tok,
1.10      kristaps  917:                                        q, node->argc,
                    918:                                        (const char **)node->argv, &res))
1.7       kristaps  919:                        return(-1);
                    920:                break;
1.3       kristaps  921:        case (MD_NS_BODY):
1.25    ! kristaps  922:                if ( ! html_bodytagname(p->mbuf, p->args, tok,
1.10      kristaps  923:                                        q, node->argc,
                    924:                                        (const char **)node->argv, &res))
1.7       kristaps  925:                        return(-1);
                    926:                break;
1.3       kristaps  927:        case (MD_NS_HEAD):
1.25    ! kristaps  928:                if ( ! html_headtagname(p->mbuf, p->args, tok,
1.10      kristaps  929:                                        q, node->argc,
                    930:                                        (const char **)node->argv, &res))
1.7       kristaps  931:                        return(-1);
                    932:                break;
1.3       kristaps  933:        default:
1.25    ! kristaps  934:                if ( ! html_inlinetagname(p->mbuf, p->args, tok, &res))
1.7       kristaps  935:                        return(-1);
1.3       kristaps  936:                break;
                    937:        }
1.2       kristaps  938:
1.8       kristaps  939:        q->last = node->parent;
                    940:
1.9       kristaps  941:        free(node);
1.8       kristaps  942:
1.7       kristaps  943:        return((ssize_t)res);
1.2       kristaps  944: }
                    945:
                    946:
1.9       kristaps  947: static int
                    948: html_alloc(void **p)
                    949: {
                    950:
                    951:        if (NULL == (*p = calloc(1, sizeof(struct htmlq)))) {
                    952:                warn("calloc");
                    953:                return(0);
                    954:        }
                    955:        return(1);
                    956: }
                    957:
                    958:
                    959: static void
                    960: html_free(void *p)
                    961: {
                    962:        struct htmlq    *q;
                    963:        struct htmlnode *n;
                    964:
                    965:        assert(p);
                    966:        q = (struct htmlq *)p;
                    967:
1.13      kristaps  968:        /* LINTED */
1.9       kristaps  969:        while ((n = q->last)) {
                    970:                q->last = n->parent;
                    971:                free(n);
                    972:        }
                    973:
                    974:        free(q);
                    975: }
                    976:
                    977:
1.23      kristaps  978: /* ARGSUSED */
1.14      kristaps  979: static ssize_t
                    980: html_beginhttp(struct md_mbuf *mbuf,
                    981:                const struct md_args *args,
                    982:                const char *buf, size_t sz)
                    983: {
                    984:        size_t           res;
1.19      kristaps  985:        struct html_pair pair;
1.14      kristaps  986:
                    987:        res = 0;
1.19      kristaps  988:        pair.attr = HTML_ATTR_HREF;
                    989:        pair.val = (char *)buf;
1.14      kristaps  990:
1.19      kristaps  991:        if ( ! html_aput(mbuf, ML_OPEN, HTML_TAG_A, &res, 1, &pair))
1.14      kristaps  992:                return(-1);
                    993:        return((ssize_t)res);
                    994: }
                    995:
                    996:
1.23      kristaps  997: /* ARGSUSED */
1.14      kristaps  998: static ssize_t
                    999: html_endhttp(struct md_mbuf *mbuf,
                   1000:                const struct md_args *args,
                   1001:                const char *buf, size_t sz)
                   1002: {
                   1003:        size_t           res;
                   1004:
                   1005:        res = 0;
1.19      kristaps 1006:        if ( ! html_tput(mbuf, ML_CLOSE, HTML_TAG_A, &res))
1.14      kristaps 1007:                return(-1);
                   1008:        return((ssize_t)res);
                   1009: }
                   1010:
                   1011:
                   1012: /* ARGSUSED */
                   1013: static ssize_t
1.25    ! kristaps 1014: html_beginstring(struct ml_args *p, const char *buf, size_t sz)
1.14      kristaps 1015: {
                   1016:
                   1017:        if (0 == strncmp(buf, "http://", 7))
1.25    ! kristaps 1018:                return(html_beginhttp(p->mbuf, p->args, buf, sz));
1.14      kristaps 1019:
                   1020:        return(0);
                   1021: }
                   1022:
                   1023:
                   1024: /* ARGSUSED */
                   1025: static ssize_t
1.25    ! kristaps 1026: html_endstring(struct ml_args *p, const char *buf, size_t sz)
1.14      kristaps 1027: {
                   1028:
                   1029:        if (0 == strncmp(buf, "http://", 7))
1.25    ! kristaps 1030:                return(html_endhttp(p->mbuf, p->args, buf, sz));
1.14      kristaps 1031:
                   1032:        return(0);
                   1033: }
                   1034:
                   1035:
1.1       kristaps 1036: int
                   1037: md_line_html(void *data, char *buf)
                   1038: {
                   1039:
1.2       kristaps 1040:        return(mlg_line((struct md_mlg *)data, buf));
1.1       kristaps 1041: }
                   1042:
                   1043:
                   1044: int
                   1045: md_exit_html(void *data, int flush)
                   1046: {
                   1047:
1.2       kristaps 1048:        return(mlg_exit((struct md_mlg *)data, flush));
1.1       kristaps 1049: }
                   1050:
                   1051:
                   1052: void *
                   1053: md_init_html(const struct md_args *args,
                   1054:                struct md_mbuf *mbuf, const struct md_rbuf *rbuf)
                   1055: {
1.9       kristaps 1056:        struct ml_cbs    cbs;
1.8       kristaps 1057:
1.9       kristaps 1058:        cbs.ml_alloc = html_alloc;
                   1059:        cbs.ml_free = html_free;
                   1060:        cbs.ml_begintag = html_begintag;
                   1061:        cbs.ml_endtag = html_endtag;
                   1062:        cbs.ml_begin = html_begin;
                   1063:        cbs.ml_end = html_end;
1.14      kristaps 1064:        cbs.ml_beginstring = html_beginstring;
                   1065:        cbs.ml_endstring = html_endstring;
1.1       kristaps 1066:
1.9       kristaps 1067:        return(mlg_alloc(args, rbuf, mbuf, &cbs));
1.1       kristaps 1068: }

CVSweb