summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile19
-rw-r--r--argv.c40
-rw-r--r--external.pngbin0 -> 165 bytes
-rw-r--r--index.sgml148
-rw-r--r--mdoc.319
-rw-r--r--mdocterm.c3
-rw-r--r--style.css52
-rw-r--r--term.c112
8 files changed, 310 insertions, 83 deletions
diff --git a/Makefile b/Makefile
index bf08ff06..5e208c5a 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,5 @@
+.SUFFIXES: .html .sgml
+
VERSION = 1.3.0
CFLAGS += -W -Wall -Wstrict-prototypes -Wno-unused-parameter -g
@@ -33,13 +35,20 @@ SRCS = macro.c mdoc.c hash.c strings.c xstd.c argv.c validate.c \
HEADS = mdoc.h private.h term.h mmain.h
+SGMLS = index.sgml
+
+HTMLS = index.html
+
+STATICS = style.css external.png
+
MANS = mdoctree.1 mdocterm.1 mdoc.3
BINS = mdocterm mdoctree mdoclint
-CLEAN = $(BINS) $(LNS) $(LLNS) $(LIBS) $(OBJS)
+CLEAN = $(BINS) $(LNS) $(LLNS) $(LIBS) $(OBJS) $(HTMLS)
-INSTALL = $(SRCS) $(HEADS) Makefile Makefile.port DESCR $(MANS)
+INSTALL = $(SRCS) $(HEADS) Makefile Makefile.port DESCR $(MANS) \
+ $(SGMLS) $(STATICS)
FAIL = regress/test.empty \
regress/test.prologue.00 \
@@ -104,6 +113,8 @@ dist: mdocml-$(VERSION).tar.gz
port: mdocml-oport-$(VERSION).tar.gz
+www: $(HTMLS)
+
regress:: mdoclint
@for f in $(FAIL); do \
echo "./mdoclint $$f" ; \
@@ -231,3 +242,7 @@ mdoctree: $(TREEOBJS) libmdoc.a
mdoclint: $(LINTOBJS) libmdoc.a
$(CC) $(CFLAGS) -o $@ $(LINTOBJS) libmdoc.a
+
+.sgml.html:
+ validate $<
+ cp -f $< $@
diff --git a/argv.c b/argv.c
index 1d05b2c9..30a1db6b 100644
--- a/argv.c
+++ b/argv.c
@@ -44,8 +44,6 @@ static int argv_single(struct mdoc *, int,
struct mdoc_arg *, int *, char *);
static int argv_multi(struct mdoc *, int,
struct mdoc_arg *, int *, char *);
-static int postargv(struct mdoc *, int,
- const struct mdoc_arg *, int);
static int pwarn(struct mdoc *, int, int, int);
static int perr(struct mdoc *, int, int, int);
@@ -59,9 +57,8 @@ static int perr(struct mdoc *, int, int, int);
/* Error messages. */
#define EQUOTTERM (0)
-#define EOFFSET (1)
-#define EARGVAL (2)
-#define EARGMANY (3)
+#define EARGVAL (1)
+#define EARGMANY (2)
static int mdoc_argflags[MDOC_MAX] = {
0, /* \" */
@@ -183,10 +180,6 @@ perr(struct mdoc *mdoc, int line, int pos, int code)
c = mdoc_perr(mdoc, line, pos,
"unterminated quoted parameter");
break;
- case (EOFFSET):
- c = mdoc_perr(mdoc, line, pos,
- "invalid value for offset argument");
- break;
case (EARGVAL):
c = mdoc_perr(mdoc, line, pos,
"argument requires a value");
@@ -637,33 +630,6 @@ lookup(int tok, const char *argv)
static int
-postargv(struct mdoc *mdoc, int line, const struct mdoc_arg *v, int pos)
-{
-
- switch (v->arg) {
- case (MDOC_Offset):
- assert(v->value);
- assert(v->value[0]);
- if (xstrcmp(v->value[0], "left"))
- break;
- if (xstrcmp(v->value[0], "right"))
- break;
- if (xstrcmp(v->value[0], "center"))
- break;
- if (xstrcmp(v->value[0], "indent"))
- break;
- if (xstrcmp(v->value[0], "indent-two"))
- break;
- return(perr(mdoc, line, pos, EOFFSET));
- default:
- break;
- }
-
- return(1);
-}
-
-
-static int
argv_multi(struct mdoc *mdoc, int line,
struct mdoc_arg *v, int *pos, char *buf)
{
@@ -795,8 +761,6 @@ mdoc_argv(struct mdoc *mdoc, int line, int tok,
ppos = *pos;
if ( ! argv(mdoc, line, v, pos, buf))
return(ARGV_ERROR);
- if ( ! postargv(mdoc, line, v, ppos))
- return(ARGV_ERROR);
return(ARGV_ARG);
}
diff --git a/external.png b/external.png
new file mode 100644
index 00000000..419c06fb
--- /dev/null
+++ b/external.png
Binary files differ
diff --git a/index.sgml b/index.sgml
new file mode 100644
index 00000000..3e916032
--- /dev/null
+++ b/index.sgml
@@ -0,0 +1,148 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <meta name="resource-type" content="document">
+ <link rel="stylesheet" href="style.css" type="text/css" media="all">
+ <title>mdocml.bsd.lv</title>
+ </head>
+ <body>
+ <table width="600">
+ <col width="100%">
+ <tbody>
+ <tr>
+ <td>
+ <div class="head">
+ <b>mdocml</b> &#8211; mdoc macro compiler
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top">
+ <h1>
+ DESCRIPTION
+ </h1>
+
+ <p>
+ <span class="nm">mdocml</span> is a suite of tools that compile &#8220;mdoc&#8221;, the roff macro
+ package of the BSD manual pages. The mission of <span class="nm">mdocml</span> is to deprecate <a
+ href="http://www.gnu.org/software/groff/" class="external">groff</a>, the GNU roff implementation, for
+ displaying BSD mdoc pages. groff amounts to over 60 000 lines of GPL C++ source, which is a
+ considerable encumbrance to BSD operating system.
+ </p>
+
+ <p>
+ The core of <span class="nm">mdocml</span> is the libmdoc library, a validating scanner-parser producing
+ intermediate-form output from mdoc input. libmdoc is a simple, fast library operating on memory buffers
+ of mdoc input. Its intermediate output, an abstract syntax tree, is fully documented in the <span
+ class="man">mdoc(3)</span> reference manual.
+ </p>
+
+ <p>
+ There are three utilities implementing <span class="man">mdoc(3)</span>:
+ </p>
+
+ <ul>
+ <li><span class="man">mdocterm(1)</span> &#8211; formats mdoc input for display on the terminal
+ <li><span class="man">mdochtml(1)</span> &#8211; formats mdoc input as strict HTML (nascent)
+ <li><span class="man">mdoclint(1)</span> &#8211; validates mdoc input
+ <li><span class="man">mdoctree(1)</span> &#8211; prints input abstract syntax tree
+ </ul>
+
+ <p>
+ The <span class="man">mdocterm(1)</span> utility is intended to deprecate usage of <a
+ href="http://www.gnu.org/software/groff/" class="external">groff</a> for displaying BSD manuals to the
+ terminal, either directly or cached as a &#8220;catman&#8221; page.
+ </p>
+
+ <p>
+ <span class="attn">Please submit patches!</span> Although a significant implementation exists, work
+ remains for the backend library and especially the front-end utilities. See the <a
+ href="#contact">contact</a> information below to submit patches and bug reports.
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <h1>
+ INSTALLING SOURCES
+ </h1>
+
+ <h2>
+ nightly source
+ </h2>
+
+ <p>
+ CVS sources are checkedout and snapshotted nightly. These may be found in the <a
+ href="/snapshots/">/snapshots/</a> directory.
+ </p>
+
+ <p class="boxed">
+ % cd /tmp<br>
+ % ftp -V -o- http://mdocml.bsd.lv/snapshots/mdocml.tgz | tar -zxf -<br>
+ % cd mdocml<br>
+ % make<br>
+ % make regress<br>
+ % make install
+ </p>
+
+ <h2>
+ nightly port
+ </h2>
+
+ <p>
+ The nightly snapshot is automatically converted into an OpenBSD port (ports for other BSD systems not
+ yet available). These may be found in the <a href="/ports-openbsd/">/ports-openbsd/</a> directory.
+ </p>
+
+ <p>
+ If installing for the first time:
+ </p>
+
+ <p class="boxed">
+ % ftp -V -o- http://mdocml.bsd.lv/ports-openbsd/mdocml.tgz | tar -zxf -<br>
+ % cd mdocml<br>
+ % sudo make<br>
+ % sudo make install
+ </p>
+
+ <p>
+ Subsequent installations:
+ </p>
+
+ <p class="boxed">
+ % sudo pkg_add -r mdocml
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <h1>
+ CONTACT
+ </h1>
+
+ <p>
+ Please contact Kristaps, kris<a class="external"
+ href="http://mailhide.recaptcha.net/d?k=01jt88xIsFONwVjHZmGpc4AQ==&amp;c=sb5E6ulipc-eTnpTVqI-BQ=="
+ onclick="window.open('http://mailhide.recaptcha.net/d?k=01jt88xIsFONwVjHZmGpc4AQ==&amp;c=sb5E6ulipc-eTnpTVqI-BQ==',
+ '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return
+ false;" title="Reveal this e-mail address">...</a>@kth.se, with questions, bug reports, patches, and so on.
+ </p>
+
+ <p>
+ If you'd like to submit patches, please contact us beforehand in case larger changes are pending but not
+ checked in. If making a bug report, please make sure it's repeatable on the most current snapshot.
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div class="foot">
+ Copyright &#169; 2009 Kristaps D&#382;onsons, $Date$
+ </div>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </body>
+</html>
diff --git a/mdoc.3 b/mdoc.3
index cbeb67ed..fe09e890 100644
--- a/mdoc.3
+++ b/mdoc.3
@@ -99,7 +99,7 @@ Both functions (see
and variables (see
.Sx Variables )
may use the following types:
-.Bl -ohang
+.Bl -ohang -offset "XXXX"
.\" LIST-ITEM
.It Vt struct mdoc
An opaque type defined in
@@ -120,7 +120,7 @@ for details.
.\" SUBSECTION
.Ss Functions
Function descriptions follow:
-.Bl -ohang
+.Bl -ohang -offset "XXXX"
.\" LIST-ITEM
.It Fn mdoc_alloc
Allocates a parsing structure. The
@@ -165,7 +165,7 @@ return 0, the data will be incomplete.
.\" SUBSECTION
.Ss Variables
The following variables are also defined:
-.Bl -ohang
+.Bl -ohang -offset "XXXX"
.\" LIST-ITEM
.It Va mdoc_macronames
An array of string-ified token names.
@@ -213,7 +213,7 @@ field).
The tree itself is arranged according to the following normal form,
where capitalised non-terminals represent nodes.
.Pp
-.Bl -tag -width "ELEMENTXX" -compact
+.Bl -tag -width "ELEMENTXX" -compact -offset "XXXX"
.\" LIST-ITEM
.It ROOT
\(<- mnode+
@@ -272,7 +272,7 @@ Note that, if the last line of the file isn't newline-terminated, this
will truncate the file's last character (see
.Xr fgetln 3 ) .
Further, this example does not error-check nor free memory upon failure.
-.Bd -literal
+.Bd -literal -offset "XXXX"
struct mdoc *mdoc;
struct mdoc_node *node;
char *buf;
@@ -318,6 +318,7 @@ is the default
.Xr groff 1
system bundled with
.Ox .
+.\" PARAGRAPH
.Pp
Un-implemented: the
.Sq \&Xc
@@ -327,12 +328,19 @@ macros aren't handled when used to span lines for the
.Sq \&It
macro. Such usage is specifically discouraged in
.Xr mdoc.samples 7 .
+.\" PARAGRAPH
.Pp
Bugs: when
.Sq \&It \-column
is invoked, whitespace is not stripped around
.Sq \&Ta
or tab-character separators.
+.\" PARAGRAPH
+.Pp
+Bugs: elements within columns for
+.Sq \&It \-column
+are not yet supported.
+.\" PARAGRAPH
.Pp
Incompatible: the
.Sq \&At
@@ -340,6 +348,7 @@ macro only accepts a single parameter. Furthermore, several macros
.Pf ( Sq \&Pp ,
.Sq \&It ,
and possibly others) accept multiple arguments with a warning.
+.\" PARAGRAPH
.Pp
Incompatible: only those macros specified by
.Xr mdoc.samples 7
diff --git a/mdocterm.c b/mdocterm.c
index 24b4132e..4174ff01 100644
--- a/mdocterm.c
+++ b/mdocterm.c
@@ -167,10 +167,9 @@ flushln(struct termp *p)
for (j = 0; j < p->offset; j++)
putchar(' ');
vis = 0;
- } else if (vis + vsz >= maxvis) {
+ } else if (vis + vsz >= maxvis)
/* FIXME */
errx(1, "word breaks right margin");
- }
/*
* Write out the word and a trailing space. Omit the
diff --git a/style.css b/style.css
new file mode 100644
index 00000000..a8d6cbc5
--- /dev/null
+++ b/style.css
@@ -0,0 +1,52 @@
+body { color: #333333;
+ font-size: smaller;
+ font-family: Verdana, Tahoma, Arial, sans-serif; }
+
+p { margin-left: 40px;
+ text-align: justify; }
+
+table { margin-left: 40px; }
+
+ul { margin-left: 40px; }
+
+p.boxed { border: 1px solid #cccccc;
+ margin-left: 40px;
+ text-align: justify;
+ padding: 2px;
+ color: black; }
+
+h1 { font-weight: bold;
+ font-size: small;
+ font-family: Verdana, Tahoma, Arial, sans-serif; }
+
+h2 { font-weight: bold;
+ font-size: small;
+ margin-left: 20px;
+ margin-bottom: 0px;
+ font-family: Verdana, Tahoma, Arial, sans-serif; }
+
+h3 { font-size: small;
+ font-weight: normal;
+ margin-left: 20px;
+ margin-bottom: 0px;
+ font-family: Verdana, Tahoma, Arial, sans-serif; }
+
+span.man { color: #000000; border-bottom: 1px dotted #999999; }
+
+span.path { color: #000000; }
+
+span.nm { color: #000000; font-weight: bold; }
+
+span.attn { color: #000000; font-weight: bold; }
+
+div.head { border-bottom: 1px dotted #cccccc;
+ padding-bottom: 5px;
+ text-align: right; }
+
+div.foot { border-top: 1px dotted #cccccc;
+ padding-top: 5px;
+ font-size: smaller;
+ text-align: right; }
+
+a.external { background: transparent url(external.png) center right no-repeat; padding-right: 12px; }
+
diff --git a/term.c b/term.c
index 214e791b..28089e2d 100644
--- a/term.c
+++ b/term.c
@@ -30,6 +30,7 @@
*/
/* FIXME: indent/tab. */
+/* FIXME: handle nested lists. */
#define TTYPE_PROG 0
#define TTYPE_CMD_FLAG 1
@@ -72,7 +73,8 @@ static int arg_hasattr(int, size_t,
const struct mdoc_arg *);
static int arg_getattr(int, size_t,
const struct mdoc_arg *);
-static size_t arg_offset(const char *);
+static size_t arg_offset(const struct mdoc_arg *);
+static size_t arg_width(const struct mdoc_arg *);
/*
* What follows describes prefix and postfix operations for the abstract
@@ -94,6 +96,7 @@ DECL_POST(name);
DECL_PREPOST(termp_aq);
DECL_PREPOST(termp_ar);
+DECL_PREPOST(termp_bd);
DECL_PREPOST(termp_d1);
DECL_PREPOST(termp_dq);
DECL_PREPOST(termp_em);
@@ -116,7 +119,6 @@ DECL_PREPOST(termp_sx);
DECL_PREPOST(termp_va);
DECL_PREPOST(termp_vt);
-DECL_PRE(termp_bd);
DECL_PRE(termp_bx);
DECL_PRE(termp_ex);
DECL_PRE(termp_nd);
@@ -139,7 +141,7 @@ const struct termact __termacts[MDOC_MAX] = {
{ termp_pp_pre, NULL }, /* Pp */
{ termp_d1_pre, termp_d1_post }, /* D1 */
{ NULL, NULL }, /* Dl */
- { termp_bd_pre, NULL }, /* Bd */
+ { termp_bd_pre, termp_bd_post }, /* Bd */
{ NULL, NULL }, /* Ed */
{ NULL, termp_bl_post }, /* Bl */
{ NULL, NULL }, /* El */
@@ -242,15 +244,27 @@ const struct termact *termacts = __termacts;
static size_t
-arg_offset(const char *v)
+arg_width(const struct mdoc_arg *arg)
{
- if (0 == strcmp(v, "indent"))
+
+ /* TODO */
+ assert(*arg->value);
+ return(strlen(*arg->value));
+}
+
+
+static size_t
+arg_offset(const struct mdoc_arg *arg)
+{
+
+ /* TODO */
+ assert(*arg->value);
+ if (0 == strcmp(*arg->value, "indent"))
return(INDENT);
- if (0 == strcmp(v, "indent-two"))
+ if (0 == strcmp(*arg->value, "indent-two"))
return(INDENT * 2);
- /* TODO */
- return(0);
+ return(strlen(*arg->value));
}
@@ -308,7 +322,7 @@ termp_it_post(DECL_ARGS)
const struct mdoc_node *n, *it;
const struct mdoc_block *bl;
int i;
- size_t width;
+ size_t width, offset;
/*
* This (and termp_it_pre()) are the most complicated functions
@@ -339,34 +353,32 @@ termp_it_post(DECL_ARGS)
/* If `-tag', adjust our margins accordingly. */
if (arg_hasattr(MDOC_Tag, bl->argc, bl->argv)) {
+ flushln(p);
+
+ /* FIXME: this should auto-size. */
i = arg_getattr(MDOC_Width, bl->argc, bl->argv);
- assert(i >= 0);
- assert(1 == bl->argv[i].sz);
- width = strlen(*bl->argv[i].value); /* XXX */
+ width = i >= 0 ? arg_width(&bl->argv[i]) : 10;
+
+ /* FIXME: nesting! Should happen at block. */
+ i = arg_getattr(MDOC_Offset, bl->argc, bl->argv);
+ offset = i >= 0 ? arg_width(&bl->argv[i]) : 0;
if (MDOC_HEAD == node->type) {
- flushln(p);
- /* FIXME: nested lists. */
p->rmargin = p->maxrmargin;
+ p->offset -= offset;
p->flags &= ~TERMP_NOBREAK;
} else {
- flushln(p);
- p->offset -= width + 1;
+ p->offset -= width;
p->flags &= ~TERMP_NOLPAD;
}
- return;
}
if (arg_hasattr(MDOC_Ohang, bl->argc, bl->argv)) {
i = arg_getattr(MDOC_Offset, bl->argc, bl->argv);
- width = 0;
- if (i >= 0) {
- assert(1 == bl->argv[i].sz);
- width = arg_offset(*bl->argv[i].value);
- }
+ offset = i >= 0 ? arg_offset(&bl->argv[i]) : 0;
flushln(p);
- p->offset -= width;
+ p->offset -= offset;
return;
}
}
@@ -379,7 +391,7 @@ termp_it_pre(DECL_ARGS)
const struct mdoc_node *n, *it;
const struct mdoc_block *bl;
int i;
- size_t width;
+ size_t width, offset;
/*
* Also see termp_it_post() for general comments.
@@ -420,24 +432,27 @@ termp_it_pre(DECL_ARGS)
assert(MDOC_HEAD == node->type
|| MDOC_BODY == node->type);
+ /* FIXME: see termp_it_post(). */
+
/* If `-tag', adjust our margins accordingly. */
if (arg_hasattr(MDOC_Tag, bl->argc, bl->argv)) {
+ p->flags |= TERMP_NOSPACE;
+
i = arg_getattr(MDOC_Width, bl->argc, bl->argv);
- assert(i >= 0); /* XXX */
- assert(1 == bl->argv[i].sz);
- width = strlen(*bl->argv[i].value); /* XXX */
+ width = i >= 0 ? arg_width(&bl->argv[i]) : 10;
- /* FIXME: nested lists. */
+ i = arg_getattr(MDOC_Offset, bl->argc, bl->argv);
+ offset = i >= 0 ? arg_offset(&bl->argv[i]) : 0;
if (MDOC_HEAD == node->type) {
p->flags |= TERMP_NOBREAK;
- p->flags |= TERMP_NOSPACE;
+ p->offset += offset;
p->rmargin = p->offset + width;
} else {
p->flags |= TERMP_NOSPACE;
p->flags |= TERMP_NOLPAD;
- p->offset += width + 1;
+ p->offset += width;
}
return(1);
}
@@ -445,15 +460,11 @@ termp_it_pre(DECL_ARGS)
/* If `-ohang', adjust left-margin. */
if (arg_hasattr(MDOC_Ohang, bl->argc, bl->argv)) {
- width = 0;
i = arg_getattr(MDOC_Offset, bl->argc, bl->argv);
- if (i >= 0) {
- assert(1 == bl->argv[i].sz);
- width = arg_offset(*bl->argv[i].value);
- }
+ offset = i >= 0 ? arg_offset(&bl->argv[i]) : 0;
p->flags |= TERMP_NOSPACE;
- p->offset += width;
+ p->offset += offset;
return(1);
}
@@ -922,6 +933,7 @@ termp_bd_pre(DECL_ARGS)
{
const struct mdoc_block *bl;
const struct mdoc_node *n;
+ int i;
if (MDOC_BLOCK == node->type) {
vspace(p);
@@ -932,6 +944,13 @@ termp_bd_pre(DECL_ARGS)
assert(MDOC_BLOCK == node->parent->type);
bl = &node->parent->data.block;
+
+ i = arg_getattr(MDOC_Offset, bl->argc, bl->argv);
+ if (-1 != i) {
+ assert(1 == bl->argv[i].sz);
+ p->offset += arg_offset(&bl->argv[i]);
+ }
+
if ( ! arg_hasattr(MDOC_Literal, bl->argc, bl->argv))
return(1);
@@ -953,6 +972,27 @@ termp_bd_pre(DECL_ARGS)
/* ARGSUSED */
+static void
+termp_bd_post(DECL_ARGS)
+{
+ int i;
+ const struct mdoc_block *bl;
+
+ if (MDOC_BODY != node->type)
+ return;
+
+ assert(MDOC_BLOCK == node->parent->type);
+ bl = &node->parent->data.block;
+
+ i = arg_getattr(MDOC_Offset, bl->argc, bl->argv);
+ if (-1 != i) {
+ assert(1 == bl->argv[i].sz);
+ p->offset -= arg_offset(&bl->argv[i]);
+ }
+}
+
+
+/* ARGSUSED */
static int
termp_qq_pre(DECL_ARGS)
{