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

Annotation of mandoc/html.c, Revision 1.18

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

CVSweb