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