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

Annotation of mandoc/html.c, Revision 1.21

1.21    ! kristaps    1: /* $Id: html.c,v 1.20 2008/12/10 00:58: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:
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.21    ! kristaps   75:                                enum roffmsec, enum roffvol);
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.21    ! kristaps  385:                const char *name, enum roffmsec msec, enum roffvol vol)
1.2       kristaps  386: {
1.19      kristaps  387:        struct html_pair attr[4];
1.21    ! kristaps  388:        char             ts[32], title[64];
1.19      kristaps  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.21    ! kristaps  394:        (void)snprintf(ts, sizeof(ts), "%s",
        !           395:                        name, roff_volname(vol));
        !           396:
        !           397:        if (vol >= ROFF_ARCH_START) {
        !           398:
        !           399:        }
        !           400:
        !           401:
1.18      kristaps  402:        i = 0;
1.4       kristaps  403:
1.19      kristaps  404:        if ( ! html_typeput(mbuf, HTML_TYPE_4_01_STRICT, NULL))
1.17      kristaps  405:                return(0);
1.19      kristaps  406:        if ( ! html_tputln(mbuf, ML_OPEN, i, HTML_TAG_HTML))
1.17      kristaps  407:                return(0);
1.19      kristaps  408:        if ( ! html_tputln(mbuf, ML_OPEN, i++, HTML_TAG_HEAD))
1.17      kristaps  409:                return(0);
1.19      kristaps  410:
                    411:        attr[0].attr = HTML_ATTR_HTTP_EQUIV;
                    412:        attr[0].val = "content-type";
                    413:        attr[1].attr = HTML_ATTR_CONTENT;
                    414:        attr[1].val = "text/html;charset=utf-8";
                    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:        attr[0].attr = HTML_ATTR_NAME;
                    420:        attr[0].val = "resource-type";
                    421:        attr[1].attr = HTML_ATTR_CONTENT;
                    422:        attr[1].val = "document";
                    423:
                    424:        if ( ! html_aputln(mbuf, ML_OPEN, i, HTML_TAG_META, 2, attr))
1.17      kristaps  425:                return(0);
1.19      kristaps  426:
                    427:        if ( ! html_tputln(mbuf, ML_OPEN, i, HTML_TAG_TITLE))
1.17      kristaps  428:                return(0);
1.19      kristaps  429:        if ( ! ml_putstring(mbuf, ts, NULL))
1.17      kristaps  430:                return(0);
1.19      kristaps  431:        if ( ! html_tputln(mbuf, ML_CLOSE, i, HTML_TAG_TITLE))
1.2       kristaps  432:                return(0);
1.4       kristaps  433:
                    434:        if (HTML_CSS_EMBED & args->params.html.flags) {
1.19      kristaps  435:                attr[0].attr = HTML_ATTR_TYPE;
                    436:                attr[0].val = "text/css";
                    437:
                    438:                if ( ! html_aputln(mbuf, ML_OPEN, i,
                    439:                                        HTML_TAG_STYLE, 1, attr))
1.4       kristaps  440:                        return(0);
1.19      kristaps  441:                if ( ! html_commentput(mbuf, ML_OPEN, NULL))
                    442:                        return(NULL);
                    443:
1.4       kristaps  444:                if ( ! html_loadcss(mbuf, args->params.html.css))
                    445:                        return(0);
1.19      kristaps  446:
                    447:                if ( ! html_commentput(mbuf, ML_CLOSE, NULL))
                    448:                        return(NULL);
                    449:                if ( ! html_tputln(mbuf, ML_CLOSE, i, HTML_TAG_STYLE))
1.4       kristaps  450:                        return(0);
1.19      kristaps  451:        } else {
                    452:                attr[0].attr = HTML_ATTR_REL;
                    453:                attr[0].val = "stylesheet";
                    454:                attr[1].attr = HTML_ATTR_TYPE;
                    455:                attr[1].val = "text/css";
                    456:                attr[2].attr = HTML_ATTR_HREF;
                    457:                attr[2].val = args->params.html.css;
                    458:
                    459:                if ( ! html_aputln(mbuf, ML_OPEN, i,
                    460:                                        HTML_TAG_LINK, 3, attr))
                    461:                        return(0);
                    462:        }
1.4       kristaps  463:
1.19      kristaps  464:        if ( ! html_tputln(mbuf, ML_CLOSE, --i, HTML_TAG_HEAD))
1.18      kristaps  465:                return(0);
1.19      kristaps  466:        if ( ! html_tputln(mbuf, ML_OPEN, i, HTML_TAG_BODY))
1.18      kristaps  467:                return(0);
1.19      kristaps  468:
                    469:        attr[0].attr = HTML_ATTR_CLASS;
                    470:        attr[0].val = "mdoc";
                    471:
                    472:        if ( ! html_aputln(mbuf, ML_OPEN, i, HTML_TAG_DIV, 1, attr))
1.18      kristaps  473:                return(0);
1.19      kristaps  474:
                    475:        attr[0].attr = HTML_ATTR_WIDTH;
                    476:        attr[0].val = "100%";
                    477:
                    478:        if ( ! html_aputln(mbuf, ML_OPEN, i++, HTML_TAG_TABLE, 1, attr))
1.18      kristaps  479:                return(0);
1.19      kristaps  480:        if ( ! html_tputln(mbuf, ML_OPEN, i++, HTML_TAG_TR))
1.18      kristaps  481:                return(0);
1.19      kristaps  482:
                    483:        if ( ! html_tputln(mbuf, ML_OPEN, i, HTML_TAG_TD))
1.2       kristaps  484:                return(0);
1.19      kristaps  485:        if ( ! ml_putstring(mbuf, ts, NULL))
1.18      kristaps  486:                return(0);
1.19      kristaps  487:        if ( ! html_tputln(mbuf, ML_CLOSE, i, HTML_TAG_TD))
1.18      kristaps  488:                return(0);
1.19      kristaps  489:
                    490:        if ( ! html_tputln(mbuf, ML_OPEN, i, HTML_TAG_TD))
1.18      kristaps  491:                return(0);
1.19      kristaps  492:        /* TODO: middle. */
                    493:        if ( ! html_tputln(mbuf, ML_CLOSE, i, HTML_TAG_TD))
1.18      kristaps  494:                return(0);
1.19      kristaps  495:
1.20      kristaps  496:        attr[0].attr = HTML_ATTR_ALIGN;
                    497:        attr[0].val = "right";
                    498:
                    499:        if ( ! html_aputln(mbuf, ML_OPEN, i, HTML_TAG_TD, 1, attr))
1.18      kristaps  500:                return(0);
1.19      kristaps  501:        if ( ! ml_putstring(mbuf, ts, NULL))
1.17      kristaps  502:                return(0);
1.19      kristaps  503:        if ( ! html_tputln(mbuf, ML_CLOSE, i, HTML_TAG_TD))
1.17      kristaps  504:                return(0);
1.19      kristaps  505:
                    506:        if ( ! html_tputln(mbuf, ML_CLOSE, --i, HTML_TAG_TR))
1.17      kristaps  507:                return(0);
1.19      kristaps  508:        return(html_tputln(mbuf, ML_CLOSE, --i, HTML_TAG_TABLE));
1.2       kristaps  509: }
                    510:
                    511:
1.3       kristaps  512: /* ARGSUSED */
1.2       kristaps  513: static int
                    514: html_end(struct md_mbuf *mbuf, const struct md_args *args)
                    515: {
                    516:
1.19      kristaps  517:        if ( ! html_tputln(mbuf, ML_CLOSE, 0, HTML_TAG_DIV))
1.18      kristaps  518:                return(0);
1.19      kristaps  519:        if ( ! html_tputln(mbuf, ML_CLOSE, 0, HTML_TAG_BODY))
1.18      kristaps  520:                return(0);
1.19      kristaps  521:        return(html_tputln(mbuf, ML_CLOSE, 0, HTML_TAG_HTML));
1.2       kristaps  522: }
                    523:
                    524:
1.3       kristaps  525: /* ARGSUSED */
1.7       kristaps  526: static int
1.12      kristaps  527: html_bodytagname(struct md_mbuf *mbuf,
1.10      kristaps  528:                const struct md_args *args, int tok, struct htmlq *q,
                    529:                const int *argc, const char **argv, size_t *res)
1.2       kristaps  530: {
1.3       kristaps  531:
1.10      kristaps  532:        switch (tok) {
                    533:        case (ROFF_Bl):
                    534:                return(html_Bl_bodytagname(mbuf, q, argc, argv, res));
1.12      kristaps  535:        case (ROFF_Fo):
1.19      kristaps  536:                return(html_stput(mbuf, HTML_TAG_SPAN, res));
1.10      kristaps  537:        case (ROFF_It):
                    538:                return(html_It_bodytagname(mbuf, q, argc, argv, res));
1.12      kristaps  539:        case (ROFF_Oo):
1.19      kristaps  540:                return(html_stput(mbuf, HTML_TAG_SPAN, res));
1.10      kristaps  541:        default:
                    542:                break;
                    543:        }
                    544:
1.19      kristaps  545:        return(html_stput(mbuf, HTML_TAG_DIV, res));
1.3       kristaps  546: }
                    547:
                    548:
                    549: /* ARGSUSED */
1.7       kristaps  550: static int
1.10      kristaps  551: html_headtagname(struct md_mbuf *mbuf,
                    552:                const struct md_args *args, int tok, struct htmlq *q,
                    553:                const int *argc, const char **argv, size_t *res)
1.3       kristaps  554: {
                    555:
1.10      kristaps  556:        switch (tok) {
                    557:        case (ROFF_It):
                    558:                return(html_It_headtagname(mbuf, q, argc, argv, res));
1.12      kristaps  559:        case (ROFF_Fo):
1.19      kristaps  560:                /* FALLTHROUGH */
1.12      kristaps  561:        case (ROFF_Oo):
1.19      kristaps  562:                return(html_stput(mbuf, HTML_TAG_SPAN, res));
1.10      kristaps  563:        case (ROFF_Sh):
1.19      kristaps  564:                return(html_stput(mbuf, HTML_TAG_H1, res));
1.10      kristaps  565:        case (ROFF_Ss):
1.19      kristaps  566:                return(html_stput(mbuf, HTML_TAG_H2, res));
1.10      kristaps  567:        default:
                    568:                break;
                    569:        }
                    570:
1.19      kristaps  571:        return(html_stput(mbuf, HTML_TAG_DIV, res));
1.3       kristaps  572: }
                    573:
                    574:
                    575: /* ARGSUSED */
1.7       kristaps  576: static int
1.10      kristaps  577: html_blocktagname(struct md_mbuf *mbuf, const struct md_args *args,
                    578:                int tok, struct htmlq *q, const int *argc,
                    579:                const char **argv, size_t *res)
1.3       kristaps  580: {
                    581:
1.10      kristaps  582:        switch (tok) {
1.12      kristaps  583:        case (ROFF_Fo):
1.19      kristaps  584:                /* FALLTHROUGH */
1.12      kristaps  585:        case (ROFF_Oo):
1.19      kristaps  586:                return(html_stput(mbuf, HTML_TAG_SPAN, res));
1.10      kristaps  587:        case (ROFF_It):
                    588:                return(html_It_blocktagname(mbuf, q, argc, argv, res));
                    589:        default:
                    590:                break;
                    591:        }
                    592:
1.19      kristaps  593:        return(html_stput(mbuf, HTML_TAG_DIV, res));
1.3       kristaps  594: }
                    595:
                    596:
1.9       kristaps  597: /* ARGSUSED */
1.7       kristaps  598: static int
                    599: html_printargs(struct md_mbuf *mbuf, int tok, const char *ns,
                    600:                const int *argc, const char **argv, size_t *res)
1.3       kristaps  601: {
                    602:
1.19      kristaps  603:        /* FIXME: use API in ml.h. */
                    604:
1.7       kristaps  605:        if ( ! ml_puts(mbuf, " class=\"", res))
                    606:                return(0);
                    607:        if ( ! ml_puts(mbuf, ns, res))
                    608:                return(0);
                    609:        if ( ! ml_puts(mbuf, "-", res))
1.3       kristaps  610:                return(0);
1.7       kristaps  611:        if ( ! ml_puts(mbuf, toknames[tok], res))
1.3       kristaps  612:                return(0);
1.9       kristaps  613:        return(ml_puts(mbuf, "\"", res));
1.3       kristaps  614: }
                    615:
                    616:
                    617: /* ARGSUSED */
1.7       kristaps  618: static int
1.10      kristaps  619: html_headtagargs(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)
1.3       kristaps  622: {
                    623:
1.7       kristaps  624:        return(html_printargs(mbuf, tok, "head", argc, argv, res));
                    625: }
1.3       kristaps  626:
                    627:
1.7       kristaps  628: /* ARGSUSED */
                    629: static int
1.12      kristaps  630: html_bodytagargs(struct md_mbuf *mbuf,
1.7       kristaps  631:                const struct md_args *args, int tok,
                    632:                const int *argc, const char **argv, size_t *res)
                    633: {
1.3       kristaps  634:
1.7       kristaps  635:        return(html_printargs(mbuf, tok, "body", argc, argv, res));
1.2       kristaps  636: }
                    637:
                    638:
                    639: /* ARGSUSED */
1.7       kristaps  640: static int
                    641: html_blocktagargs(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: {
1.3       kristaps  645:
1.7       kristaps  646:        return(html_printargs(mbuf, tok, "block", argc, argv, res));
1.2       kristaps  647: }
1.1       kristaps  648:
                    649:
                    650: /* ARGSUSED */
1.7       kristaps  651: static int
                    652: html_inlinetagargs(struct md_mbuf *mbuf,
                    653:                const struct md_args *args, int tok,
                    654:                const int *argc, const char **argv, size_t *res)
1.2       kristaps  655: {
                    656:
1.12      kristaps  657:        if ( ! html_printargs(mbuf, tok, "inline", argc, argv, res))
                    658:                return(0);
                    659:
                    660:        switch (tok) {
                    661:        case (ROFF_Sx):
1.19      kristaps  662:
                    663:                /* FIXME: use API in ml.h. */
                    664:
1.12      kristaps  665:                assert(*argv);
                    666:                if ( ! ml_nputs(mbuf, " href=\"#", 8, res))
                    667:                        return(0);
                    668:                if ( ! ml_putstring(mbuf, *argv, res))
                    669:                        return(0);
                    670:                if ( ! ml_nputs(mbuf, "\"", 1, res))
                    671:                        return(0);
1.13      kristaps  672:                break;
1.12      kristaps  673:        default:
                    674:                break;
                    675:        }
                    676:
                    677:        return(1);
1.2       kristaps  678: }
                    679:
                    680:
1.3       kristaps  681: /* ARGSUSED */
1.7       kristaps  682: static int
1.2       kristaps  683: html_inlinetagname(struct md_mbuf *mbuf,
1.7       kristaps  684:                const struct md_args *args, int tok, size_t *res)
1.2       kristaps  685: {
                    686:
                    687:        switch (tok) {
1.4       kristaps  688:        case (ROFF_Pp):
1.19      kristaps  689:                return(html_stput(mbuf, HTML_TAG_DIV, res));
1.12      kristaps  690:        case (ROFF_Sx):
1.19      kristaps  691:                return(html_stput(mbuf, HTML_TAG_A, res));
1.2       kristaps  692:        default:
1.9       kristaps  693:                break;
1.2       kristaps  694:        }
1.9       kristaps  695:
1.19      kristaps  696:        return(html_stput(mbuf, HTML_TAG_SPAN, res));
1.2       kristaps  697: }
                    698:
                    699:
                    700: static ssize_t
1.8       kristaps  701: html_begintag(struct md_mbuf *mbuf, void *data,
                    702:                const struct md_args *args, enum md_ns ns,
                    703:                int tok, const int *argc, const char **argv)
1.2       kristaps  704: {
1.7       kristaps  705:        size_t           res;
1.8       kristaps  706:        struct htmlq    *q;
                    707:        struct htmlnode *node;
1.11      kristaps  708:        int              i;
1.2       kristaps  709:
                    710:        assert(ns != MD_NS_DEFAULT);
1.7       kristaps  711:        res = 0;
                    712:
1.8       kristaps  713:        assert(data);
                    714:        q = (struct htmlq *)data;
                    715:
                    716:        if (NULL == (node = calloc(1, sizeof(struct htmlnode)))) {
                    717:                warn("calloc");
                    718:                return(-1);
                    719:        }
                    720:
                    721:        node->parent = q->last;
                    722:        node->tok = tok;
                    723:        node->ns = ns;
                    724:
1.10      kristaps  725:        if (argc)  {
                    726:                /* TODO: argv. */
                    727:
                    728:                assert(argv);
1.13      kristaps  729:                /* LINTED */
1.11      kristaps  730:                for (i = 0; ROFF_ARGMAX != argc[i]
1.10      kristaps  731:                                && i < ROFF_MAXLINEARG; i++)
                    732:                        node->argc[i] = argc[i];
                    733:                assert(i != ROFF_MAXLINEARG);
1.12      kristaps  734:        }
1.10      kristaps  735:
                    736:
1.8       kristaps  737:        q->last = node;
                    738:
1.3       kristaps  739:        switch (ns) {
                    740:        case (MD_NS_BLOCK):
1.10      kristaps  741:                if ( ! html_blocktagname(mbuf, args, tok,
                    742:                                        q, argc, argv, &res))
1.7       kristaps  743:                        return(-1);
                    744:                if ( ! html_blocktagargs(mbuf, args, tok,
                    745:                                        argc, argv, &res))
                    746:                        return(-1);
                    747:                break;
1.3       kristaps  748:        case (MD_NS_BODY):
1.12      kristaps  749:                if ( ! html_bodytagname(mbuf, args, tok,
1.10      kristaps  750:                                        q, argc, argv, &res))
1.7       kristaps  751:                        return(-1);
1.12      kristaps  752:                if ( ! html_bodytagargs(mbuf, args, tok,
1.7       kristaps  753:                                        argc, argv, &res))
                    754:                        return(-1);
                    755:                break;
1.3       kristaps  756:        case (MD_NS_HEAD):
1.10      kristaps  757:                if ( ! html_headtagname(mbuf, args, tok, q,
                    758:                                        argc, argv, &res))
1.7       kristaps  759:                        return(-1);
1.10      kristaps  760:                if ( ! html_headtagargs(mbuf, args, tok,
1.7       kristaps  761:                                        argc, argv, &res))
                    762:                        return(-1);
                    763:                break;
1.3       kristaps  764:        default:
1.7       kristaps  765:                if ( ! html_inlinetagname(mbuf, args, tok, &res))
                    766:                        return(-1);
                    767:                if ( ! html_inlinetagargs(mbuf, args, tok,
                    768:                                        argc, argv, &res))
                    769:                        return(-1);
1.3       kristaps  770:                break;
1.2       kristaps  771:        }
                    772:
1.7       kristaps  773:        return((ssize_t)res);
1.2       kristaps  774: }
                    775:
                    776:
                    777: static ssize_t
1.8       kristaps  778: html_endtag(struct md_mbuf *mbuf, void *data,
                    779:                const struct md_args *args, enum md_ns ns, int tok)
1.2       kristaps  780: {
1.7       kristaps  781:        size_t           res;
1.8       kristaps  782:        struct htmlq    *q;
                    783:        struct htmlnode *node;
1.2       kristaps  784:
                    785:        assert(ns != MD_NS_DEFAULT);
1.7       kristaps  786:        res = 0;
                    787:
1.8       kristaps  788:        assert(data);
                    789:        q = (struct htmlq *)data;
1.10      kristaps  790:        node = q->last;
1.8       kristaps  791:
1.3       kristaps  792:        switch (ns) {
                    793:        case (MD_NS_BLOCK):
1.10      kristaps  794:                if ( ! html_blocktagname(mbuf, args, tok,
                    795:                                        q, node->argc,
                    796:                                        (const char **)node->argv, &res))
1.7       kristaps  797:                        return(-1);
                    798:                break;
1.3       kristaps  799:        case (MD_NS_BODY):
1.12      kristaps  800:                if ( ! html_bodytagname(mbuf, args, tok,
1.10      kristaps  801:                                        q, node->argc,
                    802:                                        (const char **)node->argv, &res))
1.7       kristaps  803:                        return(-1);
                    804:                break;
1.3       kristaps  805:        case (MD_NS_HEAD):
1.10      kristaps  806:                if ( ! html_headtagname(mbuf, args, tok,
                    807:                                        q, node->argc,
                    808:                                        (const char **)node->argv, &res))
1.7       kristaps  809:                        return(-1);
                    810:                break;
1.3       kristaps  811:        default:
1.7       kristaps  812:                if ( ! html_inlinetagname(mbuf, args, tok, &res))
                    813:                        return(-1);
1.3       kristaps  814:                break;
                    815:        }
1.2       kristaps  816:
1.8       kristaps  817:        q->last = node->parent;
                    818:
1.9       kristaps  819:        free(node);
1.8       kristaps  820:
1.7       kristaps  821:        return((ssize_t)res);
1.2       kristaps  822: }
                    823:
                    824:
1.9       kristaps  825: static int
                    826: html_alloc(void **p)
                    827: {
                    828:
                    829:        if (NULL == (*p = calloc(1, sizeof(struct htmlq)))) {
                    830:                warn("calloc");
                    831:                return(0);
                    832:        }
                    833:        return(1);
                    834: }
                    835:
                    836:
                    837: static void
                    838: html_free(void *p)
                    839: {
                    840:        struct htmlq    *q;
                    841:        struct htmlnode *n;
                    842:
                    843:        assert(p);
                    844:        q = (struct htmlq *)p;
                    845:
1.13      kristaps  846:        /* LINTED */
1.9       kristaps  847:        while ((n = q->last)) {
                    848:                q->last = n->parent;
                    849:                free(n);
                    850:        }
                    851:
                    852:        free(q);
                    853: }
                    854:
                    855:
1.14      kristaps  856: static ssize_t
                    857: html_beginhttp(struct md_mbuf *mbuf,
                    858:                const struct md_args *args,
                    859:                const char *buf, size_t sz)
                    860: {
                    861:        size_t           res;
1.19      kristaps  862:        struct html_pair pair;
1.14      kristaps  863:
                    864:        res = 0;
1.19      kristaps  865:        pair.attr = HTML_ATTR_HREF;
                    866:        pair.val = (char *)buf;
1.14      kristaps  867:
1.19      kristaps  868:        if ( ! html_aput(mbuf, ML_OPEN, HTML_TAG_A, &res, 1, &pair))
1.14      kristaps  869:                return(-1);
                    870:        return((ssize_t)res);
                    871: }
                    872:
                    873:
                    874: static ssize_t
                    875: html_endhttp(struct md_mbuf *mbuf,
                    876:                const struct md_args *args,
                    877:                const char *buf, size_t sz)
                    878: {
                    879:        size_t           res;
                    880:
                    881:        res = 0;
1.19      kristaps  882:        if ( ! html_tput(mbuf, ML_CLOSE, HTML_TAG_A, &res))
1.14      kristaps  883:                return(-1);
                    884:        return((ssize_t)res);
                    885: }
                    886:
                    887:
                    888: /* ARGSUSED */
                    889: static ssize_t
                    890: html_beginstring(struct md_mbuf *mbuf,
                    891:                const struct md_args *args,
                    892:                const char *buf, size_t sz)
                    893: {
                    894:
                    895:        if (0 == strncmp(buf, "http://", 7))
                    896:                return(html_beginhttp(mbuf, args, buf, sz));
                    897:
                    898:        return(0);
                    899: }
                    900:
                    901:
                    902: /* ARGSUSED */
                    903: static ssize_t
                    904: html_endstring(struct md_mbuf *mbuf,
                    905:                const struct md_args *args,
                    906:                const char *buf, size_t sz)
                    907: {
                    908:
                    909:        if (0 == strncmp(buf, "http://", 7))
                    910:                return(html_endhttp(mbuf, args, buf, sz));
                    911:
                    912:        return(0);
                    913: }
                    914:
                    915:
1.1       kristaps  916: int
                    917: md_line_html(void *data, char *buf)
                    918: {
                    919:
1.2       kristaps  920:        return(mlg_line((struct md_mlg *)data, buf));
1.1       kristaps  921: }
                    922:
                    923:
                    924: int
                    925: md_exit_html(void *data, int flush)
                    926: {
                    927:
1.2       kristaps  928:        return(mlg_exit((struct md_mlg *)data, flush));
1.1       kristaps  929: }
                    930:
                    931:
                    932: void *
                    933: md_init_html(const struct md_args *args,
                    934:                struct md_mbuf *mbuf, const struct md_rbuf *rbuf)
                    935: {
1.9       kristaps  936:        struct ml_cbs    cbs;
1.8       kristaps  937:
1.9       kristaps  938:        cbs.ml_alloc = html_alloc;
                    939:        cbs.ml_free = html_free;
                    940:        cbs.ml_begintag = html_begintag;
                    941:        cbs.ml_endtag = html_endtag;
                    942:        cbs.ml_begin = html_begin;
                    943:        cbs.ml_end = html_end;
1.14      kristaps  944:        cbs.ml_beginstring = html_beginstring;
                    945:        cbs.ml_endstring = html_endstring;
1.1       kristaps  946:
1.9       kristaps  947:        return(mlg_alloc(args, rbuf, mbuf, &cbs));
1.1       kristaps  948: }

CVSweb