summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@cvs.openbsd.org>2011-04-24 16:22:03 +0000
committerIngo Schwarze <schwarze@cvs.openbsd.org>2011-04-24 16:22:03 +0000
commit8f4d5715119f71fe84fabe1ac036212fb9cd6dd4 (patch)
tree4595e6b302aaf0ccfc79216f87c3cccdca69b3b5 /usr.bin
parent1752cec47372d4848aa06c33133bac2b1f479dba (diff)
Merge version 1.11.1:
Again lots of cleanup and maintenance work by kristaps@. - simplify error reporting: less function pointers, more mandoc_[v]msg - main: split document parsing out of main.c into read.c - roff, mdoc, man: improved recognition of control characters - roff: better handling of if/else stack overflows - roff: add some predefined strings for backward compatibility - mdoc, man: empty sections are not errors - mdoc: move delimiter handling to libmdoc - some header restructuring and some minor features and fixes This merge causes two minor regressions that i will fix in separate commits right afterwards.
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/mandoc/Makefile8
-rw-r--r--usr.bin/mandoc/arch.c3
-rw-r--r--usr.bin/mandoc/att.c3
-rw-r--r--usr.bin/mandoc/chars.c6
-rw-r--r--usr.bin/mandoc/chars.h38
-rw-r--r--usr.bin/mandoc/chars.in6
-rw-r--r--usr.bin/mandoc/eqn.c3
-rw-r--r--usr.bin/mandoc/html.c11
-rw-r--r--usr.bin/mandoc/lib.c3
-rw-r--r--usr.bin/mandoc/libman.h23
-rw-r--r--usr.bin/mandoc/libmandoc.h89
-rw-r--r--usr.bin/mandoc/libmdoc.h38
-rw-r--r--usr.bin/mandoc/libroff.h10
-rw-r--r--usr.bin/mandoc/main.c819
-rw-r--r--usr.bin/mandoc/man.3283
-rw-r--r--usr.bin/mandoc/man.c115
-rw-r--r--usr.bin/mandoc/man.h30
-rw-r--r--usr.bin/mandoc/man_argv.c40
-rw-r--r--usr.bin/mandoc/man_hash.c3
-rw-r--r--usr.bin/mandoc/man_macro.c49
-rw-r--r--usr.bin/mandoc/man_term.c3
-rw-r--r--usr.bin/mandoc/man_validate.c37
-rw-r--r--usr.bin/mandoc/mandoc.c77
-rw-r--r--usr.bin/mandoc/mandoc.h77
-rw-r--r--usr.bin/mandoc/mdoc.3359
-rw-r--r--usr.bin/mandoc/mdoc.c140
-rw-r--r--usr.bin/mandoc/mdoc.h204
-rw-r--r--usr.bin/mandoc/mdoc_argv.c121
-rw-r--r--usr.bin/mandoc/mdoc_hash.c3
-rw-r--r--usr.bin/mandoc/mdoc_html.c254
-rw-r--r--usr.bin/mandoc/mdoc_macro.c89
-rw-r--r--usr.bin/mandoc/mdoc_term.c118
-rw-r--r--usr.bin/mandoc/mdoc_validate.c29
-rw-r--r--usr.bin/mandoc/msec.c3
-rw-r--r--usr.bin/mandoc/out.h77
-rw-r--r--usr.bin/mandoc/read.c761
-rw-r--r--usr.bin/mandoc/roff.3177
-rw-r--r--usr.bin/mandoc/roff.c166
-rw-r--r--usr.bin/mandoc/roff.h47
-rw-r--r--usr.bin/mandoc/st.c3
-rw-r--r--usr.bin/mandoc/tbl.c20
-rw-r--r--usr.bin/mandoc/tbl_data.c13
-rw-r--r--usr.bin/mandoc/tbl_layout.c30
-rw-r--r--usr.bin/mandoc/tbl_opts.c26
-rw-r--r--usr.bin/mandoc/term.c14
-rw-r--r--usr.bin/mandoc/tree.c7
-rw-r--r--usr.bin/mandoc/vol.c3
47 files changed, 1861 insertions, 2577 deletions
diff --git a/usr.bin/mandoc/Makefile b/usr.bin/mandoc/Makefile
index 9468b9f6ba7..8e4388b2513 100644
--- a/usr.bin/mandoc/Makefile
+++ b/usr.bin/mandoc/Makefile
@@ -1,8 +1,8 @@
-# $OpenBSD: Makefile,v 1.54 2011/04/21 22:59:54 schwarze Exp $
+# $OpenBSD: Makefile,v 1.55 2011/04/24 16:22:02 schwarze Exp $
.include <bsd.own.mk>
-VERSION=1.10.10
+VERSION=1.11.1
CFLAGS+=-DVERSION=\"${VERSION}\"
CFLAGS+=-W -Wall -Wstrict-prototypes
@@ -10,11 +10,11 @@ CFLAGS+=-W -Wall -Wstrict-prototypes
CFLAGS+=-Wno-unused-parameter
.endif
-SRCS= roff.c tbl.c tbl_opts.c tbl_layout.c tbl_data.c eqn.c mandoc.c
+SRCS= roff.c tbl.c tbl_opts.c tbl_layout.c tbl_data.c eqn.c mandoc.c read.c
SRCS+= mdoc_macro.c mdoc.c mdoc_hash.c \
mdoc_argv.c mdoc_validate.c lib.c att.c \
arch.c vol.c msec.c st.c
-SRCS+= man_macro.c man.c man_hash.c man_validate.c man_argv.c
+SRCS+= man_macro.c man.c man_hash.c man_validate.c
SRCS+= main.c mdoc_term.c chars.c term.c tree.c man_term.c
SRCS+= html.c mdoc_html.c man_html.c out.c
SRCS+= term_ps.c term_ascii.c tbl_term.c tbl_html.c
diff --git a/usr.bin/mandoc/arch.c b/usr.bin/mandoc/arch.c
index 0e0d94408e9..d754c038ca2 100644
--- a/usr.bin/mandoc/arch.c
+++ b/usr.bin/mandoc/arch.c
@@ -1,4 +1,4 @@
-/* $Id: arch.c,v 1.5 2010/07/31 23:42:04 schwarze Exp $ */
+/* $Id: arch.c,v 1.6 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -18,6 +18,7 @@
#include <string.h>
#include <time.h>
+#include "mdoc.h"
#include "mandoc.h"
#include "libmdoc.h"
diff --git a/usr.bin/mandoc/att.c b/usr.bin/mandoc/att.c
index 03086eddf22..2ed01b6cd52 100644
--- a/usr.bin/mandoc/att.c
+++ b/usr.bin/mandoc/att.c
@@ -1,4 +1,4 @@
-/* $Id: att.c,v 1.5 2010/07/31 23:42:04 schwarze Exp $ */
+/* $Id: att.c,v 1.6 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -18,6 +18,7 @@
#include <string.h>
#include <time.h>
+#include "mdoc.h"
#include "mandoc.h"
#include "libmdoc.h"
diff --git a/usr.bin/mandoc/chars.c b/usr.bin/mandoc/chars.c
index 3b115bdf253..0446fa53ea4 100644
--- a/usr.bin/mandoc/chars.c
+++ b/usr.bin/mandoc/chars.c
@@ -1,4 +1,4 @@
-/* $Id: chars.c,v 1.17 2011/04/21 22:59:54 schwarze Exp $ */
+/* $Id: chars.c,v 1.18 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -21,7 +21,7 @@
#include <string.h>
#include "mandoc.h"
-#include "chars.h"
+#include "out.h"
#define PRINT_HI 126
#define PRINT_LO 32
@@ -37,7 +37,7 @@ struct ln {
#define CHARS_BOTH (CHARS_CHAR | CHARS_STRING)
};
-#define LINES_MAX 351
+#define LINES_MAX 353
#define CHAR(in, ch, code) \
{ NULL, (in), (ch), (code), CHARS_CHAR },
diff --git a/usr.bin/mandoc/chars.h b/usr.bin/mandoc/chars.h
deleted file mode 100644
index 43ec349332e..00000000000
--- a/usr.bin/mandoc/chars.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* $Id: chars.h,v 1.6 2011/01/30 16:05:29 schwarze Exp $ */
-/*
- * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
- *
- * 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.
- */
-#ifndef CHARS_H
-#define CHARS_H
-
-__BEGIN_DECLS
-
-enum chars {
- CHARS_ASCII,
- CHARS_HTML
-};
-
-void *chars_init(enum chars);
-const char *chars_num2char(const char *, size_t);
-const char *chars_spec2str(void *, const char *, size_t, size_t *);
-int chars_spec2cp(void *, const char *, size_t);
-const char *chars_res2str(void *, const char *, size_t, size_t *);
-int chars_res2cp(void *, const char *, size_t);
-void chars_free(void *);
-
-__END_DECLS
-
-#endif /*!CHARS_H*/
diff --git a/usr.bin/mandoc/chars.in b/usr.bin/mandoc/chars.in
index 3ca3673835d..49676cd4b1e 100644
--- a/usr.bin/mandoc/chars.in
+++ b/usr.bin/mandoc/chars.in
@@ -1,6 +1,6 @@
-/* $Id: chars.in,v 1.14 2011/03/16 22:16:25 naddy Exp $ */
+/* $Id: chars.in,v 1.15 2011/04/24 16:22:02 schwarze Exp $ */
/*
- * Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -375,6 +375,8 @@ STRING("right-parenthesis", ")", 41)
STRING("right-singlequote", "\'", 8217)
STRING("rp", ")", 41)
STRING("Tm", "(Tm)", 8482)
+STRING("Px", "POSIX", 0)
+STRING("Ai", "ANSI", 0)
/* Lines. */
CHAR("ba", "|", 124)
diff --git a/usr.bin/mandoc/eqn.c b/usr.bin/mandoc/eqn.c
index c7fdffe06c6..0d5bccdea9e 100644
--- a/usr.bin/mandoc/eqn.c
+++ b/usr.bin/mandoc/eqn.c
@@ -1,4 +1,4 @@
-/* $Id: eqn.c,v 1.2 2011/04/21 22:59:54 schwarze Exp $ */
+/* $Id: eqn.c,v 1.3 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -23,7 +23,6 @@
#include <string.h>
#include "mandoc.h"
-#include "roff.h"
#include "libmandoc.h"
#include "libroff.h"
diff --git a/usr.bin/mandoc/html.c b/usr.bin/mandoc/html.c
index b39d28117e0..45197ad76ef 100644
--- a/usr.bin/mandoc/html.c
+++ b/usr.bin/mandoc/html.c
@@ -1,4 +1,4 @@
-/* $Id: html.c,v 1.24 2011/04/21 22:59:54 schwarze Exp $ */
+/* $Id: html.c,v 1.25 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -28,7 +28,6 @@
#include "mandoc.h"
#include "out.h"
-#include "chars.h"
#include "html.h"
#include "main.h"
@@ -505,15 +504,10 @@ print_doctype(struct html *h)
name, doctype, dtd);
}
-
void
print_text(struct html *h, const char *word)
{
- if (DELIM_CLOSE == mandoc_isdelim(word))
- if ( ! (HTML_IGNDELIM & h->flags))
- h->flags |= HTML_NOSPACE;
-
if ( ! (HTML_NOSPACE & h->flags)) {
/* Manage keeps! */
if ( ! (HTML_KEEP & h->flags)) {
@@ -541,9 +535,6 @@ print_text(struct html *h, const char *word)
}
h->flags &= ~HTML_IGNDELIM;
-
- if (DELIM_OPEN == mandoc_isdelim(word))
- h->flags |= HTML_NOSPACE;
}
diff --git a/usr.bin/mandoc/lib.c b/usr.bin/mandoc/lib.c
index 79c70a821f9..20b9e29c934 100644
--- a/usr.bin/mandoc/lib.c
+++ b/usr.bin/mandoc/lib.c
@@ -1,4 +1,4 @@
-/* $Id: lib.c,v 1.5 2010/07/31 23:42:04 schwarze Exp $ */
+/* $Id: lib.c,v 1.6 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -18,6 +18,7 @@
#include <string.h>
#include <time.h>
+#include "mdoc.h"
#include "mandoc.h"
#include "libmdoc.h"
diff --git a/usr.bin/mandoc/libman.h b/usr.bin/mandoc/libman.h
index a9b260961ff..1d86d1026ef 100644
--- a/usr.bin/mandoc/libman.h
+++ b/usr.bin/mandoc/libman.h
@@ -1,6 +1,6 @@
-/* $Id: libman.h,v 1.28 2011/04/21 22:59:54 schwarze Exp $ */
+/* $Id: libman.h,v 1.29 2011/04/24 16:22:02 schwarze Exp $ */
/*
- * Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -17,16 +17,13 @@
#ifndef LIBMAN_H
#define LIBMAN_H
-#include "man.h"
-
enum man_next {
MAN_NEXT_SIBLING = 0,
MAN_NEXT_CHILD
};
struct man {
- void *data; /* private application data */
- mandocmsg msg; /* output message handler */
+ struct mparse *parse; /* parse pointer */
int flags; /* parse flags */
#define MAN_HALT (1 << 0) /* badness happened: die */
#define MAN_ELINE (1 << 1) /* Next-line element scope. */
@@ -64,25 +61,19 @@ extern const struct man_macro *const man_macros;
__BEGIN_DECLS
#define man_pmsg(m, l, p, t) \
- (*(m)->msg)((t), (m)->data, (l), (p), NULL)
+ mandoc_msg((t), (m)->parse, (l), (p), NULL)
#define man_nmsg(m, n, t) \
- (*(m)->msg)((t), (m)->data, (n)->line, (n)->pos, NULL)
+ mandoc_msg((t), (m)->parse, (n)->line, (n)->pos, NULL)
int man_word_alloc(struct man *, int, int, const char *);
int man_block_alloc(struct man *, int, int, enum mant);
int man_head_alloc(struct man *, int, int, enum mant);
+int man_tail_alloc(struct man *, int, int, enum mant);
int man_body_alloc(struct man *, int, int, enum mant);
int man_elem_alloc(struct man *, int, int, enum mant);
void man_node_delete(struct man *, struct man_node *);
void man_hash_init(void);
-enum mant man_hash_find(const char *);
+enum mant man_hash_find(const char *);
int man_macroend(struct man *);
-int man_args(struct man *, int, int *, char *, char **);
-#define ARGS_ERROR (-1)
-#define ARGS_EOLN (0)
-#define ARGS_WORD (1)
-#define ARGS_QWORD (1)
-void man_vmsg(struct man *, enum mandocerr,
- int, int, const char *, ...);
int man_valid_post(struct man *);
int man_valid_pre(struct man *, struct man_node *);
int man_unscope(struct man *,
diff --git a/usr.bin/mandoc/libmandoc.h b/usr.bin/mandoc/libmandoc.h
index 8adba0fd797..eaacbfccbf1 100644
--- a/usr.bin/mandoc/libmandoc.h
+++ b/usr.bin/mandoc/libmandoc.h
@@ -1,6 +1,6 @@
-/* $Id: libmandoc.h,v 1.10 2011/04/21 22:59:54 schwarze Exp $ */
+/* $Id: libmandoc.h,v 1.11 2011/04/24 16:22:02 schwarze Exp $ */
/*
- * Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -17,14 +17,95 @@
#ifndef LIBMANDOC_H
#define LIBMANDOC_H
+enum rofferr {
+ ROFF_CONT, /* continue processing line */
+ ROFF_RERUN, /* re-run roff interpreter with offset */
+ ROFF_APPEND, /* re-run main parser, appending next line */
+ ROFF_REPARSE, /* re-run main parser on the result */
+ ROFF_SO, /* include another file */
+ ROFF_IGN, /* ignore current line */
+ ROFF_TBL, /* a table row was successfully parsed */
+ ROFF_EQN, /* an equation was successfully parsed */
+ ROFF_ERR /* badness: puke and stop */
+};
+
+enum regs {
+ REG_nS = 0, /* nS register */
+ REG__MAX
+};
+
+/*
+ * A register (struct reg) can consist of many types: this consists of
+ * normalised types from the original string form. For the time being,
+ * there's only an unsigned integer type.
+ */
+union regval {
+ unsigned u; /* unsigned integer */
+};
+
+/*
+ * A single register entity. If "set" is zero, the value of the
+ * register should be the default one, which is per-register. It's
+ * assumed that callers know which type in "v" corresponds to which
+ * register value.
+ */
+struct reg {
+ int set; /* whether set or not */
+ union regval v; /* parsed data */
+};
+
+/*
+ * The primary interface to setting register values is in libroff,
+ * although libmdoc and libman from time to time will manipulate
+ * registers (such as `.Sh SYNOPSIS' enabling REG_nS).
+ */
+struct regset {
+ struct reg regs[REG__MAX];
+};
+
__BEGIN_DECLS
+struct roff;
+struct mdoc;
+struct man;
+
+void mandoc_msg(enum mandocerr, struct mparse *,
+ int, int, const char *);
+void mandoc_vmsg(enum mandocerr, struct mparse *,
+ int, int, const char *, ...);
int mandoc_special(char *);
char *mandoc_strdup(const char *);
-char *mandoc_getarg(char **, mandocmsg, void *, int, int *);
-char *mandoc_normdate(char *, mandocmsg, void *, int, int);
+char *mandoc_getarg(struct mparse *, char **, int, int *);
+char *mandoc_normdate(struct mparse *, char *, int, int);
int mandoc_eos(const char *, size_t, int);
int mandoc_hyph(const char *, const char *);
+int mandoc_getcontrol(const char *, int *);
+
+void mdoc_free(struct mdoc *);
+struct mdoc *mdoc_alloc(struct regset *, struct mparse *);
+void mdoc_reset(struct mdoc *);
+int mdoc_parseln(struct mdoc *, int, char *, int);
+int mdoc_endparse(struct mdoc *);
+int mdoc_addspan(struct mdoc *, const struct tbl_span *);
+int mdoc_addeqn(struct mdoc *, const struct eqn *);
+
+void man_free(struct man *);
+struct man *man_alloc(struct regset *, struct mparse *);
+void man_reset(struct man *);
+int man_parseln(struct man *, int, char *, int);
+int man_endparse(struct man *);
+int man_addspan(struct man *, const struct tbl_span *);
+int man_addeqn(struct man *, const struct eqn *);
+
+void roff_free(struct roff *);
+struct roff *roff_alloc(struct regset *, struct mparse *);
+void roff_reset(struct roff *);
+enum rofferr roff_parseln(struct roff *, int,
+ char **, size_t *, int, int *);
+void roff_endparse(struct roff *);
+
+const struct tbl_span *roff_span(const struct roff *);
+const struct eqn *roff_eqn(const struct roff *);
__END_DECLS
diff --git a/usr.bin/mandoc/libmdoc.h b/usr.bin/mandoc/libmdoc.h
index 9a06007e6ee..ceffcb05332 100644
--- a/usr.bin/mandoc/libmdoc.h
+++ b/usr.bin/mandoc/libmdoc.h
@@ -1,6 +1,6 @@
-/* $Id: libmdoc.h,v 1.44 2011/04/21 22:59:54 schwarze Exp $ */
+/* $Id: libmdoc.h,v 1.45 2011/04/24 16:22:02 schwarze Exp $ */
/*
- * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -17,17 +17,14 @@
#ifndef LIBMDOC_H
#define LIBMDOC_H
-#include "mdoc.h"
-
enum mdoc_next {
MDOC_NEXT_SIBLING = 0,
MDOC_NEXT_CHILD
};
struct mdoc {
- void *data; /* private application data */
- mandocmsg msg; /* message callback */
- int flags;
+ struct mparse *parse; /* parse pointer */
+ int flags; /* parse flags */
#define MDOC_HALT (1 << 0) /* error in parse: halt */
#define MDOC_LITERAL (1 << 1) /* in a literal scope */
#define MDOC_PBODY (1 << 2) /* in the document body */
@@ -81,16 +78,31 @@ enum margverr {
ARGV_WORD
};
+/*
+ * A punctuation delimiter is opening, closing, or "middle mark"
+ * punctuation. These govern spacing.
+ * Opening punctuation (e.g., the opening parenthesis) suppresses the
+ * following space; closing punctuation (e.g., the closing parenthesis)
+ * suppresses the leading space; middle punctuation (e.g., the vertical
+ * bar) can do either. The middle punctuation delimiter bends the rules
+ * depending on usage.
+ */
+enum mdelim {
+ DELIM_NONE = 0,
+ DELIM_OPEN,
+ DELIM_MIDDLE,
+ DELIM_CLOSE,
+ DELIM_MAX
+};
+
extern const struct mdoc_macro *const mdoc_macros;
__BEGIN_DECLS
#define mdoc_pmsg(m, l, p, t) \
- (*(m)->msg)((t), (m)->data, (l), (p), NULL)
+ mandoc_msg((t), (m)->parse, (l), (p), NULL)
#define mdoc_nmsg(m, n, t) \
- (*(m)->msg)((t), (m)->data, (n)->line, (n)->pos, NULL)
-void mdoc_vmsg(struct mdoc *, enum mandocerr,
- int, int, const char *, ...);
+ mandoc_msg((t), (m)->parse, (n)->line, (n)->pos, NULL)
int mdoc_macro(MACRO_PROT_ARGS);
int mdoc_word_alloc(struct mdoc *,
int, int, const char *);
@@ -118,7 +130,6 @@ int mdoc_valid_post(struct mdoc *);
enum margverr mdoc_argv(struct mdoc *, int, enum mdoct,
struct mdoc_arg **, int *, char *);
void mdoc_argv_free(struct mdoc_arg *);
-void mdoc_argn_free(struct mdoc_arg *, int);
enum margserr mdoc_args(struct mdoc *, int,
int *, char *, enum mdoct, char **);
enum margserr mdoc_zargs(struct mdoc *, int,
@@ -129,6 +140,9 @@ enum margserr mdoc_zargs(struct mdoc *, int,
int mdoc_macroend(struct mdoc *);
+#define DELIMSZ 6 /* hint: max possible size of a delimiter */
+enum mdelim mdoc_isdelim(const char *);
+
__END_DECLS
#endif /*!LIBMDOC_H*/
diff --git a/usr.bin/mandoc/libroff.h b/usr.bin/mandoc/libroff.h
index dcac7832f0a..5769f31e105 100644
--- a/usr.bin/mandoc/libroff.h
+++ b/usr.bin/mandoc/libroff.h
@@ -1,4 +1,4 @@
-/* $Id: libroff.h,v 1.3 2011/03/20 23:36:42 schwarze Exp $ */
+/* $Id: libroff.h,v 1.4 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -27,8 +27,7 @@ enum tbl_part {
};
struct tbl_node {
- mandocmsg msg; /* status messages */
- void *data; /* privdata for messages */
+ struct mparse *parse; /* parse point */
int pos; /* invocation column */
int line; /* invocation line */
enum tbl_part part;
@@ -48,10 +47,7 @@ struct eqn_node {
struct eqn_node *next;
};
-#define TBL_MSG(tblp, type, line, col) \
- (*(tblp)->msg)((type), (tblp)->data, (line), (col), NULL)
-
-struct tbl_node *tbl_alloc(int, int, void *, mandocmsg);
+struct tbl_node *tbl_alloc(int, int, struct mparse *);
void tbl_restart(int, int, struct tbl_node *);
void tbl_free(struct tbl_node *);
void tbl_reset(struct tbl_node *);
diff --git a/usr.bin/mandoc/main.c b/usr.bin/mandoc/main.c
index 8a1752c2d83..088940778ef 100644
--- a/usr.bin/mandoc/main.c
+++ b/usr.bin/mandoc/main.c
@@ -1,4 +1,4 @@
-/* $Id: main.c,v 1.75 2011/04/21 22:59:54 schwarze Exp $ */
+/* $Id: main.c,v 1.76 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -15,13 +15,8 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
#include <assert.h>
-#include <ctype.h>
-#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
@@ -32,51 +27,25 @@
#include "main.h"
#include "mdoc.h"
#include "man.h"
-#include "roff.h"
-
-#define REPARSE_LIMIT 1000
typedef void (*out_mdoc)(void *, const struct mdoc *);
typedef void (*out_man)(void *, const struct man *);
typedef void (*out_free)(void *);
-struct buf {
- char *buf;
- size_t sz;
-};
-
-enum intt {
- INTT_AUTO,
- INTT_MDOC,
- INTT_MAN
-};
-
enum outt {
- OUTT_ASCII = 0,
- OUTT_TREE,
- OUTT_HTML,
- OUTT_XHTML,
- OUTT_LINT,
- OUTT_PS,
- OUTT_PDF
+ OUTT_ASCII = 0, /* -Tascii */
+ OUTT_TREE, /* -Ttree */
+ OUTT_HTML, /* -Thtml */
+ OUTT_XHTML, /* -Txhtml */
+ OUTT_LINT, /* -Tlint */
+ OUTT_PS, /* -Tps */
+ OUTT_PDF /* -Tpdf */
};
struct curparse {
- enum mandoclevel exit_status; /* status of all file parses */
- const char *file; /* current file-name */
- enum mandoclevel file_status; /* error status of current parse */
- int fd; /* current file-descriptor */
- int line; /* line number in the file */
+ struct mparse *mp;
enum mandoclevel wlevel; /* ignore messages below this */
int wstop; /* stop after a file with a warning */
- enum intt inttype; /* which parser to use */
- struct man *pman; /* persistent man parser */
- struct mdoc *pmdoc; /* persistent mdoc parser */
- struct man *man; /* man parser */
- struct mdoc *mdoc; /* mdoc parser */
- struct roff *roff; /* roff parser (!NULL) */
- struct regset regs; /* roff registers */
- int reparse_count; /* finite interpolation stack */
enum outt outtype; /* which output to use */
out_mdoc outmdoc; /* mdoc output ptr */
out_man outman; /* man output ptr */
@@ -85,142 +54,11 @@ struct curparse {
char outopts[BUFSIZ]; /* buf of output opts */
};
-static const char * const mandoclevels[MANDOCLEVEL_MAX] = {
- "SUCCESS",
- "RESERVED",
- "WARNING",
- "ERROR",
- "FATAL",
- "BADARG",
- "SYSERR"
-};
-
-static const enum mandocerr mandoclimits[MANDOCLEVEL_MAX] = {
- MANDOCERR_OK,
- MANDOCERR_WARNING,
- MANDOCERR_WARNING,
- MANDOCERR_ERROR,
- MANDOCERR_FATAL,
- MANDOCERR_MAX,
- MANDOCERR_MAX
-};
-
-static const char * const mandocerrs[MANDOCERR_MAX] = {
- "ok",
-
- "generic warning",
-
- /* related to the prologue */
- "no title in document",
- "document title should be all caps",
- "unknown manual section",
- "date missing, using today's date",
- "cannot parse date, using it verbatim",
- "prologue macros out of order",
- "duplicate prologue macro",
- "macro not allowed in prologue",
- "macro not allowed in body",
-
- /* related to document structure */
- ".so is fragile, better use ln(1)",
- "NAME section must come first",
- "bad NAME section contents",
- "manual name not yet set",
- "sections out of conventional order",
- "duplicate section name",
- "section not in conventional manual section",
-
- /* related to macros and nesting */
- "skipping obsolete macro",
- "skipping paragraph macro",
- "skipping no-space macro",
- "blocks badly nested",
- "child violates parent syntax",
- "nested displays are not portable",
- "already in literal mode",
-
- /* related to missing macro arguments */
- "skipping empty macro",
- "argument count wrong",
- "missing display type",
- "list type must come first",
- "tag lists require a width argument",
- "missing font type",
- "skipping end of block that is not open",
-
- /* related to bad macro arguments */
- "skipping argument",
- "duplicate argument",
- "duplicate display type",
- "duplicate list type",
- "unknown AT&T UNIX version",
- "bad Boolean value",
- "unknown font",
- "unknown standard specifier",
- "bad width argument",
-
- /* related to plain text */
- "blank line in non-literal context",
- "tab in non-literal context",
- "end of line whitespace",
- "bad comment style",
- "unknown escape sequence",
- "unterminated quoted string",
-
- "generic error",
-
- /* related to tables */
- "bad table syntax",
- "bad table option",
- "bad table layout",
- "no table layout cells specified",
- "no table data cells specified",
- "ignore data in cell",
- "data block still open",
- "ignoring extra data cells",
-
- "input stack limit exceeded, infinite loop?",
- "skipping bad character",
- "escaped character not allowed in a name",
- "skipping text before the first section header",
- "skipping unknown macro",
- "NOT IMPLEMENTED, please use groff: skipping request",
- "line scope broken",
- "argument count wrong",
- "skipping end of block that is not open",
- "missing end of block",
- "scope open on exit",
- "uname(3) system call failed",
- "macro requires line argument(s)",
- "macro requires body argument(s)",
- "macro requires argument(s)",
- "missing list type",
- "line argument(s) will be lost",
- "body argument(s) will be lost",
-
- "generic fatal error",
-
- "column syntax is inconsistent",
- "NOT IMPLEMENTED: .Bd -file",
- "line scope broken, syntax violated",
- "argument count wrong, violates syntax",
- "child violates parent syntax",
- "argument count wrong, violates syntax",
- "NOT IMPLEMENTED: .so with absolute path or \"..\"",
- "no document body",
- "no document prologue",
- "static buffer exhausted",
-};
-
-static void parsebuf(struct curparse *, struct buf, int);
-static void pdesc(struct curparse *);
-static void fdesc(struct curparse *);
-static void ffile(const char *, struct curparse *);
-static int pfile(const char *, struct curparse *);
-static int moptions(enum intt *, char *);
-static void mmsg(enum mandocerr, void *,
- int, int, const char *);
-static void pset(const char *, int, struct curparse *);
+static int moptions(enum mparset *, char *);
+static void mmsg(enum mandocerr, enum mandoclevel,
+ const char *, int, int, const char *);
+static void parse(struct curparse *, int,
+ const char *, enum mandoclevel *);
static int toptions(struct curparse *, char *);
static void usage(void) __attribute__((noreturn));
static void version(void) __attribute__((noreturn));
@@ -233,6 +71,8 @@ main(int argc, char *argv[])
{
int c;
struct curparse curp;
+ enum mparset type;
+ enum mandoclevel rc;
progname = strrchr(argv[0], '/');
if (progname == NULL)
@@ -242,16 +82,15 @@ main(int argc, char *argv[])
memset(&curp, 0, sizeof(struct curparse));
- curp.inttype = INTT_AUTO;
+ type = MPARSE_AUTO;
curp.outtype = OUTT_ASCII;
curp.wlevel = MANDOCLEVEL_FATAL;
- curp.exit_status = MANDOCLEVEL_OK;
/* LINTED */
while (-1 != (c = getopt(argc, argv, "m:O:T:VW:")))
switch (c) {
case ('m'):
- if ( ! moptions(&curp.inttype, optarg))
+ if ( ! moptions(&type, optarg))
return((int)MANDOCLEVEL_BADARG);
break;
case ('O'):
@@ -274,56 +113,50 @@ main(int argc, char *argv[])
/* NOTREACHED */
}
+ curp.mp = mparse_alloc(type, curp.wlevel, mmsg, &curp);
+
argc -= optind;
argv += optind;
- if (NULL == *argv) {
- curp.file = "<stdin>";
- curp.fd = STDIN_FILENO;
+ rc = MANDOCLEVEL_OK;
- fdesc(&curp);
- }
+ if (NULL == *argv)
+ parse(&curp, STDIN_FILENO, "<stdin>", &rc);
while (*argv) {
- ffile(*argv, &curp);
- if (MANDOCLEVEL_OK != curp.exit_status && curp.wstop)
+ parse(&curp, -1, *argv, &rc);
+ if (MANDOCLEVEL_OK != rc && curp.wstop)
break;
++argv;
}
if (curp.outfree)
(*curp.outfree)(curp.outdata);
- if (curp.pmdoc)
- mdoc_free(curp.pmdoc);
- if (curp.pman)
- man_free(curp.pman);
- if (curp.roff)
- roff_free(curp.roff);
+ if (curp.mp)
+ mparse_free(curp.mp);
- return((int)curp.exit_status);
+ return((int)rc);
}
-
static void
version(void)
{
- (void)printf("%s %s\n", progname, VERSION);
+ printf("%s %s\n", progname, VERSION);
exit((int)MANDOCLEVEL_OK);
}
-
static void
usage(void)
{
- (void)fprintf(stderr, "usage: %s "
+ fprintf(stderr, "usage: %s "
"[-V] "
"[-foption] "
"[-mformat] "
"[-Ooption] "
"[-Toutput] "
- "[-Werr] "
+ "[-Wlevel] "
"[file...]\n",
progname);
@@ -331,201 +164,31 @@ usage(void)
}
static void
-ffile(const char *file, struct curparse *curp)
-{
-
- /*
- * Called once per input file. Get the file ready for reading,
- * pass it through to the parser-driver, then close it out.
- * XXX: don't do anything special as this is only called for
- * files; stdin goes directly to fdesc().
- */
-
- curp->file = file;
-
- if (-1 == (curp->fd = open(curp->file, O_RDONLY, 0))) {
- perror(curp->file);
- curp->exit_status = MANDOCLEVEL_SYSERR;
- return;
- }
-
- fdesc(curp);
-
- if (-1 == close(curp->fd))
- perror(curp->file);
-}
-
-static int
-pfile(const char *file, struct curparse *curp)
+parse(struct curparse *curp, int fd,
+ const char *file, enum mandoclevel *level)
{
- const char *savefile;
- int fd, savefd;
-
- if (-1 == (fd = open(file, O_RDONLY, 0))) {
- perror(file);
- curp->file_status = MANDOCLEVEL_SYSERR;
- return(0);
- }
-
- savefile = curp->file;
- savefd = curp->fd;
-
- curp->file = file;
- curp->fd = fd;
+ enum mandoclevel rc;
+ struct mdoc *mdoc;
+ struct man *man;
- pdesc(curp);
+ /* Begin by parsing the file itself. */
- curp->file = savefile;
- curp->fd = savefd;
+ assert(file);
+ assert(fd >= -1);
- if (-1 == close(fd))
- perror(file);
+ rc = mparse_readfd(curp->mp, fd, file);
- return(MANDOCLEVEL_FATAL > curp->file_status ? 1 : 0);
-}
-
-
-static void
-resize_buf(struct buf *buf, size_t initial)
-{
+ /* Stop immediately if the parse has failed. */
- buf->sz = buf->sz > initial/2 ? 2 * buf->sz : initial;
- buf->buf = mandoc_realloc(buf->buf, buf->sz);
-}
-
-
-static int
-read_whole_file(struct curparse *curp, struct buf *fb, int *with_mmap)
-{
- struct stat st;
- size_t off;
- ssize_t ssz;
-
- if (-1 == fstat(curp->fd, &st)) {
- perror(curp->file);
- return(0);
- }
-
- /*
- * If we're a regular file, try just reading in the whole entry
- * via mmap(). This is faster than reading it into blocks, and
- * since each file is only a few bytes to begin with, I'm not
- * concerned that this is going to tank any machines.
- */
-
- if (S_ISREG(st.st_mode)) {
- if (st.st_size >= (1U << 31)) {
- fprintf(stderr, "%s: input too large\n",
- curp->file);
- return(0);
- }
- *with_mmap = 1;
- fb->sz = (size_t)st.st_size;
- fb->buf = mmap(NULL, fb->sz, PROT_READ,
- MAP_FILE|MAP_SHARED, curp->fd, 0);
- if (fb->buf != MAP_FAILED)
- return(1);
- }
-
- /*
- * If this isn't a regular file (like, say, stdin), then we must
- * go the old way and just read things in bit by bit.
- */
-
- *with_mmap = 0;
- off = 0;
- fb->sz = 0;
- fb->buf = NULL;
- for (;;) {
- if (off == fb->sz) {
- if (fb->sz == (1U << 31)) {
- fprintf(stderr, "%s: input too large\n",
- curp->file);
- break;
- }
- resize_buf(fb, 65536);
- }
- ssz = read(curp->fd, fb->buf + (int)off, fb->sz - off);
- if (ssz == 0) {
- fb->sz = off;
- return(1);
- }
- if (ssz == -1) {
- perror(curp->file);
- break;
- }
- off += (size_t)ssz;
- }
-
- free(fb->buf);
- fb->buf = NULL;
- return(0);
-}
-
-
-static void
-fdesc(struct curparse *curp)
-{
-
- /*
- * Called once per file with an opened file descriptor. All
- * pre-file-parse operations (whether stdin or a file) should go
- * here.
- *
- * This calls down into the nested parser, which drills down and
- * fully parses a file and all its dependences (i.e., `so'). It
- * then runs the cleanup validators and pushes to output.
- */
-
- /* Zero the parse type. */
-
- curp->mdoc = NULL;
- curp->man = NULL;
- curp->file_status = MANDOCLEVEL_OK;
-
- /* Make sure the mandotory roff parser is initialised. */
-
- if (NULL == curp->roff) {
- curp->roff = roff_alloc(&curp->regs, curp, mmsg);
- assert(curp->roff);
- }
-
- /* Fully parse the file. */
-
- pdesc(curp);
-
- if (MANDOCLEVEL_FATAL <= curp->file_status)
- goto cleanup;
-
- /* NOTE a parser may not have been assigned, yet. */
-
- if ( ! (curp->man || curp->mdoc)) {
- fprintf(stderr, "%s: Not a manual\n", curp->file);
- curp->file_status = MANDOCLEVEL_FATAL;
- goto cleanup;
- }
-
- /* Clean up the parse routine ASTs. */
-
- if (curp->mdoc && ! mdoc_endparse(curp->mdoc)) {
- assert(MANDOCLEVEL_FATAL <= curp->file_status);
+ if (MANDOCLEVEL_FATAL <= rc)
goto cleanup;
- }
-
- if (curp->man && ! man_endparse(curp->man)) {
- assert(MANDOCLEVEL_FATAL <= curp->file_status);
- goto cleanup;
- }
-
- assert(curp->roff);
- roff_endparse(curp->roff);
/*
- * With -Wstop and warnings or errors of at least
- * the requested level, do not produce output.
+ * With -Wstop and warnings or errors of at least the requested
+ * level, do not produce output.
*/
- if (MANDOCLEVEL_OK != curp->file_status && curp->wstop)
+ if (MANDOCLEVEL_OK != rc && curp->wstop)
goto cleanup;
/* If unset, allocate output dev now (if applicable). */
@@ -579,373 +242,33 @@ fdesc(struct curparse *curp)
}
}
+ mparse_result(curp->mp, &mdoc, &man);
+
/* Execute the out device, if it exists. */
- if (curp->man && curp->outman)
- (*curp->outman)(curp->outdata, curp->man);
- if (curp->mdoc && curp->outmdoc)
- (*curp->outmdoc)(curp->outdata, curp->mdoc);
+ if (man && curp->outman)
+ (*curp->outman)(curp->outdata, man);
+ if (mdoc && curp->outmdoc)
+ (*curp->outmdoc)(curp->outdata, mdoc);
cleanup:
- memset(&curp->regs, 0, sizeof(struct regset));
-
- /* Reset the current-parse compilers. */
-
- if (curp->mdoc)
- mdoc_reset(curp->mdoc);
- if (curp->man)
- man_reset(curp->man);
-
- assert(curp->roff);
- roff_reset(curp->roff);
-
- if (curp->exit_status < curp->file_status)
- curp->exit_status = curp->file_status;
-
- return;
-}
-
-static void
-pdesc(struct curparse *curp)
-{
- struct buf blk;
- int with_mmap;
-
- /*
- * Run for each opened file; may be called more than once for
- * each full parse sequence if the opened file is nested (i.e.,
- * from `so'). Simply sucks in the whole file and moves into
- * the parse phase for the file.
- */
-
- if ( ! read_whole_file(curp, &blk, &with_mmap)) {
- curp->file_status = MANDOCLEVEL_SYSERR;
- return;
- }
-
- /* Line number is per-file. */
-
- curp->line = 1;
-
- parsebuf(curp, blk, 1);
-
- if (with_mmap)
- munmap(blk.buf, blk.sz);
- else
- free(blk.buf);
-}
-
-/*
- * Main parse routine for an opened file. This is called for each
- * opened file and simply loops around the full input file, possibly
- * nesting (i.e., with `so').
- */
-static void
-parsebuf(struct curparse *curp, struct buf blk, int start)
-{
- const struct tbl_span *span;
- struct buf ln;
- enum rofferr rr;
- int i, of, rc;
- int pos; /* byte number in the ln buffer */
- int lnn; /* line number in the real file */
- unsigned char c;
-
- memset(&ln, 0, sizeof(struct buf));
-
- lnn = curp->line;
- pos = 0;
-
- for (i = 0; i < (int)blk.sz; ) {
- if (0 == pos && '\0' == blk.buf[i])
- break;
-
- if (start) {
- curp->line = lnn;
- curp->reparse_count = 0;
- }
-
- while (i < (int)blk.sz && (start || '\0' != blk.buf[i])) {
-
- /*
- * When finding an unescaped newline character,
- * leave the character loop to process the line.
- * Skip a preceding carriage return, if any.
- */
-
- if ('\r' == blk.buf[i] && i + 1 < (int)blk.sz &&
- '\n' == blk.buf[i + 1])
- ++i;
- if ('\n' == blk.buf[i]) {
- ++i;
- ++lnn;
- break;
- }
-
- /*
- * Warn about bogus characters. If you're using
- * non-ASCII encoding, you're screwing your
- * readers. Since I'd rather this not happen,
- * I'll be helpful and drop these characters so
- * we don't display gibberish. Note to manual
- * writers: use special characters.
- */
-
- c = (unsigned char) blk.buf[i];
-
- if ( ! (isascii(c) &&
- (isgraph(c) || isblank(c)))) {
- mmsg(MANDOCERR_BADCHAR, curp,
- curp->line, pos, "ignoring byte");
- i++;
- continue;
- }
-
- /* Trailing backslash = a plain char. */
-
- if ('\\' != blk.buf[i] || i + 1 == (int)blk.sz) {
- if (pos >= (int)ln.sz)
- resize_buf(&ln, 256);
- ln.buf[pos++] = blk.buf[i++];
- continue;
- }
-
- /*
- * Found escape and at least one other character.
- * When it's a newline character, skip it.
- * When there is a carriage return in between,
- * skip that one as well.
- */
-
- if ('\r' == blk.buf[i + 1] && i + 2 < (int)blk.sz &&
- '\n' == blk.buf[i + 2])
- ++i;
- if ('\n' == blk.buf[i + 1]) {
- i += 2;
- ++lnn;
- continue;
- }
-
- if ('"' == blk.buf[i + 1]) {
- i += 2;
- /* Comment, skip to end of line */
- for (; i < (int)blk.sz; ++i) {
- if ('\n' == blk.buf[i]) {
- ++i;
- ++lnn;
- break;
- }
- }
-
- /* Backout trailing whitespaces */
- for (; pos > 0; --pos) {
- if (ln.buf[pos - 1] != ' ')
- break;
- if (pos > 2 && ln.buf[pos - 2] == '\\')
- break;
- }
- break;
- }
+ mparse_reset(curp->mp);
- /* Some other escape sequence, copy & cont. */
-
- if (pos + 1 >= (int)ln.sz)
- resize_buf(&ln, 256);
-
- ln.buf[pos++] = blk.buf[i++];
- ln.buf[pos++] = blk.buf[i++];
- }
-
- if (pos >= (int)ln.sz)
- resize_buf(&ln, 256);
-
- ln.buf[pos] = '\0';
-
- /*
- * A significant amount of complexity is contained by
- * the roff preprocessor. It's line-oriented but can be
- * expressed on one line, so we need at times to
- * readjust our starting point and re-run it. The roff
- * preprocessor can also readjust the buffers with new
- * data, so we pass them in wholesale.
- */
-
- of = 0;
-
-rerun:
- rr = roff_parseln
- (curp->roff, curp->line,
- &ln.buf, &ln.sz, of, &of);
-
- switch (rr) {
- case (ROFF_REPARSE):
- if (REPARSE_LIMIT >= ++curp->reparse_count)
- parsebuf(curp, ln, 0);
- else
- mmsg(MANDOCERR_ROFFLOOP, curp,
- curp->line, pos, NULL);
- pos = 0;
- continue;
- case (ROFF_APPEND):
- pos = (int)strlen(ln.buf);
- continue;
- case (ROFF_RERUN):
- goto rerun;
- case (ROFF_IGN):
- pos = 0;
- continue;
- case (ROFF_ERR):
- assert(MANDOCLEVEL_FATAL <= curp->file_status);
- break;
- case (ROFF_SO):
- if (pfile(ln.buf + of, curp)) {
- pos = 0;
- continue;
- } else
- break;
- default:
- break;
- }
-
- /*
- * If we encounter errors in the recursive parsebuf()
- * call, make sure we don't continue parsing.
- */
-
- if (MANDOCLEVEL_FATAL <= curp->file_status)
- break;
-
- /*
- * If input parsers have not been allocated, do so now.
- * We keep these instanced betwen parsers, but set them
- * locally per parse routine since we can use different
- * parsers with each one.
- */
-
- if ( ! (curp->man || curp->mdoc))
- pset(ln.buf + of, pos - of, curp);
-
- /*
- * Lastly, push down into the parsers themselves. One
- * of these will have already been set in the pset()
- * routine.
- * If libroff returns ROFF_TBL, then add it to the
- * currently open parse. Since we only get here if
- * there does exist data (see tbl_data.c), we're
- * guaranteed that something's been allocated.
- * Do the same for ROFF_EQN.
- */
-
- rc = -1;
-
- if (ROFF_TBL == rr)
- while (NULL != (span = roff_span(curp->roff))) {
- rc = curp->man ?
- man_addspan(curp->man, span) :
- mdoc_addspan(curp->mdoc, span);
- if (0 == rc)
- break;
- }
- else if (ROFF_EQN == rr)
- rc = curp->mdoc ?
- mdoc_addeqn(curp->mdoc,
- roff_eqn(curp->roff)) :
- man_addeqn(curp->man,
- roff_eqn(curp->roff));
- else if (curp->man || curp->mdoc)
- rc = curp->man ?
- man_parseln(curp->man,
- curp->line, ln.buf, of) :
- mdoc_parseln(curp->mdoc,
- curp->line, ln.buf, of);
-
- if (0 == rc) {
- assert(MANDOCLEVEL_FATAL <= curp->file_status);
- break;
- }
-
- /* Temporary buffers typically are not full. */
-
- if (0 == start && '\0' == blk.buf[i])
- break;
-
- /* Start the next input line. */
-
- pos = 0;
- }
-
- free(ln.buf);
-}
-
-static void
-pset(const char *buf, int pos, struct curparse *curp)
-{
- int i;
-
- /*
- * Try to intuit which kind of manual parser should be used. If
- * passed in by command-line (-man, -mdoc), then use that
- * explicitly. If passed as -mandoc, then try to guess from the
- * line: either skip dot-lines, use -mdoc when finding `.Dt', or
- * default to -man, which is more lenient.
- *
- * Separate out pmdoc/pman from mdoc/man: the first persists
- * through all parsers, while the latter is used per-parse.
- */
-
- if ('.' == buf[0] || '\'' == buf[0]) {
- for (i = 1; buf[i]; i++)
- if (' ' != buf[i] && '\t' != buf[i])
- break;
- if ('\0' == buf[i])
- return;
- }
-
- switch (curp->inttype) {
- case (INTT_MDOC):
- if (NULL == curp->pmdoc)
- curp->pmdoc = mdoc_alloc
- (&curp->regs, curp, mmsg);
- assert(curp->pmdoc);
- curp->mdoc = curp->pmdoc;
- return;
- case (INTT_MAN):
- if (NULL == curp->pman)
- curp->pman = man_alloc
- (&curp->regs, curp, mmsg);
- assert(curp->pman);
- curp->man = curp->pman;
- return;
- default:
- break;
- }
-
- if (pos >= 3 && 0 == memcmp(buf, ".Dd", 3)) {
- if (NULL == curp->pmdoc)
- curp->pmdoc = mdoc_alloc
- (&curp->regs, curp, mmsg);
- assert(curp->pmdoc);
- curp->mdoc = curp->pmdoc;
- return;
- }
-
- if (NULL == curp->pman)
- curp->pman = man_alloc(&curp->regs, curp, mmsg);
- assert(curp->pman);
- curp->man = curp->pman;
+ if (*level < rc)
+ *level = rc;
}
static int
-moptions(enum intt *tflags, char *arg)
+moptions(enum mparset *tflags, char *arg)
{
if (0 == strcmp(arg, "doc"))
- *tflags = INTT_MDOC;
+ *tflags = MPARSE_MDOC;
else if (0 == strcmp(arg, "andoc"))
- *tflags = INTT_AUTO;
+ *tflags = MPARSE_AUTO;
else if (0 == strcmp(arg, "an"))
- *tflags = INTT_MAN;
+ *tflags = MPARSE_MAN;
else {
fprintf(stderr, "%s: Bad argument\n", arg);
return(0);
@@ -963,8 +286,7 @@ toptions(struct curparse *curp, char *arg)
else if (0 == strcmp(arg, "lint")) {
curp->outtype = OUTT_LINT;
curp->wlevel = MANDOCLEVEL_WARNING;
- }
- else if (0 == strcmp(arg, "tree"))
+ } else if (0 == strcmp(arg, "tree"))
curp->outtype = OUTT_TREE;
else if (0 == strcmp(arg, "html"))
curp->outtype = OUTT_HTML;
@@ -1022,26 +344,17 @@ woptions(struct curparse *curp, char *arg)
}
static void
-mmsg(enum mandocerr t, void *arg, int ln, int col, const char *msg)
+mmsg(enum mandocerr t, enum mandoclevel lvl,
+ const char *file, int line, int col, const char *msg)
{
- struct curparse *cp;
- enum mandoclevel level;
- level = MANDOCLEVEL_FATAL;
- while (t < mandoclimits[level])
- /* LINTED */
- level--;
+ fprintf(stderr, "%s:%d:%d: %s: %s",
+ file, line, col + 1,
+ mparse_strlevel(lvl),
+ mparse_strerror(t));
- cp = (struct curparse *)arg;
- if (level < cp->wlevel)
- return;
-
- fprintf(stderr, "%s:%d:%d: %s: %s",
- cp->file, ln, col + 1, mandoclevels[level], mandocerrs[t]);
if (msg)
fprintf(stderr, ": %s", msg);
- fputc('\n', stderr);
- if (cp->file_status < level)
- cp->file_status = level;
+ fputc('\n', stderr);
}
diff --git a/usr.bin/mandoc/man.3 b/usr.bin/mandoc/man.3
deleted file mode 100644
index 8f302259e57..00000000000
--- a/usr.bin/mandoc/man.3
+++ /dev/null
@@ -1,283 +0,0 @@
-.\" $Id: man.3,v 1.22 2011/03/20 23:36:42 schwarze Exp $
-.\"
-.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
-.\"
-.\" 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.
-.\"
-.Dd $Mdocdate: March 20 2011 $
-.Dt MAN 3
-.Os
-.Sh NAME
-.Nm man ,
-.Nm man_addeqn ,
-.Nm man_addspan ,
-.Nm man_alloc ,
-.Nm man_endparse ,
-.Nm man_free ,
-.Nm man_meta ,
-.Nm man_node ,
-.Nm man_parseln ,
-.Nm man_reset
-.Nd man macro compiler library
-.Sh SYNOPSIS
-.In mandoc.h
-.In man.h
-.Vt extern const char * const * man_macronames;
-.Ft int
-.Fo man_addeqn
-.Fa "struct man *man"
-.Fa "const struct eqn *eqn"
-.Fc
-.Ft int
-.Fo man_addspan
-.Fa "struct man *man"
-.Fa "const struct tbl_span *span"
-.Fc
-.Ft "struct man *"
-.Fo man_alloc
-.Fa "struct regset *regs"
-.Fa "void *data"
-.Fa "mandocmsg msgs"
-.Fc
-.Ft int
-.Fn man_endparse "struct man *man"
-.Ft void
-.Fn man_free "struct man *man"
-.Ft "const struct man_meta *"
-.Fn man_meta "const struct man *man"
-.Ft "const struct man_node *"
-.Fn man_node "const struct man *man"
-.Ft int
-.Fo man_parseln
-.Fa "struct man *man"
-.Fa "int line"
-.Fa "char *buf"
-.Fc
-.Ft void
-.Fn man_reset "struct man *man"
-.Sh DESCRIPTION
-The
-.Nm
-library parses lines of
-.Xr man 7
-input into an abstract syntax tree (AST).
-.Pp
-In general, applications initiate a parsing sequence with
-.Fn man_alloc ,
-parse each line in a document with
-.Fn man_parseln ,
-close the parsing session with
-.Fn man_endparse ,
-operate over the syntax tree returned by
-.Fn man_node
-and
-.Fn man_meta ,
-then free all allocated memory with
-.Fn man_free .
-The
-.Fn man_reset
-function may be used in order to reset the parser for another input
-sequence.
-.Pp
-Beyond the full set of macros defined in
-.Xr man 7 ,
-the
-.Nm
-library also accepts the following macro:
-.Pp
-.Bl -tag -width Ds -compact
-.It PD
-Has no effect.
-Handled as a current-scope line macro.
-.El
-.Ss Types
-.Bl -ohang
-.It Vt struct man
-An opaque type.
-Its values are only used privately within the library.
-.It Vt struct man_node
-A parsed node.
-See
-.Sx Abstract Syntax Tree
-for details.
-.El
-.Ss Functions
-If
-.Fn man_addeqn ,
-.Fn man_addspan ,
-.Fn man_parseln ,
-or
-.Fn man_endparse
-return 0, calls to any function but
-.Fn man_reset
-or
-.Fn man_free
-will raise an assertion.
-.Bl -ohang
-.It Fn man_addeqn
-Add an equation to the parsing stream.
-Returns 0 on failure, 1 on success.
-.It Fn man_addspan
-Add a table span to the parsing stream.
-Returns 0 on failure, 1 on success.
-.It Fn man_alloc
-Allocates a parsing structure.
-The
-.Fa data
-pointer is passed to
-.Fa msgs .
-Always returns a valid pointer.
-The pointer must be freed with
-.Fn man_free .
-.It Fn man_reset
-Reset the parser for another parse routine.
-After its use,
-.Fn man_parseln
-behaves as if invoked for the first time.
-.It Fn man_free
-Free all resources of a parser.
-The pointer is no longer valid after invocation.
-.It Fn man_parseln
-Parse a nil-terminated line of input.
-This line should not contain the trailing newline.
-Returns 0 on failure, 1 on success.
-The input buffer
-.Fa buf
-is modified by this function.
-.It Fn man_endparse
-Signals that the parse is complete.
-Returns 0 on failure, 1 on success.
-.It Fn man_node
-Returns the first node of the parse.
-.It Fn man_meta
-Returns the document's parsed meta-data.
-.El
-.Ss Variables
-The following variables are also defined:
-.Bl -ohang
-.It Va man_macronames
-An array of string-ified token names.
-.El
-.Ss Abstract Syntax Tree
-The
-.Nm
-functions produce an abstract syntax tree (AST) describing input in a
-regular form.
-It may be reviewed at any time with
-.Fn man_nodes ;
-however, if called before
-.Fn man_endparse ,
-or after
-.Fn man_endparse
-or
-.Fn man_parseln
-fail, it may be incomplete.
-.Pp
-This AST is governed by the ontological rules dictated in
-.Xr man 7
-and derives its terminology accordingly.
-.Pp
-The AST is composed of
-.Vt struct man_node
-nodes with element, root and text types as declared by the
-.Va type
-field.
-Each node also provides its parse point (the
-.Va line ,
-.Va sec ,
-and
-.Va pos
-fields), its position in the tree (the
-.Va parent ,
-.Va child ,
-.Va next
-and
-.Va prev
-fields) and some type-specific data.
-.Pp
-The tree itself is arranged according to the following normal form,
-where capitalised non-terminals represent nodes.
-.Pp
-.Bl -tag -width "ELEMENTXX" -compact
-.It ROOT
-\(<- mnode+
-.It mnode
-\(<- ELEMENT | TEXT | BLOCK
-.It BLOCK
-\(<- HEAD BODY
-.It HEAD
-\(<- mnode*
-.It BODY
-\(<- mnode*
-.It ELEMENT
-\(<- ELEMENT | TEXT*
-.It TEXT
-\(<- [[:alpha:]]*
-.El
-.Pp
-The only elements capable of nesting other elements are those with
-next-lint scope as documented in
-.Xr man 7 .
-.Sh EXAMPLES
-The following example reads lines from stdin and parses them, operating
-on the finished parse tree with
-.Fn parsed .
-This example does not error-check nor free memory upon failure.
-.Bd -literal -offset indent
-struct regset regs;
-struct man *man;
-struct man_node *node;
-char *buf;
-size_t len;
-int line;
-
-bzero(&regs, sizeof(struct regset));
-line = 1;
-man = man_alloc(&regs, NULL, NULL);
-buf = NULL;
-alloc_len = 0;
-
-while ((len = getline(&buf, &alloc_len, stdin)) >= 0) {
- if (len && buflen[len - 1] = '\en')
- buf[len - 1] = '\e0';
- if ( ! man_parseln(man, line, buf))
- errx(1, "man_parseln");
- line++;
-}
-
-free(buf);
-
-if ( ! man_endparse(man))
- errx(1, "man_endparse");
-if (NULL == (node = man_node(man)))
- errx(1, "man_node");
-
-parsed(man, node);
-man_free(man);
-.Ed
-.Pp
-To compile this, execute
-.Pp
-.Dl % cc main.c libman.a libmandoc.a
-.Pp
-where
-.Pa main.c
-is the example file.
-.Sh SEE ALSO
-.Xr mandoc 1 ,
-.Xr man 7
-.Sh AUTHORS
-The
-.Nm
-library was written by
-.An Kristaps Dzonsons Aq kristaps@bsd.lv .
diff --git a/usr.bin/mandoc/man.c b/usr.bin/mandoc/man.c
index b7c14eb7a15..e0d4bb26ddb 100644
--- a/usr.bin/mandoc/man.c
+++ b/usr.bin/mandoc/man.c
@@ -1,4 +1,4 @@
-/* $Id: man.c,v 1.58 2011/04/21 22:59:54 schwarze Exp $ */
+/* $Id: man.c,v 1.59 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -22,6 +22,7 @@
#include <stdio.h>
#include <string.h>
+#include "man.h"
#include "mandoc.h"
#include "libman.h"
#include "libmandoc.h"
@@ -91,15 +92,14 @@ man_free(struct man *man)
struct man *
-man_alloc(struct regset *regs, void *data, mandocmsg msg)
+man_alloc(struct regset *regs, struct mparse *parse)
{
struct man *p;
p = mandoc_calloc(1, sizeof(struct man));
man_hash_init();
- p->data = data;
- p->msg = msg;
+ p->parse = parse;
p->regs = regs;
man_alloc1(p);
@@ -126,7 +126,8 @@ man_parseln(struct man *m, int ln, char *buf, int offs)
m->flags |= MAN_NEWLINE;
assert( ! (MAN_HALT & m->flags));
- return(('.' == buf[offs] || '\'' == buf[offs]) ?
+
+ return (mandoc_getcontrol(buf, &offs) ?
man_pmacro(m, ln, buf, offs) :
man_ptext(m, ln, buf, offs));
}
@@ -199,6 +200,10 @@ man_node_append(struct man *man, struct man_node *p)
assert(MAN_BLOCK == p->parent->type);
p->parent->head = p;
break;
+ case (MAN_TAIL):
+ assert(MAN_BLOCK == p->parent->type);
+ p->parent->tail = p;
+ break;
case (MAN_BODY):
assert(MAN_BLOCK == p->parent->type);
p->parent->body = p;
@@ -257,6 +262,19 @@ man_elem_alloc(struct man *m, int line, int pos, enum mant tok)
int
+man_tail_alloc(struct man *m, int line, int pos, enum mant tok)
+{
+ struct man_node *p;
+
+ p = man_node_alloc(m, line, pos, MAN_TAIL, tok);
+ if ( ! man_node_append(m, p))
+ return(0);
+ m->next = MAN_NEXT_CHILD;
+ return(1);
+}
+
+
+int
man_head_alloc(struct man *m, int line, int pos, enum mant tok)
{
struct man_node *p;
@@ -400,21 +418,11 @@ man_descope(struct man *m, int line, int offs)
return(man_body_alloc(m, line, offs, m->last->tok));
}
-
static int
man_ptext(struct man *m, int line, char *buf, int offs)
{
int i;
- /* Ignore bogus comments. */
-
- if ('\\' == buf[offs] &&
- '.' == buf[offs + 1] &&
- '"' == buf[offs + 2]) {
- man_pmsg(m, line, offs, MANDOCERR_BADCOMMENT);
- return(1);
- }
-
/* Literal free-form text whitespace is preserved. */
if (MAN_LITERAL & m->flags) {
@@ -472,67 +480,54 @@ man_ptext(struct man *m, int line, char *buf, int offs)
return(man_descope(m, line, offs));
}
-
static int
man_pmacro(struct man *m, int ln, char *buf, int offs)
{
- int i, j, ppos;
+ int i, ppos;
enum mant tok;
char mac[5];
struct man_node *n;
- /* Comments and empties are quickly ignored. */
-
- offs++;
-
- if ('\0' == buf[offs])
+ if ('"' == buf[offs]) {
+ man_pmsg(m, ln, offs, MANDOCERR_BADCOMMENT);
+ return(1);
+ } else if ('\0' == buf[offs])
return(1);
- i = offs;
-
- /*
- * Skip whitespace between the control character and initial
- * text. "Whitespace" is both spaces and tabs.
- */
-
- if (' ' == buf[i] || '\t' == buf[i]) {
- i++;
- while (buf[i] && (' ' == buf[i] || '\t' == buf[i]))
- i++;
- if ('\0' == buf[i])
- goto out;
- }
-
- ppos = i;
+ ppos = offs;
/*
* Copy the first word into a nil-terminated buffer.
* Stop copying when a tab, space, or eoln is encountered.
*/
- j = 0;
- while (j < 4 && '\0' != buf[i] && ' ' != buf[i] && '\t' != buf[i])
- mac[j++] = buf[i++];
- mac[j] = '\0';
+ i = 0;
+ while (i < 4 && '\0' != buf[offs] &&
+ ' ' != buf[offs] && '\t' != buf[offs])
+ mac[i++] = buf[offs++];
+
+ mac[i] = '\0';
+
+ tok = (i > 0 && i < 4) ? man_hash_find(mac) : MAN_MAX;
- tok = (j > 0 && j < 4) ? man_hash_find(mac) : MAN_MAX;
if (MAN_MAX == tok) {
- man_vmsg(m, MANDOCERR_MACRO, ln, ppos, "%s", buf + ppos - 1);
+ mandoc_vmsg(MANDOCERR_MACRO, m->parse, ln,
+ ppos, "%s", buf + ppos - 1);
return(1);
}
/* The macro is sane. Jump to the next word. */
- while (buf[i] && ' ' == buf[i])
- i++;
+ while (buf[offs] && ' ' == buf[offs])
+ offs++;
/*
* Trailing whitespace. Note that tabs are allowed to be passed
* into the parser as "text", so we only warn about spaces here.
*/
- if ('\0' == buf[i] && ' ' == buf[i - 1])
- man_pmsg(m, ln, i - 1, MANDOCERR_EOLNSPACE);
+ if ('\0' == buf[offs] && ' ' == buf[offs - 1])
+ man_pmsg(m, ln, offs - 1, MANDOCERR_EOLNSPACE);
/*
* Remove prior ELINE macro, as it's being clobbered by a new
@@ -550,8 +545,8 @@ man_pmacro(struct man *m, int ln, char *buf, int offs)
if (MAN_NSCOPED & man_macros[n->tok].flags)
n = n->parent;
- man_vmsg(m, MANDOCERR_LINESCOPE, n->line, n->pos,
- "%s", man_macronames[n->tok]);
+ mandoc_vmsg(MANDOCERR_LINESCOPE, m->parse, n->line,
+ n->pos, "%s", man_macronames[n->tok]);
man_node_delete(m, n);
m->flags &= ~MAN_ELINE;
@@ -569,10 +564,9 @@ man_pmacro(struct man *m, int ln, char *buf, int offs)
/* Call to handler... */
assert(man_macros[tok].fp);
- if ( ! (*man_macros[tok].fp)(m, tok, ln, ppos, &i, buf))
+ if ( ! (*man_macros[tok].fp)(m, tok, ln, ppos, &offs, buf))
goto err;
-out:
/*
* We weren't in a block-line scope when entering the
* above-parsed macro, so return.
@@ -609,7 +603,7 @@ out:
if ( ! man_unscope(m, m->last->parent, MANDOCERR_MAX))
return(0);
- return(man_body_alloc(m, ln, offs, m->last->tok));
+ return(man_body_alloc(m, ln, ppos, m->last->tok));
err: /* Error out. */
@@ -617,21 +611,6 @@ err: /* Error out. */
return(0);
}
-
-void
-man_vmsg(struct man *man, enum mandocerr t,
- int ln, int pos, const char *fmt, ...)
-{
- char buf[256];
- va_list ap;
-
- va_start(ap, fmt);
- vsnprintf(buf, sizeof(buf) - 1, fmt, ap);
- va_end(ap);
- (*man->msg)(t, man->data, ln, pos, buf);
-}
-
-
/*
* Unlink a node from its context. If "m" is provided, the last parse
* point will also be adjusted accordingly.
diff --git a/usr.bin/mandoc/man.h b/usr.bin/mandoc/man.h
index ff0912ceb3c..4595ec66fec 100644
--- a/usr.bin/mandoc/man.h
+++ b/usr.bin/mandoc/man.h
@@ -1,4 +1,4 @@
-/* $Id: man.h,v 1.36 2011/03/20 23:36:42 schwarze Exp $ */
+/* $Id: man.h,v 1.37 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -17,9 +17,6 @@
#ifndef MAN_H
#define MAN_H
-/*
- * What follows is a list of ALL possible macros.
- */
enum mant {
MAN_br = 0,
MAN_TH,
@@ -57,9 +54,6 @@ enum mant {
MAN_MAX
};
-/*
- * Type of a syntax node.
- */
enum man_type {
MAN_TEXT,
MAN_ELEM,
@@ -67,13 +61,11 @@ enum man_type {
MAN_BLOCK,
MAN_HEAD,
MAN_BODY,
+ MAN_TAIL,
MAN_TBL,
MAN_EQN
};
-/*
- * Information from prologue.
- */
struct man_meta {
char *msec; /* `TH' section (1, 3p, etc.) */
char *date; /* `TH' normalised date */
@@ -82,9 +74,6 @@ struct man_meta {
char *source; /* `TH' source (e.g., GNU) */
};
-/*
- * Single node in tree-linked AST.
- */
struct man_node {
struct man_node *parent; /* parent AST node */
struct man_node *child; /* first child AST node */
@@ -101,30 +90,19 @@ struct man_node {
enum man_type type; /* AST node type */
char *string; /* TEXT node argument */
struct man_node *head; /* BLOCK node HEAD ptr */
+ struct man_node *tail; /* BLOCK node TAIL ptr */
struct man_node *body; /* BLOCK node BODY ptr */
const struct tbl_span *span; /* TBL */
const struct eqn *eqn; /* EQN */
};
-/*
- * Names of macros. Index is enum mant. Indexing into this returns
- * the normalised name, e.g., man_macronames[MAN_SH] -> "SH".
- */
+/* Names of macros. Index is enum mant. */
extern const char *const *man_macronames;
__BEGIN_DECLS
struct man;
-void man_free(struct man *);
-struct man *man_alloc(struct regset *, void *, mandocmsg);
-void man_reset(struct man *);
-int man_parseln(struct man *, int, char *, int);
-int man_endparse(struct man *);
-int man_addspan(struct man *,
- const struct tbl_span *);
-int man_addeqn(struct man *, const struct eqn *);
-
const struct man_node *man_node(const struct man *);
const struct man_meta *man_meta(const struct man *);
diff --git a/usr.bin/mandoc/man_argv.c b/usr.bin/mandoc/man_argv.c
deleted file mode 100644
index 25271da7a04..00000000000
--- a/usr.bin/mandoc/man_argv.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/* $Id: man_argv.c,v 1.4 2011/01/03 22:27:21 schwarze Exp $ */
-/*
- * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
- *
- * 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.
- */
-#include <sys/types.h>
-
-#include <assert.h>
-
-#include "mandoc.h"
-#include "libman.h"
-#include "libmandoc.h"
-
-
-int
-man_args(struct man *m, int line, int *pos, char *buf, char **v)
-{
- char *start;
-
- assert(*pos);
- *v = start = buf + *pos;
- assert(' ' != *start);
-
- if ('\0' == *start)
- return(ARGS_EOLN);
-
- *v = mandoc_getarg(v, m->msg, m->data, line, pos);
- return('"' == *start ? ARGS_QWORD : ARGS_WORD);
-}
diff --git a/usr.bin/mandoc/man_hash.c b/usr.bin/mandoc/man_hash.c
index 4397c552281..181da30ecf6 100644
--- a/usr.bin/mandoc/man_hash.c
+++ b/usr.bin/mandoc/man_hash.c
@@ -1,4 +1,4 @@
-/* $Id: man_hash.c,v 1.13 2010/07/31 23:42:04 schwarze Exp $ */
+/* $Id: man_hash.c,v 1.14 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -22,6 +22,7 @@
#include <stdlib.h>
#include <string.h>
+#include "man.h"
#include "mandoc.h"
#include "libman.h"
diff --git a/usr.bin/mandoc/man_macro.c b/usr.bin/mandoc/man_macro.c
index a5ad1d12447..1cebacca44b 100644
--- a/usr.bin/mandoc/man_macro.c
+++ b/usr.bin/mandoc/man_macro.c
@@ -1,6 +1,6 @@
-/* $Id: man_macro.c,v 1.28 2011/04/21 22:59:54 schwarze Exp $ */
+/* $Id: man_macro.c,v 1.29 2011/04/24 16:22:02 schwarze Exp $ */
/*
- * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -19,7 +19,9 @@
#include <stdlib.h>
#include <string.h>
+#include "man.h"
#include "mandoc.h"
+#include "libmandoc.h"
#include "libman.h"
enum rew {
@@ -32,6 +34,8 @@ static int blk_close(MACRO_PROT_ARGS);
static int blk_exp(MACRO_PROT_ARGS);
static int blk_imp(MACRO_PROT_ARGS);
static int in_line_eoln(MACRO_PROT_ARGS);
+static int man_args(struct man *, int,
+ int *, char *, char **);
static int rew_scope(enum man_type,
struct man *, enum mant);
@@ -290,7 +294,7 @@ blk_close(MACRO_PROT_ARGS)
int
blk_exp(MACRO_PROT_ARGS)
{
- int w, la;
+ int la;
char *p;
/*
@@ -311,13 +315,8 @@ blk_exp(MACRO_PROT_ARGS)
for (;;) {
la = *pos;
- w = man_args(m, line, pos, buf, &p);
-
- if (-1 == w)
- return(0);
- if (0 == w)
+ if ( ! man_args(m, line, pos, buf, &p))
break;
-
if ( ! man_word_alloc(m, line, la, p))
return(0);
}
@@ -342,7 +341,7 @@ blk_exp(MACRO_PROT_ARGS)
int
blk_imp(MACRO_PROT_ARGS)
{
- int w, la;
+ int la;
char *p;
struct man_node *n;
@@ -366,13 +365,8 @@ blk_imp(MACRO_PROT_ARGS)
for (;;) {
la = *pos;
- w = man_args(m, line, pos, buf, &p);
-
- if (-1 == w)
- return(0);
- if (0 == w)
+ if ( ! man_args(m, line, pos, buf, &p))
break;
-
if ( ! man_word_alloc(m, line, la, p))
return(0);
}
@@ -400,7 +394,7 @@ blk_imp(MACRO_PROT_ARGS)
int
in_line_eoln(MACRO_PROT_ARGS)
{
- int w, la;
+ int la;
char *p;
struct man_node *n;
@@ -411,11 +405,7 @@ in_line_eoln(MACRO_PROT_ARGS)
for (;;) {
la = *pos;
- w = man_args(m, line, pos, buf, &p);
-
- if (-1 == w)
- return(0);
- if (0 == w)
+ if ( ! man_args(m, line, pos, buf, &p))
break;
if ( ! man_word_alloc(m, line, la, p))
return(0);
@@ -478,3 +468,18 @@ man_macroend(struct man *m)
return(man_unscope(m, m->first, MANDOCERR_SCOPEEXIT));
}
+static int
+man_args(struct man *m, int line, int *pos, char *buf, char **v)
+{
+ char *start;
+
+ assert(*pos);
+ *v = start = buf + *pos;
+ assert(' ' != *start);
+
+ if ('\0' == *start)
+ return(0);
+
+ *v = mandoc_getarg(m->parse, v, line, pos);
+ return(1);
+}
diff --git a/usr.bin/mandoc/man_term.c b/usr.bin/mandoc/man_term.c
index 131580d4c9b..ab5c37bd86f 100644
--- a/usr.bin/mandoc/man_term.c
+++ b/usr.bin/mandoc/man_term.c
@@ -1,4 +1,4 @@
-/* $Id: man_term.c,v 1.66 2011/03/20 23:36:42 schwarze Exp $ */
+/* $Id: man_term.c,v 1.67 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -27,7 +27,6 @@
#include "out.h"
#include "man.h"
#include "term.h"
-#include "chars.h"
#include "main.h"
#define INDENT 7
diff --git a/usr.bin/mandoc/man_validate.c b/usr.bin/mandoc/man_validate.c
index ca981467cfe..c062c60905e 100644
--- a/usr.bin/mandoc/man_validate.c
+++ b/usr.bin/mandoc/man_validate.c
@@ -1,4 +1,4 @@
-/* $Id: man_validate.c,v 1.43 2011/04/21 22:59:54 schwarze Exp $ */
+/* $Id: man_validate.c,v 1.44 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
@@ -26,6 +26,7 @@
#include <string.h>
#include <time.h>
+#include "man.h"
#include "mandoc.h"
#include "libman.h"
#include "libmandoc.h"
@@ -192,8 +193,8 @@ check_root(CHKARGS)
m->meta.title = mandoc_strdup("unknown");
m->meta.msec = mandoc_strdup("1");
- m->meta.date = mandoc_normdate(NULL,
- m->msg, m->data, n->line, n->pos);
+ m->meta.date = mandoc_normdate
+ (m->parse, NULL, n->line, n->pos);
}
return(1);
@@ -243,7 +244,7 @@ check_##name(CHKARGS) \
{ \
if (n->nchild ineq (x)) \
return(1); \
- man_vmsg(m, MANDOCERR_ARGCOUNT, n->line, n->pos, \
+ mandoc_vmsg(MANDOCERR_ARGCOUNT, m->parse, n->line, n->pos, \
"line arguments %s %d (have %d)", \
#ineq, (x), n->nchild); \
return(1); \
@@ -295,14 +296,17 @@ check_ft(CHKARGS)
}
if (0 == ok) {
- man_vmsg(m, MANDOCERR_BADFONT,
- n->line, n->pos, "%s", cp);
+ mandoc_vmsg
+ (MANDOCERR_BADFONT, m->parse,
+ n->line, n->pos, "%s", cp);
*cp = '\0';
}
if (1 < n->nchild)
- man_vmsg(m, MANDOCERR_ARGCOUNT, n->line, n->pos,
- "want one child (have %d)", n->nchild);
+ mandoc_vmsg
+ (MANDOCERR_ARGCOUNT, m->parse, n->line,
+ n->pos, "want one child (have %d)",
+ n->nchild);
return(1);
}
@@ -311,13 +315,11 @@ static int
check_sec(CHKARGS)
{
- if (MAN_HEAD == n->type && 0 == n->nchild) {
- man_nmsg(m, n, MANDOCERR_SYNTARGCOUNT);
- return(0);
- } else if (MAN_BODY == n->type && 0 == n->nchild)
- man_nmsg(m, n, MANDOCERR_NOBODY);
+ if ( ! (MAN_HEAD == n->type && 0 == n->nchild))
+ return(1);
- return(1);
+ man_nmsg(m, n, MANDOCERR_SYNTARGCOUNT);
+ return(0);
}
@@ -326,7 +328,8 @@ check_part(CHKARGS)
{
if (MAN_BODY == n->type && 0 == n->nchild)
- man_nmsg(m, n, MANDOCERR_NOBODY);
+ mandoc_msg(MANDOCERR_ARGCWARN, m->parse, n->line,
+ n->pos, "want children (have none)");
return(1);
}
@@ -422,8 +425,8 @@ post_TH(CHKARGS)
n = n->next;
if (n)
pos = n->pos;
- m->meta.date = mandoc_normdate(n ? n->string : NULL,
- m->msg, m->data, line, pos);
+ m->meta.date = mandoc_normdate
+ (m->parse, n ? n->string : NULL, line, pos);
/* TITLE MSEC DATE ->SOURCE<- VOL */
diff --git a/usr.bin/mandoc/mandoc.c b/usr.bin/mandoc/mandoc.c
index d694cb56107..931ce863017 100644
--- a/usr.bin/mandoc/mandoc.c
+++ b/usr.bin/mandoc/mandoc.c
@@ -1,4 +1,4 @@
-/* $Id: mandoc.c,v 1.24 2011/04/21 22:59:54 schwarze Exp $ */
+/* $Id: mandoc.c,v 1.25 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -292,7 +292,7 @@ mandoc_strdup(const char *ptr)
* or to the null byte terminating the argument line.
*/
char *
-mandoc_getarg(char **cpp, mandocmsg msg, void *data, int ln, int *pos)
+mandoc_getarg(struct mparse *parse, char **cpp, int ln, int *pos)
{
char *start, *cp;
int quoted, pairs, white;
@@ -339,8 +339,8 @@ mandoc_getarg(char **cpp, mandocmsg msg, void *data, int ln, int *pos)
}
/* Quoted argument without a closing quote. */
- if (1 == quoted && msg)
- (*msg)(MANDOCERR_BADQUOTE, data, ln, *pos, NULL);
+ if (1 == quoted)
+ mandoc_msg(MANDOCERR_BADQUOTE, parse, ln, *pos, NULL);
/* Null-terminate this argument and move to the next one. */
if (pairs)
@@ -353,8 +353,8 @@ mandoc_getarg(char **cpp, mandocmsg msg, void *data, int ln, int *pos)
*pos += (int)(cp - start) + (quoted ? 1 : 0);
*cpp = cp;
- if ('\0' == *cp && msg && (white || ' ' == cp[-1]))
- (*msg)(MANDOCERR_EOLNSPACE, data, ln, *pos, NULL);
+ if ('\0' == *cp && (white || ' ' == cp[-1]))
+ mandoc_msg(MANDOCERR_EOLNSPACE, parse, ln, *pos, NULL);
return(start);
}
@@ -412,20 +412,20 @@ fail:
}
char *
-mandoc_normdate(char *in, mandocmsg msg, void *data, int ln, int pos)
+mandoc_normdate(struct mparse *parse, char *in, int ln, int pos)
{
char *out;
time_t t;
if (NULL == in || '\0' == *in ||
0 == strcmp(in, "$" "Mdocdate$")) {
- (*msg)(MANDOCERR_NODATE, data, ln, pos, NULL);
+ mandoc_msg(MANDOCERR_NODATE, parse, ln, pos, NULL);
time(&t);
}
else if (!a2time(&t, "$" "Mdocdate: %b %d %Y $", in) &&
!a2time(&t, "%b %d, %Y", in) &&
!a2time(&t, "%Y-%m-%d", in)) {
- (*msg)(MANDOCERR_BADDATE, data, ln, pos, NULL);
+ mandoc_msg(MANDOCERR_BADDATE, parse, ln, pos, NULL);
t = 0;
}
out = t ? time2a(t) : NULL;
@@ -503,52 +503,27 @@ mandoc_hyph(const char *start, const char *c)
}
/*
- * Check if a string is a punctuation delimiter. This only applies to
- * mdoc(7) documents, but as it's used in both front-ends and back-ends,
- * it needs to go here (instead of, say, in libmdoc.h).
+ * Find out whether a line is a macro line or not. If it is, adjust the
+ * current position and return one; if it isn't, return zero and don't
+ * change the current position.
*/
-enum mdelim
-mandoc_isdelim(const char *p)
+int
+mandoc_getcontrol(const char *cp, int *ppos)
{
+ int pos;
- if ('\0' == p[0])
- return(DELIM_NONE);
-
- if ('\0' == p[1])
- switch (p[0]) {
- case('('):
- /* FALLTHROUGH */
- case('['):
- return(DELIM_OPEN);
- case('|'):
- return(DELIM_MIDDLE);
- case('.'):
- /* FALLTHROUGH */
- case(','):
- /* FALLTHROUGH */
- case(';'):
- /* FALLTHROUGH */
- case(':'):
- /* FALLTHROUGH */
- case('?'):
- /* FALLTHROUGH */
- case('!'):
- /* FALLTHROUGH */
- case(')'):
- /* FALLTHROUGH */
- case(']'):
- return(DELIM_CLOSE);
- default:
- return(DELIM_NONE);
- }
+ pos = *ppos;
- if ('\\' != p[0])
- return(DELIM_NONE);
+ if ('\\' == cp[pos] && '.' == cp[pos + 1])
+ pos += 2;
+ else if ('.' == cp[pos] || '\'' == cp[pos])
+ pos++;
+ else
+ return(0);
- if (0 == strcmp(p + 1, "."))
- return(DELIM_CLOSE);
- if (0 == strcmp(p + 1, "*(Ba"))
- return(DELIM_MIDDLE);
+ while (' ' == cp[pos] || '\t' == cp[pos])
+ pos++;
- return(DELIM_NONE);
+ *ppos = pos;
+ return(1);
}
diff --git a/usr.bin/mandoc/mandoc.h b/usr.bin/mandoc/mandoc.h
index 02964787deb..70999ca7149 100644
--- a/usr.bin/mandoc/mandoc.h
+++ b/usr.bin/mandoc/mandoc.h
@@ -1,4 +1,4 @@
-/* $Id: mandoc.h,v 1.36 2011/04/21 22:59:54 schwarze Exp $ */
+/* $Id: mandoc.h,v 1.37 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -74,6 +74,7 @@ enum mandocerr {
MANDOCERR_CHILD, /* child violates parent syntax */
MANDOCERR_NESTEDDISP, /* nested displays are not portable */
MANDOCERR_SCOPEREP, /* already in literal mode */
+ MANDOCERR_LINESCOPE, /* line scope broken */
/* related to missing macro arguments */
MANDOCERR_MACROEMPTY, /* skipping empty macro */
@@ -121,7 +122,6 @@ enum mandocerr {
MANDOCERR_NOTEXT, /* skipping text before the first section header */
MANDOCERR_MACRO, /* skipping unknown macro */
MANDOCERR_REQUEST, /* NOT IMPLEMENTED: skipping request */
- MANDOCERR_LINESCOPE, /* line scope broken */
MANDOCERR_ARGCOUNT, /* argument count wrong */
MANDOCERR_NOSCOPE, /* skipping end of block that is not open */
MANDOCERR_SCOPEBROKEN, /* missing end of block */
@@ -137,6 +137,7 @@ enum mandocerr {
MANDOCERR_FATAL, /* ===== start of fatal errors ===== */
+ MANDOCERR_NOTMANUAL, /* manual isn't really a manual */
MANDOCERR_COLUMNS, /* column syntax is inconsistent */
MANDOCERR_BADDISP, /* NOT IMPLEMENTED: .Bd -file */
MANDOCERR_SYNTLINESCOPE, /* line scope broken, syntax violated */
@@ -277,67 +278,37 @@ struct eqn {
};
/*
- * Available registers (set in libroff, accessed elsewhere).
- */
-enum regs {
- REG_nS = 0,
- REG__MAX
-};
-
-/*
- * A register (struct reg) can consist of many types: this consists of
- * normalised types from the original string form.
- */
-union regval {
- unsigned u; /* unsigned integer */
-};
-
-/*
- * A single register entity. If "set" is zero, the value of the
- * register should be the default one, which is per-register. It's
- * assumed that callers know which type in "v" corresponds to which
- * register value.
+ * The type of parse sequence. This value is usually passed via the
+ * mandoc(1) command line of -man and -mdoc. It's almost exclusively
+ * -mandoc but the others have been retained for compatibility.
*/
-struct reg {
- int set; /* whether set or not */
- union regval v; /* parsed data */
+enum mparset {
+ MPARSE_AUTO, /* magically determine the document type */
+ MPARSE_MDOC, /* assume -mdoc */
+ MPARSE_MAN /* assume -man */
};
-/*
- * The primary interface to setting register values is in libroff,
- * although libmdoc and libman from time to time will manipulate
- * registers (such as `.Sh SYNOPSIS' enabling REG_nS).
- */
-struct regset {
- struct reg regs[REG__MAX];
-};
+typedef void (*mandocmsg)(enum mandocerr, enum mandoclevel,
+ const char *, int, int, const char *);
-/*
- * A punctuation delimiter, used only in mdoc(7) documents, is opening,
- * closing, or "middle mark" punctuation. These govern spacing.
- * Opening punctuation (e.g., the opening parenthesis) suppresses the
- * following space; closing punctuation (e.g., the closing parenthesis)
- * suppresses the leading space; middle punctuation (e.g., the vertical
- * bar) can do either. The middle punctuation delimiter bends the rules
- * depending on usage.
- */
-enum mdelim {
- DELIM_NONE = 0,
- DELIM_OPEN,
- DELIM_MIDDLE,
- DELIM_CLOSE
-};
-
-typedef void (*mandocmsg)(enum mandocerr, void *,
- int, int, const char *);
+struct mparse;
+struct mdoc;
+struct man;
__BEGIN_DECLS
+void mparse_free(struct mparse *);
+void mparse_reset(struct mparse *);
+struct mparse *mparse_alloc(enum mparset,
+ enum mandoclevel, mandocmsg, void *);
+enum mandoclevel mparse_readfd(struct mparse *, int, const char *);
+void mparse_result(struct mparse *, struct mdoc **, struct man **);
+const char *mparse_strerror(enum mandocerr);
+const char *mparse_strlevel(enum mandoclevel);
+
void *mandoc_calloc(size_t, size_t);
void *mandoc_malloc(size_t);
void *mandoc_realloc(void *, size_t);
-#define DELIMSZ 6 /* hint: max possible size of a delimiter */
-enum mdelim mandoc_isdelim(const char *);
__END_DECLS
diff --git a/usr.bin/mandoc/mdoc.3 b/usr.bin/mandoc/mdoc.3
deleted file mode 100644
index 24c32ccc380..00000000000
--- a/usr.bin/mandoc/mdoc.3
+++ /dev/null
@@ -1,359 +0,0 @@
-.\" $Id: mdoc.3,v 1.17 2011/03/20 23:36:42 schwarze Exp $
-.\"
-.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
-.\" Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
-.\"
-.\" 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.
-.\"
-.Dd $Mdocdate: March 20 2011 $
-.Dt MDOC 3
-.Os
-.Sh NAME
-.Nm mdoc ,
-.Nm mdoc_addeqn ,
-.Nm mdoc_addspan ,
-.Nm mdoc_alloc ,
-.Nm mdoc_endparse ,
-.Nm mdoc_free ,
-.Nm mdoc_meta ,
-.Nm mdoc_node ,
-.Nm mdoc_parseln ,
-.Nm mdoc_reset
-.Nd mdoc macro compiler library
-.Sh SYNOPSIS
-.In mandoc.h
-.In mdoc.h
-.Vt extern const char * const * mdoc_macronames;
-.Vt extern const char * const * mdoc_argnames;
-.Ft int
-.Fo mdoc_addeqn
-.Fa "struct mdoc *mdoc"
-.Fa "const struct eqn *eqn"
-.Fc
-.Ft int
-.Fo mdoc_addspan
-.Fa "struct mdoc *mdoc"
-.Fa "const struct tbl_span *span"
-.Fc
-.Ft "struct mdoc *"
-.Fo mdoc_alloc
-.Fa "struct regset *regs"
-.Fa "void *data"
-.Fa "mandocmsg msgs"
-.Fc
-.Ft int
-.Fn mdoc_endparse "struct mdoc *mdoc"
-.Ft void
-.Fn mdoc_free "struct mdoc *mdoc"
-.Ft "const struct mdoc_meta *"
-.Fn mdoc_meta "const struct mdoc *mdoc"
-.Ft "const struct mdoc_node *"
-.Fn mdoc_node "const struct mdoc *mdoc"
-.Ft int
-.Fo mdoc_parseln
-.Fa "struct mdoc *mdoc"
-.Fa "int line"
-.Fa "char *buf"
-.Fc
-.Ft int
-.Fn mdoc_reset "struct mdoc *mdoc"
-.Sh DESCRIPTION
-The
-.Nm mdoc
-library parses lines of
-.Xr mdoc 7
-input
-into an abstract syntax tree (AST).
-.Pp
-In general, applications initiate a parsing sequence with
-.Fn mdoc_alloc ,
-parse each line in a document with
-.Fn mdoc_parseln ,
-close the parsing session with
-.Fn mdoc_endparse ,
-operate over the syntax tree returned by
-.Fn mdoc_node
-and
-.Fn mdoc_meta ,
-then free all allocated memory with
-.Fn mdoc_free .
-The
-.Fn mdoc_reset
-function may be used in order to reset the parser for another input
-sequence.
-.Ss Types
-.Bl -ohang
-.It Vt struct mdoc
-An opaque type.
-Its values are only used privately within the library.
-.It Vt struct mdoc_node
-A parsed node.
-See
-.Sx Abstract Syntax Tree
-for details.
-.El
-.Ss Functions
-If
-.Fn mdoc_addeqn ,
-.Fn mdoc_addspan ,
-.Fn mdoc_parseln ,
-or
-.Fn mdoc_endparse
-return 0, calls to any function but
-.Fn mdoc_reset
-or
-.Fn mdoc_free
-will raise an assertion.
-.Bl -ohang
-.It Fn mdoc_addeqn
-Add an equation to the parsing stream.
-Returns 0 on failure, 1 on success.
-.It Fn mdoc_addspan
-Add a table span to the parsing stream.
-Returns 0 on failure, 1 on success.
-.It Fn mdoc_alloc
-Allocates a parsing structure.
-The
-.Fa data
-pointer is passed to
-.Fa msgs .
-Always returns a valid pointer.
-The pointer must be freed with
-.Fn mdoc_free .
-.It Fn mdoc_reset
-Reset the parser for another parse routine.
-After its use,
-.Fn mdoc_parseln
-behaves as if invoked for the first time.
-If it returns 0, memory could not be allocated.
-.It Fn mdoc_free
-Free all resources of a parser.
-The pointer is no longer valid after invocation.
-.It Fn mdoc_parseln
-Parse a nil-terminated line of input.
-This line should not contain the trailing newline.
-Returns 0 on failure, 1 on success.
-The input buffer
-.Fa buf
-is modified by this function.
-.It Fn mdoc_endparse
-Signals that the parse is complete.
-Returns 0 on failure, 1 on success.
-.It Fn mdoc_node
-Returns the first node of the parse.
-.It Fn mdoc_meta
-Returns the document's parsed meta-data.
-.El
-.Ss Variables
-.Bl -ohang
-.It Va mdoc_macronames
-An array of string-ified token names.
-.It Va mdoc_argnames
-An array of string-ified token argument names.
-.El
-.Ss Abstract Syntax Tree
-The
-.Nm
-functions produce an abstract syntax tree (AST) describing input in a
-regular form.
-It may be reviewed at any time with
-.Fn mdoc_nodes ;
-however, if called before
-.Fn mdoc_endparse ,
-or after
-.Fn mdoc_endparse
-or
-.Fn mdoc_parseln
-fail, it may be incomplete.
-.Pp
-This AST is governed by the ontological
-rules dictated in
-.Xr mdoc 7
-and derives its terminology accordingly.
-.Qq In-line
-elements described in
-.Xr mdoc 7
-are described simply as
-.Qq elements .
-.Pp
-The AST is composed of
-.Vt struct mdoc_node
-nodes with block, head, body, element, root and text types as declared
-by the
-.Va type
-field.
-Each node also provides its parse point (the
-.Va line ,
-.Va sec ,
-and
-.Va pos
-fields), its position in the tree (the
-.Va parent ,
-.Va child ,
-.Va nchild ,
-.Va next
-and
-.Va prev
-fields) and some type-specific data, in particular, for nodes generated
-from macros, the generating macro in the
-.Va tok
-field.
-.Pp
-The tree itself is arranged according to the following normal form,
-where capitalised non-terminals represent nodes.
-.Pp
-.Bl -tag -width "ELEMENTXX" -compact
-.It ROOT
-\(<- mnode+
-.It mnode
-\(<- BLOCK | ELEMENT | TEXT
-.It BLOCK
-\(<- HEAD [TEXT] (BODY [TEXT])+ [TAIL [TEXT]]
-.It ELEMENT
-\(<- TEXT*
-.It HEAD
-\(<- mnode*
-.It BODY
-\(<- mnode* [ENDBODY mnode*]
-.It TAIL
-\(<- mnode*
-.It TEXT
-\(<- [[:printable:],0x1e]*
-.El
-.Pp
-Of note are the TEXT nodes following the HEAD, BODY and TAIL nodes of
-the BLOCK production: these refer to punctuation marks.
-Furthermore, although a TEXT node will generally have a non-zero-length
-string, in the specific case of
-.Sq \&.Bd \-literal ,
-an empty line will produce a zero-length string.
-Multiple body parts are only found in invocations of
-.Sq \&Bl \-column ,
-where a new body introduces a new phrase.
-.Ss Badly-nested Blocks
-The ENDBODY node is available to end the formatting associated
-with a given block before the physical end of that block.
-It has a non-null
-.Va end
-field, is of the BODY
-.Va type ,
-has the same
-.Va tok
-as the BLOCK it is ending, and has a
-.Va pending
-field pointing to that BLOCK's BODY node.
-It is an indirect child of that BODY node
-and has no children of its own.
-.Pp
-An ENDBODY node is generated when a block ends while one of its child
-blocks is still open, like in the following example:
-.Bd -literal -offset indent
-\&.Ao ao
-\&.Bo bo ac
-\&.Ac bc
-\&.Bc end
-.Ed
-.Pp
-This example results in the following block structure:
-.Bd -literal -offset indent
-BLOCK Ao
- HEAD Ao
- BODY Ao
- TEXT ao
- BLOCK Bo, pending -> Ao
- HEAD Bo
- BODY Bo
- TEXT bo
- TEXT ac
- ENDBODY Ao, pending -> Ao
- TEXT bc
-TEXT end
-.Ed
-.Pp
-Here, the formatting of the
-.Sq \&Ao
-block extends from TEXT ao to TEXT ac,
-while the formatting of the
-.Sq \&Bo
-block extends from TEXT bo to TEXT bc.
-It renders as follows in
-.Fl T Ns Cm ascii
-mode:
-.Pp
-.Dl <ao [bo ac> bc] end
-.Pp
-Support for badly-nested blocks is only provided for backward
-compatibility with some older
-.Xr mdoc 7
-implementations.
-Using badly-nested blocks is
-.Em strongly discouraged :
-the
-.Fl T Ns Cm html
-and
-.Fl T Ns Cm xhtml
-front-ends are unable to render them in any meaningful way.
-Furthermore, behaviour when encountering badly-nested blocks is not
-consistent across troff implementations, especially when using multiple
-levels of badly-nested blocks.
-.Sh EXAMPLES
-The following example reads lines from stdin and parses them, operating
-on the finished parse tree with
-.Fn parsed .
-This example does not error-check nor free memory upon failure.
-.Bd -literal -offset indent
-struct regset regs;
-struct mdoc *mdoc;
-const struct mdoc_node *node;
-char *buf;
-size_t len;
-int line;
-
-bzero(&regs, sizeof(struct regset));
-line = 1;
-mdoc = mdoc_alloc(&regs, NULL, NULL);
-buf = NULL;
-alloc_len = 0;
-
-while ((len = getline(&buf, &alloc_len, stdin)) >= 0) {
- if (len && buflen[len - 1] = '\en')
- buf[len - 1] = '\e0';
- if ( ! mdoc_parseln(mdoc, line, buf))
- errx(1, "mdoc_parseln");
- line++;
-}
-
-if ( ! mdoc_endparse(mdoc))
- errx(1, "mdoc_endparse");
-if (NULL == (node = mdoc_node(mdoc)))
- errx(1, "mdoc_node");
-
-parsed(mdoc, node);
-mdoc_free(mdoc);
-.Ed
-.Pp
-To compile this, execute
-.Pp
-.Dl % cc main.c libmdoc.a libmandoc.a
-.Pp
-where
-.Pa main.c
-is the example file.
-.Sh SEE ALSO
-.Xr mandoc 1 ,
-.Xr mdoc 7
-.Sh AUTHORS
-The
-.Nm
-library was written by
-.An Kristaps Dzonsons Aq kristaps@bsd.lv .
diff --git a/usr.bin/mandoc/mdoc.c b/usr.bin/mandoc/mdoc.c
index 77e91ad23dc..c63a93a3130 100644
--- a/usr.bin/mandoc/mdoc.c
+++ b/usr.bin/mandoc/mdoc.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc.c,v 1.82 2011/04/21 22:59:54 schwarze Exp $ */
+/* $Id: mdoc.c,v 1.83 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
@@ -24,6 +24,7 @@
#include <string.h>
#include <time.h>
+#include "mdoc.h"
#include "mandoc.h"
#include "libmdoc.h"
#include "libmandoc.h"
@@ -188,14 +189,13 @@ mdoc_free(struct mdoc *mdoc)
* Allocate volatile and non-volatile parse resources.
*/
struct mdoc *
-mdoc_alloc(struct regset *regs, void *data, mandocmsg msg)
+mdoc_alloc(struct regset *regs, struct mparse *parse)
{
struct mdoc *p;
p = mandoc_calloc(1, sizeof(struct mdoc));
- p->msg = msg;
- p->data = data;
+ p->parse = parse;
p->regs = regs;
mdoc_hash_init();
@@ -293,27 +293,11 @@ mdoc_parseln(struct mdoc *m, int ln, char *buf, int offs)
m->flags &= ~MDOC_SYNOPSIS;
}
- return(('.' == buf[offs] || '\'' == buf[offs]) ?
+ return(mandoc_getcontrol(buf, &offs) ?
mdoc_pmacro(m, ln, buf, offs) :
mdoc_ptext(m, ln, buf, offs));
}
-
-void
-mdoc_vmsg(struct mdoc *mdoc, enum mandocerr t,
- int ln, int pos, const char *fmt, ...)
-{
- char buf[256];
- va_list ap;
-
- va_start(ap, fmt);
- vsnprintf(buf, sizeof(buf) - 1, fmt, ap);
- va_end(ap);
-
- (*mdoc->msg)(t, mdoc->data, ln, pos, buf);
-}
-
-
int
mdoc_macro(MACRO_PROT_ARGS)
{
@@ -341,8 +325,8 @@ mdoc_macro(MACRO_PROT_ARGS)
if (NULL == m->meta.os)
m->meta.os = mandoc_strdup("LOCAL");
if (NULL == m->meta.date)
- m->meta.date = mandoc_normdate(NULL,
- m->msg, m->data, line, ppos);
+ m->meta.date = mandoc_normdate
+ (m->parse, NULL, line, ppos);
m->flags |= MDOC_PBODY;
}
@@ -673,15 +657,6 @@ mdoc_ptext(struct mdoc *m, int line, char *buf, int offs)
char *c, *ws, *end;
struct mdoc_node *n;
- /* Ignore bogus comments. */
-
- if ('\\' == buf[offs] &&
- '.' == buf[offs + 1] &&
- '"' == buf[offs + 2]) {
- mdoc_pmsg(m, line, offs, MANDOCERR_BADCOMMENT);
- return(1);
- }
-
/* No text before an initial macro. */
if (SEC_NONE == m->lastnamed) {
@@ -808,64 +783,57 @@ static int
mdoc_pmacro(struct mdoc *m, int ln, char *buf, int offs)
{
enum mdoct tok;
- int i, j, sv;
+ int i, sv;
char mac[5];
struct mdoc_node *n;
- /* Empty lines are ignored. */
+ /* Empty post-control lines are ignored. */
- offs++;
-
- if ('\0' == buf[offs])
+ if ('"' == buf[offs]) {
+ mdoc_pmsg(m, ln, offs, MANDOCERR_BADCOMMENT);
+ return(1);
+ } else if ('\0' == buf[offs])
return(1);
- i = offs;
-
- /* Accept tabs/whitespace after the initial control char. */
-
- if (' ' == buf[i] || '\t' == buf[i]) {
- i++;
- while (buf[i] && (' ' == buf[i] || '\t' == buf[i]))
- i++;
- if ('\0' == buf[i])
- return(1);
- }
-
- sv = i;
+ sv = offs;
/*
* Copy the first word into a nil-terminated buffer.
* Stop copying when a tab, space, or eoln is encountered.
*/
- j = 0;
- while (j < 4 && '\0' != buf[i] && ' ' != buf[i] && '\t' != buf[i])
- mac[j++] = buf[i++];
- mac[j] = '\0';
+ i = 0;
+ while (i < 4 && '\0' != buf[offs] &&
+ ' ' != buf[offs] && '\t' != buf[offs])
+ mac[i++] = buf[offs++];
+
+ mac[i] = '\0';
+
+ tok = (i > 1 || i < 4) ? mdoc_hash_find(mac) : MDOC_MAX;
- tok = (j > 1 || j < 4) ? mdoc_hash_find(mac) : MDOC_MAX;
if (MDOC_MAX == tok) {
- mdoc_vmsg(m, MANDOCERR_MACRO, ln, sv, "%s", buf + sv - 1);
+ mandoc_vmsg(MANDOCERR_MACRO, m->parse,
+ ln, sv, "%s", buf + sv - 1);
return(1);
}
/* Disregard the first trailing tab, if applicable. */
- if ('\t' == buf[i])
- i++;
+ if ('\t' == buf[offs])
+ offs++;
/* Jump to the next non-whitespace word. */
- while (buf[i] && ' ' == buf[i])
- i++;
+ while (buf[offs] && ' ' == buf[offs])
+ offs++;
/*
* Trailing whitespace. Note that tabs are allowed to be passed
* into the parser as "text", so we only warn about spaces here.
*/
- if ('\0' == buf[i] && ' ' == buf[i - 1])
- mdoc_pmsg(m, ln, i - 1, MANDOCERR_EOLNSPACE);
+ if ('\0' == buf[offs] && ' ' == buf[offs - 1])
+ mdoc_pmsg(m, ln, offs - 1, MANDOCERR_EOLNSPACE);
/*
* If an initial macro or a list invocation, divert directly
@@ -873,7 +841,7 @@ mdoc_pmacro(struct mdoc *m, int ln, char *buf, int offs)
*/
if (NULL == m->last || MDOC_It == tok || MDOC_El == tok) {
- if ( ! mdoc_macro(m, tok, ln, sv, &i, buf))
+ if ( ! mdoc_macro(m, tok, ln, sv, &offs, buf))
goto err;
return(1);
}
@@ -912,7 +880,7 @@ mdoc_pmacro(struct mdoc *m, int ln, char *buf, int offs)
/* Normal processing of a macro. */
- if ( ! mdoc_macro(m, tok, ln, sv, &i, buf))
+ if ( ! mdoc_macro(m, tok, ln, sv, &offs, buf))
goto err;
return(1);
@@ -923,4 +891,48 @@ err: /* Error out. */
return(0);
}
+enum mdelim
+mdoc_isdelim(const char *p)
+{
+
+ if ('\0' == p[0])
+ return(DELIM_NONE);
+
+ if ('\0' == p[1])
+ switch (p[0]) {
+ case('('):
+ /* FALLTHROUGH */
+ case('['):
+ return(DELIM_OPEN);
+ case('|'):
+ return(DELIM_MIDDLE);
+ case('.'):
+ /* FALLTHROUGH */
+ case(','):
+ /* FALLTHROUGH */
+ case(';'):
+ /* FALLTHROUGH */
+ case(':'):
+ /* FALLTHROUGH */
+ case('?'):
+ /* FALLTHROUGH */
+ case('!'):
+ /* FALLTHROUGH */
+ case(')'):
+ /* FALLTHROUGH */
+ case(']'):
+ return(DELIM_CLOSE);
+ default:
+ return(DELIM_NONE);
+ }
+
+ if ('\\' != p[0])
+ return(DELIM_NONE);
+ if (0 == strcmp(p + 1, "."))
+ return(DELIM_CLOSE);
+ if (0 == strcmp(p + 1, "*(Ba"))
+ return(DELIM_MIDDLE);
+
+ return(DELIM_NONE);
+}
diff --git a/usr.bin/mandoc/mdoc.h b/usr.bin/mandoc/mdoc.h
index 1ac4ea25db8..ba074cbfc9f 100644
--- a/usr.bin/mandoc/mdoc.h
+++ b/usr.bin/mandoc/mdoc.h
@@ -1,4 +1,4 @@
-/* $Id: mdoc.h,v 1.45 2011/03/20 23:36:42 schwarze Exp $ */
+/* $Id: mdoc.h,v 1.46 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -17,9 +17,6 @@
#ifndef MDOC_H
#define MDOC_H
-/*
- * What follows is a list of ALL possible macros.
- */
enum mdoct {
MDOC_Ap = 0,
MDOC_Dd,
@@ -146,43 +143,37 @@ enum mdoct {
MDOC_MAX
};
-/*
- * What follows is a list of ALL possible macro arguments.
- */
enum mdocargt {
- MDOC_Split,
- MDOC_Nosplit,
- MDOC_Ragged,
- MDOC_Unfilled,
- MDOC_Literal,
- MDOC_File,
- MDOC_Offset,
- MDOC_Bullet,
- MDOC_Dash,
- MDOC_Hyphen,
- MDOC_Item,
- MDOC_Enum,
- MDOC_Tag,
- MDOC_Diag,
- MDOC_Hang,
- MDOC_Ohang,
- MDOC_Inset,
- MDOC_Column,
- MDOC_Width,
- MDOC_Compact,
- MDOC_Std,
- MDOC_Filled,
- MDOC_Words,
- MDOC_Emphasis,
- MDOC_Symbolic,
- MDOC_Nested,
- MDOC_Centred,
+ MDOC_Split, /* -split */
+ MDOC_Nosplit, /* -nospli */
+ MDOC_Ragged, /* -ragged */
+ MDOC_Unfilled, /* -unfilled */
+ MDOC_Literal, /* -literal */
+ MDOC_File, /* -file */
+ MDOC_Offset, /* -offset */
+ MDOC_Bullet, /* -bullet */
+ MDOC_Dash, /* -dash */
+ MDOC_Hyphen, /* -hyphen */
+ MDOC_Item, /* -item */
+ MDOC_Enum, /* -enum */
+ MDOC_Tag, /* -tag */
+ MDOC_Diag, /* -diag */
+ MDOC_Hang, /* -hang */
+ MDOC_Ohang, /* -ohang */
+ MDOC_Inset, /* -inset */
+ MDOC_Column, /* -column */
+ MDOC_Width, /* -width */
+ MDOC_Compact, /* -compact */
+ MDOC_Std, /* -std */
+ MDOC_Filled, /* -filled */
+ MDOC_Words, /* -words */
+ MDOC_Emphasis, /* -emphasis */
+ MDOC_Symbolic, /* -symbolic */
+ MDOC_Nested, /* -nested */
+ MDOC_Centred, /* -centered */
MDOC_ARG_MAX
};
-/*
- * Type of a syntax node.
- */
enum mdoc_type {
MDOC_TEXT,
MDOC_ELEM,
@@ -197,37 +188,36 @@ enum mdoc_type {
/*
* Section (named/unnamed) of `Sh'. Note that these appear in the
- * conventional order imposed by mdoc.7.
+ * conventional order imposed by mdoc.7. In the case of SEC_NONE, no
+ * section has been invoked (this shouldn't happen). SEC_CUSTOM refers
+ * to other sections.
*/
enum mdoc_sec {
- SEC_NONE = 0, /* No section, yet. */
- SEC_NAME,
- SEC_LIBRARY,
- SEC_SYNOPSIS,
- SEC_DESCRIPTION,
- SEC_IMPLEMENTATION,
- SEC_RETURN_VALUES,
- SEC_ENVIRONMENT,
- SEC_FILES,
- SEC_EXIT_STATUS,
- SEC_EXAMPLES,
- SEC_DIAGNOSTICS,
- SEC_COMPATIBILITY,
- SEC_ERRORS,
- SEC_SEE_ALSO,
- SEC_STANDARDS,
- SEC_HISTORY,
- SEC_AUTHORS,
- SEC_CAVEATS,
- SEC_BUGS,
- SEC_SECURITY,
- SEC_CUSTOM, /* User-defined. */
+ SEC_NONE = 0,
+ SEC_NAME, /* NAME */
+ SEC_LIBRARY, /* LIBRARY */
+ SEC_SYNOPSIS, /* SYNOPSIS */
+ SEC_DESCRIPTION, /* DESCRIPTION */
+ SEC_IMPLEMENTATION, /* IMPLEMENTATION NOTES */
+ SEC_RETURN_VALUES, /* RETURN VALUES */
+ SEC_ENVIRONMENT, /* ENVIRONMENT */
+ SEC_FILES, /* FILES */
+ SEC_EXIT_STATUS, /* EXIT STATUS */
+ SEC_EXAMPLES, /* EXAMPLES */
+ SEC_DIAGNOSTICS, /* DIAGNOSTICS */
+ SEC_COMPATIBILITY, /* COMPATIBILITY */
+ SEC_ERRORS, /* ERRORS */
+ SEC_SEE_ALSO, /* SEE ALSO */
+ SEC_STANDARDS, /* STANDARDS */
+ SEC_HISTORY, /* HISTORY */
+ SEC_AUTHORS, /* AUTHORS */
+ SEC_CAVEATS, /* CAVEATS */
+ SEC_BUGS, /* BUGS */
+ SEC_SECURITY, /* SECURITY */
+ SEC_CUSTOM,
SEC__MAX
};
-/*
- * Information from prologue.
- */
struct mdoc_meta {
char *msec; /* `Dt' section (1, 3p, etc.) */
char *vol; /* `Dt' volume (implied) */
@@ -270,68 +260,50 @@ enum mdoc_endbody {
ENDBODY_NOSPACE /* is broken: don't append a space */
};
-/*
- * Normalised `Bl' list type.
- */
enum mdoc_list {
LIST__NONE = 0,
- LIST_bullet,
- LIST_column,
- LIST_dash,
- LIST_diag,
- LIST_enum,
- LIST_hang,
- LIST_hyphen,
- LIST_inset,
- LIST_item,
- LIST_ohang,
- LIST_tag,
+ LIST_bullet, /* -bullet */
+ LIST_column, /* -column */
+ LIST_dash, /* -dash */
+ LIST_diag, /* -diag */
+ LIST_enum, /* -enum */
+ LIST_hang, /* -hang */
+ LIST_hyphen, /* -hyphen */
+ LIST_inset, /* -inset */
+ LIST_item, /* -item */
+ LIST_ohang, /* -ohang */
+ LIST_tag, /* -tag */
LIST_MAX
};
-/*
- * Normalised `Bd' display type.
- */
enum mdoc_disp {
DISP__NONE = 0,
- DISP_centred,
- DISP_ragged,
- DISP_unfilled,
- DISP_filled,
- DISP_literal
+ DISP_centred, /* -centered */
+ DISP_ragged, /* -ragged */
+ DISP_unfilled, /* -unfilled */
+ DISP_filled, /* -filled */
+ DISP_literal /* -literal */
};
-/*
- * Normalised `An' splitting argument.
- */
enum mdoc_auth {
AUTH__NONE = 0,
- AUTH_split,
- AUTH_nosplit
+ AUTH_split, /* -split */
+ AUTH_nosplit /* -nosplit */
};
-/*
- * Normalised `Bf' font type.
- */
enum mdoc_font {
FONT__NONE = 0,
- FONT_Em,
- FONT_Li,
- FONT_Sy
+ FONT_Em, /* Em, -emphasis */
+ FONT_Li, /* Li, -literal */
+ FONT_Sy /* Sy, -symbolic */
};
-/*
- * Normalised arguments for `Bd'.
- */
struct mdoc_bd {
const char *offs; /* -offset */
enum mdoc_disp type; /* -ragged, etc. */
int comp; /* -compact */
};
-/*
- * Normalised arguments for `Bl'.
- */
struct mdoc_bl {
const char *width; /* -width */
const char *offs; /* -offset */
@@ -341,16 +313,10 @@ struct mdoc_bl {
const char **cols; /* -column val ptr */
};
-/*
- * Normalised arguments for `Bf'.
- */
struct mdoc_bf {
enum mdoc_font font; /* font */
};
-/*
- * Normalised arguments for `An'.
- */
struct mdoc_an {
enum mdoc_auth auth; /* -split, etc. */
};
@@ -391,6 +357,8 @@ struct mdoc_node {
#define MDOC_LINE (1 << 3) /* first macro/text on line */
#define MDOC_SYNPRETTY (1 << 4) /* SYNOPSIS-style formatting */
#define MDOC_ENDED (1 << 5) /* rendering has been ended */
+#define MDOC_DELIMO (1 << 6)
+#define MDOC_DELIMC (1 << 7)
enum mdoc_type type; /* AST node type */
enum mdoc_sec sec; /* current named section */
union mdoc_data *norm; /* normalised args */
@@ -406,34 +374,18 @@ struct mdoc_node {
enum mdoc_endbody end; /* BODY */
};
-/*
- * Names of macros. Index is enum mdoct. Indexing into this returns
- * the normalised name, e.g., mdoc_macronames[MDOC_Sh] -> "Sh".
- */
+/* Names of macros. Index is enum mdoct. */
extern const char *const *mdoc_macronames;
-/*
- * Names of macro args. Index is enum mdocargt. Indexing into this
- * returns the normalised name, e.g., mdoc_argnames[MDOC_File] ->
- * "file".
- */
+/* Names of macro args. Index is enum mdocargt. */
extern const char *const *mdoc_argnames;
__BEGIN_DECLS
struct mdoc;
-void mdoc_free(struct mdoc *);
-struct mdoc *mdoc_alloc(struct regset *, void *, mandocmsg);
-void mdoc_reset(struct mdoc *);
-int mdoc_parseln(struct mdoc *, int, char *, int);
const struct mdoc_node *mdoc_node(const struct mdoc *);
const struct mdoc_meta *mdoc_meta(const struct mdoc *);
-int mdoc_endparse(struct mdoc *);
-int mdoc_addspan(struct mdoc *,
- const struct tbl_span *);
-int mdoc_addeqn(struct mdoc *,
- const struct eqn *);
__END_DECLS
diff --git a/usr.bin/mandoc/mdoc_argv.c b/usr.bin/mandoc/mdoc_argv.c
index 937518a7ba9..c35fcf2517c 100644
--- a/usr.bin/mandoc/mdoc_argv.c
+++ b/usr.bin/mandoc/mdoc_argv.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_argv.c,v 1.36 2011/04/21 22:59:54 schwarze Exp $ */
+/* $Id: mdoc_argv.c,v 1.37 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -22,6 +22,7 @@
#include <stdio.h>
#include <string.h>
+#include "mdoc.h"
#include "mandoc.h"
#include "libmdoc.h"
#include "libmandoc.h"
@@ -40,6 +41,7 @@ static int argv_opt_single(struct mdoc *, int,
struct mdoc_argv *, int *, char *);
static int argv_multi(struct mdoc *, int,
struct mdoc_argv *, int *, char *);
+static void argn_free(struct mdoc_arg *, int);
enum argvflag {
ARGV_NONE, /* no args to flag (e.g., -split) */
@@ -202,6 +204,60 @@ static const int argflags[MDOC_MAX] = {
0, /* Ta */
};
+static const enum mdocargt args_Ex[] = {
+ MDOC_Std,
+ MDOC_ARG_MAX
+};
+
+static const enum mdocargt args_An[] = {
+ MDOC_Split,
+ MDOC_Nosplit,
+ MDOC_ARG_MAX
+};
+
+static const enum mdocargt args_Bd[] = {
+ MDOC_Ragged,
+ MDOC_Unfilled,
+ MDOC_Filled,
+ MDOC_Literal,
+ MDOC_File,
+ MDOC_Offset,
+ MDOC_Compact,
+ MDOC_Centred,
+ MDOC_ARG_MAX
+};
+
+static const enum mdocargt args_Bf[] = {
+ MDOC_Emphasis,
+ MDOC_Literal,
+ MDOC_Symbolic,
+ MDOC_ARG_MAX
+};
+
+static const enum mdocargt args_Bk[] = {
+ MDOC_Words,
+ MDOC_ARG_MAX
+};
+
+static const enum mdocargt args_Bl[] = {
+ MDOC_Bullet,
+ MDOC_Dash,
+ MDOC_Hyphen,
+ MDOC_Item,
+ MDOC_Enum,
+ MDOC_Tag,
+ MDOC_Diag,
+ MDOC_Hang,
+ MDOC_Ohang,
+ MDOC_Inset,
+ MDOC_Column,
+ MDOC_Width,
+ MDOC_Offset,
+ MDOC_Compact,
+ MDOC_Nested,
+ MDOC_ARG_MAX
+};
+
/*
* Parse an argument from line text. This comes in the form of -key
* [value0...], which may either have a single mandatory value, at least
@@ -290,14 +346,14 @@ mdoc_argv_free(struct mdoc_arg *p)
assert(p->argc);
for (i = (int)p->argc - 1; i >= 0; i--)
- mdoc_argn_free(p, i);
+ argn_free(p, i);
free(p->argv);
free(p);
}
-void
-mdoc_argn_free(struct mdoc_arg *p, int iarg)
+static void
+argn_free(struct mdoc_arg *p, int iarg)
{
struct mdoc_argv *arg;
int j;
@@ -562,7 +618,7 @@ args_checkpunct(const char *p)
return(0);
buf[j] = '\0';
- if (DELIM_CLOSE != mandoc_isdelim(buf))
+ if (DELIM_CLOSE != mdoc_isdelim(buf))
return(0);
while (' ' == p[i])
@@ -579,7 +635,7 @@ args_checkpunct(const char *p)
return(0);
buf[j] = '\0';
- d = mandoc_isdelim(buf);
+ d = mdoc_isdelim(buf);
if (DELIM_NONE == d || DELIM_OPEN == d)
return(0);
@@ -592,69 +648,46 @@ args_checkpunct(const char *p)
/*
* Match up an argument string (e.g., `-foo bar' having "foo") with the
- * correrct identifier. It must apply to the given macro. If none was
+ * correct identifier. It must apply to the given macro. If none was
* found (including bad matches), return MDOC_ARG_MAX.
*/
static enum mdocargt
argv_a2arg(enum mdoct tok, const char *p)
{
- enum mdocargt args[MDOC_ARG_MAX];
- int i, len;
+ const enum mdocargt *args;
- len = 0;
+ args = NULL;
switch (tok) {
case (MDOC_An):
- args[len++] = MDOC_Split;
- args[len++] = MDOC_Nosplit;
+ args = args_An;
break;
case (MDOC_Bd):
- args[len++] = MDOC_Ragged;
- args[len++] = MDOC_Unfilled;
- args[len++] = MDOC_Filled;
- args[len++] = MDOC_Literal;
- args[len++] = MDOC_File;
- args[len++] = MDOC_Offset;
- args[len++] = MDOC_Compact;
- args[len++] = MDOC_Centred;
+ args = args_Bd;
break;
case (MDOC_Bf):
- args[len++] = MDOC_Emphasis;
- args[len++] = MDOC_Literal;
- args[len++] = MDOC_Symbolic;
+ args = args_Bf;
break;
case (MDOC_Bk):
- args[len++] = MDOC_Words;
+ args = args_Bk;
break;
case (MDOC_Bl):
- args[len++] = MDOC_Bullet;
- args[len++] = MDOC_Dash;
- args[len++] = MDOC_Hyphen;
- args[len++] = MDOC_Item;
- args[len++] = MDOC_Enum;
- args[len++] = MDOC_Tag;
- args[len++] = MDOC_Diag;
- args[len++] = MDOC_Hang;
- args[len++] = MDOC_Ohang;
- args[len++] = MDOC_Inset;
- args[len++] = MDOC_Column;
- args[len++] = MDOC_Width;
- args[len++] = MDOC_Offset;
- args[len++] = MDOC_Compact;
- args[len++] = MDOC_Nested;
+ args = args_Bl;
break;
case (MDOC_Rv):
/* FALLTHROUGH */
case (MDOC_Ex):
- args[len++] = MDOC_Std;
+ args = args_Ex;
break;
default:
- break;
+ return(MDOC_ARG_MAX);
}
- for (i = 0; i < len; i++)
- if (0 == strcmp(p, mdoc_argnames[args[i]]))
- return(args[i]);
+ assert(args);
+
+ for ( ; MDOC_ARG_MAX != *args ; args++)
+ if (0 == strcmp(p, mdoc_argnames[*args]))
+ return(*args);
return(MDOC_ARG_MAX);
}
diff --git a/usr.bin/mandoc/mdoc_hash.c b/usr.bin/mandoc/mdoc_hash.c
index 8d816e9ad9f..0f959709f93 100644
--- a/usr.bin/mandoc/mdoc_hash.c
+++ b/usr.bin/mandoc/mdoc_hash.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_hash.c,v 1.11 2010/07/31 23:42:04 schwarze Exp $ */
+/* $Id: mdoc_hash.c,v 1.12 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <string.h>
+#include "mdoc.h"
#include "mandoc.h"
#include "libmdoc.h"
diff --git a/usr.bin/mandoc/mdoc_html.c b/usr.bin/mandoc/mdoc_html.c
index 2779ef5838c..47112e20804 100644
--- a/usr.bin/mandoc/mdoc_html.c
+++ b/usr.bin/mandoc/mdoc_html.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_html.c,v 1.55 2011/04/21 22:59:54 schwarze Exp $ */
+/* $Id: mdoc_html.c,v 1.56 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -427,7 +427,11 @@ print_mdoc_node(MDOC_ARGS)
if (' ' == *n->string && MDOC_LINE & n->flags)
if ( ! (HTML_LITERAL & h->flags))
print_otag(h, TAG_BR, 0, NULL);
+ if (MDOC_DELIMC & n->flags)
+ h->flags |= HTML_NOSPACE;
print_text(h, n->string);
+ if (MDOC_DELIMO & n->flags)
+ h->flags |= HTML_NOSPACE;
return;
case (MDOC_EQN):
PAIR_CLASS_INIT(&tag, "eqn");
@@ -743,8 +747,7 @@ mdoc_nm_pre(MDOC_ARGS)
static int
mdoc_xr_pre(MDOC_ARGS)
{
- struct htmlpair tag[2];
- const struct mdoc_node *nn;
+ struct htmlpair tag[2];
if (NULL == n->child)
return(0);
@@ -760,16 +763,16 @@ mdoc_xr_pre(MDOC_ARGS)
} else
print_otag(h, TAG_A, 1, tag);
- nn = n->child;
- print_text(h, nn->string);
+ n = n->child;
+ print_text(h, n->string);
- if (NULL == (nn = nn->next))
+ if (NULL == (n = n->next))
return(0);
h->flags |= HTML_NOSPACE;
print_text(h, "(");
h->flags |= HTML_NOSPACE;
- print_text(h, nn->string);
+ print_text(h, n->string);
h->flags |= HTML_NOSPACE;
print_text(h, ")");
return(0);
@@ -1079,9 +1082,9 @@ mdoc_bl_pre(MDOC_ARGS)
static int
mdoc_ex_pre(MDOC_ARGS)
{
- const struct mdoc_node *nn;
- struct tag *t;
- struct htmlpair tag;
+ struct tag *t;
+ struct htmlpair tag;
+ int nchild;
if (n->prev)
print_otag(h, TAG_BR, 0, NULL);
@@ -1089,22 +1092,25 @@ mdoc_ex_pre(MDOC_ARGS)
PAIR_CLASS_INIT(&tag, "utility");
print_text(h, "The");
- for (nn = n->child; nn; nn = nn->next) {
+
+ nchild = n->nchild;
+ for (n = n->child; n; n = n->next) {
+ assert(MDOC_TEXT == n->type);
+
t = print_otag(h, TAG_B, 1, &tag);
- print_text(h, nn->string);
+ print_text(h, n->string);
print_tagq(h, t);
- h->flags |= HTML_NOSPACE;
-
- if (nn->next && NULL == nn->next->next)
- print_text(h, ", and");
- else if (nn->next)
+ if (nchild > 2 && n->next) {
+ h->flags |= HTML_NOSPACE;
print_text(h, ",");
- else
- h->flags &= ~HTML_NOSPACE;
+ }
+
+ if (n->next && NULL == n->next->next)
+ print_text(h, "and");
}
- if (n->child && n->child->next)
+ if (nchild > 1)
print_text(h, "utilities exit");
else
print_text(h, "utility exits");
@@ -1160,14 +1166,13 @@ mdoc_d1_pre(MDOC_ARGS)
static int
mdoc_sx_pre(MDOC_ARGS)
{
- struct htmlpair tag[2];
- const struct mdoc_node *nn;
- char buf[BUFSIZ];
+ struct htmlpair tag[2];
+ char buf[BUFSIZ];
strlcpy(buf, "#", BUFSIZ);
- for (nn = n->child; nn; nn = nn->next) {
- html_idcat(buf, nn->string, BUFSIZ);
- if (nn->next)
+ for (n = n->child; n; n = n->next) {
+ html_idcat(buf, n->string, BUFSIZ);
+ if (n->next)
html_idcat(buf, " ", BUFSIZ);
}
@@ -1377,12 +1382,16 @@ mdoc_fa_pre(MDOC_ARGS)
t = print_otag(h, TAG_I, 1, &tag);
print_text(h, nn->string);
print_tagq(h, t);
- if (nn->next)
+ if (nn->next) {
+ h->flags |= HTML_NOSPACE;
print_text(h, ",");
+ }
}
- if (n->child && n->next && n->next->tok == MDOC_Fa)
+ if (n->child && n->next && n->next->tok == MDOC_Fa) {
+ h->flags |= HTML_NOSPACE;
print_text(h, ",");
+ }
return(0);
}
@@ -1392,13 +1401,61 @@ mdoc_fa_pre(MDOC_ARGS)
static int
mdoc_fd_pre(MDOC_ARGS)
{
- struct htmlpair tag;
+ struct htmlpair tag[2];
+ char buf[BUFSIZ];
+ size_t sz;
+ int i;
+ struct tag *t;
synopsis_pre(h, n);
- PAIR_CLASS_INIT(&tag, "macro");
- print_otag(h, TAG_B, 1, &tag);
- return(1);
+ if (NULL == (n = n->child))
+ return(0);
+
+ assert(MDOC_TEXT == n->type);
+
+ if (strcmp(n->string, "#include")) {
+ PAIR_CLASS_INIT(&tag[0], "macro");
+ print_otag(h, TAG_B, 1, tag);
+ return(1);
+ }
+
+ PAIR_CLASS_INIT(&tag[0], "includes");
+ print_otag(h, TAG_B, 1, tag);
+ print_text(h, n->string);
+
+ if (NULL != (n = n->next)) {
+ assert(MDOC_TEXT == n->type);
+ strlcpy(buf, '<' == *n->string || '"' == *n->string ?
+ n->string + 1 : n->string, BUFSIZ);
+
+ sz = strlen(buf);
+ if (sz && ('>' == buf[sz - 1] || '"' == buf[sz - 1]))
+ buf[sz - 1] = '\0';
+
+ PAIR_CLASS_INIT(&tag[0], "link-includes");
+ bufinit(h);
+
+ i = 1;
+ if (h->base_includes) {
+ buffmt_includes(h, buf);
+ PAIR_HREF_INIT(&tag[i], h->buf);
+ i++;
+ }
+
+ t = print_otag(h, TAG_A, i, tag);
+ print_text(h, n->string);
+ print_tagq(h, t);
+
+ n = n->next;
+ }
+
+ for ( ; n; n = n->next) {
+ assert(MDOC_TEXT == n->type);
+ print_text(h, n->string);
+ }
+
+ return(0);
}
@@ -1439,13 +1496,13 @@ mdoc_ft_pre(MDOC_ARGS)
static int
mdoc_fn_pre(MDOC_ARGS)
{
- struct tag *t;
- struct htmlpair tag[2];
- const struct mdoc_node *nn;
- char nbuf[BUFSIZ];
- const char *sp, *ep;
- int sz, i;
+ struct tag *t;
+ struct htmlpair tag[2];
+ char nbuf[BUFSIZ];
+ const char *sp, *ep;
+ int sz, i, pretty;
+ pretty = MDOC_SYNPRETTY & n->flags;
synopsis_pre(h, n);
/* Split apart into type and name. */
@@ -1497,26 +1554,33 @@ mdoc_fn_pre(MDOC_ARGS)
h->flags |= HTML_NOSPACE;
print_text(h, "(");
+ h->flags |= HTML_NOSPACE;
bufinit(h);
PAIR_CLASS_INIT(&tag[0], "farg");
bufcat_style(h, "white-space", "nowrap");
PAIR_STYLE_INIT(&tag[1], h);
- for (nn = n->child->next; nn; nn = nn->next) {
+ for (n = n->child->next; n; n = n->next) {
i = 1;
if (MDOC_SYNPRETTY & n->flags)
i = 2;
t = print_otag(h, TAG_I, i, tag);
- print_text(h, nn->string);
+ print_text(h, n->string);
print_tagq(h, t);
- if (nn->next)
+ if (n->next) {
+ h->flags |= HTML_NOSPACE;
print_text(h, ",");
+ }
}
+ h->flags |= HTML_NOSPACE;
print_text(h, ")");
- if (MDOC_SYNPRETTY & n->flags)
+
+ if (pretty) {
+ h->flags |= HTML_NOSPACE;
print_text(h, ";");
+ }
return(0);
}
@@ -1587,20 +1651,22 @@ mdoc_sp_pre(MDOC_ARGS)
static int
mdoc_lk_pre(MDOC_ARGS)
{
- const struct mdoc_node *nn;
- struct htmlpair tag[2];
+ struct htmlpair tag[2];
- nn = n->child;
+ if (NULL == (n = n->child))
+ return(0);
+
+ assert(MDOC_TEXT == n->type);
PAIR_CLASS_INIT(&tag[0], "link-ext");
- PAIR_HREF_INIT(&tag[1], nn->string);
- print_otag(h, TAG_A, 2, tag);
+ PAIR_HREF_INIT(&tag[1], n->string);
- if (NULL == nn || NULL == nn->next)
- return(1);
+ print_otag(h, TAG_A, 2, tag);
- for (nn = nn->next; nn; nn = nn->next)
- print_text(h, nn->string);
+ for (n = n->next; n; n = n->next) {
+ assert(MDOC_TEXT == n->type);
+ print_text(h, n->string);
+ }
return(0);
}
@@ -1610,19 +1676,21 @@ mdoc_lk_pre(MDOC_ARGS)
static int
mdoc_mt_pre(MDOC_ARGS)
{
- struct htmlpair tag[2];
- struct tag *t;
- const struct mdoc_node *nn;
+ struct htmlpair tag[2];
+ struct tag *t;
PAIR_CLASS_INIT(&tag[0], "link-mail");
- for (nn = n->child; nn; nn = nn->next) {
+ for (n = n->child; n; n = n->next) {
+ assert(MDOC_TEXT == n->type);
+
bufinit(h);
bufcat(h, "mailto:");
- bufcat(h, nn->string);
+ bufcat(h, n->string);
+
PAIR_HREF_INIT(&tag[1], h->buf);
t = print_otag(h, TAG_A, 2, tag);
- print_text(h, nn->string);
+ print_text(h, n->string);
print_tagq(h, t);
}
@@ -1667,7 +1735,9 @@ mdoc_fo_post(MDOC_ARGS)
if (MDOC_BODY != n->type)
return;
+ h->flags |= HTML_NOSPACE;
print_text(h, ")");
+ h->flags |= HTML_NOSPACE;
print_text(h, ";");
}
@@ -1676,39 +1746,57 @@ mdoc_fo_post(MDOC_ARGS)
static int
mdoc_in_pre(MDOC_ARGS)
{
- const struct mdoc_node *nn;
- struct tag *t;
- struct htmlpair tag[2];
- int i;
+ struct tag *t;
+ struct htmlpair tag[2];
+ int i;
synopsis_pre(h, n);
PAIR_CLASS_INIT(&tag[0], "includes");
print_otag(h, TAG_B, 1, tag);
+ /*
+ * The first argument of the `In' gets special treatment as
+ * being a linked value. Subsequent values are printed
+ * afterward. groff does similarly. This also handles the case
+ * of no children.
+ */
+
if (MDOC_SYNPRETTY & n->flags && MDOC_LINE & n->flags)
print_text(h, "#include");
print_text(h, "<");
h->flags |= HTML_NOSPACE;
- for (nn = n->child; nn; nn = nn->next) {
+ if (NULL != (n = n->child)) {
+ assert(MDOC_TEXT == n->type);
+
PAIR_CLASS_INIT(&tag[0], "link-includes");
- i = 1;
bufinit(h);
+
+ i = 1;
+
if (h->base_includes) {
- buffmt_includes(h, nn->string);
+ buffmt_includes(h, n->string);
PAIR_HREF_INIT(&tag[i], h->buf);
i++;
- }
+ }
+
t = print_otag(h, TAG_A, i, tag);
- print_mdoc_node(m, nn, h);
+ print_text(h, n->string);
print_tagq(h, t);
+
+ n = n->next;
}
h->flags |= HTML_NOSPACE;
print_text(h, ">");
+ for ( ; n; n = n->next) {
+ assert(MDOC_TEXT == n->type);
+ print_text(h, n->string);
+ }
+
return(0);
}
@@ -1729,31 +1817,38 @@ mdoc_ic_pre(MDOC_ARGS)
static int
mdoc_rv_pre(MDOC_ARGS)
{
- const struct mdoc_node *nn;
- struct htmlpair tag;
- struct tag *t;
+ struct htmlpair tag;
+ struct tag *t;
+ int nchild;
if (n->prev)
print_otag(h, TAG_BR, 0, NULL);
+ PAIR_CLASS_INIT(&tag, "fname");
+
print_text(h, "The");
- for (nn = n->child; nn; nn = nn->next) {
- PAIR_CLASS_INIT(&tag, "fname");
+ nchild = n->nchild;
+ for (n = n->child; n; n = n->next) {
+ assert(MDOC_TEXT == n->type);
+
t = print_otag(h, TAG_B, 1, &tag);
- print_text(h, nn->string);
+ print_text(h, n->string);
print_tagq(h, t);
h->flags |= HTML_NOSPACE;
- if (nn->next && NULL == nn->next->next)
- print_text(h, "(), and");
- else if (nn->next)
- print_text(h, "(),");
- else
- print_text(h, "()");
+ print_text(h, "()");
+
+ if (nchild > 2 && n->next) {
+ h->flags |= HTML_NOSPACE;
+ print_text(h, ",");
+ }
+
+ if (n->next && NULL == n->next->next)
+ print_text(h, "and");
}
- if (n->child && n->child->next)
+ if (nchild > 1)
print_text(h, "functions return");
else
print_text(h, "function returns");
@@ -2028,6 +2123,7 @@ mdoc__x_post(MDOC_ARGS)
if (NULL == n->parent || MDOC_Rs != n->parent->tok)
return;
+ h->flags |= HTML_NOSPACE;
print_text(h, n->next ? "," : ".");
}
diff --git a/usr.bin/mandoc/mdoc_macro.c b/usr.bin/mandoc/mdoc_macro.c
index 7a02311a1a4..d257d863f33 100644
--- a/usr.bin/mandoc/mdoc_macro.c
+++ b/usr.bin/mandoc/mdoc_macro.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_macro.c,v 1.65 2011/04/21 22:59:54 schwarze Exp $ */
+/* $Id: mdoc_macro.c,v 1.66 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
@@ -22,6 +22,7 @@
#include <string.h>
#include <time.h>
+#include "mdoc.h"
#include "mandoc.h"
#include "libmdoc.h"
#include "libmandoc.h"
@@ -46,6 +47,8 @@ static int in_line(MACRO_PROT_ARGS);
static int obsolete(MACRO_PROT_ARGS);
static int phrase_ta(MACRO_PROT_ARGS);
+static int dword(struct mdoc *, int, int,
+ const char *, enum mdelim);
static int append_delims(struct mdoc *,
int, int *, char *);
static enum mdoct lookup(enum mdoct, const char *);
@@ -509,9 +512,9 @@ make_pending(struct mdoc_node *broken, enum mdoct tok,
taker->pending = broken->pending;
}
broken->pending = breaker;
- mdoc_vmsg(m, MANDOCERR_SCOPENEST, line, ppos,
- "%s breaks %s", mdoc_macronames[tok],
- mdoc_macronames[broken->tok]);
+ mandoc_vmsg(MANDOCERR_SCOPENEST, m->parse, line, ppos,
+ "%s breaks %s", mdoc_macronames[tok],
+ mdoc_macronames[broken->tok]);
return(1);
}
@@ -537,9 +540,10 @@ rew_sub(enum mdoc_type t, struct mdoc *m,
case (REWIND_THIS):
break;
case (REWIND_FORCE):
- mdoc_vmsg(m, MANDOCERR_SCOPEBROKEN, line, ppos,
- "%s breaks %s", mdoc_macronames[tok],
- mdoc_macronames[n->tok]);
+ mandoc_vmsg(MANDOCERR_SCOPEBROKEN, m->parse,
+ line, ppos, "%s breaks %s",
+ mdoc_macronames[tok],
+ mdoc_macronames[n->tok]);
/* FALLTHROUGH */
case (REWIND_MORE):
n = n->parent;
@@ -575,6 +579,28 @@ rew_sub(enum mdoc_type t, struct mdoc *m,
return(1);
}
+/*
+ * Allocate a word and check whether it's punctuation or not.
+ * Punctuation consists of those tokens found in mdoc_isdelim().
+ */
+static int
+dword(struct mdoc *m, int line,
+ int col, const char *p, enum mdelim d)
+{
+
+ if (DELIM_MAX == d)
+ d = mdoc_isdelim(p);
+
+ if ( ! mdoc_word_alloc(m, line, col, p))
+ return(0);
+
+ if (DELIM_OPEN == d)
+ m->last->flags |= MDOC_DELIMO;
+ else if (DELIM_CLOSE == d)
+ m->last->flags |= MDOC_DELIMC;
+
+ return(1);
+}
static int
append_delims(struct mdoc *m, int line, int *pos, char *buf)
@@ -595,9 +621,7 @@ append_delims(struct mdoc *m, int line, int *pos, char *buf)
else if (ARGS_EOLN == ac)
break;
- assert(DELIM_NONE != mandoc_isdelim(p));
- if ( ! mdoc_word_alloc(m, line, la, p))
- return(0);
+ dword(m, line, la, p, DELIM_MAX);
/*
* If we encounter end-of-sentence symbols, then trigger
@@ -741,7 +765,7 @@ blk_exp_close(MACRO_PROT_ARGS)
ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
if (MDOC_MAX == ntok) {
- if ( ! mdoc_word_alloc(m, line, lastarg, p))
+ if ( ! dword(m, line, lastarg, p, DELIM_MAX))
return(0);
continue;
}
@@ -865,7 +889,7 @@ in_line(MACRO_PROT_ARGS)
* the word.
*/
- d = ARGS_QWORD == ac ? DELIM_NONE : mandoc_isdelim(p);
+ d = ARGS_QWORD == ac ? DELIM_NONE : mdoc_isdelim(p);
if (DELIM_NONE != d) {
/*
@@ -900,7 +924,8 @@ in_line(MACRO_PROT_ARGS)
if (DELIM_NONE == d)
cnt++;
- if ( ! mdoc_word_alloc(m, line, la, p))
+
+ if ( ! dword(m, line, la, p, d))
return(0);
/*
@@ -1055,8 +1080,8 @@ blk_full(MACRO_PROT_ARGS)
ARGS_PHRASE != ac &&
ARGS_PPHRASE != ac &&
ARGS_QWORD != ac &&
- DELIM_OPEN == mandoc_isdelim(p)) {
- if ( ! mdoc_word_alloc(m, line, la, p))
+ DELIM_OPEN == mdoc_isdelim(p)) {
+ if ( ! dword(m, line, la, p, DELIM_OPEN))
return(0);
continue;
}
@@ -1108,7 +1133,7 @@ blk_full(MACRO_PROT_ARGS)
ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
if (MDOC_MAX == ntok) {
- if ( ! mdoc_word_alloc(m, line, la, p))
+ if ( ! dword(m, line, la, p, DELIM_MAX))
return(0);
continue;
}
@@ -1218,8 +1243,8 @@ blk_part_imp(MACRO_PROT_ARGS)
break;
if (NULL == body && ARGS_QWORD != ac &&
- DELIM_OPEN == mandoc_isdelim(p)) {
- if ( ! mdoc_word_alloc(m, line, la, p))
+ DELIM_OPEN == mdoc_isdelim(p)) {
+ if ( ! dword(m, line, la, p, DELIM_OPEN))
return(0);
continue;
}
@@ -1233,7 +1258,7 @@ blk_part_imp(MACRO_PROT_ARGS)
ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
if (MDOC_MAX == ntok) {
- if ( ! mdoc_word_alloc(m, line, la, p))
+ if ( ! dword(m, line, la, p, DELIM_MAX))
return(0);
continue;
}
@@ -1294,7 +1319,7 @@ blk_part_imp(MACRO_PROT_ARGS)
* crufty use of `Op' breakage.
*/
if (n != body)
- mdoc_vmsg(m, MANDOCERR_SCOPENEST, line, ppos,
+ mandoc_vmsg(MANDOCERR_SCOPENEST, m->parse, line, ppos,
"%s broken", mdoc_macronames[tok]);
if (n && ! rew_sub(MDOC_BODY, m, tok, line, ppos))
@@ -1349,9 +1374,9 @@ blk_part_exp(MACRO_PROT_ARGS)
/* Flush out leading punctuation. */
if (NULL == head && ARGS_QWORD != ac &&
- DELIM_OPEN == mandoc_isdelim(p)) {
+ DELIM_OPEN == mdoc_isdelim(p)) {
assert(NULL == body);
- if ( ! mdoc_word_alloc(m, line, la, p))
+ if ( ! dword(m, line, la, p, DELIM_OPEN))
return(0);
continue;
}
@@ -1372,7 +1397,7 @@ blk_part_exp(MACRO_PROT_ARGS)
assert(head);
/* No check whether it's a macro! */
if (MDOC_Eo == tok)
- if ( ! mdoc_word_alloc(m, line, la, p))
+ if ( ! dword(m, line, la, p, DELIM_MAX))
return(0);
if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
@@ -1390,7 +1415,7 @@ blk_part_exp(MACRO_PROT_ARGS)
ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
if (MDOC_MAX == ntok) {
- if ( ! mdoc_word_alloc(m, line, la, p))
+ if ( ! dword(m, line, la, p, DELIM_MAX))
return(0);
continue;
}
@@ -1495,9 +1520,9 @@ in_line_argn(MACRO_PROT_ARGS)
break;
if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) &&
- ARGS_QWORD != ac &&
- 0 == j && DELIM_OPEN == mandoc_isdelim(p)) {
- if ( ! mdoc_word_alloc(m, line, la, p))
+ ARGS_QWORD != ac && 0 == j &&
+ DELIM_OPEN == mdoc_isdelim(p)) {
+ if ( ! dword(m, line, la, p, DELIM_OPEN))
return(0);
continue;
} else if (0 == j)
@@ -1525,7 +1550,7 @@ in_line_argn(MACRO_PROT_ARGS)
if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) &&
ARGS_QWORD != ac &&
! flushed &&
- DELIM_NONE != mandoc_isdelim(p)) {
+ DELIM_NONE != mdoc_isdelim(p)) {
if ( ! rew_elem(m, tok))
return(0);
flushed = 1;
@@ -1544,7 +1569,7 @@ in_line_argn(MACRO_PROT_ARGS)
return(0);
}
- if ( ! mdoc_word_alloc(m, line, la, p))
+ if ( ! dword(m, line, la, p, DELIM_MAX))
return(0);
j++;
}
@@ -1615,7 +1640,7 @@ in_line_eoln(MACRO_PROT_ARGS)
ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
if (MDOC_MAX == ntok) {
- if ( ! mdoc_word_alloc(m, line, la, p))
+ if ( ! dword(m, line, la, p, DELIM_MAX))
return(0);
continue;
}
@@ -1695,7 +1720,7 @@ phrase(struct mdoc *m, int line, int ppos, char *buf)
ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup_raw(p);
if (MDOC_MAX == ntok) {
- if ( ! mdoc_word_alloc(m, line, la, p))
+ if ( ! dword(m, line, la, p, DELIM_MAX))
return(0);
continue;
}
@@ -1740,7 +1765,7 @@ phrase_ta(MACRO_PROT_ARGS)
ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup_raw(p);
if (MDOC_MAX == ntok) {
- if ( ! mdoc_word_alloc(m, line, la, p))
+ if ( ! dword(m, line, la, p, DELIM_MAX))
return(0);
continue;
}
diff --git a/usr.bin/mandoc/mdoc_term.c b/usr.bin/mandoc/mdoc_term.c
index d47781b87bb..a992ed09cf8 100644
--- a/usr.bin/mandoc/mdoc_term.c
+++ b/usr.bin/mandoc/mdoc_term.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_term.c,v 1.131 2011/03/20 23:36:42 schwarze Exp $ */
+/* $Id: mdoc_term.c,v 1.132 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
@@ -28,7 +28,6 @@
#include "out.h"
#include "term.h"
#include "mdoc.h"
-#include "chars.h"
#include "main.h"
#define INDENT 5
@@ -348,7 +347,11 @@ print_mdoc_node(DECL_ARGS)
case (MDOC_TEXT):
if (' ' == *n->string && MDOC_LINE & n->flags)
term_newln(p);
+ if (MDOC_DELIMC & n->flags)
+ p->flags |= TERMP_NOSPACE;
term_word(p, n->string);
+ if (MDOC_DELIMO & n->flags)
+ p->flags |= TERMP_NOSPACE;
break;
case (MDOC_EQN):
term_word(p, n->eqn->data);
@@ -1176,25 +1179,30 @@ termp_rs_pre(DECL_ARGS)
static int
termp_rv_pre(DECL_ARGS)
{
- const struct mdoc_node *nn;
+ int nchild;
term_newln(p);
term_word(p, "The");
- for (nn = n->child; nn; nn = nn->next) {
+ nchild = n->nchild;
+ for (n = n->child; n; n = n->next) {
term_fontpush(p, TERMFONT_BOLD);
- term_word(p, nn->string);
+ term_word(p, n->string);
term_fontpop(p);
+
p->flags |= TERMP_NOSPACE;
- if (nn->next && NULL == nn->next->next)
- term_word(p, "(), and");
- else if (nn->next)
- term_word(p, "(),");
- else
- term_word(p, "()");
+ term_word(p, "()");
+
+ if (nchild > 2 && n->next) {
+ p->flags |= TERMP_NOSPACE;
+ term_word(p, ",");
+ }
+
+ if (n->next && NULL == n->next->next)
+ term_word(p, "and");
}
- if (n->child && n->child->next)
+ if (nchild > 1)
term_word(p, "functions return");
else
term_word(p, "function returns");
@@ -1217,31 +1225,34 @@ termp_rv_pre(DECL_ARGS)
static int
termp_ex_pre(DECL_ARGS)
{
- const struct mdoc_node *nn;
+ int nchild;
+ term_newln(p);
term_word(p, "The");
- for (nn = n->child; nn; nn = nn->next) {
+ nchild = n->nchild;
+ for (n = n->child; n; n = n->next) {
term_fontpush(p, TERMFONT_BOLD);
- term_word(p, nn->string);
+ term_word(p, n->string);
term_fontpop(p);
- p->flags |= TERMP_NOSPACE;
- if (nn->next && NULL == nn->next->next)
- term_word(p, ", and");
- else if (nn->next)
+
+ if (nchild > 2 && n->next) {
+ p->flags |= TERMP_NOSPACE;
term_word(p, ",");
- else
- p->flags &= ~TERMP_NOSPACE;
+ }
+
+ if (n->next && NULL == n->next->next)
+ term_word(p, "and");
}
- if (n->child && n->child->next)
+ if (nchild > 1)
term_word(p, "utilities exit");
else
term_word(p, "utility exits");
term_word(p, "0 on success, and >0 if an error occurs.");
- p->flags |= TERMP_SENTENCE;
+ p->flags |= TERMP_SENTENCE;
return(0);
}
@@ -1281,31 +1292,33 @@ termp_bl_post(DECL_ARGS)
term_newln(p);
}
-
/* ARGSUSED */
static int
termp_xr_pre(DECL_ARGS)
{
- const struct mdoc_node *nn;
- if (NULL == n->child)
+ if (NULL == (n = n->child))
return(0);
- assert(MDOC_TEXT == n->child->type);
- nn = n->child;
+ assert(MDOC_TEXT == n->type);
+ term_word(p, n->string);
- term_word(p, nn->string);
- if (NULL == (nn = nn->next))
+ if (NULL == (n = n->next))
return(0);
+
p->flags |= TERMP_NOSPACE;
term_word(p, "(");
- term_word(p, nn->string);
+ p->flags |= TERMP_NOSPACE;
+
+ assert(MDOC_TEXT == n->type);
+ term_word(p, n->string);
+
+ p->flags |= TERMP_NOSPACE;
term_word(p, ")");
return(0);
}
-
/*
* This decides how to assert whitespace before any of the SYNOPSIS set
* of macros (which, as in the case of Ft/Fo and Ft/Fn, may contain
@@ -1519,30 +1532,43 @@ termp_ft_pre(DECL_ARGS)
static int
termp_fn_pre(DECL_ARGS)
{
- const struct mdoc_node *nn;
+ int pretty;
+
+ pretty = MDOC_SYNPRETTY & n->flags;
synopsis_pre(p, n);
+ if (NULL == (n = n->child))
+ return(0);
+
+ assert(MDOC_TEXT == n->type);
term_fontpush(p, TERMFONT_BOLD);
- term_word(p, n->child->string);
+ term_word(p, n->string);
term_fontpop(p);
p->flags |= TERMP_NOSPACE;
term_word(p, "(");
+ p->flags |= TERMP_NOSPACE;
- for (nn = n->child->next; nn; nn = nn->next) {
+ for (n = n->next; n; n = n->next) {
+ assert(MDOC_TEXT == n->type);
term_fontpush(p, TERMFONT_UNDER);
- term_word(p, nn->string);
+ term_word(p, n->string);
term_fontpop(p);
- if (nn->next)
+ if (n->next) {
+ p->flags |= TERMP_NOSPACE;
term_word(p, ",");
+ }
}
+ p->flags |= TERMP_NOSPACE;
term_word(p, ")");
- if (MDOC_SYNPRETTY & n->flags)
+ if (pretty) {
+ p->flags |= TERMP_NOSPACE;
term_word(p, ";");
+ }
return(0);
}
@@ -1564,12 +1590,16 @@ termp_fa_pre(DECL_ARGS)
term_word(p, nn->string);
term_fontpop(p);
- if (nn->next)
+ if (nn->next) {
+ p->flags |= TERMP_NOSPACE;
term_word(p, ",");
+ }
}
- if (n->child && n->next && n->next->tok == MDOC_Fa)
+ if (n->child && n->next && n->next->tok == MDOC_Fa) {
+ p->flags |= TERMP_NOSPACE;
term_word(p, ",");
+ }
return(0);
}
@@ -2004,6 +2034,7 @@ termp_fo_pre(DECL_ARGS)
} else if (MDOC_BODY == n->type) {
p->flags |= TERMP_NOSPACE;
term_word(p, "(");
+ p->flags |= TERMP_NOSPACE;
return(1);
}
@@ -2027,10 +2058,13 @@ termp_fo_post(DECL_ARGS)
if (MDOC_BODY != n->type)
return;
+ p->flags |= TERMP_NOSPACE;
term_word(p, ")");
- if (MDOC_SYNPRETTY & n->flags)
+ if (MDOC_SYNPRETTY & n->flags) {
+ p->flags |= TERMP_NOSPACE;
term_word(p, ";");
+ }
}
@@ -2104,6 +2138,7 @@ termp____post(DECL_ARGS)
if (NULL == n->parent || MDOC_Rs != n->parent->tok)
return;
+ p->flags |= TERMP_NOSPACE;
if (NULL == n->next) {
term_word(p, ".");
p->flags |= TERMP_SENTENCE;
@@ -2140,6 +2175,7 @@ termp_lk_pre(DECL_ARGS)
term_fontpop(p);
+ p->flags |= TERMP_NOSPACE;
term_word(p, ":");
term_fontpush(p, TERMFONT_BOLD);
diff --git a/usr.bin/mandoc/mdoc_validate.c b/usr.bin/mandoc/mdoc_validate.c
index a0620ecee82..b915a49b24a 100644
--- a/usr.bin/mandoc/mdoc_validate.c
+++ b/usr.bin/mandoc/mdoc_validate.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_validate.c,v 1.91 2011/04/21 22:59:54 schwarze Exp $ */
+/* $Id: mdoc_validate.c,v 1.92 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -29,6 +29,7 @@
#include <string.h>
#include <time.h>
+#include "mdoc.h"
#include "mandoc.h"
#include "libmdoc.h"
#include "libmandoc.h"
@@ -150,9 +151,9 @@ static v_post posts_notext[] = { ewarn_eq0, NULL };
static v_post posts_ns[] = { post_ns, NULL };
static v_post posts_os[] = { post_os, post_prol, NULL };
static v_post posts_rs[] = { post_rs, NULL };
-static v_post posts_sh[] = { post_ignpar, hwarn_ge1, bwarn_ge1, post_sh, NULL };
+static v_post posts_sh[] = { post_ignpar, hwarn_ge1, post_sh, NULL };
static v_post posts_sp[] = { ewarn_le1, NULL };
-static v_post posts_ss[] = { post_ignpar, hwarn_ge1, bwarn_ge1, NULL };
+static v_post posts_ss[] = { post_ignpar, hwarn_ge1, NULL };
static v_post posts_st[] = { post_st, NULL };
static v_post posts_std[] = { post_std, NULL };
static v_post posts_text[] = { ewarn_ge1, NULL };
@@ -442,7 +443,7 @@ check_count(struct mdoc *m, enum mdoc_type type,
}
t = lvl == CHECK_WARN ? MANDOCERR_ARGCWARN : MANDOCERR_ARGCOUNT;
- mdoc_vmsg(m, t, m->last->line, m->last->pos,
+ mandoc_vmsg(t, m->parse, m->last->line, m->last->pos,
"want %s%d children (have %d)",
p, val, m->last->nchild);
return(1);
@@ -577,10 +578,9 @@ check_parent(PRE_ARGS, enum mdoct tok, enum mdoc_type t)
(t == n->parent->type))
return(1);
- mdoc_vmsg(mdoc, MANDOCERR_SYNTCHILD,
- n->line, n->pos, "want parent %s",
- MDOC_ROOT == t ? "<root>" :
- mdoc_macronames[tok]);
+ mandoc_vmsg(MANDOCERR_SYNTCHILD, mdoc->parse, n->line,
+ n->pos, "want parent %s", MDOC_ROOT == t ?
+ "<root>" : mdoc_macronames[tok]);
return(0);
}
@@ -1328,7 +1328,8 @@ post_it(POST_ARGS)
else
er = MANDOCERR_SYNTARGCOUNT;
- mdoc_vmsg(mdoc, er, mdoc->last->line, mdoc->last->pos,
+ mandoc_vmsg(er, mdoc->parse, mdoc->last->line,
+ mdoc->last->pos,
"columns == %d (have %d)", cols, i);
return(MANDOCERR_ARGCOUNT == er);
default:
@@ -1997,16 +1998,16 @@ post_dd(POST_ARGS)
n = mdoc->last;
if (NULL == n->child || '\0' == n->child->string[0]) {
- mdoc->meta.date = mandoc_normdate(NULL,
- mdoc->msg, mdoc->data, n->line, n->pos);
+ mdoc->meta.date = mandoc_normdate
+ (mdoc->parse, NULL, n->line, n->pos);
return(1);
}
if ( ! concat(mdoc, buf, n->child, DATESIZE))
return(0);
- mdoc->meta.date = mandoc_normdate(buf,
- mdoc->msg, mdoc->data, n->line, n->pos);
+ mdoc->meta.date = mandoc_normdate
+ (mdoc->parse, buf, n->line, n->pos);
return(1);
}
@@ -2189,7 +2190,7 @@ post_os(POST_ARGS)
return(0);
}
#else /*!OSNAME */
- if (uname(&utsname)) {
+ if (-1 == uname(&utsname)) {
mdoc_nmsg(mdoc, n, MANDOCERR_UNAME);
mdoc->meta.os = mandoc_strdup("UNKNOWN");
return(post_prol(mdoc));
diff --git a/usr.bin/mandoc/msec.c b/usr.bin/mandoc/msec.c
index 9eac9abf39c..e5bbcf0b265 100644
--- a/usr.bin/mandoc/msec.c
+++ b/usr.bin/mandoc/msec.c
@@ -1,4 +1,4 @@
-/* $Id: msec.c,v 1.5 2010/05/24 02:29:02 schwarze Exp $ */
+/* $Id: msec.c,v 1.6 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -17,6 +17,7 @@
#include <stdlib.h>
#include <string.h>
+#include "mdoc.h"
#include "mandoc.h"
#include "libmdoc.h"
diff --git a/usr.bin/mandoc/out.h b/usr.bin/mandoc/out.h
index ee7f422fa64..0386a989d71 100644
--- a/usr.bin/mandoc/out.h
+++ b/usr.bin/mandoc/out.h
@@ -1,4 +1,4 @@
-/* $Id: out.h,v 1.9 2011/03/07 01:35:33 schwarze Exp $ */
+/* $Id: out.h,v 1.10 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -17,34 +17,17 @@
#ifndef OUT_H
#define OUT_H
-__BEGIN_DECLS
-
-struct roffcol {
- size_t width; /* width of cell */
- size_t decimal; /* decimal position in cell */
-};
-
-typedef size_t (*tbl_strlen)(const char *, void *);
-typedef size_t (*tbl_len)(size_t, void *);
-
-struct rofftbl {
- tbl_strlen slen; /* calculate string length */
- tbl_len len; /* produce width of empty space */
- struct roffcol *cols; /* master column specifiers */
- void *arg; /* passed to slen and len */
-};
-
enum roffscale {
- SCALE_CM,
- SCALE_IN,
- SCALE_PC,
- SCALE_PT,
- SCALE_EM,
- SCALE_MM,
- SCALE_EN,
- SCALE_BU,
- SCALE_VS,
- SCALE_FS,
+ SCALE_CM, /* centimeters (c) */
+ SCALE_IN, /* inches (i) */
+ SCALE_PC, /* pica (P) */
+ SCALE_PT, /* points (p) */
+ SCALE_EM, /* ems (m) */
+ SCALE_MM, /* mini-ems (M) */
+ SCALE_EN, /* ens (n) */
+ SCALE_BU, /* default horizontal (u) */
+ SCALE_VS, /* default vertical (v) */
+ SCALE_FS, /* syn. for u (f) */
SCALE_MAX
};
@@ -64,11 +47,33 @@ enum roffdeco {
DECO_MAX
};
+enum chars {
+ CHARS_ASCII, /* 7-bit ascii representation */
+ CHARS_HTML /* unicode values */
+};
+
+struct roffcol {
+ size_t width; /* width of cell */
+ size_t decimal; /* decimal position in cell */
+};
+
struct roffsu {
enum roffscale unit;
double scale;
};
+typedef size_t (*tbl_strlen)(const char *, void *);
+typedef size_t (*tbl_len)(size_t, void *);
+
+struct rofftbl {
+ tbl_strlen slen; /* calculate string length */
+ tbl_len len; /* produce width of empty space */
+ struct roffcol *cols; /* master column specifiers */
+ void *arg; /* passed to slen and len */
+};
+
+__BEGIN_DECLS
+
#define SCALE_VS_INIT(p, v) \
do { (p)->unit = SCALE_VS; \
(p)->scale = (v); } \
@@ -79,10 +84,18 @@ struct roffsu {
(p)->scale = (v); } \
while (/* CONSTCOND */ 0)
-int a2roffsu(const char *, struct roffsu *, enum roffscale);
-int a2roffdeco(enum roffdeco *, const char **, size_t *);
-void time2a(time_t, char *, size_t);
-void tblcalc(struct rofftbl *tbl, const struct tbl_span *);
+int a2roffsu(const char *, struct roffsu *, enum roffscale);
+int a2roffdeco(enum roffdeco *, const char **, size_t *);
+void time2a(time_t, char *, size_t);
+void tblcalc(struct rofftbl *tbl, const struct tbl_span *);
+
+void *chars_init(enum chars);
+const char *chars_num2char(const char *, size_t);
+const char *chars_spec2str(void *, const char *, size_t, size_t *);
+int chars_spec2cp(void *, const char *, size_t);
+const char *chars_res2str(void *, const char *, size_t, size_t *);
+int chars_res2cp(void *, const char *, size_t);
+void chars_free(void *);
__END_DECLS
diff --git a/usr.bin/mandoc/read.c b/usr.bin/mandoc/read.c
new file mode 100644
index 00000000000..d3b837fe6d7
--- /dev/null
+++ b/usr.bin/mandoc/read.c
@@ -0,0 +1,761 @@
+/* $Id: read.c,v 1.1 2011/04/24 16:22:02 schwarze Exp $ */
+/*
+ * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
+ *
+ * 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.
+ */
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "mandoc.h"
+#include "libmandoc.h"
+#include "mdoc.h"
+#include "man.h"
+
+#define REPARSE_LIMIT 1000
+
+struct buf {
+ char *buf; /* binary input buffer */
+ size_t sz; /* size of binary buffer */
+};
+
+struct mparse {
+ enum mandoclevel file_status; /* status of current parse */
+ enum mandoclevel wlevel; /* ignore messages below this */
+ int line; /* line number in the file */
+ enum mparset inttype; /* which parser to use */
+ struct man *pman; /* persistent man parser */
+ struct mdoc *pmdoc; /* persistent mdoc parser */
+ struct man *man; /* man parser */
+ struct mdoc *mdoc; /* mdoc parser */
+ struct roff *roff; /* roff parser (!NULL) */
+ struct regset regs; /* roff registers */
+ int reparse_count; /* finite interp. stack */
+ mandocmsg mmsg; /* warning/error message handler */
+ void *arg; /* argument to mmsg */
+ const char *file;
+};
+
+static void resize_buf(struct buf *, size_t);
+static void mparse_buf_r(struct mparse *, struct buf, int);
+static void mparse_readfd_r(struct mparse *, int, const char *, int);
+static void pset(const char *, int, struct mparse *);
+static void pdesc(struct mparse *, const char *, int);
+static int read_whole_file(const char *, int, struct buf *, int *);
+static void mparse_end(struct mparse *);
+
+static const enum mandocerr mandoclimits[MANDOCLEVEL_MAX] = {
+ MANDOCERR_OK,
+ MANDOCERR_WARNING,
+ MANDOCERR_WARNING,
+ MANDOCERR_ERROR,
+ MANDOCERR_FATAL,
+ MANDOCERR_MAX,
+ MANDOCERR_MAX
+};
+
+static const char * const mandocerrs[MANDOCERR_MAX] = {
+ "ok",
+
+ "generic warning",
+
+ /* related to the prologue */
+ "no title in document",
+ "document title should be all caps",
+ "unknown manual section",
+ "date missing, using today's date",
+ "cannot parse date, using it verbatim",
+ "prologue macros out of order",
+ "duplicate prologue macro",
+ "macro not allowed in prologue",
+ "macro not allowed in body",
+
+ /* related to document structure */
+ ".so is fragile, better use ln(1)",
+ "NAME section must come first",
+ "bad NAME section contents",
+ "manual name not yet set",
+ "sections out of conventional order",
+ "duplicate section name",
+ "section not in conventional manual section",
+
+ /* related to macros and nesting */
+ "skipping obsolete macro",
+ "skipping paragraph macro",
+ "skipping no-space macro",
+ "blocks badly nested",
+ "child violates parent syntax",
+ "nested displays are not portable",
+ "already in literal mode",
+ "line scope broken",
+
+ /* related to missing macro arguments */
+ "skipping empty macro",
+ "argument count wrong",
+ "missing display type",
+ "list type must come first",
+ "tag lists require a width argument",
+ "missing font type",
+ "skipping end of block that is not open",
+
+ /* related to bad macro arguments */
+ "skipping argument",
+ "duplicate argument",
+ "duplicate display type",
+ "duplicate list type",
+ "unknown AT&T UNIX version",
+ "bad Boolean value",
+ "unknown font",
+ "unknown standard specifier",
+ "bad width argument",
+
+ /* related to plain text */
+ "blank line in non-literal context",
+ "tab in non-literal context",
+ "end of line whitespace",
+ "bad comment style",
+ "unknown escape sequence",
+ "unterminated quoted string",
+
+ "generic error",
+
+ /* related to tables */
+ "bad table syntax",
+ "bad table option",
+ "bad table layout",
+ "no table layout cells specified",
+ "no table data cells specified",
+ "ignore data in cell",
+ "data block still open",
+ "ignoring extra data cells",
+
+ "input stack limit exceeded, infinite loop?",
+ "skipping bad character",
+ "escaped character not allowed in a name",
+ "skipping text before the first section header",
+ "skipping unknown macro",
+ "NOT IMPLEMENTED, please use groff: skipping request",
+ "argument count wrong",
+ "skipping end of block that is not open",
+ "missing end of block",
+ "scope open on exit",
+ "uname(3) system call failed",
+ "macro requires line argument(s)",
+ "macro requires body argument(s)",
+ "macro requires argument(s)",
+ "missing list type",
+ "line argument(s) will be lost",
+ "body argument(s) will be lost",
+
+ "generic fatal error",
+
+ "not a manual",
+ "column syntax is inconsistent",
+ "NOT IMPLEMENTED: .Bd -file",
+ "line scope broken, syntax violated",
+ "argument count wrong, violates syntax",
+ "child violates parent syntax",
+ "argument count wrong, violates syntax",
+ "NOT IMPLEMENTED: .so with absolute path or \"..\"",
+ "no document body",
+ "no document prologue",
+ "static buffer exhausted",
+};
+
+static const char * const mandoclevels[MANDOCLEVEL_MAX] = {
+ "SUCCESS",
+ "RESERVED",
+ "WARNING",
+ "ERROR",
+ "FATAL",
+ "BADARG",
+ "SYSERR"
+};
+
+static void
+resize_buf(struct buf *buf, size_t initial)
+{
+
+ buf->sz = buf->sz > initial/2 ? 2 * buf->sz : initial;
+ buf->buf = mandoc_realloc(buf->buf, buf->sz);
+}
+
+static void
+pset(const char *buf, int pos, struct mparse *curp)
+{
+ int i;
+
+ /*
+ * Try to intuit which kind of manual parser should be used. If
+ * passed in by command-line (-man, -mdoc), then use that
+ * explicitly. If passed as -mandoc, then try to guess from the
+ * line: either skip dot-lines, use -mdoc when finding `.Dt', or
+ * default to -man, which is more lenient.
+ *
+ * Separate out pmdoc/pman from mdoc/man: the first persists
+ * through all parsers, while the latter is used per-parse.
+ */
+
+ if ('.' == buf[0] || '\'' == buf[0]) {
+ for (i = 1; buf[i]; i++)
+ if (' ' != buf[i] && '\t' != buf[i])
+ break;
+ if ('\0' == buf[i])
+ return;
+ }
+
+ switch (curp->inttype) {
+ case (MPARSE_MDOC):
+ if (NULL == curp->pmdoc)
+ curp->pmdoc = mdoc_alloc(&curp->regs, curp);
+ assert(curp->pmdoc);
+ curp->mdoc = curp->pmdoc;
+ return;
+ case (MPARSE_MAN):
+ if (NULL == curp->pman)
+ curp->pman = man_alloc(&curp->regs, curp);
+ assert(curp->pman);
+ curp->man = curp->pman;
+ return;
+ default:
+ break;
+ }
+
+ if (pos >= 3 && 0 == memcmp(buf, ".Dd", 3)) {
+ if (NULL == curp->pmdoc)
+ curp->pmdoc = mdoc_alloc(&curp->regs, curp);
+ assert(curp->pmdoc);
+ curp->mdoc = curp->pmdoc;
+ return;
+ }
+
+ if (NULL == curp->pman)
+ curp->pman = man_alloc(&curp->regs, curp);
+ assert(curp->pman);
+ curp->man = curp->pman;
+}
+
+/*
+ * Main parse routine for an opened file. This is called for each
+ * opened file and simply loops around the full input file, possibly
+ * nesting (i.e., with `so').
+ */
+static void
+mparse_buf_r(struct mparse *curp, struct buf blk, int start)
+{
+ const struct tbl_span *span;
+ struct buf ln;
+ enum rofferr rr;
+ int i, of, rc;
+ int pos; /* byte number in the ln buffer */
+ int lnn; /* line number in the real file */
+ unsigned char c;
+
+ memset(&ln, 0, sizeof(struct buf));
+
+ lnn = curp->line;
+ pos = 0;
+
+ for (i = 0; i < (int)blk.sz; ) {
+ if (0 == pos && '\0' == blk.buf[i])
+ break;
+
+ if (start) {
+ curp->line = lnn;
+ curp->reparse_count = 0;
+ }
+
+ while (i < (int)blk.sz && (start || '\0' != blk.buf[i])) {
+
+ /*
+ * When finding an unescaped newline character,
+ * leave the character loop to process the line.
+ * Skip a preceding carriage return, if any.
+ */
+
+ if ('\r' == blk.buf[i] && i + 1 < (int)blk.sz &&
+ '\n' == blk.buf[i + 1])
+ ++i;
+ if ('\n' == blk.buf[i]) {
+ ++i;
+ ++lnn;
+ break;
+ }
+
+ /*
+ * Warn about bogus characters. If you're using
+ * non-ASCII encoding, you're screwing your
+ * readers. Since I'd rather this not happen,
+ * I'll be helpful and drop these characters so
+ * we don't display gibberish. Note to manual
+ * writers: use special characters.
+ */
+
+ c = (unsigned char) blk.buf[i];
+
+ if ( ! (isascii(c) &&
+ (isgraph(c) || isblank(c)))) {
+ mandoc_msg(MANDOCERR_BADCHAR, curp,
+ curp->line, pos, "ignoring byte");
+ i++;
+ continue;
+ }
+
+ /* Trailing backslash = a plain char. */
+
+ if ('\\' != blk.buf[i] || i + 1 == (int)blk.sz) {
+ if (pos >= (int)ln.sz)
+ resize_buf(&ln, 256);
+ ln.buf[pos++] = blk.buf[i++];
+ continue;
+ }
+
+ /*
+ * Found escape and at least one other character.
+ * When it's a newline character, skip it.
+ * When there is a carriage return in between,
+ * skip that one as well.
+ */
+
+ if ('\r' == blk.buf[i + 1] && i + 2 < (int)blk.sz &&
+ '\n' == blk.buf[i + 2])
+ ++i;
+ if ('\n' == blk.buf[i + 1]) {
+ i += 2;
+ ++lnn;
+ continue;
+ }
+
+ if ('"' == blk.buf[i + 1] || '#' == blk.buf[i + 1]) {
+ i += 2;
+ /* Comment, skip to end of line */
+ for (; i < (int)blk.sz; ++i) {
+ if ('\n' == blk.buf[i]) {
+ ++i;
+ ++lnn;
+ break;
+ }
+ }
+
+ /* Backout trailing whitespaces */
+ for (; pos > 0; --pos) {
+ if (ln.buf[pos - 1] != ' ')
+ break;
+ if (pos > 2 && ln.buf[pos - 2] == '\\')
+ break;
+ }
+ break;
+ }
+
+ /* Some other escape sequence, copy & cont. */
+
+ if (pos + 1 >= (int)ln.sz)
+ resize_buf(&ln, 256);
+
+ ln.buf[pos++] = blk.buf[i++];
+ ln.buf[pos++] = blk.buf[i++];
+ }
+
+ if (pos >= (int)ln.sz)
+ resize_buf(&ln, 256);
+
+ ln.buf[pos] = '\0';
+
+ /*
+ * A significant amount of complexity is contained by
+ * the roff preprocessor. It's line-oriented but can be
+ * expressed on one line, so we need at times to
+ * readjust our starting point and re-run it. The roff
+ * preprocessor can also readjust the buffers with new
+ * data, so we pass them in wholesale.
+ */
+
+ of = 0;
+
+rerun:
+ rr = roff_parseln
+ (curp->roff, curp->line,
+ &ln.buf, &ln.sz, of, &of);
+
+ switch (rr) {
+ case (ROFF_REPARSE):
+ if (REPARSE_LIMIT >= ++curp->reparse_count)
+ mparse_buf_r(curp, ln, 0);
+ else
+ mandoc_msg(MANDOCERR_ROFFLOOP, curp,
+ curp->line, pos, NULL);
+ pos = 0;
+ continue;
+ case (ROFF_APPEND):
+ pos = (int)strlen(ln.buf);
+ continue;
+ case (ROFF_RERUN):
+ goto rerun;
+ case (ROFF_IGN):
+ pos = 0;
+ continue;
+ case (ROFF_ERR):
+ assert(MANDOCLEVEL_FATAL <= curp->file_status);
+ break;
+ case (ROFF_SO):
+ mparse_readfd_r(curp, -1, ln.buf + of, 1);
+ if (MANDOCLEVEL_FATAL <= curp->file_status)
+ break;
+ pos = 0;
+ continue;
+ default:
+ break;
+ }
+
+ /*
+ * If we encounter errors in the recursive parse, make
+ * sure we don't continue parsing.
+ */
+
+ if (MANDOCLEVEL_FATAL <= curp->file_status)
+ break;
+
+ /*
+ * If input parsers have not been allocated, do so now.
+ * We keep these instanced betwen parsers, but set them
+ * locally per parse routine since we can use different
+ * parsers with each one.
+ */
+
+ if ( ! (curp->man || curp->mdoc))
+ pset(ln.buf + of, pos - of, curp);
+
+ /*
+ * Lastly, push down into the parsers themselves. One
+ * of these will have already been set in the pset()
+ * routine.
+ * If libroff returns ROFF_TBL, then add it to the
+ * currently open parse. Since we only get here if
+ * there does exist data (see tbl_data.c), we're
+ * guaranteed that something's been allocated.
+ * Do the same for ROFF_EQN.
+ */
+
+ rc = -1;
+
+ if (ROFF_TBL == rr)
+ while (NULL != (span = roff_span(curp->roff))) {
+ rc = curp->man ?
+ man_addspan(curp->man, span) :
+ mdoc_addspan(curp->mdoc, span);
+ if (0 == rc)
+ break;
+ }
+ else if (ROFF_EQN == rr)
+ rc = curp->mdoc ?
+ mdoc_addeqn(curp->mdoc,
+ roff_eqn(curp->roff)) :
+ man_addeqn(curp->man,
+ roff_eqn(curp->roff));
+ else if (curp->man || curp->mdoc)
+ rc = curp->man ?
+ man_parseln(curp->man,
+ curp->line, ln.buf, of) :
+ mdoc_parseln(curp->mdoc,
+ curp->line, ln.buf, of);
+
+ if (0 == rc) {
+ assert(MANDOCLEVEL_FATAL <= curp->file_status);
+ break;
+ }
+
+ /* Temporary buffers typically are not full. */
+
+ if (0 == start && '\0' == blk.buf[i])
+ break;
+
+ /* Start the next input line. */
+
+ pos = 0;
+ }
+
+ free(ln.buf);
+}
+
+static void
+pdesc(struct mparse *curp, const char *file, int fd)
+{
+ struct buf blk;
+ int with_mmap;
+
+ /*
+ * Run for each opened file; may be called more than once for
+ * each full parse sequence if the opened file is nested (i.e.,
+ * from `so'). Simply sucks in the whole file and moves into
+ * the parse phase for the file.
+ */
+
+ if ( ! read_whole_file(file, fd, &blk, &with_mmap)) {
+ curp->file_status = MANDOCLEVEL_SYSERR;
+ return;
+ }
+
+ /* Line number is per-file. */
+
+ curp->line = 1;
+
+ mparse_buf_r(curp, blk, 1);
+
+ if (with_mmap)
+ munmap(blk.buf, blk.sz);
+ else
+ free(blk.buf);
+}
+
+static int
+read_whole_file(const char *file, int fd, struct buf *fb, int *with_mmap)
+{
+ struct stat st;
+ size_t off;
+ ssize_t ssz;
+
+ if (-1 == fstat(fd, &st)) {
+ perror(file);
+ return(0);
+ }
+
+ /*
+ * If we're a regular file, try just reading in the whole entry
+ * via mmap(). This is faster than reading it into blocks, and
+ * since each file is only a few bytes to begin with, I'm not
+ * concerned that this is going to tank any machines.
+ */
+
+ if (S_ISREG(st.st_mode)) {
+ if (st.st_size >= (1U << 31)) {
+ fprintf(stderr, "%s: input too large\n", file);
+ return(0);
+ }
+ *with_mmap = 1;
+ fb->sz = (size_t)st.st_size;
+ fb->buf = mmap(NULL, fb->sz, PROT_READ,
+ MAP_FILE|MAP_SHARED, fd, 0);
+ if (fb->buf != MAP_FAILED)
+ return(1);
+ }
+
+ /*
+ * If this isn't a regular file (like, say, stdin), then we must
+ * go the old way and just read things in bit by bit.
+ */
+
+ *with_mmap = 0;
+ off = 0;
+ fb->sz = 0;
+ fb->buf = NULL;
+ for (;;) {
+ if (off == fb->sz) {
+ if (fb->sz == (1U << 31)) {
+ fprintf(stderr, "%s: input too large\n", file);
+ break;
+ }
+ resize_buf(fb, 65536);
+ }
+ ssz = read(fd, fb->buf + (int)off, fb->sz - off);
+ if (ssz == 0) {
+ fb->sz = off;
+ return(1);
+ }
+ if (ssz == -1) {
+ perror(file);
+ break;
+ }
+ off += (size_t)ssz;
+ }
+
+ free(fb->buf);
+ fb->buf = NULL;
+ return(0);
+}
+
+static void
+mparse_end(struct mparse *curp)
+{
+
+ if (MANDOCLEVEL_FATAL <= curp->file_status)
+ return;
+
+ if (curp->mdoc && ! mdoc_endparse(curp->mdoc)) {
+ assert(MANDOCLEVEL_FATAL <= curp->file_status);
+ return;
+ }
+
+ if (curp->man && ! man_endparse(curp->man)) {
+ assert(MANDOCLEVEL_FATAL <= curp->file_status);
+ return;
+ }
+
+ if ( ! (curp->man || curp->mdoc)) {
+ mandoc_msg(MANDOCERR_NOTMANUAL, curp, 1, 0, NULL);
+ curp->file_status = MANDOCLEVEL_FATAL;
+ return;
+ }
+
+ roff_endparse(curp->roff);
+}
+
+static void
+mparse_readfd_r(struct mparse *curp, int fd, const char *file, int re)
+{
+ const char *svfile;
+
+ if (-1 == fd)
+ if (-1 == (fd = open(file, O_RDONLY, 0))) {
+ perror(file);
+ curp->file_status = MANDOCLEVEL_SYSERR;
+ return;
+ }
+
+ svfile = curp->file;
+ curp->file = file;
+
+ pdesc(curp, file, fd);
+
+ if (0 == re && MANDOCLEVEL_FATAL > curp->file_status)
+ mparse_end(curp);
+
+ if (STDIN_FILENO != fd && -1 == close(fd))
+ perror(file);
+
+ curp->file = svfile;
+}
+
+enum mandoclevel
+mparse_readfd(struct mparse *curp, int fd, const char *file)
+{
+
+ mparse_readfd_r(curp, fd, file, 0);
+ return(curp->file_status);
+}
+
+struct mparse *
+mparse_alloc(enum mparset inttype, enum mandoclevel wlevel, mandocmsg mmsg, void *arg)
+{
+ struct mparse *curp;
+
+ assert(wlevel <= MANDOCLEVEL_FATAL);
+
+ curp = mandoc_calloc(1, sizeof(struct mparse));
+
+ curp->wlevel = wlevel;
+ curp->mmsg = mmsg;
+ curp->arg = arg;
+ curp->inttype = inttype;
+
+ curp->roff = roff_alloc(&curp->regs, curp);
+ return(curp);
+}
+
+void
+mparse_reset(struct mparse *curp)
+{
+
+ memset(&curp->regs, 0, sizeof(struct regset));
+
+ roff_reset(curp->roff);
+
+ if (curp->mdoc)
+ mdoc_reset(curp->mdoc);
+ if (curp->man)
+ man_reset(curp->man);
+
+ curp->file_status = MANDOCLEVEL_OK;
+ curp->mdoc = NULL;
+ curp->man = NULL;
+}
+
+void
+mparse_free(struct mparse *curp)
+{
+
+ if (curp->pmdoc)
+ mdoc_free(curp->pmdoc);
+ if (curp->pman)
+ man_free(curp->pman);
+ if (curp->roff)
+ roff_free(curp->roff);
+
+ free(curp);
+}
+
+void
+mparse_result(struct mparse *curp, struct mdoc **mdoc, struct man **man)
+{
+
+ if (mdoc)
+ *mdoc = curp->mdoc;
+ if (man)
+ *man = curp->man;
+}
+
+void
+mandoc_vmsg(enum mandocerr t, struct mparse *m,
+ int ln, int pos, const char *fmt, ...)
+{
+ char buf[256];
+ va_list ap;
+
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf) - 1, fmt, ap);
+ va_end(ap);
+
+ mandoc_msg(t, m, ln, pos, buf);
+}
+
+void
+mandoc_msg(enum mandocerr er, struct mparse *m,
+ int ln, int col, const char *msg)
+{
+ enum mandoclevel level;
+
+ level = MANDOCLEVEL_FATAL;
+ while (er < mandoclimits[level])
+ level--;
+
+ if (level < m->wlevel)
+ return;
+
+ if (m->mmsg)
+ (*m->mmsg)(er, level, m->file, ln, col, msg);
+
+ if (m->file_status < level)
+ m->file_status = level;
+}
+
+const char *
+mparse_strerror(enum mandocerr er)
+{
+
+ return(mandocerrs[er]);
+}
+
+const char *
+mparse_strlevel(enum mandoclevel lvl)
+{
+ return(mandoclevels[lvl]);
+}
diff --git a/usr.bin/mandoc/roff.3 b/usr.bin/mandoc/roff.3
deleted file mode 100644
index 58843b605d0..00000000000
--- a/usr.bin/mandoc/roff.3
+++ /dev/null
@@ -1,177 +0,0 @@
-.\" $Id: roff.3,v 1.6 2011/01/04 22:28:17 schwarze Exp $
-.\"
-.\" Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
-.\"
-.\" 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.
-.\"
-.Dd $Mdocdate: January 4 2011 $
-.Dt ROFF 3
-.Os
-.Sh NAME
-.Nm roff ,
-.Nm roff_alloc ,
-.Nm roff_endparse ,
-.Nm roff_free ,
-.Nm roff_parseln ,
-.Nm roff_reset ,
-.Nm roff_span
-.Nd roff macro compiler library
-.Sh SYNOPSIS
-.In mandoc.h
-.In roff.h
-.Ft "struct roff *"
-.Fo roff_alloc
-.Fa "struct regset *regs"
-.Fa "void *data"
-.Fa "mandocmsg msgs"
-.Fc
-.Ft void
-.Fn roff_endparse "struct roff *roff"
-.Ft void
-.Fn roff_free "struct roff *roff"
-.Ft "enum rofferr"
-.Fo roff_parseln
-.Fa "struct roff *roff"
-.Fa "int line"
-.Fa "char **bufp"
-.Fa "size_t *bufsz"
-.Fa "int pos"
-.Fa "int *offs"
-.Fc
-.Ft void
-.Fn roff_reset "struct roff *roff"
-.Ft "const struct tbl_span *"
-.Fn roff_span "const struct roff *roff"
-.Sh DESCRIPTION
-The
-.Nm
-library processes lines of
-.Xr roff 7
-input.
-.Pp
-In general, applications initiate a parsing sequence with
-.Fn roff_alloc ,
-parse each line in a document with
-.Fn roff_parseln ,
-close the parsing session with
-.Fn roff_endparse ,
-and finally free all allocated memory with
-.Fn roff_free .
-The
-.Fn roff_reset
-function may be used in order to reset the parser for another input
-sequence.
-.Pp
-The
-.Fn roff_parseln
-function should be invoked before passing a line into the
-.Xr mdoc 3
-or
-.Xr man 3
-libraries.
-.Pp
-See the
-.Sx EXAMPLES
-section for a full example.
-.Sh REFERENCE
-This section further defines the
-.Sx Types
-and
-.Sx Functions
-available to programmers.
-.Ss Types
-Functions (see
-.Sx Functions )
-may use the following types:
-.Bl -ohang
-.It Vt "enum rofferr"
-Instructions for further processing to the caller of
-.Fn roff_parseln .
-.It Vt struct roff
-An opaque type defined in
-.Pa roff.c .
-Its values are only used privately within the library.
-.It Vt mandocmsg
-A function callback type defined in
-.Pa mandoc.h .
-.El
-.Ss Functions
-Function descriptions follow:
-.Bl -ohang
-.It Fn roff_alloc
-Allocates a parsing structure.
-The
-.Fa data
-pointer is passed to
-.Fa msgs .
-Returns NULL on failure.
-If non-NULL, the pointer must be freed with
-.Fn roff_free .
-.It Fn roff_reset
-Reset the parser for another parse routine.
-After its use,
-.Fn roff_parseln
-behaves as if invoked for the first time.
-.It Fn roff_free
-Free all resources of a parser.
-The pointer is no longer valid after invocation.
-.It Fn roff_parseln
-Parse a nil-terminated line of input.
-The character array
-.Fa bufp
-may be modified or reallocated within this function.
-In the latter case,
-.Fa bufsz
-will be modified accordingly.
-The
-.Fa offs
-pointer will be modified if the line start during subsequent processing
-of the line is not at the zeroth index.
-This line should not contain the trailing newline.
-Returns 0 on failure, 1 on success.
-.It Fn roff_endparse
-Signals that the parse is complete.
-.It Fn roff_span
-If
-.Fn roff_parseln
-returned
-.Va ROFF_TBL ,
-return the last parsed table row.
-Returns NULL otherwise.
-.El
-.Sh EXAMPLES
-See
-.Pa main.c
-in the source distribution for an example of usage.
-.Sh SEE ALSO
-.Xr mandoc 1 ,
-.Xr man 3 ,
-.Xr mdoc 3 ,
-.Xr roff 7
-.Sh AUTHORS
-The
-.Nm
-library was written by
-.An Kristaps Dzonsons Aq kristaps@bsd.lv .
-.Sh BUGS
-The implementation of user-defined strings needs improvement:
-.Bl -dash
-.It
-String values are taken literally and are not interpreted.
-.It
-Parsing of quoted strings is incomplete.
-.It
-The stings are stored internally using a singly linked list,
-which is fine for small numbers of strings,
-but ineffient when handling many strings.
-.El
diff --git a/usr.bin/mandoc/roff.c b/usr.bin/mandoc/roff.c
index 300a9a35c53..74bb83e368a 100644
--- a/usr.bin/mandoc/roff.c
+++ b/usr.bin/mandoc/roff.c
@@ -1,4 +1,4 @@
-/* $Id: roff.c,v 1.34 2011/04/21 22:59:54 schwarze Exp $ */
+/* $Id: roff.c,v 1.35 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -24,15 +24,11 @@
#include <stdio.h>
#include "mandoc.h"
-#include "roff.h"
#include "libroff.h"
#include "libmandoc.h"
#define RSTACK_MAX 128
-#define ROFF_CTL(c) \
- ('.' == (c) || '\'' == (c))
-
enum rofft {
ROFF_ad,
ROFF_am,
@@ -80,9 +76,8 @@ struct roffstr {
};
struct roff {
+ struct mparse *parse; /* parse point */
struct roffnode *last; /* leaf of stack */
- mandocmsg msg; /* err/warn/fatal messages */
- void *data; /* privdata for messages */
enum roffrule rstack[RSTACK_MAX]; /* stack of !`ie' rules */
int rstackpos; /* position in rstack */
struct regset *regs; /* read/writable registers */
@@ -278,10 +273,6 @@ roffnode_pop(struct roff *r)
assert(r->last);
p = r->last;
- if (ROFF_el == p->tok)
- if (r->rstackpos > -1)
- r->rstackpos--;
-
r->last = r->last->parent;
free(p->name);
free(p->end);
@@ -357,14 +348,13 @@ roff_free(struct roff *r)
struct roff *
-roff_alloc(struct regset *regs, void *data, const mandocmsg msg)
+roff_alloc(struct regset *regs, struct mparse *parse)
{
struct roff *r;
r = mandoc_calloc(1, sizeof(struct roff));
r->regs = regs;
- r->msg = msg;
- r->data = data;
+ r->parse = parse;
r->rstackpos = -1;
roff_hash_init();
@@ -475,7 +465,7 @@ roff_parseln(struct roff *r, int ln, char **bufp,
{
enum rofft t;
enum rofferr e;
- int ppos;
+ int ppos, ctl;
/*
* Run the reserved-word filter only if we have some reserved
@@ -485,6 +475,9 @@ roff_parseln(struct roff *r, int ln, char **bufp,
if (r->first_string && ! roff_res(r, bufp, szp, pos))
return(ROFF_REPARSE);
+ ppos = pos;
+ ctl = mandoc_getcontrol(*bufp, &pos);
+
/*
* First, if a scope is open and we're not a macro, pass the
* text through the macro's filter. If a scope isn't open and
@@ -493,7 +486,7 @@ roff_parseln(struct roff *r, int ln, char **bufp,
* no matter our state.
*/
- if (r->last && ! ROFF_CTL((*bufp)[pos])) {
+ if (r->last && ! ctl) {
t = r->last->tok;
assert(roffs[t].text);
e = (*roffs[t].text)
@@ -502,18 +495,18 @@ roff_parseln(struct roff *r, int ln, char **bufp,
if (ROFF_CONT != e)
return(e);
if (r->eqn)
- return(eqn_read(&r->eqn, ln, *bufp, *offs));
+ return(eqn_read(&r->eqn, ln, *bufp, pos));
if (r->tbl)
- return(tbl_read(r->tbl, ln, *bufp, *offs));
+ return(tbl_read(r->tbl, ln, *bufp, pos));
return(ROFF_CONT);
- } else if ( ! ROFF_CTL((*bufp)[pos])) {
+ } else if ( ! ctl) {
if (r->eqn)
- return(eqn_read(&r->eqn, ln, *bufp, *offs));
+ return(eqn_read(&r->eqn, ln, *bufp, pos));
if (r->tbl)
- return(tbl_read(r->tbl, ln, *bufp, *offs));
+ return(tbl_read(r->tbl, ln, *bufp, pos));
return(ROFF_CONT);
} else if (r->eqn)
- return(eqn_read(&r->eqn, ln, *bufp, *offs));
+ return(eqn_read(&r->eqn, ln, *bufp, ppos));
/*
* If a scope is open, go to the child handler for that macro,
@@ -526,7 +519,7 @@ roff_parseln(struct roff *r, int ln, char **bufp,
assert(roffs[t].sub);
return((*roffs[t].sub)
(r, t, bufp, szp,
- ln, pos, pos, offs));
+ ln, ppos, pos, offs));
}
/*
@@ -535,7 +528,6 @@ roff_parseln(struct roff *r, int ln, char **bufp,
* the compilers handle it.
*/
- ppos = pos;
if (ROFF_MAX == (t = roff_parse(r, *bufp, &pos)))
return(ROFF_CONT);
@@ -551,25 +543,24 @@ roff_endparse(struct roff *r)
{
if (r->last)
- (*r->msg)(MANDOCERR_SCOPEEXIT, r->data,
+ mandoc_msg(MANDOCERR_SCOPEEXIT, r->parse,
r->last->line, r->last->col, NULL);
if (r->eqn) {
- (*r->msg)(MANDOCERR_SCOPEEXIT, r->data,
+ mandoc_msg(MANDOCERR_SCOPEEXIT, r->parse,
r->eqn->eqn.line, r->eqn->eqn.pos, NULL);
eqn_end(r->eqn);
r->eqn = NULL;
}
if (r->tbl) {
- (*r->msg)(MANDOCERR_SCOPEEXIT, r->data,
+ mandoc_msg(MANDOCERR_SCOPEEXIT, r->parse,
r->tbl->line, r->tbl->pos, NULL);
tbl_end(r->tbl);
r->tbl = NULL;
}
}
-
/*
* Parse a roff node's type from the input buffer. This must be in the
* form of ".foo xxx" in the usual way.
@@ -581,13 +572,7 @@ roff_parse(struct roff *r, const char *buf, int *pos)
size_t maclen;
enum rofft t;
- assert(ROFF_CTL(buf[*pos]));
- (*pos)++;
-
- while (' ' == buf[*pos] || '\t' == buf[*pos])
- (*pos)++;
-
- if ('\0' == buf[*pos])
+ if ('\0' == buf[*pos] || '"' == buf[*pos])
return(ROFF_MAX);
mac = buf + *pos;
@@ -597,6 +582,7 @@ roff_parse(struct roff *r, const char *buf, int *pos)
? ROFF_USERDEF : roff_hash_find(mac, maclen);
*pos += (int)maclen;
+
while (buf[*pos] && ' ' == buf[*pos])
(*pos)++;
@@ -635,7 +621,7 @@ roff_cblock(ROFF_ARGS)
*/
if (NULL == r->last) {
- (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL);
+ mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL);
return(ROFF_IGN);
}
@@ -654,12 +640,12 @@ roff_cblock(ROFF_ARGS)
case (ROFF_ig):
break;
default:
- (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL);
+ mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL);
return(ROFF_IGN);
}
if ((*bufp)[pos])
- (*r->msg)(MANDOCERR_ARGSLOST, r->data, ln, pos, NULL);
+ mandoc_msg(MANDOCERR_ARGSLOST, r->parse, ln, pos, NULL);
roffnode_pop(r);
roffnode_cleanscope(r);
@@ -686,7 +672,7 @@ roff_ccond(ROFF_ARGS)
{
if (NULL == r->last) {
- (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL);
+ mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL);
return(ROFF_IGN);
}
@@ -698,17 +684,17 @@ roff_ccond(ROFF_ARGS)
case (ROFF_if):
break;
default:
- (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL);
+ mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL);
return(ROFF_IGN);
}
if (r->last->endspan > -1) {
- (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL);
+ mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL);
return(ROFF_IGN);
}
if ((*bufp)[pos])
- (*r->msg)(MANDOCERR_ARGSLOST, r->data, ln, pos, NULL);
+ mandoc_msg(MANDOCERR_ARGSLOST, r->parse, ln, pos, NULL);
roffnode_pop(r);
roffnode_cleanscope(r);
@@ -728,7 +714,7 @@ roff_block(ROFF_ARGS)
if (ROFF_ig != tok) {
if ('\0' == (*bufp)[pos]) {
- (*r->msg)(MANDOCERR_NOARGS, r->data, ln, ppos, NULL);
+ mandoc_msg(MANDOCERR_NOARGS, r->parse, ln, ppos, NULL);
return(ROFF_IGN);
}
@@ -742,7 +728,7 @@ roff_block(ROFF_ARGS)
if (ROFF_de == tok)
name = *bufp + pos;
else
- (*r->msg)(MANDOCERR_REQUEST, r->data, ln, ppos,
+ mandoc_msg(MANDOCERR_REQUEST, r->parse, ln, ppos,
roffs[tok].name);
while ((*bufp)[pos] && ! isspace((unsigned char)(*bufp)[pos]))
@@ -790,7 +776,7 @@ roff_block(ROFF_ARGS)
r->last->end[(int)sz] = '\0';
if ((*bufp)[pos])
- (*r->msg)(MANDOCERR_ARGSLOST, r->data, ln, pos, NULL);
+ mandoc_msg(MANDOCERR_ARGSLOST, r->parse, ln, pos, NULL);
return(ROFF_IGN);
}
@@ -813,11 +799,7 @@ roff_block_sub(ROFF_ARGS)
*/
if (r->last->end) {
- i = pos + 1;
- while (' ' == (*bufp)[i] || '\t' == (*bufp)[i])
- i++;
-
- for (j = 0; r->last->end[j]; j++, i++)
+ for (i = pos, j = 0; r->last->end[j]; j++, i++)
if ((*bufp)[i] != r->last->end[j])
break;
@@ -828,6 +810,10 @@ roff_block_sub(ROFF_ARGS)
roffnode_pop(r);
roffnode_cleanscope(r);
+ while (' ' == (*bufp)[i] || '\t' == (*bufp)[i])
+ i++;
+
+ pos = i;
if (ROFF_MAX != roff_parse(r, *bufp, &pos))
return(ROFF_RERUN);
return(ROFF_IGN);
@@ -839,8 +825,8 @@ roff_block_sub(ROFF_ARGS)
* pulling it out of the hashtable.
*/
- ppos = pos;
- t = roff_parse(r, *bufp, &pos);
+ if (ROFF_MAX == (t = roff_parse(r, *bufp, &pos)))
+ return(ROFF_IGN);
/*
* Macros other than block-end are only significant
@@ -877,7 +863,6 @@ roff_cond_sub(ROFF_ARGS)
enum rofft t;
enum roffrule rr;
- ppos = pos;
rr = r->last->rule;
/*
@@ -971,7 +956,7 @@ roff_line_ignore(ROFF_ARGS)
{
if (ROFF_it == tok)
- (*r->msg)(MANDOCERR_REQUEST, r->data, ln, ppos, "it");
+ mandoc_msg(MANDOCERR_REQUEST, r->parse, ln, ppos, "it");
return(ROFF_IGN);
}
@@ -983,29 +968,20 @@ roff_cond(ROFF_ARGS)
int sv;
enum roffrule rule;
- /* Stack overflow! */
-
- if (ROFF_ie == tok && r->rstackpos == RSTACK_MAX - 1) {
- (*r->msg)(MANDOCERR_MEM, r->data, ln, ppos, NULL);
- return(ROFF_ERR);
- }
-
- /* First, evaluate the conditional. */
+ /*
+ * An `.el' has no conditional body: it will consume the value
+ * of the current rstack entry set in prior `ie' calls or
+ * defaults to DENY.
+ *
+ * If we're not an `el', however, then evaluate the conditional.
+ */
- if (ROFF_el == tok) {
- /*
- * An `.el' will get the value of the current rstack
- * entry set in prior `ie' calls or defaults to DENY.
- */
- if (r->rstackpos < 0)
- rule = ROFFRULE_DENY;
- else
- rule = r->rstack[r->rstackpos];
- } else
- rule = roff_evalcond(*bufp, &pos);
+ rule = ROFF_el == tok ?
+ (r->rstackpos < 0 ?
+ ROFFRULE_DENY : r->rstack[r->rstackpos--]) :
+ roff_evalcond(*bufp, &pos);
sv = pos;
-
while (' ' == (*bufp)[pos])
pos++;
@@ -1017,7 +993,7 @@ roff_cond(ROFF_ARGS)
*/
if ('\0' == (*bufp)[pos] && sv != pos) {
- (*r->msg)(MANDOCERR_NOARGS, r->data, ln, ppos, NULL);
+ mandoc_msg(MANDOCERR_NOARGS, r->parse, ln, ppos, NULL);
return(ROFF_IGN);
}
@@ -1025,16 +1001,20 @@ roff_cond(ROFF_ARGS)
r->last->rule = rule;
+ /*
+ * An if-else will put the NEGATION of the current evaluated
+ * conditional into the stack of rules.
+ */
+
if (ROFF_ie == tok) {
- /*
- * An if-else will put the NEGATION of the current
- * evaluated conditional into the stack.
- */
- r->rstackpos++;
- if (ROFFRULE_DENY == r->last->rule)
- r->rstack[r->rstackpos] = ROFFRULE_ALLOW;
- else
- r->rstack[r->rstackpos] = ROFFRULE_DENY;
+ if (r->rstackpos == RSTACK_MAX - 1) {
+ mandoc_msg(MANDOCERR_MEM,
+ r->parse, ln, ppos, NULL);
+ return(ROFF_ERR);
+ }
+ r->rstack[++r->rstackpos] =
+ ROFFRULE_DENY == r->last->rule ?
+ ROFFRULE_ALLOW : ROFFRULE_DENY;
}
/* If the parent has false as its rule, then so do we. */
@@ -1144,7 +1124,7 @@ roff_TE(ROFF_ARGS)
{
if (NULL == r->tbl)
- (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL);
+ mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL);
else
tbl_end(r->tbl);
@@ -1158,7 +1138,7 @@ roff_T_(ROFF_ARGS)
{
if (NULL == r->tbl)
- (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL);
+ mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL);
else
tbl_restart(ppos, ln, r->tbl);
@@ -1188,7 +1168,7 @@ static enum rofferr
roff_EN(ROFF_ARGS)
{
- (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL);
+ mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL);
return(ROFF_IGN);
}
@@ -1199,11 +1179,11 @@ roff_TS(ROFF_ARGS)
struct tbl_node *t;
if (r->tbl) {
- (*r->msg)(MANDOCERR_SCOPEBROKEN, r->data, ln, ppos, NULL);
+ mandoc_msg(MANDOCERR_SCOPEBROKEN, r->parse, ln, ppos, NULL);
tbl_end(r->tbl);
}
- t = tbl_alloc(ppos, ln, r->data, r->msg);
+ t = tbl_alloc(ppos, ln, r->parse);
if (r->last_tbl)
r->last_tbl->next = t;
@@ -1220,7 +1200,7 @@ roff_so(ROFF_ARGS)
{
char *name;
- (*r->msg)(MANDOCERR_SO, r->data, ln, ppos, NULL);
+ mandoc_msg(MANDOCERR_SO, r->parse, ln, ppos, NULL);
/*
* Handle `so'. Be EXTREMELY careful, as we shouldn't be
@@ -1231,7 +1211,7 @@ roff_so(ROFF_ARGS)
name = *bufp + pos;
if ('/' == *name || strstr(name, "../") || strstr(name, "/..")) {
- (*r->msg)(MANDOCERR_SOPATH, r->data, ln, pos, NULL);
+ mandoc_msg(MANDOCERR_SOPATH, r->parse, ln, pos, NULL);
return(ROFF_ERR);
}
@@ -1254,7 +1234,7 @@ roff_userdef(ROFF_ARGS)
cp = *bufp + pos;
for (i = 0; i < 9; i++)
arg[i] = '\0' == *cp ? "" :
- mandoc_getarg(&cp, r->msg, r->data, ln, &pos);
+ mandoc_getarg(r->parse, &cp, ln, &pos);
/*
* Expand macro arguments.
@@ -1310,7 +1290,7 @@ roff_getname(struct roff *r, char **cpp, int ln, int pos)
cp++;
if ('\\' == *cp)
continue;
- (*r->msg)(MANDOCERR_NAMESC, r->data, ln, pos, NULL);
+ mandoc_msg(MANDOCERR_NAMESC, r->parse, ln, pos, NULL);
*cp = '\0';
name = cp;
}
diff --git a/usr.bin/mandoc/roff.h b/usr.bin/mandoc/roff.h
deleted file mode 100644
index 7b9197f4eab..00000000000
--- a/usr.bin/mandoc/roff.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* $Id: roff.h,v 1.8 2011/03/20 23:36:42 schwarze Exp $ */
-/*
- * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- *
- * 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.
- */
-#ifndef ROFF_H
-#define ROFF_H
-
-enum rofferr {
- ROFF_CONT, /* continue processing line */
- ROFF_RERUN, /* re-run roff interpreter with offset */
- ROFF_APPEND, /* re-run main parser, appending next line */
- ROFF_REPARSE, /* re-run main parser on the result */
- ROFF_SO, /* include another file */
- ROFF_IGN, /* ignore current line */
- ROFF_TBL, /* a table row was successfully parsed */
- ROFF_EQN, /* an equation was successfully parsed */
- ROFF_ERR /* badness: puke and stop */
-};
-
-__BEGIN_DECLS
-
-struct roff;
-
-void roff_free(struct roff *);
-struct roff *roff_alloc(struct regset *, void *, mandocmsg);
-void roff_reset(struct roff *);
-enum rofferr roff_parseln(struct roff *, int,
- char **, size_t *, int, int *);
-void roff_endparse(struct roff *);
-const struct tbl_span *roff_span(const struct roff *);
-const struct eqn *roff_eqn(const struct roff *);
-
-__END_DECLS
-
-#endif /*!ROFF_H*/
diff --git a/usr.bin/mandoc/st.c b/usr.bin/mandoc/st.c
index b316e377180..fc1c10f2331 100644
--- a/usr.bin/mandoc/st.c
+++ b/usr.bin/mandoc/st.c
@@ -1,4 +1,4 @@
-/* $Id: st.c,v 1.5 2010/07/31 23:42:04 schwarze Exp $ */
+/* $Id: st.c,v 1.6 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -18,6 +18,7 @@
#include <string.h>
#include <time.h>
+#include "mdoc.h"
#include "mandoc.h"
#include "libmdoc.h"
diff --git a/usr.bin/mandoc/tbl.c b/usr.bin/mandoc/tbl.c
index c91b4bee7c0..b708abcb861 100644
--- a/usr.bin/mandoc/tbl.c
+++ b/usr.bin/mandoc/tbl.c
@@ -1,4 +1,4 @@
-/* $Id: tbl.c,v 1.5 2011/01/25 12:24:26 schwarze Exp $ */
+/* $Id: tbl.c,v 1.6 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -22,7 +22,6 @@
#include <time.h>
#include "mandoc.h"
-#include "roff.h"
#include "libmandoc.h"
#include "libroff.h"
@@ -67,15 +66,14 @@ tbl_read(struct tbl_node *tbl, int ln, const char *p, int offs)
}
struct tbl_node *
-tbl_alloc(int pos, int line, void *data, const mandocmsg msg)
+tbl_alloc(int pos, int line, struct mparse *parse)
{
struct tbl_node *p;
p = mandoc_calloc(1, sizeof(struct tbl_node));
p->line = line;
p->pos = pos;
- p->data = data;
- p->msg = msg;
+ p->parse = parse;
p->part = TBL_PART_OPTS;
p->opts.tab = '\t';
p->opts.linesize = 12;
@@ -126,14 +124,16 @@ void
tbl_restart(int line, int pos, struct tbl_node *tbl)
{
if (TBL_PART_CDATA == tbl->part)
- TBL_MSG(tbl, MANDOCERR_TBLBLOCK, tbl->line, tbl->pos);
+ mandoc_msg(MANDOCERR_TBLBLOCK, tbl->parse,
+ tbl->line, tbl->pos, NULL);
tbl->part = TBL_PART_LAYOUT;
tbl->line = line;
tbl->pos = pos;
if (NULL == tbl->first_span || NULL == tbl->first_span->first)
- TBL_MSG(tbl, MANDOCERR_TBLNODATA, tbl->line, tbl->pos);
+ mandoc_msg(MANDOCERR_TBLNODATA, tbl->parse,
+ tbl->line, tbl->pos, NULL);
}
const struct tbl_span *
@@ -154,12 +154,14 @@ tbl_end(struct tbl_node *tbl)
{
if (NULL == tbl->first_span || NULL == tbl->first_span->first)
- TBL_MSG(tbl, MANDOCERR_TBLNODATA, tbl->line, tbl->pos);
+ mandoc_msg(MANDOCERR_TBLNODATA, tbl->parse,
+ tbl->line, tbl->pos, NULL);
if (tbl->last_span)
tbl->last_span->flags |= TBL_SPAN_LAST;
if (TBL_PART_CDATA == tbl->part)
- TBL_MSG(tbl, MANDOCERR_TBLBLOCK, tbl->line, tbl->pos);
+ mandoc_msg(MANDOCERR_TBLBLOCK, tbl->parse,
+ tbl->line, tbl->pos, NULL);
}
diff --git a/usr.bin/mandoc/tbl_data.c b/usr.bin/mandoc/tbl_data.c
index 0a27c052083..a358e6e0945 100644
--- a/usr.bin/mandoc/tbl_data.c
+++ b/usr.bin/mandoc/tbl_data.c
@@ -1,4 +1,4 @@
-/* $Id: tbl_data.c,v 1.10 2011/04/21 22:59:54 schwarze Exp $ */
+/* $Id: tbl_data.c,v 1.11 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -60,7 +60,8 @@ data(struct tbl_node *tbl, struct tbl_span *dp,
*/
if (NULL == cp) {
- TBL_MSG(tbl, MANDOCERR_TBLEXTRADAT, ln, *pos);
+ mandoc_msg(MANDOCERR_TBLEXTRADAT,
+ tbl->parse, ln, *pos, NULL);
/* Skip to the end... */
while (p[*pos])
(*pos)++;
@@ -126,7 +127,8 @@ data(struct tbl_node *tbl, struct tbl_span *dp,
TBL_CELL_DHORIZ == dat->layout->pos ||
TBL_CELL_DOWN == dat->layout->pos)
if (TBL_DATA_DATA == dat->pos && '\0' != *dat->string)
- TBL_MSG(tbl, MANDOCERR_TBLIGNDATA, ln, sv);
+ mandoc_msg(MANDOCERR_TBLIGNDATA,
+ tbl->parse, ln, sv, NULL);
return(1);
}
@@ -168,7 +170,8 @@ tbl_cdata(struct tbl_node *tbl, int ln, const char *p)
dat->string = mandoc_strdup(p);
if (TBL_CELL_DOWN == dat->layout->pos)
- TBL_MSG(tbl, MANDOCERR_TBLIGNDATA, ln, pos);
+ mandoc_msg(MANDOCERR_TBLIGNDATA,
+ tbl->parse, ln, pos, NULL);
return(0);
}
@@ -206,7 +209,7 @@ tbl_data(struct tbl_node *tbl, int ln, const char *p)
pos = 0;
if ('\0' == p[pos]) {
- TBL_MSG(tbl, MANDOCERR_TBL, ln, pos);
+ mandoc_msg(MANDOCERR_TBL, tbl->parse, ln, pos, NULL);
return(0);
}
diff --git a/usr.bin/mandoc/tbl_layout.c b/usr.bin/mandoc/tbl_layout.c
index 28a0d2766df..85efa0ee561 100644
--- a/usr.bin/mandoc/tbl_layout.c
+++ b/usr.bin/mandoc/tbl_layout.c
@@ -1,4 +1,4 @@
-/* $Id: tbl_layout.c,v 1.7 2011/01/16 01:11:50 schwarze Exp $ */
+/* $Id: tbl_layout.c,v 1.8 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -100,7 +100,8 @@ mod:
(*pos)++;
goto mod;
}
- TBL_MSG(tbl, MANDOCERR_TBLLAYOUT, ln, *pos);
+ mandoc_msg(MANDOCERR_TBLLAYOUT,
+ tbl->parse, ln, *pos, NULL);
return(0);
}
@@ -117,7 +118,8 @@ mod:
/* No greater than 4 digits. */
if (4 == i) {
- TBL_MSG(tbl, MANDOCERR_TBLLAYOUT, ln, *pos);
+ mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse,
+ ln, *pos, NULL);
return(0);
}
@@ -156,7 +158,8 @@ mod:
(*pos)--;
break;
default:
- TBL_MSG(tbl, MANDOCERR_TBLLAYOUT, ln, *pos - 1);
+ mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse,
+ ln, *pos - 1, NULL);
return(0);
}
@@ -171,7 +174,8 @@ mod:
break;
}
- TBL_MSG(tbl, MANDOCERR_TBLLAYOUT, ln, *pos - 1);
+ mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse,
+ ln, *pos - 1, NULL);
return(0);
}
@@ -189,7 +193,8 @@ cell(struct tbl_node *tbl, struct tbl_row *rp,
break;
if (KEYS_MAX == i) {
- TBL_MSG(tbl, MANDOCERR_TBLLAYOUT, ln, *pos);
+ mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse,
+ ln, *pos, NULL);
return(0);
}
@@ -205,7 +210,8 @@ cell(struct tbl_node *tbl, struct tbl_row *rp,
if (TBL_CELL_SPAN == c) {
if (NULL == rp->first) {
- TBL_MSG(tbl, MANDOCERR_TBLLAYOUT, ln, *pos);
+ mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse,
+ ln, *pos, NULL);
return(0);
} else if (rp->last)
switch (rp->last->pos) {
@@ -213,7 +219,8 @@ cell(struct tbl_node *tbl, struct tbl_row *rp,
case (TBL_CELL_DVERT):
case (TBL_CELL_HORIZ):
case (TBL_CELL_DHORIZ):
- TBL_MSG(tbl, MANDOCERR_TBLLAYOUT, ln, *pos);
+ mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse,
+ ln, *pos, NULL);
return(0);
default:
break;
@@ -226,7 +233,7 @@ cell(struct tbl_node *tbl, struct tbl_row *rp,
*/
if (TBL_CELL_DOWN == c && rp == tbl->first_row) {
- TBL_MSG(tbl, MANDOCERR_TBLLAYOUT, ln, *pos);
+ mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse, ln, *pos, NULL);
return(0);
}
@@ -244,7 +251,7 @@ cell(struct tbl_node *tbl, struct tbl_row *rp,
if (rp->last && (TBL_CELL_VERT == c || TBL_CELL_DVERT == c) &&
(TBL_CELL_VERT == rp->last->pos ||
TBL_CELL_DVERT == rp->last->pos)) {
- TBL_MSG(tbl, MANDOCERR_TBLLAYOUT, ln, *pos - 1);
+ mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse, ln, *pos - 1, NULL);
return(0);
}
@@ -285,7 +292,8 @@ cell:
if ('.' == p[*pos]) {
tbl->part = TBL_PART_DATA;
if (NULL == tbl->first_row)
- TBL_MSG(tbl, MANDOCERR_TBLNOLAYOUT, ln, *pos);
+ mandoc_msg(MANDOCERR_TBLNOLAYOUT, tbl->parse,
+ ln, *pos, NULL);
(*pos)++;
return;
}
diff --git a/usr.bin/mandoc/tbl_opts.c b/usr.bin/mandoc/tbl_opts.c
index fbdefceb333..8111a2aea83 100644
--- a/usr.bin/mandoc/tbl_opts.c
+++ b/usr.bin/mandoc/tbl_opts.c
@@ -1,4 +1,4 @@
-/* $Id: tbl_opts.c,v 1.3 2011/04/21 22:59:54 schwarze Exp $ */
+/* $Id: tbl_opts.c,v 1.4 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -20,6 +20,7 @@
#include <string.h>
#include "mandoc.h"
+#include "libmandoc.h"
#include "libroff.h"
enum tbl_ident {
@@ -88,7 +89,8 @@ arg(struct tbl_node *tbl, int ln, const char *p, int *pos, enum tbl_ident key)
/* Arguments always begin with a parenthesis. */
if ('(' != p[*pos]) {
- TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos);
+ mandoc_msg(MANDOCERR_TBL, tbl->parse,
+ ln, *pos, NULL);
return(0);
}
@@ -103,12 +105,14 @@ arg(struct tbl_node *tbl, int ln, const char *p, int *pos, enum tbl_ident key)
switch (key) {
case (KEY_DELIM):
if ('\0' == p[(*pos)++]) {
- TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos - 1);
+ mandoc_msg(MANDOCERR_TBL, tbl->parse,
+ ln, *pos - 1, NULL);
return(0);
}
if ('\0' == p[(*pos)++]) {
- TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos - 1);
+ mandoc_msg(MANDOCERR_TBL, tbl->parse,
+ ln, *pos - 1, NULL);
return(0);
}
break;
@@ -116,7 +120,8 @@ arg(struct tbl_node *tbl, int ln, const char *p, int *pos, enum tbl_ident key)
if ('\0' != (tbl->opts.tab = p[(*pos)++]))
break;
- TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos - 1);
+ mandoc_msg(MANDOCERR_TBL, tbl->parse,
+ ln, *pos - 1, NULL);
return(0);
case (KEY_LINESIZE):
for (i = 0; i < KEY_MAXNUMSZ && p[*pos]; i++, (*pos)++) {
@@ -131,13 +136,14 @@ arg(struct tbl_node *tbl, int ln, const char *p, int *pos, enum tbl_ident key)
break;
}
- (*tbl->msg)(MANDOCERR_TBL, tbl->data, ln, *pos, NULL);
+ mandoc_msg(MANDOCERR_TBL, tbl->parse, ln, *pos, NULL);
return(0);
case (KEY_DPOINT):
if ('\0' != (tbl->opts.decimal = p[(*pos)++]))
break;
- TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos - 1);
+ mandoc_msg(MANDOCERR_TBL, tbl->parse,
+ ln, *pos - 1, NULL);
return(0);
default:
abort();
@@ -149,7 +155,7 @@ arg(struct tbl_node *tbl, int ln, const char *p, int *pos, enum tbl_ident key)
if (')' == p[(*pos)++])
return(1);
- TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos - 1);
+ mandoc_msg(MANDOCERR_TBL, tbl->parse, ln, *pos - 1, NULL);
return(0);
}
@@ -196,7 +202,7 @@ again: /*
/* Exit if buffer is empty (or overrun). */
if (KEY_MAXNAME == i || 0 == i) {
- TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos);
+ mandoc_msg(MANDOCERR_TBL, tbl->parse, ln, *pos, NULL);
return;
}
@@ -235,7 +241,7 @@ again: /*
*/
if (KEY_MAXKEYS == i)
- TBL_MSG(tbl, MANDOCERR_TBLOPT, ln, sv);
+ mandoc_msg(MANDOCERR_TBLOPT, tbl->parse, ln, sv, NULL);
goto again;
/* NOTREACHED */
diff --git a/usr.bin/mandoc/term.c b/usr.bin/mandoc/term.c
index 058710941f5..e89f927c9a6 100644
--- a/usr.bin/mandoc/term.c
+++ b/usr.bin/mandoc/term.c
@@ -1,4 +1,4 @@
-/* $Id: term.c,v 1.57 2011/04/21 22:59:54 schwarze Exp $ */
+/* $Id: term.c,v 1.58 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -25,7 +25,6 @@
#include <string.h>
#include "mandoc.h"
-#include "chars.h"
#include "out.h"
#include "term.h"
#include "main.h"
@@ -453,16 +452,10 @@ term_fontpop(struct termp *p)
void
term_word(struct termp *p, const char *word)
{
- const char *sv, *seq;
+ const char *seq;
size_t ssz;
enum roffdeco deco;
- sv = word;
-
- if (DELIM_CLOSE == mandoc_isdelim(word))
- if ( ! (TERMP_IGNDELIM & p->flags))
- p->flags |= TERMP_NOSPACE;
-
if ( ! (TERMP_NOSPACE & p->flags)) {
if ( ! (TERMP_KEEP & p->flags)) {
if (TERMP_PREKEEP & p->flags)
@@ -523,9 +516,6 @@ term_word(struct termp *p, const char *word)
if (DECO_NOSPACE == deco && '\0' == *word)
p->flags |= TERMP_NOSPACE;
}
-
- if (DELIM_OPEN == mandoc_isdelim(sv))
- p->flags |= TERMP_NOSPACE;
}
diff --git a/usr.bin/mandoc/tree.c b/usr.bin/mandoc/tree.c
index 3ad20fb2925..19b91d7f9bd 100644
--- a/usr.bin/mandoc/tree.c
+++ b/usr.bin/mandoc/tree.c
@@ -1,4 +1,4 @@
-/* $Id: tree.c,v 1.14 2011/03/20 23:36:42 schwarze Exp $ */
+/* $Id: tree.c,v 1.15 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -197,6 +197,9 @@ print_man(const struct man_node *n, int indent)
case (MAN_BODY):
t = "block-body";
break;
+ case (MAN_TAIL):
+ t = "block-tail";
+ break;
case (MAN_TBL):
t = "tbl";
break;
@@ -220,6 +223,8 @@ print_man(const struct man_node *n, int indent)
/* FALLTHROUGH */
case (MAN_HEAD):
/* FALLTHROUGH */
+ case (MAN_TAIL):
+ /* FALLTHROUGH */
case (MAN_BODY):
p = man_macronames[n->tok];
break;
diff --git a/usr.bin/mandoc/vol.c b/usr.bin/mandoc/vol.c
index 117dc42172b..156ff5e8f54 100644
--- a/usr.bin/mandoc/vol.c
+++ b/usr.bin/mandoc/vol.c
@@ -1,4 +1,4 @@
-/* $Id: vol.c,v 1.5 2010/07/31 23:42:04 schwarze Exp $ */
+/* $Id: vol.c,v 1.6 2011/04/24 16:22:02 schwarze Exp $ */
/*
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -18,6 +18,7 @@
#include <string.h>
#include <time.h>
+#include "mdoc.h"
#include "mandoc.h"
#include "libmdoc.h"