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

Annotation of mandoc/html.c, Revision 1.10

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

CVSweb