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