Annotation of mandoc/html.c, Revision 1.21
1.21 ! kristaps 1: /* $Id: html.c,v 1.20 2008/12/10 00:58:15 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:
1.19 kristaps 30: #include "html.h"
1.2 kristaps 31: #include "ml.h"
32:
1.8 kristaps 33: /* TODO: allow head/tail-less invocations (just "div" start). */
34:
1.7 kristaps 35: struct htmlnode {
1.8 kristaps 36: int tok;
37: enum md_ns ns;
1.10 kristaps 38: int argc[ROFF_MAXLINEARG];
1.7 kristaps 39: char *argv[ROFF_MAXLINEARG];
40: struct htmlnode *parent;
41: };
42:
43: struct htmlq {
44: struct htmlnode *last;
45: };
46:
47:
1.19 kristaps 48: static int html_loadcss(struct md_mbuf *,
49: const char *);
1.9 kristaps 50: static int html_alloc(void **);
51: static void html_free(void *);
1.8 kristaps 52: static ssize_t html_endtag(struct md_mbuf *, void *,
1.2 kristaps 53: const struct md_args *,
54: enum md_ns, int);
1.14 kristaps 55: static ssize_t html_beginstring(struct md_mbuf *,
56: const struct md_args *,
57: const char *, size_t);
58: static ssize_t html_beginhttp(struct md_mbuf *,
59: const struct md_args *,
60: const char *, size_t);
61: static ssize_t html_endstring(struct md_mbuf *,
62: const struct md_args *,
63: const char *, size_t);
64: static ssize_t html_endhttp(struct md_mbuf *,
65: const struct md_args *,
66: const char *, size_t);
1.8 kristaps 67: static ssize_t html_begintag(struct md_mbuf *, void *,
1.2 kristaps 68: const struct md_args *,
69: enum md_ns, int,
70: const int *, const char **);
1.4 kristaps 71: static int html_begin(struct md_mbuf *,
72: const struct md_args *,
73: const struct tm *,
74: const char *, const char *,
1.21 ! kristaps 75: enum roffmsec, enum roffvol);
1.7 kristaps 76: static int html_printargs(struct md_mbuf *, int,
77: const char *, const int *,
78: const char **, size_t *);
1.2 kristaps 79: static int html_end(struct md_mbuf *,
80: const struct md_args *);
1.7 kristaps 81: static int html_blocktagname(struct md_mbuf *,
1.10 kristaps 82: const struct md_args *, int,
83: struct htmlq *, const int *,
84: const char **, size_t *);
1.7 kristaps 85: static int html_blocktagargs(struct md_mbuf *,
1.2 kristaps 86: const struct md_args *, int,
1.7 kristaps 87: const int *, const char **, size_t *);
1.10 kristaps 88: static int html_headtagname(struct md_mbuf *,
89: const struct md_args *, int,
90: struct htmlq *, const int *,
91: const char **, size_t *);
92: static int html_headtagargs(struct md_mbuf *,
1.3 kristaps 93: const struct md_args *, int,
1.7 kristaps 94: const int *, const char **, size_t *);
1.12 kristaps 95: static int html_bodytagname(struct md_mbuf *,
1.10 kristaps 96: const struct md_args *,
97: int, struct htmlq *, const int *,
98: const char **, size_t *);
1.12 kristaps 99: static int html_bodytagargs(struct md_mbuf *,
1.3 kristaps 100: const struct md_args *, int,
1.7 kristaps 101: const int *, const char **, size_t *);
102: static int html_inlinetagname(struct md_mbuf *,
103: const struct md_args *, int, size_t *);
104: static int html_inlinetagargs(struct md_mbuf *,
1.2 kristaps 105: const struct md_args *, int,
1.7 kristaps 106: const int *, const char **, size_t *);
1.10 kristaps 107: static int html_Bl_bodytagname(struct md_mbuf *,
108: struct htmlq *, const int *,
109: const char **, size_t *);
110: static int html_It_blocktagname(struct md_mbuf *,
111: struct htmlq *, const int *,
112: const char **, size_t *);
113: static int html_It_headtagname(struct md_mbuf *,
114: struct htmlq *, const int *,
115: const char **, size_t *);
116: static int html_It_bodytagname(struct md_mbuf *,
117: struct htmlq *, const int *,
118: const char **, size_t *);
1.19 kristaps 119: static int html_tputln(struct md_mbuf *,
120: enum ml_scope, int, enum html_tag);
121: static int html_aputln(struct md_mbuf *, enum ml_scope,
122: int, enum html_tag,
123: int, const struct html_pair *);
1.10 kristaps 124:
125:
126: /* ARGSUSED */
127: static int
128: html_It_headtagname(struct md_mbuf *mbuf, struct htmlq *q,
129: const int *argc, const char **argv, size_t *res)
130: {
131: struct htmlnode *n;
1.11 kristaps 132: int i;
1.10 kristaps 133:
134: for (n = q->last; n; n = n->parent)
135: if (n->tok == ROFF_Bl)
136: break;
137:
138: assert(n);
1.13 kristaps 139:
140: /* LINTED */
1.11 kristaps 141: for (i = 0; ROFF_ARGMAX != n->argc[i] &&
1.10 kristaps 142: i < ROFF_MAXLINEARG; i++) {
143: switch (n->argc[i]) {
1.14 kristaps 144: case (ROFF_Ohang):
1.19 kristaps 145: return(html_stput(mbuf, HTML_TAG_DIV, res));
1.10 kristaps 146: case (ROFF_Tag):
147: /* FALLTHROUGH */
148: case (ROFF_Column):
1.19 kristaps 149: return(html_stput(mbuf, HTML_TAG_TD, res));
1.10 kristaps 150: default:
151: break;
152: }
153: }
154:
1.16 kristaps 155: return(0);
1.10 kristaps 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):
1.19 kristaps 194: return(html_stput(mbuf, HTML_TAG_DIV, res));
1.10 kristaps 195: case (ROFF_Tag):
196: /* FALLTHROUGH */
197: case (ROFF_Column):
1.19 kristaps 198: return(html_stput(mbuf, HTML_TAG_TD, res));
1.10 kristaps 199: default:
200: break;
201: }
202: }
203:
204: assert(i != ROFF_MAXLINEARG);
1.16 kristaps 205: return(0);
1.10 kristaps 206: }
207:
208:
209: /* ARGSUSED */
210: static int
211: html_Bl_bodytagname(struct md_mbuf *mbuf, struct htmlq *q,
212: const int *argc, const char **argv, size_t *res)
213: {
1.11 kristaps 214: int i;
1.10 kristaps 215:
1.11 kristaps 216: for (i = 0; ROFF_ARGMAX != argc[i]
1.10 kristaps 217: && i < ROFF_MAXLINEARG; i++) {
218: switch (argc[i]) {
219: case (ROFF_Enum):
1.19 kristaps 220: return(html_stput(mbuf, HTML_TAG_OL, res));
1.10 kristaps 221: case (ROFF_Bullet):
222: /* FALLTHROUGH */
223: case (ROFF_Dash):
224: /* FALLTHROUGH */
225: case (ROFF_Hyphen):
226: /* FALLTHROUGH */
227: case (ROFF_Item):
228: /* FALLTHROUGH */
229: case (ROFF_Diag):
230: /* FALLTHROUGH */
231: case (ROFF_Hang):
232: /* FALLTHROUGH */
233: case (ROFF_Ohang):
234: /* FALLTHROUGH */
235: case (ROFF_Inset):
1.19 kristaps 236: return(html_stput(mbuf, HTML_TAG_UL, res));
1.10 kristaps 237: case (ROFF_Tag):
238: /* FALLTHROUGH */
239: case (ROFF_Column):
1.19 kristaps 240: return(html_stput(mbuf, HTML_TAG_TABLE, res));
1.10 kristaps 241: default:
242: break;
243: }
244: }
245:
246: assert(i != ROFF_MAXLINEARG);
1.16 kristaps 247: return(0);
1.10 kristaps 248: }
249:
250:
251: /* ARGSUSED */
252: static int
253: html_It_blocktagname(struct md_mbuf *mbuf, struct htmlq *q,
254: const int *argc, const char **argv, size_t *res)
255: {
256: struct htmlnode *n;
1.11 kristaps 257: int i;
1.10 kristaps 258:
259: for (n = q->last; n; n = n->parent)
260: if (n->tok == ROFF_Bl)
261: break;
262:
263: assert(n);
1.13 kristaps 264:
265: /* LINTED */
1.11 kristaps 266: for (i = 0; ROFF_ARGMAX != n->argc[i] &&
1.10 kristaps 267: i < ROFF_MAXLINEARG; i++) {
268: switch (n->argc[i]) {
269: case (ROFF_Enum):
270: /* FALLTHROUGH */
271: case (ROFF_Bullet):
272: /* FALLTHROUGH */
273: case (ROFF_Dash):
274: /* FALLTHROUGH */
275: case (ROFF_Hyphen):
276: /* FALLTHROUGH */
277: case (ROFF_Item):
278: /* FALLTHROUGH */
279: case (ROFF_Diag):
280: /* FALLTHROUGH */
281: case (ROFF_Hang):
282: /* FALLTHROUGH */
283: case (ROFF_Ohang):
284: /* FALLTHROUGH */
285: case (ROFF_Inset):
1.19 kristaps 286: return(html_stput(mbuf, HTML_TAG_LI, res));
1.10 kristaps 287: case (ROFF_Tag):
288: /* FALLTHROUGH */
289: case (ROFF_Column):
1.19 kristaps 290: return(html_stput(mbuf, HTML_TAG_TR, res));
1.10 kristaps 291: default:
292: break;
293: }
294: }
295:
296: assert(i != ROFF_MAXLINEARG);
1.16 kristaps 297: return(0);
1.10 kristaps 298: }
1.2 kristaps 299:
300:
1.4 kristaps 301: static int
302: html_loadcss(struct md_mbuf *mbuf, const char *css)
303: {
304: size_t res, bufsz;
305: char *buf;
306: struct stat st;
307: int fd, c;
308: ssize_t ssz;
309:
310: c = 0;
311: res = 0;
312: buf = NULL;
313:
314: if (-1 == (fd = open(css, O_RDONLY, 0))) {
315: warn("%s", css);
316: return(0);
317: }
318:
319: if (-1 == fstat(fd, &st)) {
320: warn("%s", css);
321: goto out;
322: }
323:
324: bufsz = MAX(st.st_blksize, BUFSIZ);
325: if (NULL == (buf = malloc(bufsz))) {
326: warn("malloc");
327: goto out;
328: }
329:
330: for (;;) {
331: if (-1 == (ssz = read(fd, buf, bufsz))) {
332: warn("%s", css);
333: goto out;
334: } else if (0 == ssz)
335: break;
336: if ( ! ml_nputs(mbuf, buf, (size_t)ssz, &res))
337: goto out;
338: }
339:
340: c = 1;
341:
342: out:
343: if (-1 == close(fd)) {
344: warn("%s", css);
345: c = 0;
346: }
347:
348: if (buf)
349: free(buf);
350:
351: return(c);
352: }
353:
354:
1.18 kristaps 355: static int
1.19 kristaps 356: html_tputln(struct md_mbuf *mbuf, enum ml_scope scope,
357: int i, enum html_tag tag)
1.18 kristaps 358: {
359:
1.19 kristaps 360: if ( ! ml_putchars(mbuf, ' ', INDENT(i) * INDENT_SZ, NULL))
1.18 kristaps 361: return(0);
1.19 kristaps 362: if ( ! html_tput(mbuf, scope, tag, NULL))
1.18 kristaps 363: return(0);
1.19 kristaps 364: return(ml_nputs(mbuf, "\n", 1, NULL));
1.18 kristaps 365: }
366:
367:
368: static int
1.19 kristaps 369: html_aputln(struct md_mbuf *mbuf, enum ml_scope scope, int i,
370: enum html_tag tag, int sz, const struct html_pair *p)
1.18 kristaps 371: {
372:
1.19 kristaps 373: if ( ! ml_putchars(mbuf, ' ', INDENT(i) * INDENT_SZ, NULL))
1.18 kristaps 374: return(0);
1.19 kristaps 375: if ( ! html_aput(mbuf, scope, tag, NULL, sz, p))
376: return(0);
377: return(ml_nputs(mbuf, "\n", 1, NULL));
1.18 kristaps 378: }
379:
380:
1.3 kristaps 381: /* ARGSUSED */
1.2 kristaps 382: static int
1.4 kristaps 383: html_begin(struct md_mbuf *mbuf, const struct md_args *args,
384: const struct tm *tm, const char *os,
1.21 ! kristaps 385: const char *name, enum roffmsec msec, enum roffvol vol)
1.2 kristaps 386: {
1.19 kristaps 387: struct html_pair attr[4];
1.21 ! kristaps 388: char ts[32], title[64];
1.19 kristaps 389: int i;
1.2 kristaps 390:
1.19 kristaps 391: (void)snprintf(ts, sizeof(ts), "%s(%s)",
392: name, roff_msecname(msec));
1.4 kristaps 393:
1.21 ! kristaps 394: (void)snprintf(ts, sizeof(ts), "%s",
! 395: name, roff_volname(vol));
! 396:
! 397: if (vol >= ROFF_ARCH_START) {
! 398:
! 399: }
! 400:
! 401:
1.18 kristaps 402: i = 0;
1.4 kristaps 403:
1.19 kristaps 404: if ( ! html_typeput(mbuf, HTML_TYPE_4_01_STRICT, NULL))
1.17 kristaps 405: return(0);
1.19 kristaps 406: if ( ! html_tputln(mbuf, ML_OPEN, i, HTML_TAG_HTML))
1.17 kristaps 407: return(0);
1.19 kristaps 408: if ( ! html_tputln(mbuf, ML_OPEN, i++, HTML_TAG_HEAD))
1.17 kristaps 409: return(0);
1.19 kristaps 410:
411: attr[0].attr = HTML_ATTR_HTTP_EQUIV;
412: attr[0].val = "content-type";
413: attr[1].attr = HTML_ATTR_CONTENT;
414: attr[1].val = "text/html;charset=utf-8";
415:
416: if ( ! html_aputln(mbuf, ML_OPEN, i, HTML_TAG_META, 2, attr))
1.17 kristaps 417: return(0);
1.19 kristaps 418:
419: attr[0].attr = HTML_ATTR_NAME;
420: attr[0].val = "resource-type";
421: attr[1].attr = HTML_ATTR_CONTENT;
422: attr[1].val = "document";
423:
424: if ( ! html_aputln(mbuf, ML_OPEN, i, HTML_TAG_META, 2, attr))
1.17 kristaps 425: return(0);
1.19 kristaps 426:
427: if ( ! html_tputln(mbuf, ML_OPEN, i, HTML_TAG_TITLE))
1.17 kristaps 428: return(0);
1.19 kristaps 429: if ( ! ml_putstring(mbuf, ts, NULL))
1.17 kristaps 430: return(0);
1.19 kristaps 431: if ( ! html_tputln(mbuf, ML_CLOSE, i, HTML_TAG_TITLE))
1.2 kristaps 432: return(0);
1.4 kristaps 433:
434: if (HTML_CSS_EMBED & args->params.html.flags) {
1.19 kristaps 435: attr[0].attr = HTML_ATTR_TYPE;
436: attr[0].val = "text/css";
437:
438: if ( ! html_aputln(mbuf, ML_OPEN, i,
439: HTML_TAG_STYLE, 1, attr))
1.4 kristaps 440: return(0);
1.19 kristaps 441: if ( ! html_commentput(mbuf, ML_OPEN, NULL))
442: return(NULL);
443:
1.4 kristaps 444: if ( ! html_loadcss(mbuf, args->params.html.css))
445: return(0);
1.19 kristaps 446:
447: if ( ! html_commentput(mbuf, ML_CLOSE, NULL))
448: return(NULL);
449: if ( ! html_tputln(mbuf, ML_CLOSE, i, HTML_TAG_STYLE))
1.4 kristaps 450: return(0);
1.19 kristaps 451: } else {
452: attr[0].attr = HTML_ATTR_REL;
453: attr[0].val = "stylesheet";
454: attr[1].attr = HTML_ATTR_TYPE;
455: attr[1].val = "text/css";
456: attr[2].attr = HTML_ATTR_HREF;
457: attr[2].val = args->params.html.css;
458:
459: if ( ! html_aputln(mbuf, ML_OPEN, i,
460: HTML_TAG_LINK, 3, attr))
461: return(0);
462: }
1.4 kristaps 463:
1.19 kristaps 464: if ( ! html_tputln(mbuf, ML_CLOSE, --i, HTML_TAG_HEAD))
1.18 kristaps 465: return(0);
1.19 kristaps 466: if ( ! html_tputln(mbuf, ML_OPEN, i, HTML_TAG_BODY))
1.18 kristaps 467: return(0);
1.19 kristaps 468:
469: attr[0].attr = HTML_ATTR_CLASS;
470: attr[0].val = "mdoc";
471:
472: if ( ! html_aputln(mbuf, ML_OPEN, i, HTML_TAG_DIV, 1, attr))
1.18 kristaps 473: return(0);
1.19 kristaps 474:
475: attr[0].attr = HTML_ATTR_WIDTH;
476: attr[0].val = "100%";
477:
478: if ( ! html_aputln(mbuf, ML_OPEN, i++, HTML_TAG_TABLE, 1, attr))
1.18 kristaps 479: return(0);
1.19 kristaps 480: if ( ! html_tputln(mbuf, ML_OPEN, i++, HTML_TAG_TR))
1.18 kristaps 481: return(0);
1.19 kristaps 482:
483: if ( ! html_tputln(mbuf, ML_OPEN, i, HTML_TAG_TD))
1.2 kristaps 484: return(0);
1.19 kristaps 485: if ( ! ml_putstring(mbuf, ts, NULL))
1.18 kristaps 486: return(0);
1.19 kristaps 487: if ( ! html_tputln(mbuf, ML_CLOSE, i, HTML_TAG_TD))
1.18 kristaps 488: return(0);
1.19 kristaps 489:
490: if ( ! html_tputln(mbuf, ML_OPEN, i, HTML_TAG_TD))
1.18 kristaps 491: return(0);
1.19 kristaps 492: /* TODO: middle. */
493: if ( ! html_tputln(mbuf, ML_CLOSE, i, HTML_TAG_TD))
1.18 kristaps 494: return(0);
1.19 kristaps 495:
1.20 kristaps 496: attr[0].attr = HTML_ATTR_ALIGN;
497: attr[0].val = "right";
498:
499: if ( ! html_aputln(mbuf, ML_OPEN, i, HTML_TAG_TD, 1, attr))
1.18 kristaps 500: return(0);
1.19 kristaps 501: if ( ! ml_putstring(mbuf, ts, NULL))
1.17 kristaps 502: return(0);
1.19 kristaps 503: if ( ! html_tputln(mbuf, ML_CLOSE, i, HTML_TAG_TD))
1.17 kristaps 504: return(0);
1.19 kristaps 505:
506: if ( ! html_tputln(mbuf, ML_CLOSE, --i, HTML_TAG_TR))
1.17 kristaps 507: return(0);
1.19 kristaps 508: return(html_tputln(mbuf, ML_CLOSE, --i, HTML_TAG_TABLE));
1.2 kristaps 509: }
510:
511:
1.3 kristaps 512: /* ARGSUSED */
1.2 kristaps 513: static int
514: html_end(struct md_mbuf *mbuf, const struct md_args *args)
515: {
516:
1.19 kristaps 517: if ( ! html_tputln(mbuf, ML_CLOSE, 0, HTML_TAG_DIV))
1.18 kristaps 518: return(0);
1.19 kristaps 519: if ( ! html_tputln(mbuf, ML_CLOSE, 0, HTML_TAG_BODY))
1.18 kristaps 520: return(0);
1.19 kristaps 521: return(html_tputln(mbuf, ML_CLOSE, 0, HTML_TAG_HTML));
1.2 kristaps 522: }
523:
524:
1.3 kristaps 525: /* ARGSUSED */
1.7 kristaps 526: static int
1.12 kristaps 527: html_bodytagname(struct md_mbuf *mbuf,
1.10 kristaps 528: const struct md_args *args, int tok, struct htmlq *q,
529: const int *argc, const char **argv, size_t *res)
1.2 kristaps 530: {
1.3 kristaps 531:
1.10 kristaps 532: switch (tok) {
533: case (ROFF_Bl):
534: return(html_Bl_bodytagname(mbuf, q, argc, argv, res));
1.12 kristaps 535: case (ROFF_Fo):
1.19 kristaps 536: return(html_stput(mbuf, HTML_TAG_SPAN, res));
1.10 kristaps 537: case (ROFF_It):
538: return(html_It_bodytagname(mbuf, q, argc, argv, res));
1.12 kristaps 539: case (ROFF_Oo):
1.19 kristaps 540: return(html_stput(mbuf, HTML_TAG_SPAN, res));
1.10 kristaps 541: default:
542: break;
543: }
544:
1.19 kristaps 545: return(html_stput(mbuf, HTML_TAG_DIV, res));
1.3 kristaps 546: }
547:
548:
549: /* ARGSUSED */
1.7 kristaps 550: static int
1.10 kristaps 551: html_headtagname(struct md_mbuf *mbuf,
552: const struct md_args *args, int tok, struct htmlq *q,
553: const int *argc, const char **argv, size_t *res)
1.3 kristaps 554: {
555:
1.10 kristaps 556: switch (tok) {
557: case (ROFF_It):
558: return(html_It_headtagname(mbuf, q, argc, argv, res));
1.12 kristaps 559: case (ROFF_Fo):
1.19 kristaps 560: /* FALLTHROUGH */
1.12 kristaps 561: case (ROFF_Oo):
1.19 kristaps 562: return(html_stput(mbuf, HTML_TAG_SPAN, res));
1.10 kristaps 563: case (ROFF_Sh):
1.19 kristaps 564: return(html_stput(mbuf, HTML_TAG_H1, res));
1.10 kristaps 565: case (ROFF_Ss):
1.19 kristaps 566: return(html_stput(mbuf, HTML_TAG_H2, res));
1.10 kristaps 567: default:
568: break;
569: }
570:
1.19 kristaps 571: return(html_stput(mbuf, HTML_TAG_DIV, res));
1.3 kristaps 572: }
573:
574:
575: /* ARGSUSED */
1.7 kristaps 576: static int
1.10 kristaps 577: html_blocktagname(struct md_mbuf *mbuf, const struct md_args *args,
578: int tok, struct htmlq *q, const int *argc,
579: const char **argv, size_t *res)
1.3 kristaps 580: {
581:
1.10 kristaps 582: switch (tok) {
1.12 kristaps 583: case (ROFF_Fo):
1.19 kristaps 584: /* FALLTHROUGH */
1.12 kristaps 585: case (ROFF_Oo):
1.19 kristaps 586: return(html_stput(mbuf, HTML_TAG_SPAN, res));
1.10 kristaps 587: case (ROFF_It):
588: return(html_It_blocktagname(mbuf, q, argc, argv, res));
589: default:
590: break;
591: }
592:
1.19 kristaps 593: return(html_stput(mbuf, HTML_TAG_DIV, res));
1.3 kristaps 594: }
595:
596:
1.9 kristaps 597: /* ARGSUSED */
1.7 kristaps 598: static int
599: html_printargs(struct md_mbuf *mbuf, int tok, const char *ns,
600: const int *argc, const char **argv, size_t *res)
1.3 kristaps 601: {
602:
1.19 kristaps 603: /* FIXME: use API in ml.h. */
604:
1.7 kristaps 605: if ( ! ml_puts(mbuf, " class=\"", res))
606: return(0);
607: if ( ! ml_puts(mbuf, ns, res))
608: return(0);
609: if ( ! ml_puts(mbuf, "-", res))
1.3 kristaps 610: return(0);
1.7 kristaps 611: if ( ! ml_puts(mbuf, toknames[tok], res))
1.3 kristaps 612: return(0);
1.9 kristaps 613: return(ml_puts(mbuf, "\"", res));
1.3 kristaps 614: }
615:
616:
617: /* ARGSUSED */
1.7 kristaps 618: static int
1.10 kristaps 619: html_headtagargs(struct md_mbuf *mbuf,
1.7 kristaps 620: const struct md_args *args, int tok,
621: const int *argc, const char **argv, size_t *res)
1.3 kristaps 622: {
623:
1.7 kristaps 624: return(html_printargs(mbuf, tok, "head", argc, argv, res));
625: }
1.3 kristaps 626:
627:
1.7 kristaps 628: /* ARGSUSED */
629: static int
1.12 kristaps 630: html_bodytagargs(struct md_mbuf *mbuf,
1.7 kristaps 631: const struct md_args *args, int tok,
632: const int *argc, const char **argv, size_t *res)
633: {
1.3 kristaps 634:
1.7 kristaps 635: return(html_printargs(mbuf, tok, "body", argc, argv, res));
1.2 kristaps 636: }
637:
638:
639: /* ARGSUSED */
1.7 kristaps 640: static int
641: html_blocktagargs(struct md_mbuf *mbuf,
642: const struct md_args *args, int tok,
643: const int *argc, const char **argv, size_t *res)
1.2 kristaps 644: {
1.3 kristaps 645:
1.7 kristaps 646: return(html_printargs(mbuf, tok, "block", argc, argv, res));
1.2 kristaps 647: }
1.1 kristaps 648:
649:
650: /* ARGSUSED */
1.7 kristaps 651: static int
652: html_inlinetagargs(struct md_mbuf *mbuf,
653: const struct md_args *args, int tok,
654: const int *argc, const char **argv, size_t *res)
1.2 kristaps 655: {
656:
1.12 kristaps 657: if ( ! html_printargs(mbuf, tok, "inline", argc, argv, res))
658: return(0);
659:
660: switch (tok) {
661: case (ROFF_Sx):
1.19 kristaps 662:
663: /* FIXME: use API in ml.h. */
664:
1.12 kristaps 665: assert(*argv);
666: if ( ! ml_nputs(mbuf, " href=\"#", 8, res))
667: return(0);
668: if ( ! ml_putstring(mbuf, *argv, res))
669: return(0);
670: if ( ! ml_nputs(mbuf, "\"", 1, res))
671: return(0);
1.13 kristaps 672: break;
1.12 kristaps 673: default:
674: break;
675: }
676:
677: return(1);
1.2 kristaps 678: }
679:
680:
1.3 kristaps 681: /* ARGSUSED */
1.7 kristaps 682: static int
1.2 kristaps 683: html_inlinetagname(struct md_mbuf *mbuf,
1.7 kristaps 684: const struct md_args *args, int tok, size_t *res)
1.2 kristaps 685: {
686:
687: switch (tok) {
1.4 kristaps 688: case (ROFF_Pp):
1.19 kristaps 689: return(html_stput(mbuf, HTML_TAG_DIV, res));
1.12 kristaps 690: case (ROFF_Sx):
1.19 kristaps 691: return(html_stput(mbuf, HTML_TAG_A, res));
1.2 kristaps 692: default:
1.9 kristaps 693: break;
1.2 kristaps 694: }
1.9 kristaps 695:
1.19 kristaps 696: return(html_stput(mbuf, HTML_TAG_SPAN, res));
1.2 kristaps 697: }
698:
699:
700: static ssize_t
1.8 kristaps 701: html_begintag(struct md_mbuf *mbuf, void *data,
702: const struct md_args *args, enum md_ns ns,
703: int tok, const int *argc, const char **argv)
1.2 kristaps 704: {
1.7 kristaps 705: size_t res;
1.8 kristaps 706: struct htmlq *q;
707: struct htmlnode *node;
1.11 kristaps 708: int i;
1.2 kristaps 709:
710: assert(ns != MD_NS_DEFAULT);
1.7 kristaps 711: res = 0;
712:
1.8 kristaps 713: assert(data);
714: q = (struct htmlq *)data;
715:
716: if (NULL == (node = calloc(1, sizeof(struct htmlnode)))) {
717: warn("calloc");
718: return(-1);
719: }
720:
721: node->parent = q->last;
722: node->tok = tok;
723: node->ns = ns;
724:
1.10 kristaps 725: if (argc) {
726: /* TODO: argv. */
727:
728: assert(argv);
1.13 kristaps 729: /* LINTED */
1.11 kristaps 730: for (i = 0; ROFF_ARGMAX != argc[i]
1.10 kristaps 731: && i < ROFF_MAXLINEARG; i++)
732: node->argc[i] = argc[i];
733: assert(i != ROFF_MAXLINEARG);
1.12 kristaps 734: }
1.10 kristaps 735:
736:
1.8 kristaps 737: q->last = node;
738:
1.3 kristaps 739: switch (ns) {
740: case (MD_NS_BLOCK):
1.10 kristaps 741: if ( ! html_blocktagname(mbuf, args, tok,
742: q, argc, argv, &res))
1.7 kristaps 743: return(-1);
744: if ( ! html_blocktagargs(mbuf, args, tok,
745: argc, argv, &res))
746: return(-1);
747: break;
1.3 kristaps 748: case (MD_NS_BODY):
1.12 kristaps 749: if ( ! html_bodytagname(mbuf, args, tok,
1.10 kristaps 750: q, argc, argv, &res))
1.7 kristaps 751: return(-1);
1.12 kristaps 752: if ( ! html_bodytagargs(mbuf, args, tok,
1.7 kristaps 753: argc, argv, &res))
754: return(-1);
755: break;
1.3 kristaps 756: case (MD_NS_HEAD):
1.10 kristaps 757: if ( ! html_headtagname(mbuf, args, tok, q,
758: argc, argv, &res))
1.7 kristaps 759: return(-1);
1.10 kristaps 760: if ( ! html_headtagargs(mbuf, args, tok,
1.7 kristaps 761: argc, argv, &res))
762: return(-1);
763: break;
1.3 kristaps 764: default:
1.7 kristaps 765: if ( ! html_inlinetagname(mbuf, args, tok, &res))
766: return(-1);
767: if ( ! html_inlinetagargs(mbuf, args, tok,
768: argc, argv, &res))
769: return(-1);
1.3 kristaps 770: break;
1.2 kristaps 771: }
772:
1.7 kristaps 773: return((ssize_t)res);
1.2 kristaps 774: }
775:
776:
777: static ssize_t
1.8 kristaps 778: html_endtag(struct md_mbuf *mbuf, void *data,
779: const struct md_args *args, enum md_ns ns, int tok)
1.2 kristaps 780: {
1.7 kristaps 781: size_t res;
1.8 kristaps 782: struct htmlq *q;
783: struct htmlnode *node;
1.2 kristaps 784:
785: assert(ns != MD_NS_DEFAULT);
1.7 kristaps 786: res = 0;
787:
1.8 kristaps 788: assert(data);
789: q = (struct htmlq *)data;
1.10 kristaps 790: node = q->last;
1.8 kristaps 791:
1.3 kristaps 792: switch (ns) {
793: case (MD_NS_BLOCK):
1.10 kristaps 794: if ( ! html_blocktagname(mbuf, args, tok,
795: q, node->argc,
796: (const char **)node->argv, &res))
1.7 kristaps 797: return(-1);
798: break;
1.3 kristaps 799: case (MD_NS_BODY):
1.12 kristaps 800: if ( ! html_bodytagname(mbuf, args, tok,
1.10 kristaps 801: q, node->argc,
802: (const char **)node->argv, &res))
1.7 kristaps 803: return(-1);
804: break;
1.3 kristaps 805: case (MD_NS_HEAD):
1.10 kristaps 806: if ( ! html_headtagname(mbuf, args, tok,
807: q, node->argc,
808: (const char **)node->argv, &res))
1.7 kristaps 809: return(-1);
810: break;
1.3 kristaps 811: default:
1.7 kristaps 812: if ( ! html_inlinetagname(mbuf, args, tok, &res))
813: return(-1);
1.3 kristaps 814: break;
815: }
1.2 kristaps 816:
1.8 kristaps 817: q->last = node->parent;
818:
1.9 kristaps 819: free(node);
1.8 kristaps 820:
1.7 kristaps 821: return((ssize_t)res);
1.2 kristaps 822: }
823:
824:
1.9 kristaps 825: static int
826: html_alloc(void **p)
827: {
828:
829: if (NULL == (*p = calloc(1, sizeof(struct htmlq)))) {
830: warn("calloc");
831: return(0);
832: }
833: return(1);
834: }
835:
836:
837: static void
838: html_free(void *p)
839: {
840: struct htmlq *q;
841: struct htmlnode *n;
842:
843: assert(p);
844: q = (struct htmlq *)p;
845:
1.13 kristaps 846: /* LINTED */
1.9 kristaps 847: while ((n = q->last)) {
848: q->last = n->parent;
849: free(n);
850: }
851:
852: free(q);
853: }
854:
855:
1.14 kristaps 856: static ssize_t
857: html_beginhttp(struct md_mbuf *mbuf,
858: const struct md_args *args,
859: const char *buf, size_t sz)
860: {
861: size_t res;
1.19 kristaps 862: struct html_pair pair;
1.14 kristaps 863:
864: res = 0;
1.19 kristaps 865: pair.attr = HTML_ATTR_HREF;
866: pair.val = (char *)buf;
1.14 kristaps 867:
1.19 kristaps 868: if ( ! html_aput(mbuf, ML_OPEN, HTML_TAG_A, &res, 1, &pair))
1.14 kristaps 869: return(-1);
870: return((ssize_t)res);
871: }
872:
873:
874: static ssize_t
875: html_endhttp(struct md_mbuf *mbuf,
876: const struct md_args *args,
877: const char *buf, size_t sz)
878: {
879: size_t res;
880:
881: res = 0;
1.19 kristaps 882: if ( ! html_tput(mbuf, ML_CLOSE, HTML_TAG_A, &res))
1.14 kristaps 883: return(-1);
884: return((ssize_t)res);
885: }
886:
887:
888: /* ARGSUSED */
889: static ssize_t
890: html_beginstring(struct md_mbuf *mbuf,
891: const struct md_args *args,
892: const char *buf, size_t sz)
893: {
894:
895: if (0 == strncmp(buf, "http://", 7))
896: return(html_beginhttp(mbuf, args, buf, sz));
897:
898: return(0);
899: }
900:
901:
902: /* ARGSUSED */
903: static ssize_t
904: html_endstring(struct md_mbuf *mbuf,
905: const struct md_args *args,
906: const char *buf, size_t sz)
907: {
908:
909: if (0 == strncmp(buf, "http://", 7))
910: return(html_endhttp(mbuf, args, buf, sz));
911:
912: return(0);
913: }
914:
915:
1.1 kristaps 916: int
917: md_line_html(void *data, char *buf)
918: {
919:
1.2 kristaps 920: return(mlg_line((struct md_mlg *)data, buf));
1.1 kristaps 921: }
922:
923:
924: int
925: md_exit_html(void *data, int flush)
926: {
927:
1.2 kristaps 928: return(mlg_exit((struct md_mlg *)data, flush));
1.1 kristaps 929: }
930:
931:
932: void *
933: md_init_html(const struct md_args *args,
934: struct md_mbuf *mbuf, const struct md_rbuf *rbuf)
935: {
1.9 kristaps 936: struct ml_cbs cbs;
1.8 kristaps 937:
1.9 kristaps 938: cbs.ml_alloc = html_alloc;
939: cbs.ml_free = html_free;
940: cbs.ml_begintag = html_begintag;
941: cbs.ml_endtag = html_endtag;
942: cbs.ml_begin = html_begin;
943: cbs.ml_end = html_end;
1.14 kristaps 944: cbs.ml_beginstring = html_beginstring;
945: cbs.ml_endstring = html_endstring;
1.1 kristaps 946:
1.9 kristaps 947: return(mlg_alloc(args, rbuf, mbuf, &cbs));
1.1 kristaps 948: }
CVSweb