Annotation of mandoc/html.c, Revision 1.12
1.12 ! kristaps 1: /* $Id: html.c,v 1.11 2008/12/05 22:54:44 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.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.12 ! kristaps 412: html_bodytagname(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));
1.12 ! kristaps 420: case (ROFF_Fo):
! 421: return(ml_nputs(mbuf, "span", 4, res));
1.10 kristaps 422: case (ROFF_It):
423: return(html_It_bodytagname(mbuf, q, argc, argv, res));
1.12 ! kristaps 424: case (ROFF_Oo):
! 425: return(ml_nputs(mbuf, "span", 4, res));
1.10 kristaps 426: default:
427: break;
428: }
429:
1.7 kristaps 430: return(ml_puts(mbuf, "div", res));
1.3 kristaps 431: }
432:
433:
434: /* ARGSUSED */
1.7 kristaps 435: static int
1.10 kristaps 436: html_headtagname(struct md_mbuf *mbuf,
437: const struct md_args *args, int tok, struct htmlq *q,
438: const int *argc, const char **argv, size_t *res)
1.3 kristaps 439: {
440:
1.10 kristaps 441: switch (tok) {
442: case (ROFF_It):
443: return(html_It_headtagname(mbuf, q, argc, argv, res));
1.12 ! kristaps 444: case (ROFF_Fo):
! 445: return(ml_nputs(mbuf, "span", 4, res));
! 446: case (ROFF_Oo):
! 447: return(ml_nputs(mbuf, "span", 4, res));
1.10 kristaps 448: case (ROFF_Sh):
1.12 ! kristaps 449: return(ml_nputs(mbuf, "h1", 2, res));
1.10 kristaps 450: case (ROFF_Ss):
1.12 ! kristaps 451: return(ml_nputs(mbuf, "h2", 2, res));
1.10 kristaps 452: default:
453: break;
454: }
455:
1.12 ! kristaps 456: return(ml_nputs(mbuf, "div", 3, res));
1.3 kristaps 457: }
458:
459:
460: /* ARGSUSED */
1.7 kristaps 461: static int
1.10 kristaps 462: html_blocktagname(struct md_mbuf *mbuf, const struct md_args *args,
463: int tok, struct htmlq *q, const int *argc,
464: const char **argv, size_t *res)
1.3 kristaps 465: {
466:
1.10 kristaps 467: switch (tok) {
1.12 ! kristaps 468: case (ROFF_Fo):
! 469: return(ml_nputs(mbuf, "span", 4, res));
! 470: case (ROFF_Oo):
! 471: return(ml_nputs(mbuf, "span", 4, res));
1.10 kristaps 472: case (ROFF_It):
473: return(html_It_blocktagname(mbuf, q, argc, argv, res));
474: default:
475: break;
476: }
477:
1.7 kristaps 478: return(ml_puts(mbuf, "div", res));
1.3 kristaps 479: }
480:
481:
1.9 kristaps 482: /* ARGSUSED */
1.7 kristaps 483: static int
484: html_printargs(struct md_mbuf *mbuf, int tok, const char *ns,
485: const int *argc, const char **argv, size_t *res)
1.3 kristaps 486: {
487:
1.7 kristaps 488: if ( ! ml_puts(mbuf, " class=\"", res))
489: return(0);
490: if ( ! ml_puts(mbuf, ns, res))
491: return(0);
492: if ( ! ml_puts(mbuf, "-", res))
1.3 kristaps 493: return(0);
1.7 kristaps 494: if ( ! ml_puts(mbuf, toknames[tok], res))
1.3 kristaps 495: return(0);
1.9 kristaps 496: return(ml_puts(mbuf, "\"", res));
1.3 kristaps 497: }
498:
499:
500: /* ARGSUSED */
1.7 kristaps 501: static int
1.10 kristaps 502: html_headtagargs(struct md_mbuf *mbuf,
1.7 kristaps 503: const struct md_args *args, int tok,
504: const int *argc, const char **argv, size_t *res)
1.3 kristaps 505: {
506:
1.7 kristaps 507: return(html_printargs(mbuf, tok, "head", argc, argv, res));
508: }
1.3 kristaps 509:
510:
1.7 kristaps 511: /* ARGSUSED */
512: static int
1.12 ! kristaps 513: html_bodytagargs(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)
516: {
1.3 kristaps 517:
1.7 kristaps 518: return(html_printargs(mbuf, tok, "body", argc, argv, res));
1.2 kristaps 519: }
520:
521:
522: /* ARGSUSED */
1.7 kristaps 523: static int
524: html_blocktagargs(struct md_mbuf *mbuf,
525: const struct md_args *args, int tok,
526: const int *argc, const char **argv, size_t *res)
1.2 kristaps 527: {
1.3 kristaps 528:
1.7 kristaps 529: return(html_printargs(mbuf, tok, "block", argc, argv, res));
1.2 kristaps 530: }
1.1 kristaps 531:
532:
533: /* ARGSUSED */
1.7 kristaps 534: static int
535: html_inlinetagargs(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: {
539:
1.12 ! kristaps 540: if ( ! html_printargs(mbuf, tok, "inline", argc, argv, res))
! 541: return(0);
! 542:
! 543: switch (tok) {
! 544: case (ROFF_Sx):
! 545: assert(*argv);
! 546: if ( ! ml_nputs(mbuf, " href=\"#", 8, res))
! 547: return(0);
! 548: if ( ! ml_putstring(mbuf, *argv, res))
! 549: return(0);
! 550: if ( ! ml_nputs(mbuf, "\"", 1, res))
! 551: return(0);
! 552: default:
! 553: break;
! 554: }
! 555:
! 556: return(1);
1.2 kristaps 557: }
558:
559:
1.3 kristaps 560: /* ARGSUSED */
1.7 kristaps 561: static int
1.2 kristaps 562: html_inlinetagname(struct md_mbuf *mbuf,
1.7 kristaps 563: const struct md_args *args, int tok, size_t *res)
1.2 kristaps 564: {
565:
566: switch (tok) {
1.4 kristaps 567: case (ROFF_Pp):
1.12 ! kristaps 568: return(ml_nputs(mbuf, "div", 3, res));
! 569: case (ROFF_Sx):
! 570: return(ml_nputs(mbuf, "a", 1, res));
1.2 kristaps 571: default:
1.9 kristaps 572: break;
1.2 kristaps 573: }
1.9 kristaps 574:
575: return(ml_puts(mbuf, "span", res));
1.2 kristaps 576: }
577:
578:
579: static ssize_t
1.8 kristaps 580: html_begintag(struct md_mbuf *mbuf, void *data,
581: const struct md_args *args, enum md_ns ns,
582: int tok, const int *argc, const char **argv)
1.2 kristaps 583: {
1.7 kristaps 584: size_t res;
1.8 kristaps 585: struct htmlq *q;
586: struct htmlnode *node;
1.11 kristaps 587: int i;
1.2 kristaps 588:
589: assert(ns != MD_NS_DEFAULT);
1.7 kristaps 590: res = 0;
591:
1.8 kristaps 592: assert(data);
593: q = (struct htmlq *)data;
594:
595: if (NULL == (node = calloc(1, sizeof(struct htmlnode)))) {
596: warn("calloc");
597: return(-1);
598: }
599:
600: node->parent = q->last;
601: node->tok = tok;
602: node->ns = ns;
603:
1.10 kristaps 604: if (argc) {
605: /* TODO: argv. */
606:
607: assert(argv);
1.11 kristaps 608: for (i = 0; ROFF_ARGMAX != argc[i]
1.10 kristaps 609: && i < ROFF_MAXLINEARG; i++)
610: node->argc[i] = argc[i];
611: assert(i != ROFF_MAXLINEARG);
1.12 ! kristaps 612: }
1.10 kristaps 613:
614:
1.8 kristaps 615: q->last = node;
616:
1.3 kristaps 617: switch (ns) {
618: case (MD_NS_BLOCK):
1.10 kristaps 619: if ( ! html_blocktagname(mbuf, args, tok,
620: q, argc, argv, &res))
1.7 kristaps 621: return(-1);
622: if ( ! html_blocktagargs(mbuf, args, tok,
623: argc, argv, &res))
624: return(-1);
625: break;
1.3 kristaps 626: case (MD_NS_BODY):
1.12 ! kristaps 627: if ( ! html_bodytagname(mbuf, args, tok,
1.10 kristaps 628: q, argc, argv, &res))
1.7 kristaps 629: return(-1);
1.12 ! kristaps 630: if ( ! html_bodytagargs(mbuf, args, tok,
1.7 kristaps 631: argc, argv, &res))
632: return(-1);
633: break;
1.3 kristaps 634: case (MD_NS_HEAD):
1.10 kristaps 635: if ( ! html_headtagname(mbuf, args, tok, q,
636: argc, argv, &res))
1.7 kristaps 637: return(-1);
1.10 kristaps 638: if ( ! html_headtagargs(mbuf, args, tok,
1.7 kristaps 639: argc, argv, &res))
640: return(-1);
641: break;
1.3 kristaps 642: default:
1.7 kristaps 643: if ( ! html_inlinetagname(mbuf, args, tok, &res))
644: return(-1);
645: if ( ! html_inlinetagargs(mbuf, args, tok,
646: argc, argv, &res))
647: return(-1);
1.3 kristaps 648: break;
1.2 kristaps 649: }
650:
1.7 kristaps 651: return((ssize_t)res);
1.2 kristaps 652: }
653:
654:
655: static ssize_t
1.8 kristaps 656: html_endtag(struct md_mbuf *mbuf, void *data,
657: const struct md_args *args, enum md_ns ns, int tok)
1.2 kristaps 658: {
1.7 kristaps 659: size_t res;
1.8 kristaps 660: struct htmlq *q;
661: struct htmlnode *node;
1.2 kristaps 662:
663: assert(ns != MD_NS_DEFAULT);
1.7 kristaps 664: res = 0;
665:
1.8 kristaps 666: assert(data);
667: q = (struct htmlq *)data;
1.10 kristaps 668: node = q->last;
1.8 kristaps 669:
1.3 kristaps 670: switch (ns) {
671: case (MD_NS_BLOCK):
1.10 kristaps 672: if ( ! html_blocktagname(mbuf, args, tok,
673: q, node->argc,
674: (const char **)node->argv, &res))
1.7 kristaps 675: return(-1);
676: break;
1.3 kristaps 677: case (MD_NS_BODY):
1.12 ! kristaps 678: if ( ! html_bodytagname(mbuf, args, tok,
1.10 kristaps 679: q, node->argc,
680: (const char **)node->argv, &res))
1.7 kristaps 681: return(-1);
682: break;
1.3 kristaps 683: case (MD_NS_HEAD):
1.10 kristaps 684: if ( ! html_headtagname(mbuf, args, tok,
685: q, node->argc,
686: (const char **)node->argv, &res))
1.7 kristaps 687: return(-1);
688: break;
1.3 kristaps 689: default:
1.7 kristaps 690: if ( ! html_inlinetagname(mbuf, args, tok, &res))
691: return(-1);
1.3 kristaps 692: break;
693: }
1.2 kristaps 694:
1.8 kristaps 695: q->last = node->parent;
696:
1.9 kristaps 697: free(node);
1.8 kristaps 698:
1.7 kristaps 699: return((ssize_t)res);
1.2 kristaps 700: }
701:
702:
1.9 kristaps 703: static int
704: html_alloc(void **p)
705: {
706:
707: if (NULL == (*p = calloc(1, sizeof(struct htmlq)))) {
708: warn("calloc");
709: return(0);
710: }
711: return(1);
712: }
713:
714:
715: static void
716: html_free(void *p)
717: {
718: struct htmlq *q;
719: struct htmlnode *n;
720:
721: assert(p);
722: q = (struct htmlq *)p;
723:
724: while ((n = q->last)) {
725: q->last = n->parent;
726: free(n);
727: }
728:
729: free(q);
730: }
731:
732:
1.1 kristaps 733: int
734: md_line_html(void *data, char *buf)
735: {
736:
1.2 kristaps 737: return(mlg_line((struct md_mlg *)data, buf));
1.1 kristaps 738: }
739:
740:
741: int
742: md_exit_html(void *data, int flush)
743: {
744:
1.2 kristaps 745: return(mlg_exit((struct md_mlg *)data, flush));
1.1 kristaps 746: }
747:
748:
749: void *
750: md_init_html(const struct md_args *args,
751: struct md_mbuf *mbuf, const struct md_rbuf *rbuf)
752: {
1.9 kristaps 753: struct ml_cbs cbs;
1.8 kristaps 754:
1.9 kristaps 755: cbs.ml_alloc = html_alloc;
756: cbs.ml_free = html_free;
757: cbs.ml_begintag = html_begintag;
758: cbs.ml_endtag = html_endtag;
759: cbs.ml_begin = html_begin;
760: cbs.ml_end = html_end;
1.1 kristaps 761:
1.9 kristaps 762: return(mlg_alloc(args, rbuf, mbuf, &cbs));
1.1 kristaps 763: }
1.2 kristaps 764:
CVSweb