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