aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--Makefile8
-rw-r--r--mdocml.11
-rw-r--r--private.h4
-rw-r--r--roff.c295
-rw-r--r--xml.c97
5 files changed, 252 insertions, 153 deletions
diff --git a/Makefile b/Makefile
index e659dbc0..d9d25126 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-CFLAGS += -W -Wall -Wno-unused-parameter -g
+CFLAGS += -W -Wall -Wno-unused-parameter -g
LINTFLAGS += -c -e -f -u
@@ -21,11 +21,13 @@ CLEAN = mdocml mdocml.tgz $(LLNS) $(LNS) $(OBJS) $(LIBS)
INSTALL = Makefile $(HEADS) $(SRCS) $(MANS)
FAIL = test.0 test.1 test.2 test.3 test.4 test.5 test.6 \
- test.15 test.20 test.22 test.24 test.26 test.27 test.30
+ test.15 test.20 test.22 test.24 test.26 test.27 test.30 \
+ test.36
SUCCEED = test.7 test.8 test.9 test.10 test.11 test.12 test.13 \
test.14 test.16 test.17 test.18 test.19 test.21 test.23 \
- test.25 test.28 test.29 test.31 test.32 test.33 test.34
+ test.25 test.28 test.29 test.31 test.32 test.33 test.34 \
+ test.35
all: mdocml
diff --git a/mdocml.1 b/mdocml.1
index d04ce971..21262438 100644
--- a/mdocml.1
+++ b/mdocml.1
@@ -86,7 +86,6 @@ The engine doesn't understand the
.Sq \&Xc ,
.Sq \&No ,
.Sq \&Db ,
-.Sq \&Sm ,
.Sq \&Xc ,
and
.Sq \&Xo
diff --git a/private.h b/private.h
index ff6f7abf..99951234 100644
--- a/private.h
+++ b/private.h
@@ -1,4 +1,4 @@
-/* $Id: private.h,v 1.21 2008/12/01 15:32:36 kristaps Exp $ */
+/* $Id: private.h,v 1.22 2008/12/02 13:20:24 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -222,7 +222,7 @@ struct roffcb {
int (*roffout)(void *, int);
int (*roffblkin)(void *, int, int *, char **);
int (*roffblkout)(void *, int);
- int (*roffspecial)(void *, int);
+ int (*roffspecial)(void *, int, int *, char **, char **);
};
__BEGIN_DECLS
diff --git a/roff.c b/roff.c
index 46c1899e..aa3be033 100644
--- a/roff.c
+++ b/roff.c
@@ -1,4 +1,4 @@
-/* $Id: roff.c,v 1.32 2008/12/02 00:15:41 kristaps Exp $ */
+/* $Id: roff.c,v 1.33 2008/12/02 13:20:24 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -17,6 +17,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/param.h>
+#include <sys/types.h>
#include <assert.h>
#include <ctype.h>
@@ -30,6 +31,8 @@
#include "libmdocml.h"
#include "private.h"
+/* FIXME: First letters of quoted-text interpreted in rofffindtok. */
+/* FIXME: `No' not implemented. */
/* TODO: warn if Pp occurs before/after Sh etc. (see mdoc.samples). */
/* TODO: warn about "X section only" macros. */
/* TODO: warn about empty lists. */
@@ -104,6 +107,7 @@ static int roff_Dd(ROFFCALL_ARGS);
static int roff_Dt(ROFFCALL_ARGS);
static int roff_Os(ROFFCALL_ARGS);
static int roff_Ns(ROFFCALL_ARGS);
+static int roff_Sm(ROFFCALL_ARGS);
static int roff_layout(ROFFCALL_ARGS);
static int roff_text(ROFFCALL_ARGS);
static int roff_noop(ROFFCALL_ARGS);
@@ -126,9 +130,19 @@ static int roffnextopt(const struct rofftree *,
int, char ***, char **);
static int roffparseopts(struct rofftree *, int,
char ***, int *, char **);
+static int roffcall(struct rofftree *, int, char **);
static int roffparse(struct rofftree *, char *);
static int textparse(const struct rofftree *, char *);
+#ifdef __linux__
+static size_t strlcat(char *, const char *, size_t);
+static size_t strlcpy(char *, const char *, size_t);
+extern int vsnprintf(char *, size_t,
+ const char *, va_list);
+extern char *strptime(const char *, const char *,
+ struct tm *);
+#endif
+
static const int roffarg_An[] = { ROFF_Split, ROFF_Nosplit, ROFF_ARGMAX };
static const int roffarg_Bd[] = { ROFF_Ragged, ROFF_Unfilled, ROFF_Literal,
@@ -252,7 +266,7 @@ static const struct rofftok tokens[ROFF_MAX] = {
{ roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Sc */
{ roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* So */
{ roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_LSCOPE }, /* Sq */
- { NULL, NULL, NULL, NULL, 0, ROFF_SPECIAL, 0 }, /* Sm */
+ { roff_Sm, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* Sm */
{ roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Sx */
{ roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Sy */
{ roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Tn */
@@ -818,6 +832,21 @@ roffnode_free(struct rofftree *tree)
static int
+roffcall(struct rofftree *tree, int tok, char **argv)
+{
+
+ if (NULL == tokens[tok].cb) {
+ roff_err(tree, *argv, "unsupported macro `%s'",
+ toknames[tok]);
+ return(0);
+ }
+ if ( ! (*tokens[tok].cb)(tok, tree, argv, ROFF_ENTER))
+ return(0);
+ return(1);
+}
+
+
+static int
roffnextopt(const struct rofftree *tree, int tok,
char ***in, char **val)
{
@@ -835,7 +864,7 @@ roffnextopt(const struct rofftree *tree, int tok,
if (ROFF_ARGMAX == (v = rofffindarg(arg + 1))) {
roff_warn(tree, arg, "argument-like parameter `%s' to "
- "`%s'", &arg[1], toknames[tok]);
+ "`%s'", arg, toknames[tok]);
return(-1);
}
@@ -1053,73 +1082,86 @@ roff_Dt(ROFFCALL_ARGS)
/* ARGSUSED */
static int
-roff_Ns(ROFFCALL_ARGS)
+roff_Sm(ROFFCALL_ARGS)
{
- int j, c, first;
+ int argcp[1];
+ char *argvp[1], *morep[1], *p;
- first = (*argv == tree->cur);
+ p = *argv++;
- argv++;
+ argcp[0] = ROFF_ARGMAX;
+ argvp[0] = NULL;
+ if (NULL == (morep[0] = *argv++)) {
+ roff_err(tree, p, "`Sm' expects an argument");
+ return(0);
+ } else if (0 != strcmp(morep[0], "on") &&
+ 0 != strcmp(morep[0], "off")) {
+ roff_err(tree, p, "`Sm' has invalid argument");
+ return(0);
+ }
- if (ROFF_MAX != (c = rofffindcallable(*argv))) {
- if (NULL == tokens[c].cb) {
- roff_err(tree, *argv, "unsupported macro `%s'",
- toknames[c]);
- return(0);
- }
- if ( ! (*tree->cb.roffspecial)(tree->arg, tok))
- return(0);
- if ( ! (*tokens[c].cb)(c, tree, argv, ROFF_ENTER))
- return(0);
- if ( ! first)
- return(1);
- return(roffpurgepunct(tree, argv));
- }
+ if (*argv)
+ roff_warn(tree, *argv, "`Sm' shouldn't have arguments");
- if ( ! (*tree->cb.roffdata)(tree->arg, 0, *argv++))
+ if ( ! (*tree->cb.roffspecial)(tree->arg,
+ tok, argcp, argvp, morep))
return(0);
while (*argv) {
- if (ROFF_MAX == (c = rofffindcallable(*argv))) {
- if ( ! roffispunct(*argv)) {
- if ( ! (*tree->cb.roffdata)
- (tree->arg, 1, *argv++))
- return(0);
- continue;
- }
-
- /* FIXME: this is identical to that of
- * roff_text. */
+ if ((*tree->cb.roffdata)(tree->arg, 1, *argv++))
+ continue;
+ return(0);
+ }
- /* See if only punctuation remains. */
+ return(1);
+}
- for (j = 0; argv[j]; j++)
- if ( ! roffispunct(argv[j]))
- break;
- if (argv[j]) {
- if ( ! (*tree->cb.roffdata)
- (tree->arg, 0, *argv++))
- return(0);
- continue;
- }
+/* ARGSUSED */
+static int
+roff_Ns(ROFFCALL_ARGS)
+{
+ int j, c, first;
+ int argcp[1];
+ char *argvp[1], *morep[1];
+
+ first = (*argv++ == tree->cur);
+
+ argcp[0] = ROFF_ARGMAX;
+ argvp[0] = morep[0] = NULL;
- /* Only punctuation remains. */
+ if ( ! (*tree->cb.roffspecial)(tree->arg,
+ tok, argcp, argvp, morep))
+ return(0);
+ while (*argv) {
+ if (ROFF_MAX != (c = rofffindcallable(*argv))) {
+ if ( ! roffcall(tree, c, argv))
+ return(0);
break;
}
- if (NULL == tokens[c].cb) {
- roff_err(tree, *argv, "unsupported macro `%s'",
- toknames[c]);
+
+ if ( ! roffispunct(*argv)) {
+ if ((*tree->cb.roffdata)(tree->arg, 1, *argv++))
+ continue;
return(0);
}
- if ( ! (*tokens[c].cb)(c, tree, argv, ROFF_ENTER))
+ for (j = 0; argv[j]; j++)
+ if ( ! roffispunct(argv[j]))
+ break;
+
+ if (argv[j]) {
+ if ((*tree->cb.roffdata)(tree->arg, 0, *argv++))
+ continue;
return(0);
+ }
+
break;
}
if ( ! first)
return(1);
+
return(roffpurgepunct(tree, argv));
}
@@ -1240,16 +1282,8 @@ roff_layout(ROFFCALL_ARGS)
i = 1;
continue;
}
-
- if (NULL == tokens[c].cb) {
- roff_err(tree, *argv, "unsupported macro `%s'",
- toknames[c]);
+ if ( ! roffcall(tree, c, argv))
return(0);
- }
-
- if ( ! (*tokens[c].cb)(c, tree, argv, ROFF_ENTER))
- return(0);
-
break;
}
@@ -1316,60 +1350,41 @@ roff_text(ROFFCALL_ARGS)
i = 0;
while (*argv) {
- if (ROFF_MAX == (c = rofffindcallable(*argv))) {
- if ( ! roffispunct(*argv)) {
- if ( ! (*tree->cb.roffdata)
- (tree->arg, i, *argv++))
+ if (ROFF_MAX != (c = rofffindcallable(*argv))) {
+ if ( ! (ROFF_LSCOPE & tokens[tok].flags))
+ if ( ! (*tree->cb.roffout)(tree->arg, tok))
return(0);
- i = 1;
- continue;
- }
-
- /* See if only punctuation remains. */
-
- i = 1;
- for (j = 0; argv[j]; j++)
- if ( ! roffispunct(argv[j]))
- break;
-
- if (argv[j]) {
- if ( ! (*tree->cb.roffdata)
- (tree->arg, 0, *argv++))
- return(0);
- continue;
- }
-
- /* Only punctuation remains. */
-
- if ( ! (*tree->cb.roffout)(tree->arg, tok))
+
+ if ( ! roffcall(tree, c, argv))
return(0);
+
+ if (ROFF_LSCOPE & tokens[tok].flags)
+ if ( ! (*tree->cb.roffout)(tree->arg, tok))
+ return(0);
+
break;
}
- /*
- * A sub-command has been found. Execute it and
- * discontinue parsing for arguments. If we're
- * line-scoped, then close out after it returns; if we
- * aren't, then close out before.
- */
-
- if (NULL == tokens[c].cb) {
- roff_err(tree, *argv, "unsupported macro `%s'",
- toknames[c]);
- return(0);
- }
-
- if ( ! (ROFF_LSCOPE & tokens[tok].flags))
- if ( ! (*tree->cb.roffout)(tree->arg, tok))
+ if ( ! roffispunct(*argv)) {
+ if ( ! (*tree->cb.roffdata)(tree->arg, i, *argv++))
return(0);
-
- if ( ! (*tokens[c].cb)(c, tree, argv, ROFF_ENTER))
- return(0);
+ i = 1;
+ continue;
+ }
- if (ROFF_LSCOPE & tokens[tok].flags)
- if ( ! (*tree->cb.roffout)(tree->arg, tok))
+ i = 1;
+ for (j = 0; argv[j]; j++)
+ if ( ! roffispunct(argv[j]))
+ break;
+
+ if (argv[j]) {
+ if ( ! (*tree->cb.roffdata)(tree->arg, 0, *argv++))
return(0);
+ continue;
+ }
+ if ( ! (*tree->cb.roffout)(tree->arg, tok))
+ return(0);
break;
}
@@ -1429,3 +1444,81 @@ roff_err(const struct rofftree *tree, const char *pos, char *fmt, ...)
(*tree->cb.roffmsg)(tree->arg,
ROFF_ERROR, tree->cur, pos, buf);
}
+
+
+#ifdef __linux
+/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */
+
+/*
+ * 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__*/
diff --git a/xml.c b/xml.c
index 49dabb8c..36f3295d 100644
--- a/xml.c
+++ b/xml.c
@@ -1,4 +1,4 @@
-/* $Id: xml.c,v 1.7 2008/12/02 00:15:41 kristaps Exp $ */
+/* $Id: xml.c,v 1.8 2008/12/02 13:20:24 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -31,10 +31,6 @@
#define MAXINDENT 8
#define COLUMNS 72
-#ifdef __linux__ /* FIXME */
-#define strlcat strncat
-#endif
-
enum md_ns {
MD_NS_BLOCK,
MD_NS_INLINE,
@@ -42,12 +38,11 @@ enum md_ns {
};
enum md_tok {
- MD_BLKIN,
+ MD_BLKIN, /* Controls spacing. */
MD_BLKOUT,
MD_IN,
MD_OUT,
- MD_TEXT,
- MD_OVERRIDE
+ MD_TEXT
};
struct md_xml {
@@ -60,7 +55,9 @@ struct md_xml {
size_t pos;
enum md_tok last;
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,
@@ -72,8 +69,9 @@ static int roffdata(void *, int, char *);
static int roffout(void *, int);
static int roffblkin(void *, int, int *, char **);
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_indent(struct md_xml *);
static int mbuf_data(struct md_xml *, int, char *);
@@ -90,6 +88,14 @@ static int mbuf_endtag(struct md_xml *,
const char *, enum md_ns);
+static void
+mbuf_mode(struct md_xml *p, enum md_ns ns)
+{
+ p->flags &= ~MD_OVERRIDE_ONE;
+ p->last = ns;
+}
+
+
static int
mbuf_begintag(struct md_xml *p, const char *name, enum md_ns ns,
int *argc, char **argv)
@@ -257,6 +263,9 @@ mbuf_data(struct md_xml *p, int space, char *buf)
assert(p->mbuf);
assert(0 != p->indent);
+ if (MD_OVERRIDE_ONE & p->flags || MD_OVERRIDE_ALL & p->flags)
+ space = 0;
+
if (MD_LITERAL & p->flags)
return(mbuf_putstring(p, buf));
@@ -281,11 +290,11 @@ mbuf_data(struct md_xml *p, int space, char *buf)
return(0);
if ( ! mbuf_nputstring(p, bufp, sz))
return(0);
- if (p->indent * MAXINDENT + sz >= COLUMNS) {
+ if (p->indent * MAXINDENT + sz >= COLUMNS)
if ( ! mbuf_newline(p))
return(0);
- continue;
- }
+ if ( ! (MD_OVERRIDE_ALL & p->flags))
+ space = 1;
continue;
}
@@ -302,9 +311,8 @@ mbuf_data(struct md_xml *p, int space, char *buf)
if ( ! mbuf_nputstring(p, bufp, sz))
return(0);
- if ( ! space && p->pos >= COLUMNS)
- if ( ! mbuf_newline(p))
- return(0);
+ if ( ! (MD_OVERRIDE_ALL & p->flags))
+ space = 1;
}
return(1);
@@ -388,7 +396,7 @@ roffhead(void *arg)
return(0);
p->indent++;
- p->last = MD_BLKIN;
+ mbuf_mode(p, MD_BLKIN);
return(mbuf_newline(p));
}
@@ -404,16 +412,16 @@ rofftail(void *arg)
if (0 != p->pos && ! mbuf_newline(p))
return(0);
- p->last = MD_BLKOUT;
+ mbuf_mode(p, MD_BLKOUT);
if ( ! mbuf_endtag(p, "mdoc", MD_NS_DEFAULT))
return(0);
-
return(mbuf_newline(p));
}
+/* ARGSUSED */
static int
-roffspecial(void *arg, int tok)
+roffspecial(void *arg, int tok, int *argc, char **argv, char **more)
{
struct md_xml *p;
@@ -424,7 +432,14 @@ roffspecial(void *arg, int tok)
switch (tok) {
case (ROFF_Ns):
- p->last = MD_OVERRIDE;
+ 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;
@@ -452,8 +467,8 @@ roffblkin(void *arg, int tok, int *argc, char **argv)
/* FIXME: xml won't like standards args (e.g., p1003.1-90). */
- p->last = MD_BLKIN;
p->indent++;
+ mbuf_mode(p, MD_BLKIN);
if ( ! mbuf_begintag(p, toknames[tok], MD_NS_BLOCK,
argc, argv))
@@ -480,8 +495,7 @@ roffblkout(void *arg, int tok)
} else if ( ! mbuf_indent(p))
return(0);
- p->last = MD_BLKOUT;
-
+ mbuf_mode(p, MD_BLKOUT);
if ( ! mbuf_endtag(p, toknames[tok], MD_NS_BLOCK))
return(0);
return(mbuf_newline(p));
@@ -496,31 +510,22 @@ roffin(void *arg, int tok, int *argc, char **argv)
assert(arg);
p = (struct md_xml *)arg;
- /*
- * FIXME: put all of this in a buffer, then check the buffer
- * length versus the column width for nicer output. This is a
- * bit hacky.
- */
-
- if (p->pos + 11 > COLUMNS)
+ if ( ! (MD_OVERRIDE_ONE & p->flags) &&
+ ! (MD_OVERRIDE_ALL & p->flags) &&
+ p->pos + 11 > COLUMNS)
if ( ! mbuf_newline(p))
return(0);
- if (0 != p->pos) {
- switch (p->last) {
- case (MD_TEXT):
- /* FALLTHROUGH */
- case (MD_OUT):
- if ( ! mbuf_nputs(p, " ", 1))
- return(0);
- break;
- default:
- break;
- }
- } else if ( ! mbuf_indent(p))
+ if (0 != p->pos && (MD_TEXT == p->last || MD_OUT == p->last)
+ && ! (MD_OVERRIDE_ONE & p->flags)
+ && ! (MD_OVERRIDE_ALL & p->flags))
+ if ( ! mbuf_nputs(p, " ", 1))
+ return(0);
+
+ if (0 == p->pos && ! mbuf_indent(p))
return(0);
- p->last = MD_IN;
+ mbuf_mode(p, MD_IN);
return(mbuf_begintag(p, toknames[tok],
MD_NS_INLINE, argc, argv));
}
@@ -537,7 +542,7 @@ roffout(void *arg, int tok)
if (0 == p->pos && ! mbuf_indent(p))
return(0);
- p->last = MD_OUT;
+ mbuf_mode(p, MD_OUT);
return(mbuf_endtag(p, toknames[tok], MD_NS_INLINE));
}
@@ -586,7 +591,7 @@ roffdata(void *arg, int space, char *buf)
if ( ! mbuf_data(p, space, buf))
return(0);
- p->last = MD_TEXT;
+ mbuf_mode(p, MD_TEXT);
return(1);
}