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

Annotation of mandoc/html.c, Revision 1.19

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

CVSweb