version 1.2, 2008/11/30 23:05:57 |
version 1.9, 2008/12/02 18:26:57 |
|
|
#include "libmdocml.h" |
#include "libmdocml.h" |
#include "private.h" |
#include "private.h" |
|
|
#define INDENT 4 |
#define COLUMNS 72 |
#define COLUMNS 60 |
|
|
|
#ifdef __linux__ /* FIXME */ |
enum md_ns { |
#define strlcat strncat |
MD_NS_BLOCK, |
#endif |
MD_NS_INLINE, |
|
MD_NS_DEFAULT |
|
}; |
|
|
enum md_tok { |
enum md_tok { |
MD_BLKIN, |
MD_BLKIN, /* Controls spacing. */ |
MD_BLKOUT, |
MD_BLKOUT, |
MD_IN, |
MD_IN, |
MD_OUT, |
MD_OUT, |
|
|
size_t pos; |
size_t pos; |
enum md_tok last; |
enum md_tok last; |
int flags; |
int flags; |
#define MD_LITERAL (1 << 0) /* FIXME */ |
#define MD_LITERAL (1 << 0) /* TODO */ |
|
#define MD_OVERRIDE_ONE (1 << 1) |
|
#define MD_OVERRIDE_ALL (1 << 2) |
}; |
}; |
|
|
static void roffmsg(void *arg, enum roffmsg, |
static void roffmsg(void *arg, enum roffmsg, |
Line 65 static int roffdata(void *, int, char *); |
|
Line 68 static int roffdata(void *, int, char *); |
|
static int roffout(void *, int); |
static int roffout(void *, int); |
static int roffblkin(void *, int, int *, char **); |
static int roffblkin(void *, int, int *, char **); |
static int roffblkout(void *, int); |
static int roffblkout(void *, int); |
static int roffspecial(void *, int); |
static int roffspecial(void *, int, int *, char **, char **); |
|
|
|
static void mbuf_mode(struct md_xml *, enum md_ns); |
static int mbuf_newline(struct md_xml *); |
static int mbuf_newline(struct md_xml *); |
static int mbuf_indent(struct md_xml *); |
static int xml_indent(struct md_xml *); |
static int mbuf_data(struct md_xml *, int, char *); |
static int mbuf_data(struct md_xml *, int, char *); |
static int mbuf_putstring(struct md_xml *, |
static int xml_nputstring(struct md_xml *, |
const char *); |
|
static int mbuf_nputstring(struct md_xml *, |
|
const char *, size_t); |
const char *, size_t); |
static int mbuf_puts(struct md_xml *, const char *); |
static int xml_puts(struct md_xml *, const char *); |
static int mbuf_nputs(struct md_xml *, |
static int xml_nputs(struct md_xml *, |
const char *, size_t); |
const char *, size_t); |
|
static int xml_begintag(struct md_xml *, const char *, |
|
enum md_ns, int *, char **); |
|
static int xml_endtag(struct md_xml *, |
|
const char *, enum md_ns); |
|
|
|
#ifdef __linux__ /* FIXME: remove */ |
|
static size_t strlcat(char *, const char *, size_t); |
|
static size_t strlcpy(char *, const char *, size_t); |
|
#endif |
|
|
|
|
|
static void |
|
mbuf_mode(struct md_xml *p, enum md_ns ns) |
|
{ |
|
p->flags &= ~MD_OVERRIDE_ONE; |
|
p->last = ns; |
|
} |
|
|
|
|
static int |
static int |
mbuf_putstring(struct md_xml *p, const char *buf) |
xml_begintag(struct md_xml *p, const char *name, enum md_ns ns, |
|
int *argc, char **argv) |
{ |
{ |
|
char buf[64]; |
|
ssize_t sz; |
|
size_t res; |
|
|
return(mbuf_nputstring(p, buf, strlen(buf))); |
switch (ns) { |
|
case (MD_NS_BLOCK): |
|
res = strlcpy(buf, "block:", sizeof(buf)); |
|
assert(res < sizeof(buf)); |
|
break; |
|
case (MD_NS_INLINE): |
|
res = strlcpy(buf, "inline:", sizeof(buf)); |
|
assert(res < sizeof(buf)); |
|
break; |
|
default: |
|
*buf = 0; |
|
break; |
|
} |
|
|
|
res = strlcat(buf, name, sizeof(buf)); |
|
assert(res < sizeof(buf)); |
|
|
|
if (-1 == (sz = ml_begintag(p->mbuf, buf, argc, argv))) |
|
return(0); |
|
|
|
p->pos += sz; |
|
return(1); |
} |
} |
|
|
|
|
static int |
static int |
mbuf_nputstring(struct md_xml *p, const char *buf, size_t sz) |
xml_endtag(struct md_xml *p, const char *name, enum md_ns ns) |
{ |
{ |
size_t i; |
char buf[64]; |
|
ssize_t sz; |
|
size_t res; |
|
|
for (i = 0; i < sz; i++) { |
switch (ns) { |
switch (buf[i]) { |
case (MD_NS_BLOCK): |
case ('&'): |
res = strlcpy(buf, "block:", sizeof(buf)); |
if ( ! md_buf_puts(p->mbuf, "&", 5)) |
assert(res < sizeof(buf)); |
return(0); |
break; |
p->pos += 5; |
case (MD_NS_INLINE): |
break; |
res = strlcpy(buf, "inline:", sizeof(buf)); |
case ('"'): |
assert(res < sizeof(buf)); |
if ( ! md_buf_puts(p->mbuf, """, 6)) |
break; |
return(0); |
default: |
p->pos += 6; |
*buf = 0; |
break; |
break; |
default: |
|
if ( ! md_buf_putchar(p->mbuf, buf[i])) |
|
return(0); |
|
p->pos++; |
|
break; |
|
} |
|
} |
} |
|
|
|
res = strlcat(buf, name, sizeof(buf)); |
|
assert(res < sizeof(buf)); |
|
|
|
if (-1 == (sz = ml_endtag(p->mbuf, buf))) |
|
return(0); |
|
|
|
p->pos += sz; |
return(1); |
return(1); |
} |
} |
|
|
|
|
static int |
static int |
mbuf_nputs(struct md_xml *p, const char *buf, size_t sz) |
xml_nputstring(struct md_xml *p, const char *buf, size_t sz) |
{ |
{ |
|
ssize_t res; |
|
|
p->pos += sz; |
if (-1 == (res = ml_nputstring(p->mbuf, buf, sz))) |
return(md_buf_puts(p->mbuf, buf, sz)); |
return(0); |
|
p->pos += res; |
|
return(1); |
} |
} |
|
|
|
|
static int |
static int |
mbuf_puts(struct md_xml *p, const char *buf) |
xml_nputs(struct md_xml *p, const char *buf, size_t sz) |
{ |
{ |
|
ssize_t res; |
|
|
return(mbuf_nputs(p, buf, strlen(buf))); |
if (-1 == (res = ml_nputs(p->mbuf, buf, sz))) |
|
return(0); |
|
p->pos += res; |
|
return(1); |
} |
} |
|
|
|
|
static int |
static int |
mbuf_indent(struct md_xml *p) |
xml_puts(struct md_xml *p, const char *buf) |
{ |
{ |
size_t i; |
|
|
|
assert(p->pos == 0); |
return(xml_nputs(p, buf, strlen(buf))); |
|
} |
|
|
/* LINTED */ |
|
for (i = 0; i < MIN(p->indent, INDENT); i++) |
|
if ( ! md_buf_putstring(p->mbuf, " ")) |
|
return(0); |
|
|
|
p->pos += i * INDENT; |
static int |
|
xml_indent(struct md_xml *p) |
|
{ |
|
ssize_t res; |
|
|
|
if (-1 == (res = ml_indent(p->mbuf, p->indent))) |
|
return(0); |
|
p->pos += res; |
return(1); |
return(1); |
} |
} |
|
|
Line 170 mbuf_data(struct md_xml *p, int space, char *buf) |
|
Line 228 mbuf_data(struct md_xml *p, int space, char *buf) |
|
assert(p->mbuf); |
assert(p->mbuf); |
assert(0 != p->indent); |
assert(0 != p->indent); |
|
|
|
if (MD_OVERRIDE_ONE & p->flags || MD_OVERRIDE_ALL & p->flags) |
|
space = 0; |
|
|
if (MD_LITERAL & p->flags) |
if (MD_LITERAL & p->flags) |
return(mbuf_putstring(p, buf)); |
return(xml_nputstring(p, buf, sizeof(buf))); |
|
|
while (*buf) { |
while (*buf) { |
while (*buf && isspace(*buf)) |
while (*buf && isspace(*buf)) |
Line 190 mbuf_data(struct md_xml *p, int space, char *buf) |
|
Line 251 mbuf_data(struct md_xml *p, int space, char *buf) |
|
sz = strlen(bufp); |
sz = strlen(bufp); |
|
|
if (0 == p->pos) { |
if (0 == p->pos) { |
if ( ! mbuf_indent(p)) |
if ( ! xml_indent(p)) |
return(0); |
return(0); |
if ( ! mbuf_nputstring(p, bufp, sz)) |
if ( ! xml_nputstring(p, bufp, sz)) |
return(0); |
return(0); |
if (p->indent * INDENT + sz >= COLUMNS) { |
if (p->indent * MAXINDENT + sz >= COLUMNS) |
if ( ! mbuf_newline(p)) |
if ( ! mbuf_newline(p)) |
return(0); |
return(0); |
continue; |
if ( ! (MD_OVERRIDE_ALL & p->flags)) |
} |
space = 1; |
continue; |
continue; |
} |
} |
|
|
if (space && sz + p->pos >= COLUMNS) { |
if (space && sz + p->pos >= COLUMNS) { |
if ( ! mbuf_newline(p)) |
if ( ! mbuf_newline(p)) |
return(0); |
return(0); |
if ( ! mbuf_indent(p)) |
if ( ! xml_indent(p)) |
return(0); |
return(0); |
} else if (space) { |
} else if (space) { |
if ( ! mbuf_nputs(p, " ", 1)) |
if ( ! xml_nputs(p, " ", 1)) |
return(0); |
return(0); |
} |
} |
|
|
if ( ! mbuf_nputstring(p, bufp, sz)) |
if ( ! xml_nputstring(p, bufp, sz)) |
return(0); |
return(0); |
|
|
if ( ! space && p->pos >= COLUMNS) |
if ( ! (MD_OVERRIDE_ALL & p->flags)) |
if ( ! mbuf_newline(p)) |
space = 1; |
return(0); |
|
} |
} |
|
|
return(1); |
return(1); |
Line 292 roffhead(void *arg) |
|
Line 352 roffhead(void *arg) |
|
assert(arg); |
assert(arg); |
p = (struct md_xml *)arg; |
p = (struct md_xml *)arg; |
|
|
if ( ! mbuf_puts(p, "<?xml version=\"1.0\" " |
if (-1 == xml_puts(p, "<?xml version=\"1.0\" " |
"encoding=\"UTF-8\"?>\n")) |
"encoding=\"UTF-8\"?>\n")) |
return(0); |
return(0); |
if ( ! mbuf_puts(p, "<mdoc xmlns:block=\"block\" " |
if (-1 == xml_puts(p, "<mdoc xmlns:block=\"block\" " |
"xmlns:special=\"special\" " |
"xmlns:special=\"special\" " |
"xmlns:inline=\"inline\">")) |
"xmlns:inline=\"inline\">")) |
return(0); |
return(0); |
|
|
p->indent++; |
p->indent++; |
p->last = MD_BLKIN; |
mbuf_mode(p, MD_BLKIN); |
return(mbuf_newline(p)); |
return(mbuf_newline(p)); |
} |
} |
|
|
Line 317 rofftail(void *arg) |
|
Line 377 rofftail(void *arg) |
|
if (0 != p->pos && ! mbuf_newline(p)) |
if (0 != p->pos && ! mbuf_newline(p)) |
return(0); |
return(0); |
|
|
if ( ! mbuf_puts(p, "</mdoc>")) |
mbuf_mode(p, MD_BLKOUT); |
|
if ( ! xml_endtag(p, "mdoc", MD_NS_DEFAULT)) |
return(0); |
return(0); |
|
|
p->last = MD_BLKOUT; |
|
return(mbuf_newline(p)); |
return(mbuf_newline(p)); |
} |
} |
|
|
|
|
/* ARGSUSED */ |
/* ARGSUSED */ |
static int |
static int |
roffspecial(void *arg, int tok) |
roffspecial(void *arg, int tok, int *argc, char **argv, char **more) |
{ |
{ |
|
struct md_xml *p; |
|
|
/* FIXME */ |
assert(arg); |
|
p = (struct md_xml *)arg; |
|
|
|
/* FIXME: this is completely ad hoc. */ |
|
|
|
switch (tok) { |
|
case (ROFF_Ns): |
|
p->flags |= MD_OVERRIDE_ONE; |
|
break; |
|
case (ROFF_Sm): |
|
assert(*more); |
|
if (0 == strcmp(*more, "on")) |
|
p->flags |= MD_OVERRIDE_ALL; |
|
else |
|
p->flags &= ~MD_OVERRIDE_ALL; |
|
break; |
|
default: |
|
break; |
|
} |
|
|
return(1); |
return(1); |
} |
} |
|
|
|
|
roffblkin(void *arg, int tok, int *argc, char **argv) |
roffblkin(void *arg, int tok, int *argc, char **argv) |
{ |
{ |
struct md_xml *p; |
struct md_xml *p; |
int i; |
|
|
|
assert(arg); |
assert(arg); |
p = (struct md_xml *)arg; |
p = (struct md_xml *)arg; |
Line 347 roffblkin(void *arg, int tok, int *argc, char **argv) |
|
Line 425 roffblkin(void *arg, int tok, int *argc, char **argv) |
|
if (0 != p->pos) { |
if (0 != p->pos) { |
if ( ! mbuf_newline(p)) |
if ( ! mbuf_newline(p)) |
return(0); |
return(0); |
if ( ! mbuf_indent(p)) |
if ( ! xml_indent(p)) |
return(0); |
return(0); |
} else if ( ! mbuf_indent(p)) |
} else if ( ! xml_indent(p)) |
return(0); |
return(0); |
|
|
if ( ! mbuf_nputs(p, "<", 1)) |
|
return(0); |
|
if ( ! mbuf_nputs(p, "block:", 6)) |
|
return(0); |
|
if ( ! mbuf_puts(p, toknames[tok])) |
|
return(0); |
|
|
|
/* FIXME: xml won't like standards args (e.g., p1003.1-90). */ |
/* FIXME: xml won't like standards args (e.g., p1003.1-90). */ |
|
|
for (i = 0; ROFF_ARGMAX != argc[i]; i++) { |
p->indent++; |
if ( ! mbuf_nputs(p, " ", 1)) |
mbuf_mode(p, MD_BLKIN); |
return(0); |
|
if ( ! mbuf_puts(p, tokargnames[argc[i]])) |
|
return(0); |
|
if ( ! mbuf_nputs(p, "=\"", 2)) |
|
return(0); |
|
if ( ! mbuf_putstring(p, argv[i] ? argv[i] : "true")) |
|
return(0); |
|
if ( ! mbuf_nputs(p, "\"", 1)) |
|
return(0); |
|
} |
|
|
|
if ( ! mbuf_nputs(p, ">", 1)) |
if ( ! xml_begintag(p, toknames[tok], MD_NS_BLOCK, |
|
argc, argv)) |
return(0); |
return(0); |
|
|
p->last = MD_BLKIN; |
|
p->indent++; |
|
return(mbuf_newline(p)); |
return(mbuf_newline(p)); |
} |
} |
|
|
Line 396 roffblkout(void *arg, int tok) |
|
Line 455 roffblkout(void *arg, int tok) |
|
if (0 != p->pos) { |
if (0 != p->pos) { |
if ( ! mbuf_newline(p)) |
if ( ! mbuf_newline(p)) |
return(0); |
return(0); |
if ( ! mbuf_indent(p)) |
if ( ! xml_indent(p)) |
return(0); |
return(0); |
} else if ( ! mbuf_indent(p)) |
} else if ( ! xml_indent(p)) |
return(0); |
return(0); |
|
|
if ( ! mbuf_nputs(p, "</", 2)) |
mbuf_mode(p, MD_BLKOUT); |
|
if ( ! xml_endtag(p, toknames[tok], MD_NS_BLOCK)) |
return(0); |
return(0); |
if ( ! mbuf_nputs(p, "block:", 6)) |
|
return(0); |
|
if ( ! mbuf_puts(p, toknames[tok])) |
|
return(0); |
|
if ( ! mbuf_nputs(p, ">", 1)) |
|
return(0); |
|
|
|
p->last = MD_BLKOUT; |
|
return(mbuf_newline(p)); |
return(mbuf_newline(p)); |
} |
} |
|
|
|
|
roffin(void *arg, int tok, int *argc, char **argv) |
roffin(void *arg, int tok, int *argc, char **argv) |
{ |
{ |
struct md_xml *p; |
struct md_xml *p; |
int i; |
|
|
|
assert(arg); |
assert(arg); |
p = (struct md_xml *)arg; |
p = (struct md_xml *)arg; |
|
|
/* |
if ( ! (MD_OVERRIDE_ONE & p->flags) && |
* FIXME: put all of this in a buffer, then check the buffer |
! (MD_OVERRIDE_ALL & p->flags) && |
* length versus the column width for nicer output. This is a |
p->pos + 11 > COLUMNS) |
* bit hacky. |
|
*/ |
|
|
|
if (p->pos + 11 > COLUMNS) |
|
if ( ! mbuf_newline(p)) |
if ( ! mbuf_newline(p)) |
return(0); |
return(0); |
|
|
if (0 != p->pos) { |
if (0 != p->pos && (MD_TEXT == p->last || MD_OUT == p->last) |
switch (p->last) { |
&& ! (MD_OVERRIDE_ONE & p->flags) |
case (MD_TEXT): |
&& ! (MD_OVERRIDE_ALL & p->flags)) |
/* FALLTHROUGH */ |
if ( ! xml_nputs(p, " ", 1)) |
case (MD_OUT): |
return(0); |
if ( ! mbuf_nputs(p, " ", 1)) |
|
return(0); |
|
break; |
|
default: |
|
break; |
|
} |
|
} else if ( ! mbuf_indent(p)) |
|
return(0); |
|
|
|
p->last = MD_IN; |
if (0 == p->pos && ! xml_indent(p)) |
|
|
if ( ! mbuf_nputs(p, "<", 1)) |
|
return(0); |
return(0); |
if ( ! mbuf_nputs(p, "inline:", 7)) |
|
return(0); |
|
if ( ! mbuf_puts(p, toknames[tok])) |
|
return(0); |
|
|
|
for (i = 0; ROFF_ARGMAX != argc[i]; i++) { |
mbuf_mode(p, MD_IN); |
if ( ! mbuf_nputs(p, " ", 1)) |
return(xml_begintag(p, toknames[tok], |
return(0); |
MD_NS_INLINE, argc, argv)); |
if ( ! mbuf_puts(p, tokargnames[argc[i]])) |
|
return(0); |
|
if ( ! mbuf_nputs(p, "=\"", 2)) |
|
return(0); |
|
if ( ! mbuf_putstring(p, argv[i] ? argv[i] : "true")) |
|
return(0); |
|
if ( ! mbuf_nputs(p, "\"", 1)) |
|
return(0); |
|
} |
|
return(mbuf_nputs(p, ">", 1)); |
|
} |
} |
|
|
|
|
Line 481 roffout(void *arg, int tok) |
|
Line 504 roffout(void *arg, int tok) |
|
assert(arg); |
assert(arg); |
p = (struct md_xml *)arg; |
p = (struct md_xml *)arg; |
|
|
if (0 == p->pos && ! mbuf_indent(p)) |
if (0 == p->pos && ! xml_indent(p)) |
return(0); |
return(0); |
|
|
p->last = MD_OUT; |
mbuf_mode(p, MD_OUT); |
|
return(xml_endtag(p, toknames[tok], MD_NS_INLINE)); |
if ( ! mbuf_nputs(p, "</", 2)) |
|
return(0); |
|
if ( ! mbuf_nputs(p, "inline:", 7)) |
|
return(0); |
|
if ( ! mbuf_puts(p, toknames[tok])) |
|
return(0); |
|
return(mbuf_nputs(p, ">", 1)); |
|
} |
} |
|
|
|
|
Line 540 roffdata(void *arg, int space, char *buf) |
|
Line 556 roffdata(void *arg, int space, char *buf) |
|
if ( ! mbuf_data(p, space, buf)) |
if ( ! mbuf_data(p, space, buf)) |
return(0); |
return(0); |
|
|
p->last = MD_TEXT; |
mbuf_mode(p, MD_TEXT); |
return(1); |
return(1); |
} |
} |
|
|
|
|
|
#ifdef __linux /* FIXME: remove. */ |
|
/* $OpenBSD$ */ |
|
|
|
/* |
|
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> |
|
* |
|
* Permission to use, copy, modify, and distribute this software for any |
|
* purpose with or without fee is hereby granted, provided that the |
|
* above copyright notice and this permission notice appear in all |
|
* copies. |
|
* |
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
|
* PERFORMANCE OF THIS SOFTWARE. |
|
*/ |
|
static size_t |
|
strlcat(char *dst, const char *src, size_t siz) |
|
{ |
|
char *d = dst; |
|
const char *s = src; |
|
size_t n = siz; |
|
size_t dlen; |
|
|
|
/* Find the end of dst and adjust bytes left but don't go past |
|
* end */ |
|
while (n-- != 0 && *d != '\0') |
|
d++; |
|
dlen = d - dst; |
|
n = siz - dlen; |
|
|
|
if (n == 0) |
|
return(dlen + strlen(s)); |
|
while (*s != '\0') { |
|
if (n != 1) { |
|
*d++ = *s; |
|
n--; |
|
} |
|
s++; |
|
} |
|
*d = '\0'; |
|
|
|
return(dlen + (s - src)); /* count does not include NUL */ |
|
} |
|
|
|
|
|
static size_t |
|
strlcpy(char *dst, const char *src, size_t siz) |
|
{ |
|
char *d = dst; |
|
const char *s = src; |
|
size_t n = siz; |
|
|
|
/* Copy as many bytes as will fit */ |
|
if (n != 0) { |
|
while (--n != 0) { |
|
if ((*d++ = *s++) == '\0') |
|
break; |
|
} |
|
} |
|
|
|
/* Not enough room in dst, add NUL and traverse rest of src */ |
|
if (n == 0) { |
|
if (siz != 0) |
|
*d = '\0'; /* NUL-terminate dst */ |
|
while (*s++) |
|
; |
|
} |
|
|
|
return(s - src - 1); /* count does not include NUL */ |
|
} |
|
#endif /*__linux__*/ |