Annotation of mandoc/html.c, Revision 1.7
1.7 ! kristaps 1: /* $Id: html.c,v 1.6 2008/12/04 23:10:51 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.7 ! kristaps 35: struct htmlnode {
! 36: int type;
! 37: int *argc[ROFF_MAXLINEARG];
! 38: char *argv[ROFF_MAXLINEARG];
! 39: struct htmlnode *parent;
! 40: };
! 41:
! 42:
! 43: struct htmlq {
! 44: struct htmlnode *last;
! 45: };
! 46:
! 47:
1.4 kristaps 48: static int html_loadcss(struct md_mbuf *, const char *);
49:
1.2 kristaps 50: static ssize_t html_endtag(struct md_mbuf *,
51: const struct md_args *,
52: enum md_ns, int);
53: static ssize_t html_begintag(struct md_mbuf *,
54: const struct md_args *,
55: enum md_ns, int,
56: const int *, const char **);
1.4 kristaps 57: static int html_begin(struct md_mbuf *,
58: const struct md_args *,
59: const struct tm *,
60: const char *, const char *,
61: const char *, const char *);
1.7 ! kristaps 62: static int html_printargs(struct md_mbuf *, int,
! 63: const char *, const int *,
! 64: const char **, size_t *);
1.2 kristaps 65: static int html_end(struct md_mbuf *,
66: const struct md_args *);
1.7 ! kristaps 67: static int html_blocktagname(struct md_mbuf *,
! 68: const struct md_args *, int, size_t *);
! 69: static int html_blocktagargs(struct md_mbuf *,
1.2 kristaps 70: const struct md_args *, int,
1.7 ! kristaps 71: const int *, const char **, size_t *);
! 72: static int html_blockheadtagname(struct md_mbuf *,
! 73: const struct md_args *, int, size_t *);
! 74: static int html_blockheadtagargs(struct md_mbuf *,
1.3 kristaps 75: const struct md_args *, int,
1.7 ! kristaps 76: const int *, const char **, size_t *);
! 77: static int html_blockbodytagname(struct md_mbuf *,
! 78: const struct md_args *, int, size_t *);
! 79: static int html_blockbodytagargs(struct md_mbuf *,
1.3 kristaps 80: const struct md_args *, int,
1.7 ! kristaps 81: const int *, const char **, size_t *);
! 82: static int html_inlinetagname(struct md_mbuf *,
! 83: const struct md_args *, int, size_t *);
! 84: static int html_inlinetagargs(struct md_mbuf *,
1.2 kristaps 85: const struct md_args *, int,
1.7 ! kristaps 86: const int *, const char **, size_t *);
1.2 kristaps 87:
88:
1.4 kristaps 89: static int
90: html_loadcss(struct md_mbuf *mbuf, const char *css)
91: {
92: size_t res, bufsz;
93: char *buf;
94: struct stat st;
95: int fd, c;
96: ssize_t ssz;
97:
98: c = 0;
99: res = 0;
100: buf = NULL;
101:
102: if (-1 == (fd = open(css, O_RDONLY, 0))) {
103: warn("%s", css);
104: return(0);
105: }
106:
107: if (-1 == fstat(fd, &st)) {
108: warn("%s", css);
109: goto out;
110: }
111:
112: bufsz = MAX(st.st_blksize, BUFSIZ);
113: if (NULL == (buf = malloc(bufsz))) {
114: warn("malloc");
115: goto out;
116: }
117:
118: for (;;) {
119: if (-1 == (ssz = read(fd, buf, bufsz))) {
120: warn("%s", css);
121: goto out;
122: } else if (0 == ssz)
123: break;
124: if ( ! ml_nputs(mbuf, buf, (size_t)ssz, &res))
125: goto out;
126: }
127:
128: c = 1;
129:
130: out:
131: if (-1 == close(fd)) {
132: warn("%s", css);
133: c = 0;
134: }
135:
136: if (buf)
137: free(buf);
138:
139: return(c);
140: }
141:
142:
1.3 kristaps 143: /* ARGSUSED */
1.2 kristaps 144: static int
1.4 kristaps 145: html_begin(struct md_mbuf *mbuf, const struct md_args *args,
146: const struct tm *tm, const char *os,
147: const char *title, const char *section,
148: const char *vol)
1.2 kristaps 149: {
1.4 kristaps 150: const char *preamble, *css, *trail;
151: char buf[512];
1.2 kristaps 152: size_t res;
153:
1.4 kristaps 154: preamble =
155: "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n"
156: " \"http://www.w3.org/TR/html4/strict.dtd\">\n"
157: "<html>\n"
158: "<head>\n"
159: " <meta http-equiv=\"Content-Type\"\n"
160: " content=\"text/html;charset=utf-8\">\n"
161: " <meta name=\"resource-type\" content=\"document\">\n"
162: " <title>Manual Page for %s(%s)</title>\n";
163:
164: css =
165: " <link rel=\"stylesheet\" type=\"text/css\"\n"
166: " href=\"%s\">\n";
167: trail =
168: "</head>\n"
169: "<body>\n"
170: "<div class=\"mdoc\">\n";
171:
1.2 kristaps 172: res = 0;
1.4 kristaps 173:
174: (void)snprintf(buf, sizeof(buf) - 1,
175: preamble, title, section);
176:
177: if ( ! ml_puts(mbuf, buf, &res))
1.2 kristaps 178: return(0);
1.4 kristaps 179:
180: assert(args->params.html.css);
181: if (HTML_CSS_EMBED & args->params.html.flags) {
1.5 kristaps 182: if ( ! ml_puts(mbuf, " <style type=\"text/css\"><!--\n", &res))
1.4 kristaps 183: return(0);
184: if ( ! html_loadcss(mbuf, args->params.html.css))
185: return(0);
186: if ( ! ml_puts(mbuf, " --!></style>\n", &res))
187: return(0);
188: } else {
189: (void)snprintf(buf, sizeof(buf) - 1, css,
190: args->params.html.css);
191: if ( ! ml_puts(mbuf, buf, &res))
192: return(0);
193: }
194:
195: if ( ! ml_puts(mbuf, trail, &res))
1.2 kristaps 196: return(0);
197:
198: return(1);
199: }
200:
201:
1.3 kristaps 202: /* ARGSUSED */
1.2 kristaps 203: static int
204: html_end(struct md_mbuf *mbuf, const struct md_args *args)
205: {
206: size_t res;
207:
208: res = 0;
1.4 kristaps 209: if ( ! ml_puts(mbuf, "</div></body>\n</html>", &res))
1.2 kristaps 210: return(0);
211:
212: return(1);
213: }
214:
215:
1.3 kristaps 216: /* ARGSUSED */
1.7 ! kristaps 217: static int
1.3 kristaps 218: html_blockbodytagname(struct md_mbuf *mbuf,
1.7 ! kristaps 219: const struct md_args *args, int tok, size_t *res)
1.2 kristaps 220: {
1.3 kristaps 221:
1.7 ! kristaps 222: return(ml_puts(mbuf, "div", res));
1.3 kristaps 223: }
224:
225:
226:
227:
228: /* ARGSUSED */
1.7 ! kristaps 229: static int
1.3 kristaps 230: html_blockheadtagname(struct md_mbuf *mbuf,
1.7 ! kristaps 231: const struct md_args *args, int tok, size_t *res)
1.3 kristaps 232: {
233:
1.7 ! kristaps 234: return(ml_puts(mbuf, "div", res));
1.3 kristaps 235: }
236:
237:
238: /* ARGSUSED */
1.7 ! kristaps 239: static int
1.3 kristaps 240: html_blocktagname(struct md_mbuf *mbuf,
1.7 ! kristaps 241: const struct md_args *args, int tok, size_t *res)
1.3 kristaps 242: {
243:
1.7 ! kristaps 244: return(ml_puts(mbuf, "div", res));
1.3 kristaps 245: }
246:
247:
1.7 ! kristaps 248: static int
! 249: html_printargs(struct md_mbuf *mbuf, int tok, const char *ns,
! 250: const int *argc, const char **argv, size_t *res)
1.3 kristaps 251: {
1.7 ! kristaps 252: int i, c;
1.3 kristaps 253:
1.7 ! kristaps 254: if ( ! ml_puts(mbuf, " class=\"", res))
! 255: return(0);
! 256: if ( ! ml_puts(mbuf, ns, res))
! 257: return(0);
! 258: if ( ! ml_puts(mbuf, "-", res))
1.3 kristaps 259: return(0);
1.7 ! kristaps 260: if ( ! ml_puts(mbuf, toknames[tok], res))
1.3 kristaps 261: return(0);
1.7 ! kristaps 262: if ( ! ml_puts(mbuf, "\"", res))
1.3 kristaps 263: return(0);
264:
1.7 ! kristaps 265: if (NULL == argv || NULL == argc)
! 266: return(1);
! 267: assert(argv && argc);
! 268:
! 269: /* FIXME: ignores values. */
! 270:
! 271: for (i = 0; ROFF_ARGMAX != (c = argc[i]); i++) {
! 272: if (argv[i])
! 273: continue;
! 274: if ( ! ml_puts(mbuf, " class=\"", res))
! 275: return(0);
! 276: if ( ! ml_puts(mbuf, ns, res))
! 277: return(0);
! 278: if ( ! ml_puts(mbuf, "-", res))
! 279: return(0);
! 280: if ( ! ml_puts(mbuf, toknames[tok], res))
! 281: return(0);
! 282: if ( ! ml_puts(mbuf, "-", res))
! 283: return(0);
! 284: if ( ! ml_puts(mbuf, tokargnames[c], res))
! 285: return(0);
! 286: if ( ! ml_puts(mbuf, "\"", res))
! 287: return(0);
1.3 kristaps 288: }
289:
1.7 ! kristaps 290: return(1);
1.3 kristaps 291: }
292:
293:
294: /* ARGSUSED */
1.7 ! kristaps 295: static int
! 296: html_blockheadtagargs(struct md_mbuf *mbuf,
! 297: const struct md_args *args, int tok,
! 298: const int *argc, const char **argv, size_t *res)
1.3 kristaps 299: {
300:
1.7 ! kristaps 301: return(html_printargs(mbuf, tok, "head", argc, argv, res));
! 302: }
1.3 kristaps 303:
304:
1.7 ! kristaps 305: /* ARGSUSED */
! 306: static int
! 307: html_blockbodytagargs(struct md_mbuf *mbuf,
! 308: const struct md_args *args, int tok,
! 309: const int *argc, const char **argv, size_t *res)
! 310: {
1.3 kristaps 311:
1.7 ! kristaps 312: return(html_printargs(mbuf, tok, "body", argc, argv, res));
1.2 kristaps 313: }
314:
315:
316: /* ARGSUSED */
1.7 ! kristaps 317: static int
! 318: html_blocktagargs(struct md_mbuf *mbuf,
! 319: const struct md_args *args, int tok,
! 320: const int *argc, const char **argv, size_t *res)
1.2 kristaps 321: {
1.3 kristaps 322:
1.7 ! kristaps 323: return(html_printargs(mbuf, tok, "block", argc, argv, res));
1.2 kristaps 324: }
1.1 kristaps 325:
326:
327: /* ARGSUSED */
1.7 ! kristaps 328: static int
! 329: html_inlinetagargs(struct md_mbuf *mbuf,
! 330: const struct md_args *args, int tok,
! 331: const int *argc, const char **argv, size_t *res)
1.2 kristaps 332: {
333:
1.7 ! kristaps 334: return(html_printargs(mbuf, tok, "inline", argc, argv, res));
1.2 kristaps 335: }
336:
337:
1.3 kristaps 338: /* ARGSUSED */
1.7 ! kristaps 339: static int
1.2 kristaps 340: html_inlinetagname(struct md_mbuf *mbuf,
1.7 ! kristaps 341: const struct md_args *args, int tok, size_t *res)
1.2 kristaps 342: {
343:
344: switch (tok) {
1.4 kristaps 345: case (ROFF_Pp):
1.7 ! kristaps 346: return(ml_puts(mbuf, "div", res));
1.2 kristaps 347: default:
1.7 ! kristaps 348: return(ml_puts(mbuf, "span", res));
1.2 kristaps 349: }
1.7 ! kristaps 350: return(1);
1.2 kristaps 351: }
352:
353:
354: static ssize_t
355: html_begintag(struct md_mbuf *mbuf, const struct md_args *args,
356: enum md_ns ns, int tok,
357: const int *argc, const char **argv)
358: {
1.7 ! kristaps 359: size_t res;
1.2 kristaps 360:
361: assert(ns != MD_NS_DEFAULT);
1.7 ! kristaps 362: res = 0;
! 363:
1.3 kristaps 364: switch (ns) {
365: case (MD_NS_BLOCK):
1.7 ! kristaps 366: if ( ! html_blocktagname(mbuf, args, tok, &res))
! 367: return(-1);
! 368: if ( ! html_blocktagargs(mbuf, args, tok,
! 369: argc, argv, &res))
! 370: return(-1);
! 371: break;
1.3 kristaps 372: case (MD_NS_BODY):
1.7 ! kristaps 373: if ( ! html_blockbodytagname(mbuf, args, tok, &res))
! 374: return(-1);
! 375: if ( ! html_blockbodytagargs(mbuf, args, tok,
! 376: argc, argv, &res))
! 377: return(-1);
! 378: break;
1.3 kristaps 379: case (MD_NS_HEAD):
1.7 ! kristaps 380: if ( ! html_blockheadtagname(mbuf, args, tok, &res))
! 381: return(-1);
! 382: if ( ! html_blockheadtagargs(mbuf, args, tok,
! 383: argc, argv, &res))
! 384: return(-1);
! 385: break;
1.3 kristaps 386: default:
1.7 ! kristaps 387: if ( ! html_inlinetagname(mbuf, args, tok, &res))
! 388: return(-1);
! 389: if ( ! html_inlinetagargs(mbuf, args, tok,
! 390: argc, argv, &res))
! 391: return(-1);
1.3 kristaps 392: break;
1.2 kristaps 393: }
394:
1.7 ! kristaps 395: return((ssize_t)res);
1.2 kristaps 396: }
397:
398:
399: static ssize_t
400: html_endtag(struct md_mbuf *mbuf, const struct md_args *args,
401: enum md_ns ns, int tok)
402: {
1.7 ! kristaps 403: size_t res;
1.2 kristaps 404:
405: assert(ns != MD_NS_DEFAULT);
1.7 ! kristaps 406: res = 0;
! 407:
1.3 kristaps 408: switch (ns) {
409: case (MD_NS_BLOCK):
1.7 ! kristaps 410: if ( ! html_blocktagname(mbuf, args, tok, &res))
! 411: return(-1);
! 412: break;
1.3 kristaps 413: case (MD_NS_BODY):
1.7 ! kristaps 414: if ( ! html_blockbodytagname(mbuf, args, tok, &res))
! 415: return(-1);
! 416: break;
1.3 kristaps 417: case (MD_NS_HEAD):
1.7 ! kristaps 418: if ( ! html_blockheadtagname(mbuf, args, tok, &res))
! 419: return(-1);
! 420: break;
1.3 kristaps 421: default:
1.7 ! kristaps 422: if ( ! html_inlinetagname(mbuf, args, tok, &res))
! 423: return(-1);
1.3 kristaps 424: break;
425: }
1.2 kristaps 426:
1.7 ! kristaps 427: return((ssize_t)res);
1.2 kristaps 428: }
429:
430:
1.1 kristaps 431: int
432: md_line_html(void *data, char *buf)
433: {
434:
1.2 kristaps 435: return(mlg_line((struct md_mlg *)data, buf));
1.1 kristaps 436: }
437:
438:
439: int
440: md_exit_html(void *data, int flush)
441: {
442:
1.2 kristaps 443: return(mlg_exit((struct md_mlg *)data, flush));
1.1 kristaps 444: }
445:
446:
447: void *
448: md_init_html(const struct md_args *args,
449: struct md_mbuf *mbuf, const struct md_rbuf *rbuf)
450: {
451:
1.2 kristaps 452: return(mlg_alloc(args, rbuf, mbuf, html_begintag,
453: html_endtag, html_begin, html_end));
1.1 kristaps 454: }
1.2 kristaps 455:
CVSweb