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

Annotation of mandoc/html.c, Revision 1.8

1.8     ! kristaps    1: /* $Id: html.c,v 1.7 2008/12/05 11:28:16 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: /* FIXME: free htmlq. */
        !            37:
1.7       kristaps   38: struct htmlnode {
1.8     ! kristaps   39:        int              tok;
        !            40:        enum md_ns       ns;
1.7       kristaps   41:        int             *argc[ROFF_MAXLINEARG];
                     42:        char            *argv[ROFF_MAXLINEARG];
                     43:        struct htmlnode *parent;
                     44: };
                     45:
                     46:
                     47: struct htmlq {
                     48:        struct htmlnode *last;
                     49: };
                     50:
                     51:
1.8     ! kristaps   52: static void            htmlnode_free(struct htmlnode *);
        !            53: static void            htmlnode_free(struct htmlnode *);
        !            54:
1.4       kristaps   55: static int             html_loadcss(struct md_mbuf *, const char *);
                     56:
1.8     ! kristaps   57: static ssize_t         html_endtag(struct md_mbuf *, void *,
1.2       kristaps   58:                                const struct md_args *,
                     59:                                enum md_ns, int);
1.8     ! kristaps   60: static ssize_t         html_begintag(struct md_mbuf *, void *,
1.2       kristaps   61:                                const struct md_args *,
                     62:                                enum md_ns, int,
                     63:                                const int *, const char **);
1.4       kristaps   64: static int             html_begin(struct md_mbuf *,
                     65:                                const struct md_args *,
                     66:                                const struct tm *,
                     67:                                const char *, const char *,
                     68:                                const char *, const char *);
1.7       kristaps   69: static int             html_printargs(struct md_mbuf *, int,
                     70:                                const char *, const int *,
                     71:                                const char **, size_t *);
1.2       kristaps   72: static int             html_end(struct md_mbuf *,
                     73:                                const struct md_args *);
1.7       kristaps   74: static int             html_blocktagname(struct md_mbuf *,
                     75:                                const struct md_args *, int, size_t *);
                     76: static int             html_blocktagargs(struct md_mbuf *,
1.2       kristaps   77:                                const struct md_args *, int,
1.7       kristaps   78:                                const int *, const char **, size_t *);
                     79: static int             html_blockheadtagname(struct md_mbuf *,
                     80:                                const struct md_args *, int, size_t *);
                     81: static int             html_blockheadtagargs(struct md_mbuf *,
1.3       kristaps   82:                                const struct md_args *, int,
1.7       kristaps   83:                                const int *, const char **, size_t *);
                     84: static int             html_blockbodytagname(struct md_mbuf *,
                     85:                                const struct md_args *, int, size_t *);
                     86: static int             html_blockbodytagargs(struct md_mbuf *,
1.3       kristaps   87:                                const struct md_args *, int,
1.7       kristaps   88:                                const int *, const char **, size_t *);
                     89: static int             html_inlinetagname(struct md_mbuf *,
                     90:                                const struct md_args *, int, size_t *);
                     91: static int             html_inlinetagargs(struct md_mbuf *,
1.2       kristaps   92:                                const struct md_args *, int,
1.7       kristaps   93:                                const int *, const char **, size_t *);
1.2       kristaps   94:
                     95:
1.4       kristaps   96: static int
                     97: html_loadcss(struct md_mbuf *mbuf, const char *css)
                     98: {
                     99:        size_t           res, bufsz;
                    100:        char            *buf;
                    101:        struct stat      st;
                    102:        int              fd, c;
                    103:        ssize_t          ssz;
                    104:
                    105:        c = 0;
                    106:        res = 0;
                    107:        buf = NULL;
                    108:
                    109:        if (-1 == (fd = open(css, O_RDONLY, 0))) {
                    110:                warn("%s", css);
                    111:                return(0);
                    112:        }
                    113:
                    114:        if (-1 == fstat(fd, &st)) {
                    115:                warn("%s", css);
                    116:                goto out;
                    117:        }
                    118:
                    119:        bufsz = MAX(st.st_blksize, BUFSIZ);
                    120:        if (NULL == (buf = malloc(bufsz))) {
                    121:                warn("malloc");
                    122:                goto out;
                    123:        }
                    124:
                    125:        for (;;) {
                    126:                if (-1 == (ssz = read(fd, buf, bufsz))) {
                    127:                        warn("%s", css);
                    128:                        goto out;
                    129:                } else if (0 == ssz)
                    130:                        break;
                    131:                if ( ! ml_nputs(mbuf, buf, (size_t)ssz, &res))
                    132:                        goto out;
                    133:        }
                    134:
                    135:        c = 1;
                    136:
                    137: out:
                    138:        if (-1 == close(fd)) {
                    139:                warn("%s", css);
                    140:                c = 0;
                    141:        }
                    142:
                    143:        if (buf)
                    144:                free(buf);
                    145:
                    146:        return(c);
                    147: }
                    148:
                    149:
1.3       kristaps  150: /* ARGSUSED */
1.2       kristaps  151: static int
1.4       kristaps  152: html_begin(struct md_mbuf *mbuf, const struct md_args *args,
                    153:                const struct tm *tm, const char *os,
                    154:                const char *title, const char *section,
                    155:                const char *vol)
1.2       kristaps  156: {
1.4       kristaps  157:        const char      *preamble, *css, *trail;
                    158:        char             buf[512];
1.2       kristaps  159:        size_t           res;
                    160:
1.4       kristaps  161:        preamble =
                    162:        "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n"
                    163:        "    \"http://www.w3.org/TR/html4/strict.dtd\">\n"
                    164:        "<html>\n"
                    165:        "<head>\n"
                    166:        "    <meta http-equiv=\"Content-Type\"\n"
                    167:        "         content=\"text/html;charset=utf-8\">\n"
                    168:        "    <meta name=\"resource-type\" content=\"document\">\n"
                    169:        "    <title>Manual Page for %s(%s)</title>\n";
                    170:
                    171:        css =
                    172:        "    <link rel=\"stylesheet\" type=\"text/css\"\n"
                    173:        "         href=\"%s\">\n";
                    174:        trail =
                    175:        "</head>\n"
                    176:        "<body>\n"
                    177:        "<div class=\"mdoc\">\n";
                    178:
1.2       kristaps  179:        res = 0;
1.4       kristaps  180:
                    181:        (void)snprintf(buf, sizeof(buf) - 1,
                    182:                        preamble, title, section);
                    183:
                    184:        if ( ! ml_puts(mbuf, buf, &res))
1.2       kristaps  185:                return(0);
1.4       kristaps  186:
                    187:        assert(args->params.html.css);
                    188:        if (HTML_CSS_EMBED & args->params.html.flags) {
1.5       kristaps  189:                if ( ! ml_puts(mbuf, "    <style type=\"text/css\"><!--\n", &res))
1.4       kristaps  190:                        return(0);
                    191:                if ( ! html_loadcss(mbuf, args->params.html.css))
                    192:                        return(0);
                    193:                if ( ! ml_puts(mbuf, "    --!></style>\n", &res))
                    194:                        return(0);
                    195:        } else {
                    196:                (void)snprintf(buf, sizeof(buf) - 1, css,
                    197:                                args->params.html.css);
                    198:                if ( ! ml_puts(mbuf, buf, &res))
                    199:                        return(0);
                    200:        }
                    201:
                    202:        if ( ! ml_puts(mbuf, trail, &res))
1.2       kristaps  203:                return(0);
                    204:
                    205:        return(1);
                    206: }
                    207:
                    208:
1.3       kristaps  209: /* ARGSUSED */
1.2       kristaps  210: static int
                    211: html_end(struct md_mbuf *mbuf, const struct md_args *args)
                    212: {
                    213:        size_t           res;
                    214:
                    215:        res = 0;
1.4       kristaps  216:        if ( ! ml_puts(mbuf, "</div></body>\n</html>", &res))
1.2       kristaps  217:                return(0);
                    218:
                    219:        return(1);
                    220: }
                    221:
                    222:
1.3       kristaps  223: /* ARGSUSED */
1.7       kristaps  224: static int
1.3       kristaps  225: html_blockbodytagname(struct md_mbuf *mbuf,
1.7       kristaps  226:                const struct md_args *args, int tok, size_t *res)
1.2       kristaps  227: {
1.3       kristaps  228:
1.7       kristaps  229:        return(ml_puts(mbuf, "div", res));
1.3       kristaps  230: }
                    231:
                    232:
                    233:
                    234:
                    235: /* ARGSUSED */
1.7       kristaps  236: static int
1.3       kristaps  237: html_blockheadtagname(struct md_mbuf *mbuf,
1.7       kristaps  238:                const struct md_args *args, int tok, size_t *res)
1.3       kristaps  239: {
                    240:
1.7       kristaps  241:        return(ml_puts(mbuf, "div", res));
1.3       kristaps  242: }
                    243:
                    244:
                    245: /* ARGSUSED */
1.7       kristaps  246: static int
1.3       kristaps  247: html_blocktagname(struct md_mbuf *mbuf,
1.7       kristaps  248:                const struct md_args *args, int tok, size_t *res)
1.3       kristaps  249: {
                    250:
1.7       kristaps  251:        return(ml_puts(mbuf, "div", res));
1.3       kristaps  252: }
                    253:
                    254:
1.7       kristaps  255: static int
                    256: html_printargs(struct md_mbuf *mbuf, int tok, const char *ns,
                    257:                const int *argc, const char **argv, size_t *res)
1.3       kristaps  258: {
1.7       kristaps  259:        int              i, c;
1.3       kristaps  260:
1.7       kristaps  261:        if ( ! ml_puts(mbuf, " class=\"", res))
                    262:                return(0);
                    263:        if ( ! ml_puts(mbuf, ns, res))
                    264:                return(0);
                    265:        if ( ! ml_puts(mbuf, "-", res))
1.3       kristaps  266:                return(0);
1.7       kristaps  267:        if ( ! ml_puts(mbuf, toknames[tok], res))
1.3       kristaps  268:                return(0);
1.7       kristaps  269:        if ( ! ml_puts(mbuf, "\"", res))
1.3       kristaps  270:                return(0);
                    271:
1.7       kristaps  272:        if (NULL == argv || NULL == argc)
                    273:                return(1);
                    274:        assert(argv && argc);
                    275:
                    276:        /* FIXME: ignores values. */
                    277:
                    278:        for (i = 0; ROFF_ARGMAX != (c = argc[i]); i++) {
                    279:                if (argv[i])
                    280:                        continue;
                    281:                if ( ! ml_puts(mbuf, " class=\"", res))
                    282:                        return(0);
                    283:                if ( ! ml_puts(mbuf, ns, res))
                    284:                        return(0);
                    285:                if ( ! ml_puts(mbuf, "-", res))
                    286:                        return(0);
                    287:                if ( ! ml_puts(mbuf, toknames[tok], res))
                    288:                        return(0);
                    289:                if ( ! ml_puts(mbuf, "-", res))
                    290:                        return(0);
                    291:                if ( ! ml_puts(mbuf, tokargnames[c], res))
                    292:                        return(0);
                    293:                if ( ! ml_puts(mbuf, "\"", res))
                    294:                        return(0);
1.3       kristaps  295:        }
                    296:
1.7       kristaps  297:        return(1);
1.3       kristaps  298: }
                    299:
                    300:
                    301: /* ARGSUSED */
1.7       kristaps  302: static int
                    303: html_blockheadtagargs(struct md_mbuf *mbuf,
                    304:                const struct md_args *args, int tok,
                    305:                const int *argc, const char **argv, size_t *res)
1.3       kristaps  306: {
                    307:
1.7       kristaps  308:        return(html_printargs(mbuf, tok, "head", argc, argv, res));
                    309: }
1.3       kristaps  310:
                    311:
1.7       kristaps  312: /* ARGSUSED */
                    313: static int
                    314: html_blockbodytagargs(struct md_mbuf *mbuf,
                    315:                const struct md_args *args, int tok,
                    316:                const int *argc, const char **argv, size_t *res)
                    317: {
1.3       kristaps  318:
1.7       kristaps  319:        return(html_printargs(mbuf, tok, "body", argc, argv, res));
1.2       kristaps  320: }
                    321:
                    322:
                    323: /* ARGSUSED */
1.7       kristaps  324: static int
                    325: html_blocktagargs(struct md_mbuf *mbuf,
                    326:                const struct md_args *args, int tok,
                    327:                const int *argc, const char **argv, size_t *res)
1.2       kristaps  328: {
1.3       kristaps  329:
1.7       kristaps  330:        return(html_printargs(mbuf, tok, "block", argc, argv, res));
1.2       kristaps  331: }
1.1       kristaps  332:
                    333:
                    334: /* ARGSUSED */
1.7       kristaps  335: static int
                    336: html_inlinetagargs(struct md_mbuf *mbuf,
                    337:                const struct md_args *args, int tok,
                    338:                const int *argc, const char **argv, size_t *res)
1.2       kristaps  339: {
                    340:
1.7       kristaps  341:        return(html_printargs(mbuf, tok, "inline", argc, argv, res));
1.2       kristaps  342: }
                    343:
                    344:
1.3       kristaps  345: /* ARGSUSED */
1.7       kristaps  346: static int
1.2       kristaps  347: html_inlinetagname(struct md_mbuf *mbuf,
1.7       kristaps  348:                const struct md_args *args, int tok, size_t *res)
1.2       kristaps  349: {
                    350:
                    351:        switch (tok) {
1.4       kristaps  352:        case (ROFF_Pp):
1.7       kristaps  353:                return(ml_puts(mbuf, "div", res));
1.2       kristaps  354:        default:
1.7       kristaps  355:                return(ml_puts(mbuf, "span", res));
1.2       kristaps  356:        }
1.7       kristaps  357:        return(1);
1.2       kristaps  358: }
                    359:
                    360:
                    361: static ssize_t
1.8     ! kristaps  362: html_begintag(struct md_mbuf *mbuf, void *data,
        !           363:                const struct md_args *args, enum md_ns ns,
        !           364:                int tok, const int *argc, const char **argv)
1.2       kristaps  365: {
1.7       kristaps  366:        size_t           res;
1.8     ! kristaps  367:        struct htmlq    *q;
        !           368:        struct htmlnode *node;
1.2       kristaps  369:
                    370:        assert(ns != MD_NS_DEFAULT);
1.7       kristaps  371:        res = 0;
                    372:
1.8     ! kristaps  373:        assert(data);
        !           374:        q = (struct htmlq *)data;
        !           375:
        !           376:        if (NULL == (node = calloc(1, sizeof(struct htmlnode)))) {
        !           377:                warn("calloc");
        !           378:                return(-1);
        !           379:        }
        !           380:
        !           381:        node->parent = q->last;
        !           382:        node->tok = tok;
        !           383:        node->ns = ns;
        !           384:
        !           385:        q->last = node;
        !           386:
1.3       kristaps  387:        switch (ns) {
                    388:        case (MD_NS_BLOCK):
1.7       kristaps  389:                if ( ! html_blocktagname(mbuf, args, tok, &res))
                    390:                        return(-1);
                    391:                if ( ! html_blocktagargs(mbuf, args, tok,
                    392:                                        argc, argv, &res))
                    393:                        return(-1);
                    394:                break;
1.3       kristaps  395:        case (MD_NS_BODY):
1.7       kristaps  396:                if ( ! html_blockbodytagname(mbuf, args, tok, &res))
                    397:                        return(-1);
                    398:                if ( ! html_blockbodytagargs(mbuf, args, tok,
                    399:                                        argc, argv, &res))
                    400:                        return(-1);
                    401:                break;
1.3       kristaps  402:        case (MD_NS_HEAD):
1.7       kristaps  403:                if ( ! html_blockheadtagname(mbuf, args, tok, &res))
                    404:                        return(-1);
                    405:                if ( ! html_blockheadtagargs(mbuf, args, tok,
                    406:                                        argc, argv, &res))
                    407:                        return(-1);
                    408:                break;
1.3       kristaps  409:        default:
1.7       kristaps  410:                if ( ! html_inlinetagname(mbuf, args, tok, &res))
                    411:                        return(-1);
                    412:                if ( ! html_inlinetagargs(mbuf, args, tok,
                    413:                                        argc, argv, &res))
                    414:                        return(-1);
1.3       kristaps  415:                break;
1.2       kristaps  416:        }
                    417:
1.7       kristaps  418:        return((ssize_t)res);
1.2       kristaps  419: }
                    420:
                    421:
                    422: static ssize_t
1.8     ! kristaps  423: html_endtag(struct md_mbuf *mbuf, void *data,
        !           424:                const struct md_args *args, enum md_ns ns, int tok)
1.2       kristaps  425: {
1.7       kristaps  426:        size_t           res;
1.8     ! kristaps  427:        struct htmlq    *q;
        !           428:        struct htmlnode *node;
1.2       kristaps  429:
                    430:        assert(ns != MD_NS_DEFAULT);
1.7       kristaps  431:        res = 0;
                    432:
1.8     ! kristaps  433:        assert(data);
        !           434:        q = (struct htmlq *)data;
        !           435:
1.3       kristaps  436:        switch (ns) {
                    437:        case (MD_NS_BLOCK):
1.7       kristaps  438:                if ( ! html_blocktagname(mbuf, args, tok, &res))
                    439:                        return(-1);
                    440:                break;
1.3       kristaps  441:        case (MD_NS_BODY):
1.7       kristaps  442:                if ( ! html_blockbodytagname(mbuf, args, tok, &res))
                    443:                        return(-1);
                    444:                break;
1.3       kristaps  445:        case (MD_NS_HEAD):
1.7       kristaps  446:                if ( ! html_blockheadtagname(mbuf, args, tok, &res))
                    447:                        return(-1);
                    448:                break;
1.3       kristaps  449:        default:
1.7       kristaps  450:                if ( ! html_inlinetagname(mbuf, args, tok, &res))
                    451:                        return(-1);
1.3       kristaps  452:                break;
                    453:        }
1.2       kristaps  454:
1.8     ! kristaps  455:        node = q->last;
        !           456:        q->last = node->parent;
        !           457:
        !           458:        htmlnode_free(node);
        !           459:
1.7       kristaps  460:        return((ssize_t)res);
1.2       kristaps  461: }
                    462:
                    463:
1.1       kristaps  464: int
                    465: md_line_html(void *data, char *buf)
                    466: {
                    467:
1.2       kristaps  468:        return(mlg_line((struct md_mlg *)data, buf));
1.1       kristaps  469: }
                    470:
                    471:
                    472: int
                    473: md_exit_html(void *data, int flush)
                    474: {
                    475:
1.2       kristaps  476:        return(mlg_exit((struct md_mlg *)data, flush));
1.1       kristaps  477: }
                    478:
                    479:
                    480: void *
                    481: md_init_html(const struct md_args *args,
                    482:                struct md_mbuf *mbuf, const struct md_rbuf *rbuf)
                    483: {
1.8     ! kristaps  484:        struct htmlq    *q;
        !           485:
        !           486:        if (NULL == (q = calloc(1, sizeof(struct htmlq)))) {
        !           487:                warn("calloc");
        !           488:                return(NULL);
        !           489:        }
1.1       kristaps  490:
1.8     ! kristaps  491:        return(mlg_alloc(args, q, rbuf, mbuf, html_begintag,
1.2       kristaps  492:                                html_endtag, html_begin, html_end));
1.1       kristaps  493: }
1.2       kristaps  494:

CVSweb