]>
git.cameronkatri.com Git - mandoc.git/blob - xml.c
1 /* $Id: xml.c,v 1.9 2008/12/02 18:26:57 kristaps Exp $ */
3 * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
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
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.
19 #include <sys/param.h>
28 #include "libmdocml.h"
40 MD_BLKIN
, /* Controls spacing. */
48 const struct md_args
*args
;
49 const struct md_rbuf
*rbuf
;
52 struct rofftree
*tree
;
57 #define MD_LITERAL (1 << 0) /* TODO */
58 #define MD_OVERRIDE_ONE (1 << 1)
59 #define MD_OVERRIDE_ALL (1 << 2)
62 static void roffmsg(void *arg
, enum roffmsg
,
63 const char *, const char *, char *);
64 static int roffhead(void *);
65 static int rofftail(void *);
66 static int roffin(void *, int, int *, char **);
67 static int roffdata(void *, int, char *);
68 static int roffout(void *, int);
69 static int roffblkin(void *, int, int *, char **);
70 static int roffblkout(void *, int);
71 static int roffspecial(void *, int, int *, char **, char **);
73 static void mbuf_mode(struct md_xml
*, enum md_ns
);
74 static int mbuf_newline(struct md_xml
*);
75 static int xml_indent(struct md_xml
*);
76 static int mbuf_data(struct md_xml
*, int, char *);
77 static int xml_nputstring(struct md_xml
*,
78 const char *, size_t);
79 static int xml_puts(struct md_xml
*, const char *);
80 static int xml_nputs(struct md_xml
*,
81 const char *, size_t);
82 static int xml_begintag(struct md_xml
*, const char *,
83 enum md_ns
, int *, char **);
84 static int xml_endtag(struct md_xml
*,
85 const char *, enum md_ns
);
87 #ifdef __linux__ /* FIXME: remove */
88 static size_t strlcat(char *, const char *, size_t);
89 static size_t strlcpy(char *, const char *, size_t);
94 mbuf_mode(struct md_xml
*p
, enum md_ns ns
)
96 p
->flags
&= ~MD_OVERRIDE_ONE
;
102 xml_begintag(struct md_xml
*p
, const char *name
, enum md_ns ns
,
103 int *argc
, char **argv
)
111 res
= strlcpy(buf
, "block:", sizeof(buf
));
112 assert(res
< sizeof(buf
));
115 res
= strlcpy(buf
, "inline:", sizeof(buf
));
116 assert(res
< sizeof(buf
));
123 res
= strlcat(buf
, name
, sizeof(buf
));
124 assert(res
< sizeof(buf
));
126 if (-1 == (sz
= ml_begintag(p
->mbuf
, buf
, argc
, argv
)))
135 xml_endtag(struct md_xml
*p
, const char *name
, enum md_ns ns
)
143 res
= strlcpy(buf
, "block:", sizeof(buf
));
144 assert(res
< sizeof(buf
));
147 res
= strlcpy(buf
, "inline:", sizeof(buf
));
148 assert(res
< sizeof(buf
));
155 res
= strlcat(buf
, name
, sizeof(buf
));
156 assert(res
< sizeof(buf
));
158 if (-1 == (sz
= ml_endtag(p
->mbuf
, buf
)))
167 xml_nputstring(struct md_xml
*p
, const char *buf
, size_t sz
)
171 if (-1 == (res
= ml_nputstring(p
->mbuf
, buf
, sz
)))
179 xml_nputs(struct md_xml
*p
, const char *buf
, size_t sz
)
183 if (-1 == (res
= ml_nputs(p
->mbuf
, buf
, sz
)))
191 xml_puts(struct md_xml
*p
, const char *buf
)
194 return(xml_nputs(p
, buf
, strlen(buf
)));
199 xml_indent(struct md_xml
*p
)
203 if (-1 == (res
= ml_indent(p
->mbuf
, p
->indent
)))
211 mbuf_newline(struct md_xml
*p
)
214 if ( ! md_buf_putchar(p
->mbuf
, '\n'))
223 mbuf_data(struct md_xml
*p
, int space
, char *buf
)
229 assert(0 != p
->indent
);
231 if (MD_OVERRIDE_ONE
& p
->flags
|| MD_OVERRIDE_ALL
& p
->flags
)
234 if (MD_LITERAL
& p
->flags
)
235 return(xml_nputstring(p
, buf
, sizeof(buf
)));
238 while (*buf
&& isspace(*buf
))
245 while (*buf
&& ! isspace(*buf
))
254 if ( ! xml_indent(p
))
256 if ( ! xml_nputstring(p
, bufp
, sz
))
258 if (p
->indent
* MAXINDENT
+ sz
>= COLUMNS
)
259 if ( ! mbuf_newline(p
))
261 if ( ! (MD_OVERRIDE_ALL
& p
->flags
))
266 if (space
&& sz
+ p
->pos
>= COLUMNS
) {
267 if ( ! mbuf_newline(p
))
269 if ( ! xml_indent(p
))
272 if ( ! xml_nputs(p
, " ", 1))
276 if ( ! xml_nputstring(p
, bufp
, sz
))
279 if ( ! (MD_OVERRIDE_ALL
& p
->flags
))
288 md_line_xml(void *arg
, char *buf
)
292 p
= (struct md_xml
*)arg
;
293 return(roff_engine(p
->tree
, buf
));
298 md_exit_xml(void *data
, int flush
)
303 p
= (struct md_xml
*)data
;
304 c
= roff_free(p
->tree
, flush
);
312 md_init_xml(const struct md_args
*args
,
313 struct md_mbuf
*mbuf
, const struct md_rbuf
*rbuf
)
318 cb
.roffhead
= roffhead
;
319 cb
.rofftail
= rofftail
;
321 cb
.roffout
= roffout
;
322 cb
.roffblkin
= roffblkin
;
323 cb
.roffblkout
= roffblkout
;
324 cb
.roffspecial
= roffspecial
;
325 cb
.roffmsg
= roffmsg
;
326 cb
.roffdata
= roffdata
;
328 if (NULL
== (p
= calloc(1, sizeof(struct md_xml
))))
337 if (NULL
== (p
->tree
= roff_alloc(&cb
, p
))) {
353 p
= (struct md_xml
*)arg
;
355 if (-1 == xml_puts(p
, "<?xml version=\"1.0\" "
356 "encoding=\"UTF-8\"?>\n"))
358 if (-1 == xml_puts(p
, "<mdoc xmlns:block=\"block\" "
359 "xmlns:special=\"special\" "
360 "xmlns:inline=\"inline\">"))
364 mbuf_mode(p
, MD_BLKIN
);
365 return(mbuf_newline(p
));
375 p
= (struct md_xml
*)arg
;
377 if (0 != p
->pos
&& ! mbuf_newline(p
))
380 mbuf_mode(p
, MD_BLKOUT
);
381 if ( ! xml_endtag(p
, "mdoc", MD_NS_DEFAULT
))
383 return(mbuf_newline(p
));
389 roffspecial(void *arg
, int tok
, int *argc
, char **argv
, char **more
)
394 p
= (struct md_xml
*)arg
;
396 /* FIXME: this is completely ad hoc. */
400 p
->flags
|= MD_OVERRIDE_ONE
;
404 if (0 == strcmp(*more
, "on"))
405 p
->flags
|= MD_OVERRIDE_ALL
;
407 p
->flags
&= ~MD_OVERRIDE_ALL
;
418 roffblkin(void *arg
, int tok
, int *argc
, char **argv
)
423 p
= (struct md_xml
*)arg
;
426 if ( ! mbuf_newline(p
))
428 if ( ! xml_indent(p
))
430 } else if ( ! xml_indent(p
))
433 /* FIXME: xml won't like standards args (e.g., p1003.1-90). */
436 mbuf_mode(p
, MD_BLKIN
);
438 if ( ! xml_begintag(p
, toknames
[tok
], MD_NS_BLOCK
,
441 return(mbuf_newline(p
));
446 roffblkout(void *arg
, int tok
)
451 p
= (struct md_xml
*)arg
;
456 if ( ! mbuf_newline(p
))
458 if ( ! xml_indent(p
))
460 } else if ( ! xml_indent(p
))
463 mbuf_mode(p
, MD_BLKOUT
);
464 if ( ! xml_endtag(p
, toknames
[tok
], MD_NS_BLOCK
))
466 return(mbuf_newline(p
));
471 roffin(void *arg
, int tok
, int *argc
, char **argv
)
476 p
= (struct md_xml
*)arg
;
478 if ( ! (MD_OVERRIDE_ONE
& p
->flags
) &&
479 ! (MD_OVERRIDE_ALL
& p
->flags
) &&
480 p
->pos
+ 11 > COLUMNS
)
481 if ( ! mbuf_newline(p
))
484 if (0 != p
->pos
&& (MD_TEXT
== p
->last
|| MD_OUT
== p
->last
)
485 && ! (MD_OVERRIDE_ONE
& p
->flags
)
486 && ! (MD_OVERRIDE_ALL
& p
->flags
))
487 if ( ! xml_nputs(p
, " ", 1))
490 if (0 == p
->pos
&& ! xml_indent(p
))
494 return(xml_begintag(p
, toknames
[tok
],
495 MD_NS_INLINE
, argc
, argv
));
500 roffout(void *arg
, int tok
)
505 p
= (struct md_xml
*)arg
;
507 if (0 == p
->pos
&& ! xml_indent(p
))
510 mbuf_mode(p
, MD_OUT
);
511 return(xml_endtag(p
, toknames
[tok
], MD_NS_INLINE
));
516 roffmsg(void *arg
, enum roffmsg lvl
,
517 const char *buf
, const char *pos
, char *msg
)
523 p
= (struct md_xml
*)arg
;
527 if ( ! (MD_WARN_ALL
& p
->args
->warnings
))
539 (void)fprintf(stderr
, "%s:%zu: %s: %s (column %zu)\n",
540 p
->rbuf
->name
, p
->rbuf
->line
, level
,
543 (void)fprintf(stderr
, "%s: %s: %s\n",
544 p
->rbuf
->name
, level
, msg
);
550 roffdata(void *arg
, int space
, char *buf
)
555 p
= (struct md_xml
*)arg
;
556 if ( ! mbuf_data(p
, space
, buf
))
559 mbuf_mode(p
, MD_TEXT
);
564 #ifdef __linux /* FIXME: remove. */
565 /* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */
568 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
570 * Permission to use, copy, modify, and distribute this software for any
571 * purpose with or without fee is hereby granted, provided that the
572 * above copyright notice and this permission notice appear in all
575 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
576 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
577 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
578 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
579 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
580 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
581 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
582 * PERFORMANCE OF THIS SOFTWARE.
585 strlcat(char *dst
, const char *src
, size_t siz
)
592 /* Find the end of dst and adjust bytes left but don't go past
594 while (n
-- != 0 && *d
!= '\0')
600 return(dlen
+ strlen(s
));
610 return(dlen
+ (s
- src
)); /* count does not include NUL */
615 strlcpy(char *dst
, const char *src
, size_t siz
)
621 /* Copy as many bytes as will fit */
624 if ((*d
++ = *s
++) == '\0')
629 /* Not enough room in dst, add NUL and traverse rest of src */
632 *d
= '\0'; /* NUL-terminate dst */
637 return(s
- src
- 1); /* count does not include NUL */