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

Annotation of mandoc/html.c, Revision 1.9

1.9     ! kristaps    1: /* $Id: html.c,v 1.8 2008/12/05 17:43:14 kristaps Exp $ */
1.1       kristaps    2: /*
                      3:  * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the
                      7:  * above copyright notice and this permission notice appear in all
                      8:  * copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
                     11:  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
                     12:  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
                     13:  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
                     14:  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
                     15:  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
                     16:  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
                     17:  * PERFORMANCE OF THIS SOFTWARE.
                     18:  */
1.4       kristaps   19: #include <sys/param.h>
                     20: #include <sys/stat.h>
                     21:
1.1       kristaps   22: #include <assert.h>
1.4       kristaps   23: #include <err.h>
                     24: #include <fcntl.h>
1.1       kristaps   25: #include <stdlib.h>
1.4       kristaps   26: #include <stdio.h>
1.2       kristaps   27: #include <string.h>
1.4       kristaps   28: #include <unistd.h>
1.1       kristaps   29:
                     30: #include "libmdocml.h"
                     31: #include "private.h"
1.2       kristaps   32: #include "ml.h"
                     33:
                     34:
1.8       kristaps   35: /* TODO: allow head/tail-less invocations (just "div" start). */
                     36:
1.7       kristaps   37: struct htmlnode {
1.8       kristaps   38:        int              tok;
                     39:        enum md_ns       ns;
1.7       kristaps   40:        int             *argc[ROFF_MAXLINEARG];
                     41:        char            *argv[ROFF_MAXLINEARG];
                     42:        struct htmlnode *parent;
                     43: };
                     44:
                     45:
                     46: struct htmlq {
                     47:        struct htmlnode *last;
                     48: };
                     49:
                     50:
1.4       kristaps   51: static int             html_loadcss(struct md_mbuf *, const char *);
                     52:
1.9     ! kristaps   53: static int             html_alloc(void **);
        !            54: static void            html_free(void *);
1.8       kristaps   55: static ssize_t         html_endtag(struct md_mbuf *, void *,
1.2       kristaps   56:                                const struct md_args *,
                     57:                                enum md_ns, int);
1.8       kristaps   58: static ssize_t         html_begintag(struct md_mbuf *, void *,
1.2       kristaps   59:                                const struct md_args *,
                     60:                                enum md_ns, int,
                     61:                                const int *, const char **);
1.4       kristaps   62: static int             html_begin(struct md_mbuf *,
                     63:                                const struct md_args *,
                     64:                                const struct tm *,
                     65:                                const char *, const char *,
                     66:                                const char *, const char *);
1.7       kristaps   67: static int             html_printargs(struct md_mbuf *, int,
                     68:                                const char *, const int *,
                     69:                                const char **, size_t *);
1.2       kristaps   70: static int             html_end(struct md_mbuf *,
                     71:                                const struct md_args *);
1.7       kristaps   72: static int             html_blocktagname(struct md_mbuf *,
                     73:                                const struct md_args *, int, size_t *);
                     74: static int             html_blocktagargs(struct md_mbuf *,
1.2       kristaps   75:                                const struct md_args *, int,
1.7       kristaps   76:                                const int *, const char **, size_t *);
                     77: static int             html_blockheadtagname(struct md_mbuf *,
                     78:                                const struct md_args *, int, size_t *);
                     79: static int             html_blockheadtagargs(struct md_mbuf *,
1.3       kristaps   80:                                const struct md_args *, int,
1.7       kristaps   81:                                const int *, const char **, size_t *);
                     82: static int             html_blockbodytagname(struct md_mbuf *,
                     83:                                const struct md_args *, int, size_t *);
                     84: static int             html_blockbodytagargs(struct md_mbuf *,
1.3       kristaps   85:                                const struct md_args *, int,
1.7       kristaps   86:                                const int *, const char **, size_t *);
                     87: static int             html_inlinetagname(struct md_mbuf *,
                     88:                                const struct md_args *, int, size_t *);
                     89: static int             html_inlinetagargs(struct md_mbuf *,
1.2       kristaps   90:                                const struct md_args *, int,
1.7       kristaps   91:                                const int *, const char **, size_t *);
1.2       kristaps   92:
                     93:
1.4       kristaps   94: static int
                     95: html_loadcss(struct md_mbuf *mbuf, const char *css)
                     96: {
                     97:        size_t           res, bufsz;
                     98:        char            *buf;
                     99:        struct stat      st;
                    100:        int              fd, c;
                    101:        ssize_t          ssz;
                    102:
                    103:        c = 0;
                    104:        res = 0;
                    105:        buf = NULL;
                    106:
                    107:        if (-1 == (fd = open(css, O_RDONLY, 0))) {
                    108:                warn("%s", css);
                    109:                return(0);
                    110:        }
                    111:
                    112:        if (-1 == fstat(fd, &st)) {
                    113:                warn("%s", css);
                    114:                goto out;
                    115:        }
                    116:
                    117:        bufsz = MAX(st.st_blksize, BUFSIZ);
                    118:        if (NULL == (buf = malloc(bufsz))) {
                    119:                warn("malloc");
                    120:                goto out;
                    121:        }
                    122:
                    123:        for (;;) {
                    124:                if (-1 == (ssz = read(fd, buf, bufsz))) {
                    125:                        warn("%s", css);
                    126:                        goto out;
                    127:                } else if (0 == ssz)
                    128:                        break;
                    129:                if ( ! ml_nputs(mbuf, buf, (size_t)ssz, &res))
                    130:                        goto out;
                    131:        }
                    132:
                    133:        c = 1;
                    134:
                    135: out:
                    136:        if (-1 == close(fd)) {
                    137:                warn("%s", css);
                    138:                c = 0;
                    139:        }
                    140:
                    141:        if (buf)
                    142:                free(buf);
                    143:
                    144:        return(c);
                    145: }
                    146:
                    147:
1.3       kristaps  148: /* ARGSUSED */
1.2       kristaps  149: static int
1.4       kristaps  150: html_begin(struct md_mbuf *mbuf, const struct md_args *args,
                    151:                const struct tm *tm, const char *os,
                    152:                const char *title, const char *section,
                    153:                const char *vol)
1.2       kristaps  154: {
1.4       kristaps  155:        const char      *preamble, *css, *trail;
                    156:        char             buf[512];
1.2       kristaps  157:        size_t           res;
                    158:
1.4       kristaps  159:        preamble =
                    160:        "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n"
                    161:        "    \"http://www.w3.org/TR/html4/strict.dtd\">\n"
                    162:        "<html>\n"
                    163:        "<head>\n"
                    164:        "    <meta http-equiv=\"Content-Type\"\n"
                    165:        "         content=\"text/html;charset=utf-8\">\n"
                    166:        "    <meta name=\"resource-type\" content=\"document\">\n"
                    167:        "    <title>Manual Page for %s(%s)</title>\n";
                    168:
                    169:        css =
                    170:        "    <link rel=\"stylesheet\" type=\"text/css\"\n"
                    171:        "         href=\"%s\">\n";
                    172:        trail =
                    173:        "</head>\n"
                    174:        "<body>\n"
                    175:        "<div class=\"mdoc\">\n";
                    176:
1.2       kristaps  177:        res = 0;
1.4       kristaps  178:
                    179:        (void)snprintf(buf, sizeof(buf) - 1,
                    180:                        preamble, title, section);
                    181:
                    182:        if ( ! ml_puts(mbuf, buf, &res))
1.2       kristaps  183:                return(0);
1.4       kristaps  184:
                    185:        assert(args->params.html.css);
                    186:        if (HTML_CSS_EMBED & args->params.html.flags) {
1.5       kristaps  187:                if ( ! ml_puts(mbuf, "    <style type=\"text/css\"><!--\n", &res))
1.4       kristaps  188:                        return(0);
                    189:                if ( ! html_loadcss(mbuf, args->params.html.css))
                    190:                        return(0);
                    191:                if ( ! ml_puts(mbuf, "    --!></style>\n", &res))
                    192:                        return(0);
                    193:        } else {
                    194:                (void)snprintf(buf, sizeof(buf) - 1, css,
                    195:                                args->params.html.css);
                    196:                if ( ! ml_puts(mbuf, buf, &res))
                    197:                        return(0);
                    198:        }
                    199:
                    200:        if ( ! ml_puts(mbuf, trail, &res))
1.2       kristaps  201:                return(0);
                    202:
                    203:        return(1);
                    204: }
                    205:
                    206:
1.3       kristaps  207: /* ARGSUSED */
1.2       kristaps  208: static int
                    209: html_end(struct md_mbuf *mbuf, const struct md_args *args)
                    210: {
                    211:
1.9     ! kristaps  212:        return(ml_puts(mbuf, "</div></body>\n</html>", NULL));
1.2       kristaps  213: }
                    214:
                    215:
1.3       kristaps  216: /* ARGSUSED */
1.7       kristaps  217: static int
1.3       kristaps  218: html_blockbodytagname(struct md_mbuf *mbuf,
1.7       kristaps  219:                const struct md_args *args, int tok, size_t *res)
1.2       kristaps  220: {
1.3       kristaps  221:
1.7       kristaps  222:        return(ml_puts(mbuf, "div", res));
1.3       kristaps  223: }
                    224:
                    225:
                    226: /* ARGSUSED */
1.7       kristaps  227: static int
1.3       kristaps  228: html_blockheadtagname(struct md_mbuf *mbuf,
1.7       kristaps  229:                const struct md_args *args, int tok, size_t *res)
1.3       kristaps  230: {
                    231:
1.7       kristaps  232:        return(ml_puts(mbuf, "div", res));
1.3       kristaps  233: }
                    234:
                    235:
                    236: /* ARGSUSED */
1.7       kristaps  237: static int
1.3       kristaps  238: html_blocktagname(struct md_mbuf *mbuf,
1.7       kristaps  239:                const struct md_args *args, int tok, size_t *res)
1.3       kristaps  240: {
                    241:
1.7       kristaps  242:        return(ml_puts(mbuf, "div", res));
1.3       kristaps  243: }
                    244:
                    245:
1.9     ! kristaps  246: /* ARGSUSED */
1.7       kristaps  247: static int
                    248: html_printargs(struct md_mbuf *mbuf, int tok, const char *ns,
                    249:                const int *argc, const char **argv, size_t *res)
1.3       kristaps  250: {
                    251:
1.7       kristaps  252:        if ( ! ml_puts(mbuf, " class=\"", res))
                    253:                return(0);
                    254:        if ( ! ml_puts(mbuf, ns, res))
                    255:                return(0);
                    256:        if ( ! ml_puts(mbuf, "-", res))
1.3       kristaps  257:                return(0);
1.7       kristaps  258:        if ( ! ml_puts(mbuf, toknames[tok], res))
1.3       kristaps  259:                return(0);
1.9     ! kristaps  260:        return(ml_puts(mbuf, "\"", res));
1.3       kristaps  261: }
                    262:
                    263:
                    264: /* ARGSUSED */
1.7       kristaps  265: static int
                    266: html_blockheadtagargs(struct md_mbuf *mbuf,
                    267:                const struct md_args *args, int tok,
                    268:                const int *argc, const char **argv, size_t *res)
1.3       kristaps  269: {
                    270:
1.7       kristaps  271:        return(html_printargs(mbuf, tok, "head", argc, argv, res));
                    272: }
1.3       kristaps  273:
                    274:
1.7       kristaps  275: /* ARGSUSED */
                    276: static int
                    277: html_blockbodytagargs(struct md_mbuf *mbuf,
                    278:                const struct md_args *args, int tok,
                    279:                const int *argc, const char **argv, size_t *res)
                    280: {
1.3       kristaps  281:
1.7       kristaps  282:        return(html_printargs(mbuf, tok, "body", argc, argv, res));
1.2       kristaps  283: }
                    284:
                    285:
                    286: /* ARGSUSED */
1.7       kristaps  287: static int
                    288: html_blocktagargs(struct md_mbuf *mbuf,
                    289:                const struct md_args *args, int tok,
                    290:                const int *argc, const char **argv, size_t *res)
1.2       kristaps  291: {
1.3       kristaps  292:
1.7       kristaps  293:        return(html_printargs(mbuf, tok, "block", argc, argv, res));
1.2       kristaps  294: }
1.1       kristaps  295:
                    296:
                    297: /* ARGSUSED */
1.7       kristaps  298: static int
                    299: html_inlinetagargs(struct md_mbuf *mbuf,
                    300:                const struct md_args *args, int tok,
                    301:                const int *argc, const char **argv, size_t *res)
1.2       kristaps  302: {
                    303:
1.7       kristaps  304:        return(html_printargs(mbuf, tok, "inline", argc, argv, res));
1.2       kristaps  305: }
                    306:
                    307:
1.3       kristaps  308: /* ARGSUSED */
1.7       kristaps  309: static int
1.2       kristaps  310: html_inlinetagname(struct md_mbuf *mbuf,
1.7       kristaps  311:                const struct md_args *args, int tok, size_t *res)
1.2       kristaps  312: {
                    313:
                    314:        switch (tok) {
1.4       kristaps  315:        case (ROFF_Pp):
1.7       kristaps  316:                return(ml_puts(mbuf, "div", res));
1.2       kristaps  317:        default:
1.9     ! kristaps  318:                break;
1.2       kristaps  319:        }
1.9     ! kristaps  320:
        !           321:        return(ml_puts(mbuf, "span", res));
1.2       kristaps  322: }
                    323:
                    324:
                    325: static ssize_t
1.8       kristaps  326: html_begintag(struct md_mbuf *mbuf, void *data,
                    327:                const struct md_args *args, enum md_ns ns,
                    328:                int tok, const int *argc, const char **argv)
1.2       kristaps  329: {
1.7       kristaps  330:        size_t           res;
1.8       kristaps  331:        struct htmlq    *q;
                    332:        struct htmlnode *node;
1.2       kristaps  333:
                    334:        assert(ns != MD_NS_DEFAULT);
1.7       kristaps  335:        res = 0;
                    336:
1.8       kristaps  337:        assert(data);
                    338:        q = (struct htmlq *)data;
                    339:
                    340:        if (NULL == (node = calloc(1, sizeof(struct htmlnode)))) {
                    341:                warn("calloc");
                    342:                return(-1);
                    343:        }
                    344:
                    345:        node->parent = q->last;
                    346:        node->tok = tok;
                    347:        node->ns = ns;
                    348:
                    349:        q->last = node;
                    350:
1.3       kristaps  351:        switch (ns) {
                    352:        case (MD_NS_BLOCK):
1.7       kristaps  353:                if ( ! html_blocktagname(mbuf, args, tok, &res))
                    354:                        return(-1);
                    355:                if ( ! html_blocktagargs(mbuf, args, tok,
                    356:                                        argc, argv, &res))
                    357:                        return(-1);
                    358:                break;
1.3       kristaps  359:        case (MD_NS_BODY):
1.7       kristaps  360:                if ( ! html_blockbodytagname(mbuf, args, tok, &res))
                    361:                        return(-1);
                    362:                if ( ! html_blockbodytagargs(mbuf, args, tok,
                    363:                                        argc, argv, &res))
                    364:                        return(-1);
                    365:                break;
1.3       kristaps  366:        case (MD_NS_HEAD):
1.7       kristaps  367:                if ( ! html_blockheadtagname(mbuf, args, tok, &res))
                    368:                        return(-1);
                    369:                if ( ! html_blockheadtagargs(mbuf, args, tok,
                    370:                                        argc, argv, &res))
                    371:                        return(-1);
                    372:                break;
1.3       kristaps  373:        default:
1.7       kristaps  374:                if ( ! html_inlinetagname(mbuf, args, tok, &res))
                    375:                        return(-1);
                    376:                if ( ! html_inlinetagargs(mbuf, args, tok,
                    377:                                        argc, argv, &res))
                    378:                        return(-1);
1.3       kristaps  379:                break;
1.2       kristaps  380:        }
                    381:
1.7       kristaps  382:        return((ssize_t)res);
1.2       kristaps  383: }
                    384:
                    385:
                    386: static ssize_t
1.8       kristaps  387: html_endtag(struct md_mbuf *mbuf, void *data,
                    388:                const struct md_args *args, enum md_ns ns, int tok)
1.2       kristaps  389: {
1.7       kristaps  390:        size_t           res;
1.8       kristaps  391:        struct htmlq    *q;
                    392:        struct htmlnode *node;
1.2       kristaps  393:
                    394:        assert(ns != MD_NS_DEFAULT);
1.7       kristaps  395:        res = 0;
                    396:
1.8       kristaps  397:        assert(data);
                    398:        q = (struct htmlq *)data;
                    399:
1.3       kristaps  400:        switch (ns) {
                    401:        case (MD_NS_BLOCK):
1.7       kristaps  402:                if ( ! html_blocktagname(mbuf, args, tok, &res))
                    403:                        return(-1);
                    404:                break;
1.3       kristaps  405:        case (MD_NS_BODY):
1.7       kristaps  406:                if ( ! html_blockbodytagname(mbuf, args, tok, &res))
                    407:                        return(-1);
                    408:                break;
1.3       kristaps  409:        case (MD_NS_HEAD):
1.7       kristaps  410:                if ( ! html_blockheadtagname(mbuf, args, tok, &res))
                    411:                        return(-1);
                    412:                break;
1.3       kristaps  413:        default:
1.7       kristaps  414:                if ( ! html_inlinetagname(mbuf, args, tok, &res))
                    415:                        return(-1);
1.3       kristaps  416:                break;
                    417:        }
1.2       kristaps  418:
1.8       kristaps  419:        node = q->last;
                    420:        q->last = node->parent;
                    421:
1.9     ! kristaps  422:        free(node);
1.8       kristaps  423:
1.7       kristaps  424:        return((ssize_t)res);
1.2       kristaps  425: }
                    426:
                    427:
1.9     ! kristaps  428: static int
        !           429: html_alloc(void **p)
        !           430: {
        !           431:
        !           432:        if (NULL == (*p = calloc(1, sizeof(struct htmlq)))) {
        !           433:                warn("calloc");
        !           434:                return(0);
        !           435:        }
        !           436:        return(1);
        !           437: }
        !           438:
        !           439:
        !           440: static void
        !           441: html_free(void *p)
        !           442: {
        !           443:        struct htmlq    *q;
        !           444:        struct htmlnode *n;
        !           445:
        !           446:        assert(p);
        !           447:        q = (struct htmlq *)p;
        !           448:
        !           449:        while ((n = q->last)) {
        !           450:                q->last = n->parent;
        !           451:                free(n);
        !           452:        }
        !           453:
        !           454:        free(q);
        !           455: }
        !           456:
        !           457:
1.1       kristaps  458: int
                    459: md_line_html(void *data, char *buf)
                    460: {
                    461:
1.2       kristaps  462:        return(mlg_line((struct md_mlg *)data, buf));
1.1       kristaps  463: }
                    464:
                    465:
                    466: int
                    467: md_exit_html(void *data, int flush)
                    468: {
                    469:
1.2       kristaps  470:        return(mlg_exit((struct md_mlg *)data, flush));
1.1       kristaps  471: }
                    472:
                    473:
                    474: void *
                    475: md_init_html(const struct md_args *args,
                    476:                struct md_mbuf *mbuf, const struct md_rbuf *rbuf)
                    477: {
1.9     ! kristaps  478:        struct ml_cbs    cbs;
1.8       kristaps  479:
1.9     ! kristaps  480:        cbs.ml_alloc = html_alloc;
        !           481:        cbs.ml_free = html_free;
        !           482:        cbs.ml_begintag = html_begintag;
        !           483:        cbs.ml_endtag = html_endtag;
        !           484:        cbs.ml_begin = html_begin;
        !           485:        cbs.ml_end = html_end;
1.1       kristaps  486:
1.9     ! kristaps  487:        return(mlg_alloc(args, rbuf, mbuf, &cbs));
1.1       kristaps  488: }
1.2       kristaps  489:

CVSweb