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