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