aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--Makefile141
-rw-r--r--action.c9
-rw-r--r--arch.c34
-rw-r--r--arch.in86
-rw-r--r--argv.c64
-rw-r--r--ascii.c169
-rw-r--r--ascii.in134
-rw-r--r--att.c34
-rw-r--r--att.in58
-rw-r--r--lib.c34
-rw-r--r--lib.in97
-rw-r--r--macro.c844
-rw-r--r--mdoc.39
-rw-r--r--mdoc.7285
-rw-r--r--mdoc.c13
-rw-r--r--mdoc.h8
-rw-r--r--mdocterm.1139
-rw-r--r--mdocterm.c172
-rw-r--r--mmain.c11
-rw-r--r--mmain.h16
-rw-r--r--msec.c34
-rw-r--r--msec.in64
-rw-r--r--private.h4
-rw-r--r--st.c34
-rw-r--r--st.in91
-rw-r--r--strings.sh89
-rw-r--r--term.c4
-rw-r--r--term.h90
-rw-r--r--validate.c61
-rw-r--r--vol.c34
-rw-r--r--vol.in55
-rw-r--r--xstd.c86
32 files changed, 1503 insertions, 1500 deletions
diff --git a/Makefile b/Makefile
index 3584ee67..b33a43b6 100644
--- a/Makefile
+++ b/Makefile
@@ -25,7 +25,7 @@ LIBLNS = macro.ln mdoc.ln hash.ln strings.ln xstd.ln argv.ln \
TREELNS = mdoctree.ln mmain.ln
-TERMLNS = mdoctree.ln mmain.ln term.ln
+TERMLNS = mdoctree.ln mmain.ln term.ln ascii.ln
LINTLNS = mdoclint.ln mmain.ln
@@ -39,7 +39,7 @@ LIBOBJS = macro.o mdoc.o hash.o strings.o xstd.o argv.o \
validate.o action.o lib.o att.o arch.o vol.o msec.o \
st.o
-TERMOBJS= mdocterm.o mmain.o term.o
+TERMOBJS= mdocterm.o mmain.o term.o ascii.o
TREEOBJS= mdoctree.o mmain.o
@@ -50,11 +50,7 @@ OBJS = $(LIBOBJS) $(TERMOBJS) $(TREEOBJS) $(LINTOBJS)
SRCS = macro.c mdoc.c hash.c strings.c xstd.c argv.c validate.c \
action.c term.c mdoctree.c mdocterm.c mmain.c mdoclint.c
-SCRIPTS = strings.sh
-
-DATAS = arch.in att.in lib.in msec.in st.in vol.in
-
-GEN = lib.c att.c arch.c vol.c msec.c st.c
+DATAS = arch.in att.in lib.in msec.in st.in vol.in ascii.in
HEADS = mdoc.h private.h term.h mmain.h
@@ -72,84 +68,10 @@ MANS = mdoctree.1 mdocterm.1 mdoclint.1 mdoc.3 mdoc.7
BINS = mdocterm mdoctree mdoclint
CLEAN = $(BINS) $(LNS) $(LLNS) $(LIBS) $(OBJS) $(HTMLS) \
- $(TARGZS) $(GEN)
+ $(TARGZS)
INSTALL = $(SRCS) $(HEADS) Makefile DESCR $(MANS) $(SGMLS) \
- $(STATICS) $(SCRIPTS) Makefile.netbsd Makefile.openbsd \
- $(DATAS)
-
-FAIL = regress/test.empty \
- regress/test.prologue.00 \
- regress/test.prologue.01 \
- regress/test.prologue.02 \
- regress/test.prologue.03 \
- regress/test.prologue.04 \
- regress/test.prologue.06 \
- regress/test.prologue.19 \
- regress/test.prologue.23 \
- regress/test.prologue.24 \
- regress/test.prologue.27 \
- regress/test.prologue.28 \
- regress/test.prologue.30 \
- regress/test.prologue.31 \
- regress/test.prologue.32 \
- regress/test.sh.03 \
- regress/test.escape.01 \
- regress/test.escape.02 \
- regress/test.escape.03 \
- regress/test.escape.04 \
- regress/test.escape.06 \
- regress/test.escape.07 \
- regress/test.escape.08 \
- regress/test.escape.09 \
- regress/test.escape.11 \
- regress/test.escape.12 \
- regress/test.escape.14 \
- regress/test.argv.01 \
- regress/test.argv.02
-
-SUCCEED = regress/test.prologue.05 \
- regress/test.prologue.07 \
- regress/test.prologue.08 \
- regress/test.prologue.09 \
- regress/test.prologue.10 \
- regress/test.prologue.11 \
- regress/test.prologue.12 \
- regress/test.prologue.13 \
- regress/test.prologue.14 \
- regress/test.prologue.15 \
- regress/test.prologue.16 \
- regress/test.prologue.17 \
- regress/test.prologue.18 \
- regress/test.prologue.20 \
- regress/test.prologue.21 \
- regress/test.prologue.22 \
- regress/test.prologue.25 \
- regress/test.prologue.26 \
- regress/test.prologue.29 \
- regress/test.prologue.33 \
- regress/test.sh.00 \
- regress/test.name.00 \
- regress/test.name.01 \
- regress/test.name.02 \
- regress/test.name.03 \
- regress/test.list.00 \
- regress/test.list.01 \
- regress/test.list.02 \
- regress/test.list.03 \
- regress/test.list.04 \
- regress/test.list.05 \
- regress/test.list.06 \
- regress/test.list.07 \
- regress/test.sh.01 \
- regress/test.sh.02 \
- regress/test.escape.00 \
- regress/test.escape.05 \
- regress/test.escape.10 \
- regress/test.escape.13 \
- regress/test.argv.00
-
-REGRESS = $(FAIL) $(SUCCEED)
+ $(STATICS) Makefile.netbsd Makefile.openbsd $(DATAS)
all: $(BINS)
@@ -176,14 +98,6 @@ installwww: www
install -m 0444 mdocml-nport-$(VERSION).tar.gz $(PREFIX)/ports-netbsd/
install -m 0444 mdocml-nport-$(VERSION).tar.gz $(PREFIX)/ports-netbsd/mdocml.tar.gz
-#regress: mdoclint $(FAIL) $(SUCCEED)
-# @for f in $(FAIL); do \
-# echo "./mdoclint $$f" ; \
-# ./mdoclint $$f 2>/dev/null || continue ; exit 1 ; done
-# @for f in $(SUCCEED); do \
-# echo "./mdoclint $$f" ; \
- ./mdoclint $$f 2>/dev/null || exit 1 ; done
-
install:
mkdir -p $(BINDIR)
mkdir -p $(INCLUDEDIR)
@@ -211,41 +125,26 @@ uninstall:
rm -f $(LIBDIR)/libmdoc.a
rm -f $(INCLUDEDIR)/mdoc.h
-lib.ln: lib.c private.h
-lib.o: lib.c private.h
-
-att.ln: att.c private.h
-att.o: att.c private.h
-
-arch.ln: arch.c private.h
-arch.o: arch.c private.h
-
-vol.ln: vol.c private.h
-vol.o: vol.c private.h
-
-msec.ln: msec.c private.h
-msec.o: msec.c private.h
-
-st.ln: st.c private.h
-st.o: st.c private.h
+lib.ln: lib.c lib.in private.h
+lib.o: lib.c lib.in private.h
-lib.c: lib.in strings.sh
- sh strings.sh -o $@ lib lib.in
+att.ln: att.c att.in private.h
+att.o: att.c att.in private.h
-st.c: st.in strings.sh
- sh strings.sh -o $@ st st.in
+arch.ln: arch.c arch.in private.h
+arch.o: arch.c arch.in private.h
-msec.c: msec.in strings.sh
- sh strings.sh -o $@ msec msec.in
+vol.ln: vol.c vol.in private.h
+vol.o: vol.c vol.in private.h
-att.c: att.in strings.sh
- sh strings.sh -o $@ att att.in
+ascii.ln: ascii.c ascii.in term.h
+ascii.o: ascii.c ascii.in term.h
-arch.c: arch.in strings.sh
- sh strings.sh -o $@ arch arch.in
+msec.ln: msec.c msec.in private.h
+msec.o: msec.c msec.in private.h
-vol.c: vol.in strings.sh
- sh strings.sh -o $@ vol vol.in
+st.ln: st.c st.in private.h
+st.o: st.c st.in private.h
macro.ln: macro.c private.h
macro.o: macro.c private.h
@@ -336,9 +235,7 @@ mdocml-oport-$(VERSION).tar.gz: mdocml-$(VERSION).tar.gz Makefile.openbsd DESCR
mdocml-$(VERSION).tar.gz: $(INSTALL)
mkdir -p .dist/mdocml/mdocml-$(VERSION)/
- mkdir -p .dist/mdocml/mdocml-$(VERSION)/regress/
install -m 0644 $(INSTALL) .dist/mdocml/mdocml-$(VERSION)/
- install -m 0644 $(REGRESS) .dist/mdocml/mdocml-$(VERSION)/regress/
( cd .dist/mdocml/ && tar zcf ../../$@ mdocml-$(VERSION)/ )
rm -rf .dist/
diff --git a/action.c b/action.c
index c50cc7c1..589f16aa 100644
--- a/action.c
+++ b/action.c
@@ -1,4 +1,4 @@
-/* $Id: action.c,v 1.41 2009/03/12 16:30:50 kristaps Exp $ */
+/* $Id: action.c,v 1.42 2009/03/16 22:19:19 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -62,6 +62,9 @@ static int post_sh(struct mdoc *);
static int post_std(struct mdoc *);
static int post_prologue(struct mdoc *);
+#define merr(m, t) nerr((m), (m)->last, (t))
+#define mwarn(m, t) nwarn((m), (m)->last, (t))
+
const struct actions mdoc_actions[MDOC_MAX] = {
{ NULL }, /* \" */
{ post_dd }, /* Dd */
@@ -178,10 +181,11 @@ const struct actions mdoc_actions[MDOC_MAX] = {
{ NULL }, /* Bro */
{ NULL }, /* Brc */
{ NULL }, /* %C */
+ { NULL }, /* Es */
+ { NULL }, /* En */
};
-#define merr(m, t) nerr((m), (m)->last, (t))
static int
nerr(struct mdoc *m, const struct mdoc_node *n, enum merr type)
{
@@ -200,7 +204,6 @@ nerr(struct mdoc *m, const struct mdoc_node *n, enum merr type)
}
-#define mwarn(m, t) nwarn((m), (m)->last, (t))
static int
nwarn(struct mdoc *m, const struct mdoc_node *n, enum mwarn type)
{
diff --git a/arch.c b/arch.c
new file mode 100644
index 00000000..9fc1c4e1
--- /dev/null
+++ b/arch.c
@@ -0,0 +1,34 @@
+/* $Id: arch.c,v 1.1 2009/03/16 22:19:19 kristaps Exp $ */
+/*
+ * Copyright (c) 2009 Kristaps Dzonsons <kristaps@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 <stdlib.h>
+#include <string.h>
+
+#include "private.h"
+
+#define LINE(x, y) \
+ if (0 == strcmp(p, x)) return(y);
+
+const char *
+mdoc_a2arch(const char *p)
+{
+
+#include "arch.in"
+
+ return(NULL);
+}
diff --git a/arch.in b/arch.in
index 3e45ca7f..bcb4cb81 100644
--- a/arch.in
+++ b/arch.in
@@ -1,34 +1,54 @@
-# $Id: arch.in,v 1.2 2009/03/06 14:24:49 kristaps Exp $
-#
-# This file defines the `.Dt' macro 'arch' argument. Lines are composed
-# of tab-delimited fields -- multiple tabs may delimit fields. Comment
-# lines begin with '#'; blank lines are also ok.
-#
-# These were last grok'd from OpenBSD-4.4's mdoc.samples(7).
+/* $Id: arch.in,v 1.3 2009/03/16 22:19:19 kristaps Exp $ */
+/*
+ * Copyright (c) 2009 Kristaps Dzonsons <kristaps@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.
+ */
-alpha Alpha
-amd64 AMD64
-amiga Amiga
-arc ARC
-arm ARM
-armish ARMISH
-aviion AViiON
-hp300 HP300
-hppa HPPA
-hppa64 HPPA64
-i386 i386
-landisk LANDISK
-luna88k Luna88k
-mac68k Mac68k
-macppc MacPPC
-mvme68k MVME68k
-mvme88k MVME88k
-mvmeppc MVMEPPC
-pmax PMAX
-sgi SGI
-socppc SOCPPC
-sparc SPARC
-sparc64 SPARC64
-sun3 Sun3
-vax VAX
-zaurus Zaurus
+/*
+ * This file defines the architecture token of the .Dt prologue macro.
+ * All architectures that your system supports (or the manuals of your
+ * system) should be included here. The right-hand-side is the
+ * formatted output.
+ *
+ * Be sure to escape strings.
+ */
+
+LINE("alpha", "Alpha")
+LINE("amd64", "AMD64")
+LINE("amiga", "Amiga")
+LINE("arc", "ARC")
+LINE("arm", "ARM")
+LINE("armish", "ARMISH")
+LINE("aviion", "AViiON")
+LINE("hp300", "HP300")
+LINE("hppa", "HPPA")
+LINE("hppa64", "HPPA64")
+LINE("i386", "i386")
+LINE("landisk", "LANDISK")
+LINE("luna88k", "Luna88k")
+LINE("mac68k", "Mac68k")
+LINE("macppc", "MacPPC")
+LINE("mvme68k", "MVME68k")
+LINE("mvme88k", "MVME88k")
+LINE("mvmeppc", "MVMEPPC")
+LINE("pmax", "PMAX")
+LINE("sgi", "SGI")
+LINE("socppc", "SOCPPC")
+LINE("sparc", "SPARC")
+LINE("sparc64", "SPARC64")
+LINE("sun3", "Sun3")
+LINE("vax", "VAX")
+LINE("zaurus", "Zaurus")
diff --git a/argv.c b/argv.c
index 572d9590..20eaa3fb 100644
--- a/argv.c
+++ b/argv.c
@@ -1,4 +1,4 @@
-/* $Id: argv.c,v 1.51 2009/03/14 05:21:58 kristaps Exp $ */
+/* $Id: argv.c,v 1.52 2009/03/16 22:19:19 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -45,6 +45,8 @@
#define ARGV_MULTI (1 << 2)
#define ARGV_OPT_SINGLE (1 << 3)
+#define MULTI_STEP 5
+
enum mwarn {
WQUOTPARM,
WARGVPARM,
@@ -218,6 +220,8 @@ static int mdoc_argflags[MDOC_MAX] = {
0, /* Bro */
ARGS_DELIM, /* Brc */
ARGS_QUOTED, /* %C */
+ 0, /* Es */
+ 0, /* En */
};
@@ -238,11 +242,13 @@ mdoc_argv(struct mdoc *mdoc, int line, int tok,
if (0 == buf[*pos])
return(ARGV_EOLN);
- assert( ! isspace((u_char)buf[*pos]));
+ assert(' ' != buf[*pos]);
- if ('-' != buf[*pos])
+ if ('-' != buf[*pos] || ARGS_ARGVLIKE & mdoc_argflags[tok])
return(ARGV_WORD);
+ /* Parse through to the first unescaped space. */
+
i = *pos;
p = &buf[++(*pos)];
@@ -250,17 +256,13 @@ mdoc_argv(struct mdoc *mdoc, int line, int tok,
/* LINTED */
while (buf[*pos]) {
- if (isspace((u_char)buf[*pos]))
+ if (' ' == buf[*pos])
if ('\\' != buf[*pos - 1])
break;
(*pos)++;
}
- /*
- * XXX: save the nullified byte as we'll restore it if this
- * doesn't end up being a command after all. This is a little
- * bit hacky. I don't like it, but it works for now.
- */
+ /* XXX - save zeroed byte, if not an argument. */
sv = 0;
if (buf[*pos]) {
@@ -272,14 +274,10 @@ mdoc_argv(struct mdoc *mdoc, int line, int tok,
tmp.line = line;
tmp.pos = *pos;
- /*
- * We now parse out the per-macro arguments. XXX - this can be
- * made much cleaner using per-argument tables. See argv_a2arg
- * for details.
- */
+ /* See if our token accepts the argument. */
if (MDOC_ARG_MAX == (tmp.arg = argv_a2arg(tok, p))) {
- /* XXX - restore saved byte. */
+ /* XXX - restore saved zeroed byte. */
if (sv)
buf[*pos - 1] = sv;
if ( ! pwarn(mdoc, line, i, WARGVPARM))
@@ -287,11 +285,9 @@ mdoc_argv(struct mdoc *mdoc, int line, int tok,
return(ARGV_WORD);
}
- while (buf[*pos] && isspace((u_char)buf[*pos]))
+ while (buf[*pos] && ' ' == buf[*pos])
(*pos)++;
- /* FIXME: whitespace if no value. */
-
if ( ! argv(mdoc, line, &tmp, pos, buf))
return(ARGV_ERROR);
@@ -448,8 +444,6 @@ mdoc_args(struct mdoc *mdoc, int line,
break;
}
- /* Continue parsing the arguments themselves... */
-
return(args(mdoc, line, pos, buf, fl, v));
}
@@ -486,10 +480,10 @@ args(struct mdoc *mdoc, int line,
break;
i++;
/* There must be at least one space... */
- if (0 == buf[i] || ! isspace((u_char)buf[i]))
+ if (0 == buf[i] || ' ' != buf[i])
break;
i++;
- while (buf[i] && isspace((u_char)buf[i]))
+ while (buf[i] && ' ' == buf[i])
i++;
}
if (0 == buf[i]) {
@@ -505,24 +499,16 @@ args(struct mdoc *mdoc, int line,
/*
* Thar be dragons here! If we're tab-separated, search
- * ahead for either a tab or the `Ta' macro. If a tab
- * is detected, it mustn't be escaped; if a `Ta' is
- * detected, it must be space-buffered before and after.
- * If either of these hold true, then prune out the
+ * ahead for either a tab or the `Ta' macro.
+ * If a `Ta' is detected, it must be space-buffered before and
+ * after. If either of these hold true, then prune out the
* extra spaces and call it an argument.
*/
if (ARGS_TABSEP & fl) {
/* Scan ahead to unescaped tab. */
- for (p = *v; ; p++) {
- if (NULL == (p = strchr(p, '\t')))
- break;
- if (p == *v)
- break;
- if ('\\' != *(p - 1))
- break;
- }
+ p = strchr(*v, '\t');
/* Scan ahead to unescaped `Ta'. */
@@ -597,7 +583,7 @@ args(struct mdoc *mdoc, int line,
if ( ! (ARGS_TABSEP & fl))
while (buf[*pos]) {
- if (isspace((u_char)buf[*pos]))
+ if (' ' == buf[*pos])
if ('\\' != buf[*pos - 1])
break;
(*pos)++;
@@ -612,7 +598,7 @@ args(struct mdoc *mdoc, int line,
return(ARGS_WORD);
if ( ! (ARGS_TABSEP & fl))
- while (buf[*pos] && isspace((u_char)buf[*pos]))
+ while (buf[*pos] && ' ' == buf[*pos])
(*pos)++;
if (buf[*pos])
@@ -644,7 +630,7 @@ args(struct mdoc *mdoc, int line,
if (0 == buf[*pos])
return(ARGS_QWORD);
- while (buf[*pos] && isspace((u_char)buf[*pos]))
+ while (buf[*pos] && ' ' == buf[*pos])
(*pos)++;
if (buf[*pos])
@@ -773,9 +759,9 @@ argv_multi(struct mdoc *mdoc, int line,
else if (ARGS_EOLN == c)
break;
- if (0 == v->sz % 5)
+ if (0 == v->sz % MULTI_STEP)
v->value = xrealloc(v->value,
- (v->sz + 5) * sizeof(char *));
+ (v->sz + MULTI_STEP) * sizeof(char *));
v->value[(int)v->sz] = xstrdup(p);
}
diff --git a/ascii.c b/ascii.c
new file mode 100644
index 00000000..80523e5f
--- /dev/null
+++ b/ascii.c
@@ -0,0 +1,169 @@
+/* $Id: ascii.c,v 1.1 2009/03/16 22:19:19 kristaps Exp $ */
+/*
+ * Copyright (c) 2009 Kristaps Dzonsons <kristaps@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 <assert.h>
+#include <err.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "term.h"
+
+#define ASCII_PRINT_HI 126
+#define ASCII_PRINT_LO 32
+
+/*
+ * Lookup and hashing routines for constructing the ASCII symbol table,
+ * which should contain a significant portion of mdoc(7)'s special
+ * symbols.
+ */
+
+struct line {
+ const char *code;
+ const char *out;
+ /* 32- and 64-bit alignment safe. */
+ size_t codesz;
+ size_t outsz;
+};
+
+struct linep {
+ const struct line *line;
+ struct linep *next;
+};
+
+#define LINE(w, x, y, z) \
+ { (w), (y), (x), (z) },
+static const struct line lines[] = {
+#include "ascii.in"
+};
+
+
+static inline int match(const struct line *,
+ const char *, size_t);
+
+
+void *
+ascii2htab(void)
+{
+ void **htab;
+ struct linep *pp, *p;
+ int i, len, hash;
+
+ /*
+ * Constructs a very basic chaining hashtable. The hash routine
+ * is simply the integral value of the first character.
+ * Subsequent entries are chained in the order they're processed
+ * (they're in-line re-ordered during lookup).
+ */
+
+ assert(0 == sizeof(lines) % sizeof(struct line));
+ len = sizeof(lines) / sizeof(struct line);
+
+ if (NULL == (p = calloc((size_t)len, sizeof(struct linep))))
+ err(1, "malloc");
+
+ htab = calloc(ASCII_PRINT_HI - ASCII_PRINT_LO + 1,
+ sizeof(struct linep **));
+
+ if (NULL == htab)
+ err(1, "malloc");
+
+ for (i = 0; i < len; i++) {
+ assert(lines[i].codesz > 0);
+ assert(lines[i].code);
+ assert(lines[i].out);
+
+ p[i].line = &lines[i];
+
+ hash = (int)lines[i].code[0] - ASCII_PRINT_LO;
+
+ if (NULL == (pp = ((struct linep **)htab)[hash])) {
+ htab[hash] = &p[i];
+ continue;
+ }
+
+ for ( ; pp->next; pp = pp->next)
+ /* Scan ahead. */ ;
+
+ pp->next = &p[i];
+ }
+
+ return((void *)htab);
+}
+
+
+const char *
+a2ascii(void *htabp, const char *p, size_t sz, size_t *rsz)
+{
+ struct linep *pp, *prev;
+ void **htab;
+ int hash;
+
+ htab = (void **)htabp;
+
+ assert(p);
+ assert(sz > 0);
+ assert(p[0] >= ASCII_PRINT_LO && p[0] <= ASCII_PRINT_HI);
+
+ /*
+ * Lookup the symbol in the symbol hash. See ascii2htab for the
+ * hashtable specs. This dynamically re-orders the hash chain
+ * to optimise for repeat hits.
+ */
+
+ hash = (int)p[0] - ASCII_PRINT_LO;
+
+ if (NULL == (pp = ((struct linep **)htab)[hash]))
+ return(NULL);
+
+ if (NULL == pp->next) {
+ if ( ! match(pp->line, p, sz))
+ return(NULL);
+ *rsz = pp->line->outsz;
+ return(pp->line->out);
+ }
+
+ for (prev = NULL; pp; pp = pp->next) {
+ if ( ! match(pp->line, p, sz)) {
+ prev = pp;
+ continue;
+ }
+
+ /* Re-order the hash chain. */
+
+ if (prev) {
+ prev->next = pp->next;
+ pp->next = ((struct linep **)htab)[hash];
+ htab[hash] = pp;
+ }
+
+ *rsz = pp->line->outsz;
+ return(pp->line->out);
+ }
+
+ return(NULL);
+}
+
+
+static inline int
+match(const struct line *line, const char *p, size_t sz)
+{
+
+ if (line->codesz != sz)
+ return(0);
+ return(0 == strncmp(line->code, p, sz));
+}
diff --git a/ascii.in b/ascii.in
new file mode 100644
index 00000000..c65f243d
--- /dev/null
+++ b/ascii.in
@@ -0,0 +1,134 @@
+/* $Id: ascii.in,v 1.1 2009/03/16 22:19:19 kristaps Exp $ */
+/*
+ * Copyright (c) 2009 Kristaps Dzonsons <kristaps@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.
+ */
+
+/*
+ * The ASCII translation table. The left-hand side corresponds to the
+ * escape sequence (\x, \(xx and so on) whose length is listed second
+ * element. The right-hand side is what's produced by the front-end,
+ * with the fourth element being its length.
+ *
+ * Be sure to escape strings.
+ */
+
+LINE("\\", 1, "\\", 1)
+LINE("\'", 1, "\'", 1)
+LINE("`", 1, "`", 1)
+LINE("-", 1, "-", 1)
+LINE(" ", 1, " ", 1)
+LINE(".", 1, ".", 1)
+LINE("&", 1, "", 0)
+LINE("e", 1, "\\", 1)
+LINE("q", 1, "\"", 1)
+LINE("|", 1, "", 0)
+LINE("rC", 2, "}", 1)
+LINE("lC", 2, "{", 1)
+LINE("rB", 2, "]", 1)
+LINE("lB", 2, "[", 1)
+LINE("ra", 2, ">", 1)
+LINE("la", 2, "<", 1)
+LINE("Lq", 2, "``", 2)
+LINE("lq", 2, "``", 2)
+LINE("Rq", 2, "\'\'", 2)
+LINE("rq", 2, "\'\'", 2)
+LINE("oq", 2, "`", 1)
+LINE("aq", 2, "\'", 1)
+LINE("<-", 2, "<-", 2)
+LINE("->", 2, "->", 2)
+LINE("<>", 2, "<>", 2)
+LINE("ua", 2, "^", 1)
+LINE("da", 2, "v", 1)
+LINE("bu", 2, "o", 1)
+LINE("Ba", 2, "|", 1)
+LINE("ba", 2, "|", 1)
+LINE("co", 2, "(C)", 3)
+LINE("rg", 2, "(R)", 3)
+LINE("tm", 2, "tm", 2)
+LINE("Am", 2, "&", 1)
+LINE("Le", 2, "<=", 2)
+LINE("<=", 2, "<=", 2)
+LINE("Ge", 2, ">=", 2)
+LINE(">=", 2, ">=", 2)
+LINE("==", 2, "==", 2)
+LINE("Ne", 2, "!=", 2)
+LINE("!=", 2, "!=", 2)
+LINE("Pm", 2, "+-", 2)
+LINE("+-", 2, "+-", 2)
+LINE("If", 2, "infinity", 8)
+LINE("if", 2, "oo", 2)
+LINE("Na", 2, "NaN", 3)
+LINE("na", 2, "NaN", 3)
+LINE("**", 2, "*", 1)
+LINE("Gt", 2, ">", 1)
+LINE("Lt", 2, "<", 1)
+LINE("aa", 2, "\'", 1)
+LINE("a~", 2, "~", 1)
+LINE("ga", 2, "`", 1)
+LINE("en", 2, "-", 1)
+LINE("em", 2, "--", 2)
+LINE("Pi", 2, "pi", 2)
+LINE("<<", 2, "<<", 2)
+LINE(">>", 2, ">>", 2)
+LINE("lh", 2, "<=", 2)
+LINE("rh", 2, "=>", 2)
+LINE("ae", 2, "ae", 2)
+LINE("AE", 2, "AE", 2)
+LINE("oe", 2, "oe", 2)
+LINE("OE", 2, "OE", 2)
+LINE("\'A", 2, "A", 1)
+LINE("\'E", 2, "E", 1)
+LINE("\'I", 2, "I", 1)
+LINE("\'O", 2, "O", 1)
+LINE("\'U", 2, "U", 1)
+LINE("\'a", 2, "a", 1)
+LINE("\'e", 2, "e", 1)
+LINE("\'i", 2, "i", 1)
+LINE("\'o", 2, "o", 1)
+LINE("\'u", 2, "u", 1)
+LINE("`A", 2, "A", 1)
+LINE("`E", 2, "E", 1)
+LINE("`I", 2, "I", 1)
+LINE("`O", 2, "O", 1)
+LINE("`U", 2, "U", 1)
+LINE("`a", 2, "a", 1)
+LINE("`e", 2, "e", 1)
+LINE("`i", 2, "i", 1)
+LINE("`o", 2, "o", 1)
+LINE("`u", 2, "u", 1)
+LINE("~A", 2, "A", 1)
+LINE("~N", 2, "N", 1)
+LINE("~O", 2, "O", 1)
+LINE("~a", 2, "a", 1)
+LINE("~n", 2, "n", 1)
+LINE("~o", 2, "o", 1)
+LINE("lA", 2, "<=", 2)
+LINE("rA", 2, "=>", 2)
+LINE("uA", 2, "^", 1)
+LINE("dA", 2, "v", 1)
+LINE("hA", 2, "<=>", 3)
+LINE(":A", 2, "A", 1)
+LINE(":E", 2, "E", 1)
+LINE(":I", 2, "I", 1)
+LINE(":O", 2, "O", 1)
+LINE(":U", 2, "U", 1)
+LINE(":a", 2, "a", 1)
+LINE(":e", 2, "e", 1)
+LINE(":i", 2, "i", 1)
+LINE(":o", 2, "o", 1)
+LINE(":u", 2, "u", 1)
+LINE(":y", 2, "y", 1)
diff --git a/att.c b/att.c
new file mode 100644
index 00000000..573bb6cb
--- /dev/null
+++ b/att.c
@@ -0,0 +1,34 @@
+/* $Id: att.c,v 1.1 2009/03/16 22:19:19 kristaps Exp $ */
+/*
+ * Copyright (c) 2009 Kristaps Dzonsons <kristaps@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 <stdlib.h>
+#include <string.h>
+
+#include "private.h"
+
+#define LINE(x, y) \
+ if (0 == strcmp(p, x)) return(y);
+
+const char *
+mdoc_a2att(const char *p)
+{
+
+#include "att.in"
+
+ return(NULL);
+}
diff --git a/att.in b/att.in
index 6784dc39..170604c9 100644
--- a/att.in
+++ b/att.in
@@ -1,21 +1,39 @@
-# $Id: att.in,v 1.2 2009/03/06 14:24:49 kristaps Exp $
-#
-# This file defines the `.At' macro argument. Lines are composed of
-# tab-delimited fields -- multiple tabs may delimit fields. Comment
-# lines begin with '#'; blank lines are also ok.
-#
-# These were last grok'd from OpenBSD-4.4's mdoc.samples(7).
+/* $Id: att.in,v 1.3 2009/03/16 22:19:19 kristaps Exp $ */
+/*
+ * Copyright (c) 2009 Kristaps Dzonsons <kristaps@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.
+ */
-v1 Version 1 AT&T UNIX
-v2 Version 2 AT&T UNIX
-v3 Version 3 AT&T UNIX
-v4 Version 4 AT&T UNIX
-v5 Version 5 AT&T UNIX
-v6 Version 6 AT&T UNIX
-v7 Version 7 AT&T UNIX
-32v Version 32V AT&T UNIX
-V AT&T System V UNIX
-V.1 AT&T System V.1 UNIX
-V.2 AT&T System V.2 UNIX
-V.3 AT&T System V.3 UNIX
-V.4 AT&T System V.4 UNIX
+/*
+ * This file defines the AT&T versions of the .At macro. This probably
+ * isn't going to change. The right-hand side is the formatted string.
+ *
+ * Be sure to escape strings.
+ */
+
+LINE("v1", "Version 1 AT&T UNIX")
+LINE("v2", "Version 2 AT&T UNIX")
+LINE("v3", "Version 3 AT&T UNIX")
+LINE("v4", "Version 4 AT&T UNIX")
+LINE("v5", "Version 5 AT&T UNIX")
+LINE("v6", "Version 6 AT&T UNIX")
+LINE("v7", "Version 7 AT&T UNIX")
+LINE("32v", "Version 32V AT&T UNIX")
+LINE("V", "AT&T System V UNIX")
+LINE("V.1", "AT&T System V.1 UNIX")
+LINE("V.2", "AT&T System V.2 UNIX")
+LINE("V.3", "AT&T System V.3 UNIX")
+LINE("V.4", "AT&T System V.4 UNIX")
diff --git a/lib.c b/lib.c
new file mode 100644
index 00000000..28b704cf
--- /dev/null
+++ b/lib.c
@@ -0,0 +1,34 @@
+/* $Id: lib.c,v 1.1 2009/03/16 22:19:19 kristaps Exp $ */
+/*
+ * Copyright (c) 2009 Kristaps Dzonsons <kristaps@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 <stdlib.h>
+#include <string.h>
+
+#include "private.h"
+
+#define LINE(x, y) \
+ if (0 == strcmp(p, x)) return(y);
+
+const char *
+mdoc_a2lib(const char *p)
+{
+
+#include "lib.in"
+
+ return(NULL);
+}
diff --git a/lib.in b/lib.in
index f366cbab..3cd8673c 100644
--- a/lib.in
+++ b/lib.in
@@ -1,40 +1,59 @@
-# $Id: lib.in,v 1.2 2009/03/06 14:24:49 kristaps Exp $
-#
-# This file defines the `.Lb' macro argument. Lines are composed of
-# tab-delimited fields -- multiple tabs may delimit fields. Comment
-# lines begin with '#'; blank lines are also ok.
-#
-# These were last grok'd from NetBSD-4.0.1's mdoc.samples(7).
+/* $Id: lib.in,v 1.3 2009/03/16 22:19:19 kristaps Exp $ */
+/*
+ * Copyright (c) 2009 Kristaps Dzonsons <kristaps@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.
+ */
-libarm ARM Architecture Library (libarm, -larm)
-libarm32 ARM32 Architecture Library (libarm32, -larm32)
-libc Standard C Library (libc, -lc)
-libcdk Curses Development Kit Library (libcdk, -lcdk)
-libcompat Compatibility Library (libcompat, -lcompat)
-libcrypt Crypt Library (libcrypt, -lcrypt)
-libcurses Curses Library (libcurses, -lcurses)
-libedit Command Line Editor Library (libedit, -ledit)
-libevent Event Notification Library (libevent, -levent)
-libform Curses Form Library (libform, -lform)
-libi386 i386 Architecture Library (libi386, -li386)
-libintl Internationalized Message Handling Library (libintl, -lintl)
-libipsec IPsec Policy Control Library (libipsec, -lipsec)
-libkvm Kernel Data Access Library (libkvm, -lkvm)
-libm Math Library (libm, -lm)
-libm68k m68k Architecture Library (libm68k, -lm68k)
-libmagic Magic Number Recognition Library (libmagic, -lmagic)
-libmenu Curses Menu Library (libmenu, -lmenu)
-libossaudio OSS Audio Emulation Library (libossaudio, -lossaudio)
-libpam Pluggable Authentication Module Library (libpam, -lpam)
-libpcap Capture Library (libpcap, -lpcap)
-libpci PCI Bus Access Library (libpci, -lpci)
-libpmc Performance Counters Library (libpmc, -lpmc)
-libposix POSIX Compatibility Library (libposix, -lposix)
-libpthread POSIX Threads Library (libpthread, -lpthread)
-libresolv DNS Resolver Library (libresolv, -lresolv)
-librt POSIX Real-time Library (librt, -lrt)
-libtermcap Termcap Access Library (libtermcap, -ltermcap)
-libusbhid USB Human Interface Devices Library (libusbhid, -lusbhid)
-libutil System Utilities Library (libutil, -lutil)
-libx86_64 x86_64 Architecture Library (libx86_64, -lx86_64)
-libz Compression Library (libz, -lz)
+/*
+ * These are all possible .Lb strings. When a new library is added, add
+ * its short-string to the left-hand side and formatted string to the
+ * right-hand side.
+ *
+ * Be sure to escape strings.
+ */
+
+LINE("libarm", "ARM Architecture Library (libarm, \\-larm)")
+LINE("libarm32", "ARM32 Architecture Library (libarm32, \\-larm32)")
+LINE("libc", "Standard C Library (libc, \\-lc)")
+LINE("libcdk", "Curses Development Kit Library (libcdk, \\-lcdk)")
+LINE("libcompat", "Compatibility Library (libcompat, \\-lcompat)")
+LINE("libcrypt", "Crypt Library (libcrypt, \\-lcrypt)")
+LINE("libcurses", "Curses Library (libcurses, \\-lcurses)")
+LINE("libedit", "Command Line Editor Library (libedit, \\-ledit)")
+LINE("libevent", "Event Notification Library (libevent, \\-levent)")
+LINE("libform", "Curses Form Library (libform, \\-lform)")
+LINE("libi386", "i386 Architecture Library (libi386, \\-li386)")
+LINE("libintl", "Internationalized Message Handling Library (libintl, \\-lintl)")
+LINE("libipsec", "IPsec Policy Control Library (libipsec, \\-lipsec)")
+LINE("libkvm", "Kernel Data Access Library (libkvm, \\-lkvm)")
+LINE("libm", "Math Library (libm, \\-lm)")
+LINE("libm68k", "m68k Architecture Library (libm68k, \\-lm68k)")
+LINE("libmagic", "Magic Number Recognition Library (libmagic, \\-lmagic)")
+LINE("libmenu", "Curses Menu Library (libmenu, \\-lmenu)")
+LINE("libossaudio", "OSS Audio Emulation Library (libossaudio, \\-lossaudio)")
+LINE("libpam", "Pluggable Authentication Module Library (libpam, \\-lpam)")
+LINE("libpcap", "Capture Library (libpcap, \\-lpcap)")
+LINE("libpci", "PCI Bus Access Library (libpci, \\-lpci)")
+LINE("libpmc", "Performance Counters Library (libpmc, \\-lpmc)")
+LINE("libposix", "POSIX Compatibility Library (libposix, \\-lposix)")
+LINE("libpthread", "POSIX Threads Library (libpthread, \\-lpthread)")
+LINE("libresolv", "DNS Resolver Library (libresolv, \\-lresolv)")
+LINE("librt", "POSIX Real\\-time Library (librt, -lrt)")
+LINE("libtermcap", "Termcap Access Library (libtermcap, \\-ltermcap)")
+LINE("libusbhid", "USB Human Interface Devices Library (libusbhid, \\-lusbhid)")
+LINE("libutil", "System Utilities Library (libutil, \\-lutil)")
+LINE("libx86_64", "x86_64 Architecture Library (libx86_64, \\-lx86_64)")
+LINE("libz", "Compression Library (libz, \\-lz)")
diff --git a/macro.c b/macro.c
index 2953e26c..dff02ed4 100644
--- a/macro.c
+++ b/macro.c
@@ -1,4 +1,4 @@
-/* $Id: macro.c,v 1.71 2009/03/12 23:05:21 kristaps Exp $ */
+/* $Id: macro.c,v 1.72 2009/03/16 22:19:19 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -32,244 +32,222 @@
/* FIXME: .Fl, .Ar, .Cd handling of `|'. */
-static int macro_obsolete(MACRO_PROT_ARGS);
-static int macro_constant(MACRO_PROT_ARGS);
-static int macro_constant_scoped(MACRO_PROT_ARGS);
-static int macro_constant_delimited(MACRO_PROT_ARGS);
-static int macro_text(MACRO_PROT_ARGS);
-static int macro_scoped(MACRO_PROT_ARGS);
-static int macro_scoped_close(MACRO_PROT_ARGS);
-static int macro_scoped_line(MACRO_PROT_ARGS);
-static int macro_phrase(struct mdoc *, int, int, char *);
+enum mwarn {
+ WMACPARM,
+ WOBS
+};
+
+enum merr {
+ EOPEN,
+ EQUOT,
+ ENOCTX,
+ ENOPARMS
+};
#define REWIND_REWIND (1 << 0)
#define REWIND_NOHALT (1 << 1)
#define REWIND_HALT (1 << 2)
-static int rewind_dohalt(int, enum mdoc_type,
+static int obsolete(MACRO_PROT_ARGS);
+static int blk_part_exp(MACRO_PROT_ARGS);
+static int in_line_eoln(MACRO_PROT_ARGS);
+static int in_line_argn(MACRO_PROT_ARGS);
+static int in_line(MACRO_PROT_ARGS);
+static int blk_full(MACRO_PROT_ARGS);
+static int blk_exp_close(MACRO_PROT_ARGS);
+static int blk_part_imp(MACRO_PROT_ARGS);
+
+static int phrase(struct mdoc *, int, int, char *);
+static int rew_dohalt(int, enum mdoc_type,
const struct mdoc_node *);
-static int rewind_alt(int);
-static int rewind_dobreak(int, const struct mdoc_node *);
-static int rewind_elem(struct mdoc *, int);
-static int rewind_impblock(struct mdoc *, int, int, int);
-static int rewind_expblock(struct mdoc *, int, int, int);
-static int rewind_subblock(enum mdoc_type,
+static int rew_alt(int);
+static int rew_dobreak(int, const struct mdoc_node *);
+static int rew_elem(struct mdoc *, int);
+static int rew_impblock(struct mdoc *, int, int, int);
+static int rew_expblock(struct mdoc *, int, int, int);
+static int rew_subblock(enum mdoc_type,
struct mdoc *, int, int, int);
-static int rewind_last(struct mdoc *, struct mdoc_node *);
+static int rew_last(struct mdoc *, struct mdoc_node *);
static int append_delims(struct mdoc *, int, int *, char *);
static int lookup(struct mdoc *, int, int, int, const char *);
-static int pwarn(struct mdoc *, int, int, int);
-static int perr(struct mdoc *, int, int, int);
-static int scopewarn(struct mdoc *, enum mdoc_type, int, int,
+static int pwarn(struct mdoc *, int, int, enum mwarn);
+static int perr(struct mdoc *, int, int, enum merr);
+static int swarn(struct mdoc *, enum mdoc_type, int, int,
const struct mdoc_node *);
-#define WMACPARM (1)
-#define WOBS (2)
-
-#define ENOCTX (1)
-#define ENOPARMS (2)
+#define nerr(m, n, t) perr((m), (n)->line, (n)->pos, (t))
/* Central table of library: who gets parsed how. */
const struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
{ NULL, 0 }, /* \" */
- { macro_constant, MDOC_PROLOGUE }, /* Dd */
- { macro_constant, MDOC_PROLOGUE }, /* Dt */
- { macro_constant, MDOC_PROLOGUE }, /* Os */
- { macro_scoped, 0 }, /* Sh */
- { macro_scoped, 0 }, /* Ss */
- { macro_text, 0 }, /* Pp */
- { macro_scoped_line, MDOC_PARSED }, /* D1 */
- { macro_scoped_line, MDOC_PARSED }, /* Dl */
- { macro_scoped, MDOC_EXPLICIT }, /* Bd */
- { macro_scoped_close, MDOC_EXPLICIT }, /* Ed */
- { macro_scoped, MDOC_EXPLICIT }, /* Bl */
- { macro_scoped_close, MDOC_EXPLICIT }, /* El */
- { macro_scoped, MDOC_PARSED }, /* It */
- { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */
- { macro_text, MDOC_PARSED }, /* An */
- { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */
- { macro_constant, MDOC_CALLABLE }, /* Cd */
- { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */
- { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */
- { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Er */
- { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Ev */
- { macro_constant, 0 }, /* Ex */
- { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Fa */
- { macro_constant, 0 }, /* Fd */
- { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Fl */
- { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Fn */
- { macro_text, MDOC_PARSED }, /* Ft */
- { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Ic */
- { macro_constant, 0 }, /* In */
- { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Li */
- { macro_constant, 0 }, /* Nd */
- { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Nm */
- { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Op */
- { macro_obsolete, 0 }, /* Ot */
- { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Pa */
- { macro_constant, 0 }, /* Rv */
- /* XXX - .St supposed to be (but isn't) callable. */
- { macro_constant_delimited, MDOC_PARSED }, /* St */
- { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Va */
- { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */
- { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Xr */
- { macro_constant, 0 }, /* %A */
- { macro_constant, 0 }, /* %B */
- { macro_constant, 0 }, /* %D */
- { macro_constant, 0 }, /* %I */
- { macro_constant, 0 }, /* %J */
- { macro_constant, 0 }, /* %N */
- { macro_constant, 0 }, /* %O */
- { macro_constant, 0 }, /* %P */
- { macro_constant, 0 }, /* %R */
- { macro_constant, 0 }, /* %T */
- { macro_constant, 0 }, /* %V */
- { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ac */
- { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ao */
- { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Aq */
- { macro_constant_delimited, MDOC_CALLABLE | MDOC_PARSED }, /* At */
- { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Bc */
- { macro_scoped, MDOC_EXPLICIT }, /* Bf */
- { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bo */
- { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Bq */
- { macro_constant_delimited, MDOC_CALLABLE | MDOC_PARSED }, /* Bsx */
- { macro_constant_delimited, MDOC_CALLABLE | MDOC_PARSED }, /* Bx */
- { macro_constant, 0 }, /* Db */
- { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Dc */
- { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Do */
- { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dq */
- { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ec */
- { macro_scoped_close, MDOC_EXPLICIT }, /* Ef */
- { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Em */
- { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Eo */
- { macro_constant_delimited, MDOC_CALLABLE | MDOC_PARSED }, /* Fx */
- { macro_text, MDOC_PARSED }, /* Ms */
- { macro_constant_delimited, MDOC_CALLABLE | MDOC_PARSED }, /* No */
- { macro_constant_delimited, MDOC_CALLABLE | MDOC_PARSED }, /* Ns */
- { macro_constant_delimited, MDOC_CALLABLE | MDOC_PARSED }, /* Nx */
- { macro_constant_delimited, MDOC_CALLABLE | MDOC_PARSED }, /* Ox */
- { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Pc */
- { macro_constant_delimited, MDOC_PARSED }, /* Pf */
- { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Po */
- { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Pq */
- { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Qc */
- { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ql */
- { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Qo */
- { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Qq */
- { macro_scoped_close, MDOC_EXPLICIT }, /* Re */
- { macro_scoped, MDOC_EXPLICIT }, /* Rs */
- { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Sc */
- { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* So */
- { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sq */
- { macro_constant, 0 }, /* Sm */
- { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Sx */
- { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Sy */
- { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Tn */
- { macro_constant_delimited, MDOC_CALLABLE | MDOC_PARSED }, /* Ux */
- { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Xc */
- { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Xo */
- /* XXX - .Fo supposed to be (but isn't) callable. */
- { macro_scoped, MDOC_EXPLICIT }, /* Fo */
- { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Fc */
- { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Oo */
- { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Oc */
- { macro_scoped, MDOC_EXPLICIT }, /* Bk */
- { macro_scoped_close, MDOC_EXPLICIT }, /* Ek */
- { macro_constant, 0 }, /* Bt */
- { macro_constant, 0 }, /* Hf */
- { macro_obsolete, 0 }, /* Fr */
- { macro_constant, 0 }, /* Ud */
- { macro_constant, 0 }, /* Lb */
- { macro_constant_delimited, MDOC_CALLABLE | MDOC_PARSED }, /* Ap */
- { macro_text, 0 }, /* Lp */
- { macro_text, MDOC_PARSED }, /* Lk */
- { macro_text, MDOC_PARSED }, /* Mt */
- { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Brq */
- { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bro */
- { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Brc */
- { macro_constant, 0 }, /* %C */
+ { in_line_eoln, MDOC_PROLOGUE }, /* Dd */
+ { in_line_eoln, MDOC_PROLOGUE }, /* Dt */
+ { in_line_eoln, MDOC_PROLOGUE }, /* Os */
+ { blk_full, 0 }, /* Sh */
+ { blk_full, 0 }, /* Ss */
+ { in_line, 0 }, /* Pp */
+ { blk_part_imp, MDOC_PARSED }, /* D1 */
+ { blk_part_imp, MDOC_PARSED }, /* Dl */
+ { blk_full, MDOC_EXPLICIT }, /* Bd */
+ { blk_exp_close, MDOC_EXPLICIT }, /* Ed */
+ { blk_full, MDOC_EXPLICIT }, /* Bl */
+ { blk_exp_close, MDOC_EXPLICIT }, /* El */
+ { blk_full, MDOC_PARSED }, /* It */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */
+ { in_line, MDOC_PARSED }, /* An */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */
+ { in_line_eoln, MDOC_CALLABLE }, /* Cd */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Er */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ev */
+ { in_line_eoln, 0 }, /* Ex */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fa */
+ { in_line_eoln, 0 }, /* Fd */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fl */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fn */
+ { in_line, MDOC_PARSED }, /* Ft */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ic */
+ { in_line_eoln, 0 }, /* In */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Li */
+ { in_line_eoln, 0 }, /* Nd */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Nm */
+ { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Op */
+ { obsolete, 0 }, /* Ot */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Pa */
+ { in_line_eoln, 0 }, /* Rv */
+ { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* St */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Va */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Xr */
+ { in_line_eoln, 0 }, /* %A */
+ { in_line_eoln, 0 }, /* %B */
+ { in_line_eoln, 0 }, /* %D */
+ { in_line_eoln, 0 }, /* %I */
+ { in_line_eoln, 0 }, /* %J */
+ { in_line_eoln, 0 }, /* %N */
+ { in_line_eoln, 0 }, /* %O */
+ { in_line_eoln, 0 }, /* %P */
+ { in_line_eoln, 0 }, /* %R */
+ { in_line_eoln, 0 }, /* %T */
+ { in_line_eoln, 0 }, /* %V */
+ { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ac */
+ { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ao */
+ { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Aq */
+ { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* At */
+ { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Bc */
+ { blk_full, MDOC_EXPLICIT }, /* Bf */
+ { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bo */
+ { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Bq */
+ { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bsx */
+ { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bx */
+ { in_line_eoln, 0 }, /* Db */
+ { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Dc */
+ { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Do */
+ { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Dq */
+ { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ec */
+ { blk_exp_close, MDOC_EXPLICIT }, /* Ef */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Em */
+ { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Eo */
+ { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Fx */
+ { in_line, MDOC_PARSED }, /* Ms */
+ { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* No */
+ { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ns */
+ { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Nx */
+ { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ox */
+ { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Pc */
+ { in_line_argn, MDOC_PARSED | MDOC_IGNDELIM }, /* Pf */
+ { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Po */
+ { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Pq */
+ { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Qc */
+ { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Ql */
+ { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Qo */
+ { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Qq */
+ { blk_exp_close, MDOC_EXPLICIT }, /* Re */
+ { blk_full, MDOC_EXPLICIT }, /* Rs */
+ { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Sc */
+ { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* So */
+ { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Sq */
+ { in_line_eoln, 0 }, /* Sm */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sx */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sy */
+ { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Tn */
+ { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ux */
+ { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Xc */
+ { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Xo */
+ { blk_full, MDOC_EXPLICIT | MDOC_CALLABLE }, /* Fo */
+ { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Fc */
+ { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Oo */
+ { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Oc */
+ { blk_full, MDOC_EXPLICIT }, /* Bk */
+ { blk_exp_close, MDOC_EXPLICIT }, /* Ek */
+ { in_line_eoln, 0 }, /* Bt */
+ { in_line_eoln, 0 }, /* Hf */
+ { obsolete, 0 }, /* Fr */
+ { in_line_eoln, 0 }, /* Ud */
+ { in_line_eoln, 0 }, /* Lb */
+ { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ap */
+ { in_line, 0 }, /* Lp */
+ { in_line, MDOC_PARSED }, /* Lk */
+ { in_line, MDOC_PARSED }, /* Mt */
+ { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Brq */
+ { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bro */
+ { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Brc */
+ { in_line_eoln, 0 }, /* %C */
+ { obsolete, 0 }, /* Es */
+ { obsolete, 0 }, /* En */
};
const struct mdoc_macro * const mdoc_macros = __mdoc_macros;
-/*
- * This is called at the end of parsing. It must traverse up the tree,
- * closing out open [implicit] scopes. Obviously, open explicit scopes
- * are errors.
- */
-int
-macro_end(struct mdoc *mdoc)
-{
- struct mdoc_node *n;
-
- assert(mdoc->first);
- assert(mdoc->last);
-
- /* Scan for open explicit scopes. */
-
- n = MDOC_VALID & mdoc->last->flags ?
- mdoc->last->parent : mdoc->last;
-
- for ( ; n; n = n->parent) {
- if (MDOC_BLOCK != n->type)
- continue;
- if ( ! (MDOC_EXPLICIT & mdoc_macros[n->tok].flags))
- continue;
- return(mdoc_nerr(mdoc, n,
- "macro scope still open on exit"));
- }
-
- return(rewind_last(mdoc, mdoc->first));
-}
-
-
static int
-perr(struct mdoc *mdoc, int line, int pos, int type)
+perr(struct mdoc *mdoc, int line, int pos, enum merr type)
{
- int c;
+ char *p;
+ p = NULL;
switch (type) {
+ case (EOPEN):
+ p = "explicit scope still open on exit";
+ break;
+ case (EQUOT):
+ p = "unterminated quotation";
+ break;
case (ENOCTX):
- c = mdoc_perr(mdoc, line, pos,
- "closing macro has no prior context");
+ p = "closure has no prior context";
break;
case (ENOPARMS):
- c = mdoc_perr(mdoc, line, pos,
- "macro doesn't expect parameters");
+ p = "unexpect line arguments";
break;
- default:
- abort();
- /* NOTREACHED */
}
- return(c);
+ assert(p);
+ return(mdoc_perr(mdoc, line, pos, p));
}
+
static int
-pwarn(struct mdoc *mdoc, int line, int pos, int type)
+pwarn(struct mdoc *mdoc, int line, int pos, enum mwarn type)
{
- int c;
+ char *p;
+ p = NULL;
switch (type) {
case (WMACPARM):
- c = mdoc_pwarn(mdoc, line, pos, WARN_SYNTAX,
- "macro-like parameter");
+ p = "macro-like parameter";
break;
case (WOBS):
- c = mdoc_pwarn(mdoc, line, pos, WARN_SYNTAX,
- "macro is marked obsolete");
+ p = "macro marked obsolete";
break;
- default:
- abort();
- /* NOTREACHED */
}
- return(c);
+ assert(p);
+ return(mdoc_pwarn(mdoc, line, pos, WARN_SYNTAX, p));
}
static int
-scopewarn(struct mdoc *mdoc, enum mdoc_type type,
+swarn(struct mdoc *mdoc, enum mdoc_type type,
int line, int pos, const struct mdoc_node *p)
{
const char *n, *t, *tt;
@@ -315,6 +293,35 @@ scopewarn(struct mdoc *mdoc, enum mdoc_type type,
}
+/*
+ * This is called at the end of parsing. It must traverse up the tree,
+ * closing out open [implicit] scopes. Obviously, open explicit scopes
+ * are errors.
+ */
+int
+macro_end(struct mdoc *mdoc)
+{
+ struct mdoc_node *n;
+
+ assert(mdoc->first);
+ assert(mdoc->last);
+
+ /* Scan for open explicit scopes. */
+
+ n = MDOC_VALID & mdoc->last->flags ?
+ mdoc->last->parent : mdoc->last;
+
+ for ( ; n; n = n->parent) {
+ if (MDOC_BLOCK != n->type)
+ continue;
+ if ( ! (MDOC_EXPLICIT & mdoc_macros[n->tok].flags))
+ continue;
+ return(nerr(mdoc, n, EOPEN));
+ }
+
+ return(rew_last(mdoc, mdoc->first));
+}
+
static int
lookup(struct mdoc *mdoc, int line, int pos, int from, const char *p)
{
@@ -332,7 +339,7 @@ lookup(struct mdoc *mdoc, int line, int pos, int from, const char *p)
static int
-rewind_last(struct mdoc *mdoc, struct mdoc_node *to)
+rew_last(struct mdoc *mdoc, struct mdoc_node *to)
{
assert(to);
@@ -355,7 +362,7 @@ rewind_last(struct mdoc *mdoc, struct mdoc_node *to)
static int
-rewind_alt(int tok)
+rew_alt(int tok)
{
switch (tok) {
case (MDOC_Ac):
@@ -399,7 +406,7 @@ rewind_alt(int tok)
static int
-rewind_dohalt(int tok, enum mdoc_type type, const struct mdoc_node *p)
+rew_dohalt(int tok, enum mdoc_type type, const struct mdoc_node *p)
{
if (MDOC_ROOT == p->type)
@@ -524,7 +531,7 @@ rewind_dohalt(int tok, enum mdoc_type type, const struct mdoc_node *p)
case (MDOC_Sc):
/* FALLTHROUGH */
case (MDOC_Xc):
- if (type == p->type && rewind_alt(tok) == p->tok)
+ if (type == p->type && rew_alt(tok) == p->tok)
return(REWIND_REWIND);
break;
default:
@@ -537,7 +544,7 @@ rewind_dohalt(int tok, enum mdoc_type type, const struct mdoc_node *p)
static int
-rewind_dobreak(int tok, const struct mdoc_node *p)
+rew_dobreak(int tok, const struct mdoc_node *p)
{
assert(MDOC_ROOT != p->type);
@@ -569,7 +576,7 @@ rewind_dobreak(int tok, const struct mdoc_node *p)
}
if (MDOC_EXPLICIT & mdoc_macros[tok].flags)
- return(p->tok == rewind_alt(tok));
+ return(p->tok == rew_alt(tok));
else if (MDOC_BLOCK == p->type)
return(1);
@@ -578,7 +585,7 @@ rewind_dobreak(int tok, const struct mdoc_node *p)
static int
-rewind_elem(struct mdoc *mdoc, int tok)
+rew_elem(struct mdoc *mdoc, int tok)
{
struct mdoc_node *n;
@@ -588,12 +595,12 @@ rewind_elem(struct mdoc *mdoc, int tok)
assert(MDOC_ELEM == n->type);
assert(tok == n->tok);
- return(rewind_last(mdoc, n));
+ return(rew_last(mdoc, n));
}
static int
-rewind_subblock(enum mdoc_type type, struct mdoc *mdoc,
+rew_subblock(enum mdoc_type type, struct mdoc *mdoc,
int tok, int line, int ppos)
{
struct mdoc_node *n;
@@ -601,67 +608,67 @@ rewind_subblock(enum mdoc_type type, struct mdoc *mdoc,
/* LINTED */
for (n = mdoc->last; n; n = n->parent) {
- c = rewind_dohalt(tok, type, n);
+ c = rew_dohalt(tok, type, n);
if (REWIND_HALT == c)
return(1);
if (REWIND_REWIND == c)
break;
- else if (rewind_dobreak(tok, n))
+ else if (rew_dobreak(tok, n))
continue;
- if ( ! scopewarn(mdoc, type, line, ppos, n))
+ if ( ! swarn(mdoc, type, line, ppos, n))
return(0);
}
assert(n);
- return(rewind_last(mdoc, n));
+ return(rew_last(mdoc, n));
}
static int
-rewind_expblock(struct mdoc *mdoc, int tok, int line, int ppos)
+rew_expblock(struct mdoc *mdoc, int tok, int line, int ppos)
{
struct mdoc_node *n;
int c;
/* LINTED */
for (n = mdoc->last; n; n = n->parent) {
- c = rewind_dohalt(tok, MDOC_BLOCK, n);
+ c = rew_dohalt(tok, MDOC_BLOCK, n);
if (REWIND_HALT == c)
return(perr(mdoc, line, ppos, ENOCTX));
if (REWIND_REWIND == c)
break;
- else if (rewind_dobreak(tok, n))
+ else if (rew_dobreak(tok, n))
continue;
- if ( ! scopewarn(mdoc, MDOC_BLOCK, line, ppos, n))
+ if ( ! swarn(mdoc, MDOC_BLOCK, line, ppos, n))
return(0);
}
assert(n);
- return(rewind_last(mdoc, n));
+ return(rew_last(mdoc, n));
}
static int
-rewind_impblock(struct mdoc *mdoc, int tok, int line, int ppos)
+rew_impblock(struct mdoc *mdoc, int tok, int line, int ppos)
{
struct mdoc_node *n;
int c;
/* LINTED */
for (n = mdoc->last; n; n = n->parent) {
- c = rewind_dohalt(tok, MDOC_BLOCK, n);
+ c = rew_dohalt(tok, MDOC_BLOCK, n);
if (REWIND_HALT == c)
return(1);
else if (REWIND_REWIND == c)
break;
- else if (rewind_dobreak(tok, n))
+ else if (rew_dobreak(tok, n))
continue;
- if ( ! scopewarn(mdoc, MDOC_BLOCK, line, ppos, n))
+ if ( ! swarn(mdoc, MDOC_BLOCK, line, ppos, n))
return(0);
}
assert(n);
- return(rewind_last(mdoc, n));
+ return(rew_last(mdoc, n));
}
@@ -694,13 +701,12 @@ append_delims(struct mdoc *mdoc, int line, int *pos, char *buf)
/*
- * Close out an explicit scope. This optionally parses a TAIL type with
- * a set number of TEXT children.
+ * Close out block partial/full explicit.
*/
static int
-macro_scoped_close(MACRO_PROT_ARGS)
+blk_exp_close(MACRO_PROT_ARGS)
{
- int tt, j, c, lastarg, maxargs, flushed;
+ int j, c, lastarg, maxargs, flushed;
char *p;
switch (tok) {
@@ -712,44 +718,36 @@ macro_scoped_close(MACRO_PROT_ARGS)
break;
}
- tt = rewind_alt(tok);
-
- mdoc_msg(mdoc, "parse: %s closing %s",
- mdoc_macronames[tok], mdoc_macronames[tt]);
-
if ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags)) {
if (0 == buf[*pos]) {
- if ( ! rewind_subblock(MDOC_BODY, mdoc,
+ if ( ! rew_subblock(MDOC_BODY, mdoc,
tok, line, ppos))
return(0);
- return(rewind_expblock(mdoc, tok, line, ppos));
+ return(rew_expblock(mdoc, tok, line, ppos));
}
return(perr(mdoc, line, ppos, ENOPARMS));
}
- if ( ! rewind_subblock(MDOC_BODY, mdoc, tok, line, ppos))
+ if ( ! rew_subblock(MDOC_BODY, mdoc, tok, line, ppos))
return(0);
- lastarg = ppos;
- flushed = 0;
-
if (maxargs > 0) {
- if ( ! mdoc_tail_alloc(mdoc, line, ppos, tt))
+ if ( ! mdoc_tail_alloc(mdoc, line,
+ ppos, rew_alt(tok)))
return(0);
mdoc->next = MDOC_NEXT_CHILD;
}
- for (j = 0; /* No sentinel. */; j++) {
+ for (lastarg = ppos, flushed = j = 0; ; j++) {
lastarg = *pos;
if (j == maxargs && ! flushed) {
- if ( ! rewind_expblock(mdoc, tok, line, ppos))
+ if ( ! rew_expblock(mdoc, tok, line, ppos))
return(0);
flushed = 1;
}
c = mdoc_args(mdoc, line, pos, buf, tok, &p);
- assert(ARGS_PHRASE != c);
if (ARGS_ERROR == c)
return(0);
@@ -762,7 +760,7 @@ macro_scoped_close(MACRO_PROT_ARGS)
return(0);
else if (MDOC_MAX != c) {
if ( ! flushed) {
- if ( ! rewind_expblock(mdoc, tok,
+ if ( ! rew_expblock(mdoc, tok,
line, ppos))
return(0);
flushed = 1;
@@ -777,7 +775,7 @@ macro_scoped_close(MACRO_PROT_ARGS)
mdoc->next = MDOC_NEXT_SIBLING;
}
- if ( ! flushed && ! rewind_expblock(mdoc, tok, line, ppos))
+ if ( ! flushed && ! rew_expblock(mdoc, tok, line, ppos))
return(0);
if (ppos > 1)
@@ -787,64 +785,40 @@ macro_scoped_close(MACRO_PROT_ARGS)
/*
- * A general text macro. This is a complex case because of punctuation.
- * If a text macro is followed by words, then punctuation, the macro is
- * "stopped" and "reopened" following the punctuation. Thus, the
- * following arises:
- *
- * .Fl a ; b
- *
- * ELEMENT (.Fl)
- * TEXT (`a')
- * TEXT (`;')
- * ELEMENT (.Fl)
- * TEXT (`b')
- *
- * This must handle the following situations:
- *
- * .Fl Ar b ; ;
- *
- * ELEMENT (.Fl)
- * ELEMENT (.Ar)
- * TEXT (`b')
- * TEXT (`;')
- * TEXT (`;')
+ * In-line macros where reserved words cause scope close-reopen.
*/
static int
-macro_text(MACRO_PROT_ARGS)
+in_line(MACRO_PROT_ARGS)
{
int la, lastpunct, c, w;
struct mdoc_arg *arg;
char *p;
- la = ppos;
- lastpunct = 0;
- arg = NULL;
-
- for (;;) {
+ for (la = ppos, arg = NULL;; ) {
la = *pos;
c = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
- if (ARGV_EOLN == c)
- break;
+
if (ARGV_WORD == c) {
*pos = la;
break;
- } else if (ARGV_ARG == c)
+ }
+
+ if (ARGV_EOLN == c)
+ break;
+ if (ARGV_ARG == c)
continue;
+
mdoc_argv_free(arg);
return(0);
}
if ( ! mdoc_elem_alloc(mdoc, line, ppos, tok, arg))
return(0);
-
mdoc->next = MDOC_NEXT_CHILD;
- lastpunct = 0;
- for (;;) {
+ for (lastpunct = 0;; ) {
la = *pos;
w = mdoc_args(mdoc, line, pos, buf, tok, &p);
- assert(ARGS_PHRASE != w);
if (ARGS_ERROR == w)
return(0);
@@ -861,7 +835,7 @@ macro_text(MACRO_PROT_ARGS)
/* MDOC_MAX (not a macro) or -1 (error). */
if (MDOC_MAX != c && -1 != c) {
- if (0 == lastpunct && ! rewind_elem(mdoc, tok))
+ if (0 == lastpunct && ! rew_elem(mdoc, tok))
return(0);
c = mdoc_macro(mdoc, c, line, la, pos, buf);
if (0 == c)
@@ -875,7 +849,7 @@ macro_text(MACRO_PROT_ARGS)
/* Non-quote-enclosed punctuation. */
if (ARGS_QWORD != w && mdoc_isdelim(p)) {
- if (0 == lastpunct && ! rewind_elem(mdoc, tok))
+ if (0 == lastpunct && ! rew_elem(mdoc, tok))
return(0);
lastpunct = 1;
} else if (lastpunct) {
@@ -893,7 +867,7 @@ macro_text(MACRO_PROT_ARGS)
mdoc->next = MDOC_NEXT_SIBLING;
}
- if (0 == lastpunct && ! rewind_elem(mdoc, tok))
+ if (0 == lastpunct && ! rew_elem(mdoc, tok))
return(0);
if (ppos > 1)
return(1);
@@ -902,76 +876,49 @@ macro_text(MACRO_PROT_ARGS)
/*
- * Handle explicit-scope (having a different closure token) and implicit
- * scope (closing out prior scopes when re-invoked) macros. These
- * constitute the BLOCK type and usually span multiple lines. These
- * always have HEAD and sometimes have BODY types. In the multi-line
- * case:
- *
- * .Bd -ragged
- * Text.
- * .Fl macro
- * Another.
- * .Ed
- *
- * BLOCK (.Bd)
- * HEAD
- * BODY
- * TEXT (`Text.')
- * ELEMENT (.Fl)
- * TEXT (`macro')
- * TEXT (`Another.')
- *
- * Note that the `.It' macro, possibly the most difficult (as it has
- * embedded scope, etc.) is handled by this routine. It handles
- * columnar output, where columns are "phrases" and denote multiple
- * block heads.
+ * Block full-explicit and full-implicit.
*/
static int
-macro_scoped(MACRO_PROT_ARGS)
+blk_full(MACRO_PROT_ARGS)
{
int c, lastarg, reopen;
struct mdoc_arg *arg;
char *p;
- assert ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags));
-
- /* First rewind extant implicit scope. */
-
if ( ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)) {
- if ( ! rewind_subblock(MDOC_BODY, mdoc, tok, line, ppos))
+ if ( ! rew_subblock(MDOC_BODY, mdoc,
+ tok, line, ppos))
return(0);
- if ( ! rewind_impblock(mdoc, tok, line, ppos))
+ if ( ! rew_impblock(mdoc, tok, line, ppos))
return(0);
}
- /* Parse arguments. */
-
- arg = NULL;
-
- for (;;) {
+ for (arg = NULL;; ) {
lastarg = *pos;
c = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
- if (ARGV_EOLN == c)
- break;
+
if (ARGV_WORD == c) {
*pos = lastarg;
break;
- } else if (ARGV_ARG == c)
+ }
+
+ if (ARGV_EOLN == c)
+ break;
+ if (ARGV_ARG == c)
continue;
+
mdoc_argv_free(arg);
return(0);
}
if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, arg))
return(0);
-
mdoc->next = MDOC_NEXT_CHILD;
if (0 == buf[*pos]) {
if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
return(0);
- if ( ! rewind_subblock(MDOC_HEAD, mdoc,
+ if ( ! rew_subblock(MDOC_HEAD, mdoc,
tok, line, ppos))
return(0);
if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
@@ -982,12 +929,9 @@ macro_scoped(MACRO_PROT_ARGS)
if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
return(0);
-
- /* Indicate that columnar scope shouldn't be reopened. */
- reopen = 0;
mdoc->next = MDOC_NEXT_CHILD;
- for (;;) {
+ for (reopen = 0;; ) {
lastarg = *pos;
c = mdoc_args(mdoc, line, pos, buf, tok, &p);
@@ -996,18 +940,19 @@ macro_scoped(MACRO_PROT_ARGS)
if (ARGS_EOLN == c)
break;
if (ARGS_PHRASE == c) {
- if (reopen && ! mdoc_head_alloc(mdoc, line, ppos, tok))
+ if (reopen && ! mdoc_head_alloc
+ (mdoc, line, ppos, tok))
return(0);
mdoc->next = MDOC_NEXT_CHILD;
-
/*
* Phrases are self-contained macro phrases used
* in the columnar output of a macro. They need
* special handling.
*/
- if ( ! macro_phrase(mdoc, line, lastarg, buf))
+ if ( ! phrase(mdoc, line, lastarg, buf))
return(0);
- if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
+ if ( ! rew_subblock(MDOC_HEAD, mdoc,
+ tok, line, ppos))
return(0);
reopen = 1;
@@ -1031,7 +976,7 @@ macro_scoped(MACRO_PROT_ARGS)
if (1 == ppos && ! append_delims(mdoc, line, pos, buf))
return(0);
- if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
+ if ( ! rew_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
return(0);
if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
@@ -1043,26 +988,10 @@ macro_scoped(MACRO_PROT_ARGS)
/*
- * This handles a case of implicitly-scoped macro (BLOCK) limited to a
- * single line. Instead of being closed out by a subsequent call to
- * another macro, the scope is closed at the end of line. These don't
- * have BODY or TAIL types. Notice that the punctuation falls outside
- * of the HEAD type.
- *
- * .Qq a Fl b Ar d ; ;
- *
- * BLOCK (Qq)
- * HEAD
- * TEXT (`a')
- * ELEMENT (.Fl)
- * TEXT (`b')
- * ELEMENT (.Ar)
- * TEXT (`d')
- * TEXT (`;')
- * TEXT (`;')
+ * Block partial-imnplicit scope.
*/
static int
-macro_scoped_line(MACRO_PROT_ARGS)
+blk_part_imp(MACRO_PROT_ARGS)
{
int lastarg, c;
char *p;
@@ -1080,8 +1009,7 @@ macro_scoped_line(MACRO_PROT_ARGS)
/* XXX - no known argument macros. */
- lastarg = ppos;
- for (;;) {
+ for (lastarg = ppos;; ) {
lastarg = *pos;
c = mdoc_args(mdoc, line, pos, buf, tok, &p);
assert(ARGS_PHRASE != c);
@@ -1108,33 +1036,21 @@ macro_scoped_line(MACRO_PROT_ARGS)
}
if (1 == ppos) {
- if ( ! rewind_subblock(MDOC_BODY, mdoc, tok, line, ppos))
+ if ( ! rew_subblock(MDOC_BODY, mdoc, tok, line, ppos))
return(0);
if ( ! append_delims(mdoc, line, pos, buf))
return(0);
- } else if ( ! rewind_subblock(MDOC_BODY, mdoc, tok, line, ppos))
+ } else if ( ! rew_subblock(MDOC_BODY, mdoc, tok, line, ppos))
return(0);
- return(rewind_impblock(mdoc, tok, line, ppos));
+ return(rew_impblock(mdoc, tok, line, ppos));
}
/*
- * A constant-scoped macro is like a simple-scoped macro (mdoc_scoped)
- * except that it doesn't handle implicit scopes and explicit ones have
- * a fixed number of TEXT children to the BODY.
- *
- * .Fl a So b Sc ;
- *
- * ELEMENT (.Fl)
- * TEXT (`a')
- * BLOCK (.So)
- * HEAD
- * BODY
- * TEXT (`b')
- * TEXT (';')
+ * Block partial-explicit macros.
*/
static int
-macro_constant_scoped(MACRO_PROT_ARGS)
+blk_part_exp(MACRO_PROT_ARGS)
{
int lastarg, flushed, j, c, maxargs;
char *p;
@@ -1142,6 +1058,10 @@ macro_constant_scoped(MACRO_PROT_ARGS)
lastarg = ppos;
flushed = 0;
+ /*
+ * Number of arguments (head arguments). Only `Eo' has these,
+ */
+
switch (tok) {
case (MDOC_Eo):
maxargs = 1;
@@ -1158,7 +1078,8 @@ macro_constant_scoped(MACRO_PROT_ARGS)
if (0 == maxargs) {
if ( ! mdoc_head_alloc(mdoc, line, ppos, tok))
return(0);
- if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
+ if ( ! rew_subblock(MDOC_HEAD, mdoc,
+ tok, line, ppos))
return(0);
if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
return(0);
@@ -1168,11 +1089,11 @@ macro_constant_scoped(MACRO_PROT_ARGS)
mdoc->next = MDOC_NEXT_CHILD;
- for (j = 0; /* No sentinel. */; j++) {
+ for (j = 0; ; j++) {
lastarg = *pos;
-
if (j == maxargs && ! flushed) {
- if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
+ if ( ! rew_subblock(MDOC_HEAD, mdoc,
+ tok, line, ppos))
return(0);
flushed = 1;
if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
@@ -1194,7 +1115,7 @@ macro_constant_scoped(MACRO_PROT_ARGS)
return(0);
else if (MDOC_MAX != c) {
if ( ! flushed) {
- if ( ! rewind_subblock(MDOC_HEAD, mdoc,
+ if ( ! rew_subblock(MDOC_HEAD, mdoc,
tok, line, ppos))
return(0);
flushed = 1;
@@ -1210,7 +1131,7 @@ macro_constant_scoped(MACRO_PROT_ARGS)
}
if ( ! flushed && mdoc_isdelim(p)) {
- if ( ! rewind_subblock(MDOC_HEAD, mdoc,
+ if ( ! rew_subblock(MDOC_HEAD, mdoc,
tok, line, ppos))
return(0);
flushed = 1;
@@ -1225,7 +1146,7 @@ macro_constant_scoped(MACRO_PROT_ARGS)
}
if ( ! flushed) {
- if ( ! rewind_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
+ if ( ! rew_subblock(MDOC_HEAD, mdoc, tok, line, ppos))
return(0);
if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
return(0);
@@ -1239,32 +1160,20 @@ macro_constant_scoped(MACRO_PROT_ARGS)
/*
- * A delimited constant is very similar to the macros parsed by
- * macro_text except that, in the event of punctuation, the macro isn't
- * "re-opened" as it is in macro_text. Also, these macros have a fixed
- * number of parameters.
- *
- * .Fl a No b
- *
- * ELEMENT (.Fl)
- * TEXT (`a')
- * ELEMENT (.No)
- * TEXT (`b')
+ * In-line macros where reserved words signal closure of the macro.
+ * Macros also have a fixed number of arguments.
*/
static int
-macro_constant_delimited(MACRO_PROT_ARGS)
+in_line_argn(MACRO_PROT_ARGS)
{
- int lastarg, flushed, j, c, maxargs,
- igndelim, ignargs;
+ int lastarg, flushed, j, c, maxargs;
struct mdoc_arg *arg;
char *p;
- lastarg = ppos;
- flushed = 0;
/*
- * Maximum arguments per macro. Some of these have none and
- * exit as soon as they're parsed.
+ * Fixed maximum arguments per macro. Some of these have none
+ * and close as soon as the invocation is parsed.
*/
switch (tok) {
@@ -1282,68 +1191,38 @@ macro_constant_delimited(MACRO_PROT_ARGS)
break;
}
- /*
- * Whether to ignore delimiter characters. `Pf' accepts its
- * first token as a parameter no matter what it looks like (if
- * it's text).
- */
+ for (lastarg = ppos, arg = NULL;; ) {
+ lastarg = *pos;
+ c = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
- switch (tok) {
- case (MDOC_Pf):
- igndelim = 1;
- break;
- default:
- igndelim = 0;
- break;
- }
+ if (ARGV_WORD == c) {
+ *pos = lastarg;
+ break;
+ }
- /*
- * Whether to ignore arguments: `St', for example, handles its
- * argument-like parameters as regular parameters.
- */
+ if (ARGV_EOLN == c)
+ break;
+ if (ARGV_ARG == c)
+ continue;
- switch (tok) {
- case (MDOC_St):
- ignargs = 1;
- break;
- default:
- ignargs = 0;
- break;
+ mdoc_argv_free(arg);
+ return(0);
}
- arg = NULL;
-
- if ( ! ignargs)
- for (;;) {
- lastarg = *pos;
- c = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
- if (ARGV_EOLN == c)
- break;
- if (ARGV_WORD == c) {
- *pos = lastarg;
- break;
- } else if (ARGV_ARG == c)
- continue;
- mdoc_argv_free(arg);
- return(0);
- }
-
if ( ! mdoc_elem_alloc(mdoc, line, ppos, tok, arg))
return(0);
-
mdoc->next = MDOC_NEXT_CHILD;
- for (j = 0; /* No sentinel. */; j++) {
+ for (flushed = j = 0; ; j++) {
lastarg = *pos;
if (j == maxargs && ! flushed) {
- if ( ! rewind_elem(mdoc, tok))
+ if ( ! rew_elem(mdoc, tok))
return(0);
flushed = 1;
}
c = mdoc_args(mdoc, line, pos, buf, tok, &p);
- assert(ARGS_PHRASE != c);
if (ARGS_ERROR == c)
return(0);
@@ -1355,7 +1234,7 @@ macro_constant_delimited(MACRO_PROT_ARGS)
if (-1 == (c = lookup(mdoc, line, lastarg, tok, p)))
return(0);
else if (MDOC_MAX != c) {
- if ( ! flushed && ! rewind_elem(mdoc, tok))
+ if ( ! flushed && ! rew_elem(mdoc, tok))
return(0);
flushed = 1;
if ( ! mdoc_macro(mdoc, c, line, lastarg, pos, buf))
@@ -1363,8 +1242,9 @@ macro_constant_delimited(MACRO_PROT_ARGS)
break;
}
- if ( ! flushed && mdoc_isdelim(p) && ! igndelim) {
- if ( ! rewind_elem(mdoc, tok))
+ if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) &&
+ ! flushed && mdoc_isdelim(p)) {
+ if ( ! rew_elem(mdoc, tok))
return(0);
flushed = 1;
}
@@ -1374,7 +1254,7 @@ macro_constant_delimited(MACRO_PROT_ARGS)
mdoc->next = MDOC_NEXT_SIBLING;
}
- if ( ! flushed && ! rewind_elem(mdoc, tok))
+ if ( ! flushed && ! rew_elem(mdoc, tok))
return(0);
if (ppos > 1)
@@ -1384,28 +1264,33 @@ macro_constant_delimited(MACRO_PROT_ARGS)
/*
- * A constant macro is the simplest classification. It spans an entire
- * line.
+ * In-line macro that spans an entire line. May be callable, but has no
+ * subsequent parsed arguments.
*/
static int
-macro_constant(MACRO_PROT_ARGS)
+in_line_eoln(MACRO_PROT_ARGS)
{
int c, w, la;
struct mdoc_arg *arg;
char *p;
+ assert( ! (MDOC_PARSED & mdoc_macros[tok].flags));
+
arg = NULL;
for (;;) {
la = *pos;
c = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
- if (ARGV_EOLN == c)
- break;
+
if (ARGV_WORD == c) {
*pos = la;
break;
- } else if (ARGV_ARG == c)
+ }
+ if (ARGV_EOLN == c)
+ break;
+ if (ARGV_ARG == c)
continue;
+
mdoc_argv_free(arg);
return(0);
}
@@ -1418,7 +1303,6 @@ macro_constant(MACRO_PROT_ARGS)
for (;;) {
la = *pos;
w = mdoc_args(mdoc, line, pos, buf, tok, &p);
- assert(ARGS_PHRASE != c);
if (ARGS_ERROR == w)
return(0);
@@ -1429,7 +1313,7 @@ macro_constant(MACRO_PROT_ARGS)
lookup(mdoc, line, la, tok, p);
if (MDOC_MAX != c && -1 != c) {
- if ( ! rewind_elem(mdoc, tok))
+ if ( ! rew_elem(mdoc, tok))
return(0);
return(mdoc_macro(mdoc, c, line, la, pos, buf));
} else if (-1 == c)
@@ -1440,13 +1324,13 @@ macro_constant(MACRO_PROT_ARGS)
mdoc->next = MDOC_NEXT_SIBLING;
}
- return(rewind_elem(mdoc, tok));
+ return(rew_elem(mdoc, tok));
}
/* ARGSUSED */
static int
-macro_obsolete(MACRO_PROT_ARGS)
+obsolete(MACRO_PROT_ARGS)
{
return(pwarn(mdoc, line, ppos, WOBS));
@@ -1454,42 +1338,76 @@ macro_obsolete(MACRO_PROT_ARGS)
static int
-macro_phrase(struct mdoc *mdoc, int line, int ppos, char *buf)
+phrase(struct mdoc *mdoc, int line, int ppos, char *buf)
{
- int i, la, c;
+ int i, la, c, quoted;
+
+ /*
+ * Parse over words in a phrase. We have to handle this
+ * specially because we assume no calling context -- in normal
+ * circumstances, we switch argument parsing based on whether
+ * the parent macro accepts quotes, tabs, etc. Here, anything
+ * goes.
+ */
for (i = ppos; buf[i]; ) {
assert(' ' != buf[i]);
-
la = i;
- if ('\"' == buf[i]) {
- la = ++i;
- while (buf[i] && '\"' != buf[i])
- i++;
+ quoted = 0;
+
+ /*
+ * Read to next token. If quoted (check not escaped),
+ * scan ahead to next unescaped quote. If not quoted or
+ * escape-quoted, then scan ahead to next space.
+ */
+
+ if ((i && '\"' == buf[i] && '\\' != buf[i - 1]) ||
+ (0 == i && '\"' == buf[i])) {
+ for (la = ++i; buf[i]; i++)
+ if ('\"' != buf[i])
+ continue;
+ else if ('\\' != buf[i - 1])
+ break;
if (0 == buf[i])
- return(mdoc_err(mdoc, "unterminated quoted parameter"));
+ return(perr(mdoc, line, la, EQUOT));
+ quoted = 1;
} else
- while (buf[i] && ! isspace ((unsigned char)buf[i]))
- i++;
+ for ( ; buf[i]; i++)
+ if (i && ' ' == buf[i]) {
+ if ('\\' != buf[i - 1])
+ break;
+ } else if (' ' == buf[i])
+ break;
+
+ /* If not end-of-line, terminate argument. */
if (buf[i])
buf[i++] = 0;
- while (buf[i] && isspace((unsigned char)buf[i]))
- i++;
+ /* Read to next argument. */
- if (MDOC_MAX != (c = mdoc_tokhash_find(mdoc->htab, &buf[la]))) {
+ for ( ; buf[i] && ' ' == buf[i]; i++)
+ /* Spin. */ ;
+
+ /*
+ * If we're a non-quoted string, try to look up the
+ * value as a macro and execute it, if found.
+ */
+
+ c = quoted ? MDOC_MAX :
+ mdoc_tokhash_find(mdoc->htab, &buf[la]);
+
+ if (MDOC_MAX != c) {
if ( ! mdoc_macro(mdoc, c, line, la, &i, buf))
return(0);
return(append_delims(mdoc, line, &i, buf));
}
+ /* A regular word or quoted string. */
+
if ( ! mdoc_word_alloc(mdoc, line, la, &buf[la]))
return(0);
mdoc->next = MDOC_NEXT_SIBLING;
-
- while (buf[i] && isspace((unsigned char)buf[i]))
- i++;
}
return(1);
diff --git a/mdoc.3 b/mdoc.3
index 7b858397..37b68091 100644
--- a/mdoc.3
+++ b/mdoc.3
@@ -1,4 +1,4 @@
-.\" $Id: mdoc.3,v 1.17 2009/03/14 05:21:58 kristaps Exp $
+.\" $Id: mdoc.3,v 1.18 2009/03/16 22:19:19 kristaps Exp $
.\"
.\" Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
.\"
@@ -16,7 +16,7 @@
.\" TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
.\" PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: March 14 2009 $
+.Dd $Mdocdate: March 16 2009 $
.Dt mdoc 3
.Os
.\" SECTION
@@ -182,7 +182,10 @@ or after
.Fn mdoc_endparse
or
.Fn mdoc_parseln
-fail, it may be incomplete. This AST is governed by the ontological
+fail, it may be incomplete.
+.\" PARAGRAPH
+.Pp
+This AST is governed by the ontological
rules dictated in
.Xr mdoc 7
and derives its terminology accordingly.
diff --git a/mdoc.7 b/mdoc.7
index 2d66c1f0..cbadee2e 100644
--- a/mdoc.7
+++ b/mdoc.7
@@ -1,4 +1,4 @@
-.\" $Id: mdoc.7,v 1.4 2009/03/14 05:21:58 kristaps Exp $
+.\" $Id: mdoc.7,v 1.5 2009/03/16 22:19:19 kristaps Exp $
.\"
.\" Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
.\"
@@ -16,7 +16,7 @@
.\" TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
.\" PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: March 14 2009 $
+.Dd $Mdocdate: March 16 2009 $
.Dt mdoc 7
.Os
.\" SECTION
@@ -72,14 +72,16 @@ Within a macro line, the following characters are reserved:
.It \&?
.Pq question
.It \&!
-.Pq exclmamation
+.Pq exclamation
.El
+.\" PARAGRAPH
.Pp
-Use of these characters must either be escaped with a non-breaking space
-.Pq Sq \e&
-or, if applicable, an appropriate escape-sequence used. Use of reserved
-characters is described in
+Use of reserved characters is described in
.Sx Closure .
+For general non-reserved use, characters must either be escaped with a
+non-breaking space
+.Pq Sq \e&
+or, if applicable, an appropriate escape-sequence used.
.\" SUB-SECTION
.Ss Special Characters
Special character sequences begin with the escape character
@@ -121,6 +123,14 @@ Grammatic:
.Pp
Enclosures:
.Bl -tag -width 12n -offset "XXXX" -compact
+.It \\(lh
+.Pq left hand
+.It \\(rh
+.Pq right hand
+.It \\(<<
+.Pq left guillemot
+.It \\(>>
+.Pq right guillemot
.It \\(rC
.Pq right brace
.It \\(lC
@@ -160,6 +170,18 @@ Indicatives:
.Pq up arrow
.It \\(da
.Pq down arrow
+.It \\(<>
+.Pq left-right arrow
+.It \\(lA
+.Pq left double-arrow
+.It \\(rA
+.Pq right double-arrow
+.It \\(uA
+.Pq up double-arrow
+.It \\(dA
+.Pq down double-arrow
+.It \\(hA
+.Pq left-right double-arrow
.El
.\" PARAGRAPH
.Pp
@@ -200,12 +222,98 @@ Mathematical:
.El
.\" PARAGRAPH
.Pp
-Diacritics:
+Diacritics and letter combinations:
.Bl -tag -width 12n -offset "XXXX" -compact
.It \\(ga
.Pq accent grave
.It \\(aa
.Pq accent accute
+.It \\(ad
+.Pq accent dieresis
+.It \\(a~
+.Pq accent tilde
+.It \\(AE
+.Pq upper-case AE
+.It \\(ae
+.Pq lower-case AE
+.It \\(OE
+.Pq upper-case OE
+.It \\(oe
+.Pq lower-case OE
+.It \\('A
+.Pq upper-case acute A
+.It \\('E
+.Pq upper-case acute E
+.It \\('I
+.Pq upper-case acute I
+.It \\('O
+.Pq upper-case acute O
+.It \\('U
+.Pq upper-case acute U
+.It \\('a
+.Pq lower-case acute a
+.It \\('e
+.Pq lower-case acute e
+.It \\('i
+.Pq lower-case acute i
+.It \\('o
+.Pq lower-case acute o
+.It \\('u
+.Pq lower-case acute u
+.It \\(`A
+.Pq upper-case grave A
+.It \\(`E
+.Pq upper-case grave E
+.It \\(`I
+.Pq upper-case grave I
+.It \\(`O
+.Pq upper-case grave O
+.It \\(`U
+.Pq upper-case grave U
+.It \\(`a
+.Pq lower-case grave a
+.It \\(`e
+.Pq lower-case grave e
+.It \\(`i
+.Pq lower-case grave i
+.It \\(`o
+.Pq lower-case grave o
+.It \\(`u
+.Pq lower-case grave u
+.It \\(~A
+.Pq upper-case tilde A
+.It \\(~N
+.Pq upper-case tilde N
+.It \\(~O
+.Pq upper-case tilde O
+.It \\(~a
+.Pq lower-case tilde a
+.It \\(~n
+.Pq lower-case tilde n
+.It \\(~o
+.Pq lower-case tilde o
+.It \\(:A
+.Pq upper-case dieresis A
+.It \\(:E
+.Pq upper-case dieresis E
+.It \\(:I
+.Pq upper-case dieresis I
+.It \\(:O
+.Pq upper-case dieresis O
+.It \\(:U
+.Pq upper-case dieresis U
+.It \\(:a
+.Pq lower-case dieresis a
+.It \\(:e
+.Pq lower-case dieresis e
+.It \\(:i
+.Pq lower-case dieresis i
+.It \\(:o
+.Pq lower-case dieresis o
+.It \\(:u
+.Pq lower-case dieresis u
+.It \\(:y
+.Pq lower-case dieresis y
.El
.\" PARAGRAPH
.Pp
@@ -219,6 +327,10 @@ Special symbols:
.Pq bar, deprecated
.It \\(co
.Pq copyright
+.It \\(rg
+.Pq registered
+.It \\(tm
+.Pq trademarked
.It \\&
.Pq non-breaking space
.It \\e
@@ -239,17 +351,18 @@ may span multiple lines.
.Bl -inset -offset XXXX
.\" LIST-ITEM
.It Em Full-block
-macros always span multiple lines. They consist optionally of one or
+macros always span multiple lines. They consist of zero or
more
.Qq heads ,
-subsequent macros or text on the same line following invocation; a
+subsequent macros or text on the same line following invocation; an
+optional
.Qq body ,
which spans subsequent lines of text or macros; and an optional
.Qq tail ,
macros or text on the same line following closure.
.\" LIST-ITEM
.It Em Partial-block
-macros may span multiple lines. They consists optionally of a
+macros may span multiple lines. They consists of a optional
.Qq head ,
text immediately following invocation; always a
.Qq body ,
@@ -307,95 +420,6 @@ are followed by non-reserved characters, the behaviour differs per
macro. In general, scope of the macro is closed and re-opened:
subsequent tokens are interpreted as if the scope had just been opened.
In other circumstances, scope is simply closed out.
-.\" .\" SUB-SECTION
-.\" .Ss Examples
-.\" The following examples illustrate each macro classification.
-.\" .\" PARAGRAPH
-.\" .Pp
-.\" Implicit full-block. Has head, body and no tail. Scope closed by
-.\" second
-.\" .Sq \&Sh
-.\" invocation.
-.\" .Bd -literal -offset XXXX
-.\" \&.Sh SECTION 1
-.\" body...
-.\" \&.Sh SECTION 2
-.\" .Ed
-.\" .\" PARAGRAPH
-.\" .Pp
-.\" Nested implicit full-block, where the subsection
-.\" .Sq \&Ss
-.\" is within the scope of the parent section
-.\" .Sq \&Sh
-.\" and closed along with its parent by the subsequent
-.\" .Sq \&Sh .
-.\" .Bd -literal -offset XXXX
-.\" \&.Sh SECTION 1
-.\" \&.Ss Subsection 1
-.\" body...
-.\" \&.Sh SECTION 2
-.\" .Ed
-.\" .\" PARAGRAPH
-.\" .Pp
-.\" Explicit full-block. Has a head, a body and no tail. Scope closed by
-.\" .Sq \&Ef
-.\" invocation.
-.\" .Bd -literal -offset XXXX
-.\" \&.Bf symbolic
-.\" body...
-.\" \&.Ef
-.\" .Ed
-.\" .\" PARAGRAPH
-.\" .Pp
-.\" Nested explicit/implicit scope.
-.\" .Sq \&It
-.\" macro is an implicit block whose scope is closed by the explicit
-.\" .Sq \&El
-.\" closure.
-.\" .Bd -literal -offset XXXX
-.\" \&.Bl \-bullet
-.\" \&.It head
-.\" body...
-.\" \&.El
-.\" .Ed
-.\" .\" PARAGRAPH
-.\" .Pp
-.\" Explicit partial-block. Has head, body and tail. Scope closed by
-.\" .Sq \&Ec
-.\" invocation.
-.\" .Bd -literal -offset XXX
-.\" \&.Eo head body... \&Ec tail
-.\" .Ed
-.\" .\" PARAGRAPH
-.\" .Pp
-.\" Implicit partial-block. Has only body. Scope is closed by end-of-line.
-.\" .Bd -literal -offset XXX
-.\" \&.Sq body...
-.\" .Ed
-.\" .\" PARAGRAPH
-.\" .Pp
-.\" Explicit partial-block with only body and scope closed by
-.\" .Sq \&Ac
-.\" invocation.
-.\" .Bd -literal -offset XXXX
-.\" \&.Ao body... \&Ac
-.\" .Ed
-.\" .\" PARAGRAPH
-.\" .Pp
-.\" Implicit partial-block enclosing explicit partial-block.
-.\" .Bd -literal -offset XXX
-.\" \&.Sq body... \&Ao body... \&Ac
-.\" .Ed
-.\" .\" PARAGRAPH
-.\" .Pp
-.\" Inline macros, several in sequence. Scope is closed for
-.\" .Sq \&Fl
-.\" by the punctuation delimiter and
-.\" .Sq \&Ar
-.\" by the end-of-line.
-.\" .Bd -literal -offset XXXX
-.\" \&.Fl text0 text1 ; Ar text0 text1
-.\" .Ed
.\" SECTION
.Sh SYNTAX
Macros are generally two and at times three characters in length. The
@@ -640,6 +664,12 @@ compatibility with these systems.
.Bl -dash -compact
.\" LIST-ITEM
.It
+.Sq \&Fo
+and
+.Sq \&St
+historically weren't always callable. Both are now correctly callable.
+.\" LIST-ITEM
+.It
.Sq \&It \-nested
is assumed for all lists: any list may be nested and
.Sq \-enum
@@ -689,3 +719,58 @@ The
.Nm
utility was written by
.An Kristaps Dzonsons Aq kristaps@kth.se .
+.\" SECTION
+.Sh CAVEATS
+There are several ambiguous parts of mdoc.
+.Pp
+.Bl -dash -compact
+.\" LIST-ITEM
+.It
+.Sq \&Fa
+should be
+.Sq \&Va
+as function arguments are variables.
+.\" LIST-ITEM
+.It
+.Sq \&Ft
+should be
+.Sq \&Vt
+as function return types are still types. Furthermore, the
+.Sq \&Ft
+should be removed and
+.Sq \&Fo ,
+which ostensibly follows it, should follow the same convention as
+.Sq \&Va .
+.\" LIST-ITEM
+.It
+.Sq \&Va
+should formalise that only one or two arguments are acceptable: a
+variable name and optional, preceeding type.
+.\" LIST-ITEM
+.It
+.Sq \&Fd
+is ambiguous. It's commonly used to indicate an include file in the
+synopsis section.
+.Sq \&In
+should be used, instead.
+.\" LIST-ITEM
+.It
+Only the
+.Sq \-literal
+argument to
+.Sq \&Bd
+makes sense. The remaining ones should be removed.
+.\" LIST-ITEM
+.It
+The
+.Sq \&Xo
+and
+.Sq \&Xc
+macros should be deprecated.
+.\" LIST-ITEM
+.It
+The
+.Sq \&Dt
+macro lacks clarity. It should be absolutely clear which title will
+render when formatting the manual page.
+.El
diff --git a/mdoc.c b/mdoc.c
index 880888de..e99cb376 100644
--- a/mdoc.c
+++ b/mdoc.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc.c,v 1.64 2009/03/12 16:30:50 kristaps Exp $ */
+/* $Id: mdoc.c,v 1.65 2009/03/16 22:19:19 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -74,7 +74,8 @@ const char *const __mdoc_macronames[MDOC_MAX] = {
"Fr", "Ud", "Lb", "Ap",
"Lp", "Lk", "Mt", "Brq",
/* LINTED */
- "Bro", "Brc", "\%C"
+ "Bro", "Brc", "\%C", "Es",
+ "En"
};
const char *const __mdoc_argnames[MDOC_ARG_MAX] = {
@@ -527,9 +528,9 @@ parsemacro(struct mdoc *m, int ln, char *buf)
if (0 == buf[1])
return(1);
- if (isspace((unsigned char)buf[1])) {
+ if (' ' == buf[1]) {
i = 2;
- while (buf[i] && isspace((unsigned char)buf[i]))
+ while (buf[i] && ' ' == buf[i])
i++;
if (0 == buf[i])
return(1);
@@ -545,7 +546,7 @@ parsemacro(struct mdoc *m, int ln, char *buf)
for (i = 1; i < 5; i++) {
if (0 == (mac[i - 1] = buf[i]))
break;
- else if (isspace((unsigned char)buf[i]))
+ else if (' ' == buf[i])
break;
}
@@ -565,7 +566,7 @@ parsemacro(struct mdoc *m, int ln, char *buf)
/* The macro is sane. Jump to the next word. */
- while (buf[i] && isspace((unsigned char)buf[i]))
+ while (buf[i] && ' ' == buf[i])
i++;
/* Begin recursive parse sequence. */
diff --git a/mdoc.h b/mdoc.h
index 0803dd0c..6e55aaf4 100644
--- a/mdoc.h
+++ b/mdoc.h
@@ -1,4 +1,4 @@
-/* $Id: mdoc.h,v 1.47 2009/03/12 16:30:50 kristaps Exp $ */
+/* $Id: mdoc.h,v 1.48 2009/03/16 22:19:19 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -31,8 +31,6 @@
/* What follows is a list of ALL possible macros. */
-/* TODO: Brq et al. */
-
#define MDOC___ 0
#define MDOC_Dd 1
#define MDOC_Dt 2
@@ -148,7 +146,9 @@
#define MDOC_Bro 112
#define MDOC_Brc 113
#define MDOC__C 114
-#define MDOC_MAX 115
+#define MDOC_Es 115
+#define MDOC_En 116
+#define MDOC_MAX 117
/* What follows is a list of ALL possible macro arguments. */
diff --git a/mdocterm.1 b/mdocterm.1
index 8e2dcb3c..f3fa7ddc 100644
--- a/mdocterm.1
+++ b/mdocterm.1
@@ -1,4 +1,4 @@
-.\" $Id: mdocterm.1,v 1.22 2009/03/15 10:34:11 kristaps Exp $
+.\" $Id: mdocterm.1,v 1.23 2009/03/16 22:19:19 kristaps Exp $
.\"
.\" Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
.\"
@@ -16,7 +16,7 @@
.\" TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
.\" PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: March 15 2009 $
+.Dd $Mdocdate: March 16 2009 $
.Dt mdocterm 1
.Os
.\" SECTION
@@ -167,131 +167,20 @@ options may be grouped and delimited with a comma. Using
for example, will try to ignore scope and character-escape errors.
.\" SUB-SECTION
.Ss Character Escapes
-The following table shows all
+The
+.Nm
+utility correctly renders all
+.Sx Special Characters
+in
.Xr mdoc 7
-character escapes rendered by
-.Nm .
-Note that the
-.Em Output
-column will render differently whether executed with
-.Xr mdocterm 1
-or another output filter.
-.\" PARAGRAPH
-.Pp
-Grammatic:
-.Pp
-.Bl -tag -width "OutputXXXX" -offset "XXXX" -compact
-.It Em Output
-.Em Input (Name)
-.It \(em
-\\(em (em-dash)
-.It \(en
-\\(en (en-dash)
-.It \-
-\\- (hyphen)
-.It \\
-\\\\ (back-slash)
-.El
-.\" PARAGRAPH
-.Pp
-Enclosures:
-.Pp
-.Bl -tag -width "OutputXXXX" -offset "XXXX" -compact
-.It Em Output
-.Em Input (Name)
-.It \(rC
-\\(rC (right brace)
-.It \(lC
-\\(lC (left brace)
-.It \(ra
-\\(ra (right angle)
-.It \(la
-\\(la (left angle)
-.It \(rB
-\\(rB (right bracket)
-.It \(lB
-\\(lB (left bracket)
-.It \q
-\\q (double-quote)
-.It \(lq
-\\(lq (left double-quote)
-.It \(rq
-\\(rq (right double-quote)
-.It \(oq
-\\(oq, \\` (left single-quote)
-.It \(aq
-\\(aq, \\' (right single-quote, apostrophe)
-.El
-.\" PARAGRAPH
-.Pp
-Indicatives:
-.Pp
-.Bl -tag -width "OutputXXXX" -offset "XXXX" -compact
-.It Em Output
-.Em Input (Name)
-.It \(<-
-\\(<- (left arrow)
-.It \(->
-\\(-> (right arrow)
-.It \(ua
-\\(ua (up arrow)
-.It \(da
-\\(da (down arrow)
-.El
-.\" PARAGRAPH
-.Pp
-Mathematical:
-.Pp
-.Bl -tag -width "OutputXXXX" -offset "XXXX" -compact
-.It Em Output
-.Em Input (Name)
-.It \(<=
-\\(<= (less-than-equal)
-.It \(>=
-\\(>= (greater-than-equal)
-.It \(==
-\\(== (equal)
-.It \(!=
-\\(!= (not equal)
-.It \(if
-\\(if (infinity)
-.It \(na
-\\(na (NaN)*
-.It \(+-
-\\(+- (plus-minus)
-.It \(**
-\\(** (asterisk)
-.El
-.\" PARAGRAPH
-.Pp
-Diacritics:
+in 7-bit ASCII.
.Pp
-.Bl -tag -width "OutputXXXX" -offset "XXXX" -compact
-.It Em Output
-.Em Input (Name)
-.It \(ga
-\\(ga (accent grave)
-.It \(aa
-\\(aa (accent accute)
-.El
-.\" PARAGRAPH
-.Pp
-Special symbols:
-.Pp
-.Bl -tag -width "OutputXXXX" -offset "XXXX" -compact
-.It Em Output
-.Em Input (Name)
-.It \(bu
-\\(bu (bullet)
-.It \(ba
-\\(ba (bar)
-.It \(co
-\\(co (copyright)
-.El
-.Pp
-*This is a deviation from the standard, as NaN is usually rendered as
-\\*(Na, which is a deprecated form. We introduce \\(na, which follows
-the more general syntax.
+In the general sense,
+.Nm
+will make a
+.Pq best-effort
+to render complex characters; however, if a manual is using considerable
+special characters, some meaning may be lost in translation.
.\" SECTION
.Sh EXAMPLES
To display this manual page:
diff --git a/mdocterm.c b/mdocterm.c
index cb7756ea..a742328c 100644
--- a/mdocterm.c
+++ b/mdocterm.c
@@ -1,4 +1,4 @@
-/* $Id: mdocterm.c,v 1.45 2009/03/15 10:34:11 kristaps Exp $ */
+/* $Id: mdocterm.c,v 1.46 2009/03/16 22:19:19 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -41,12 +41,7 @@ struct nroffopt {
struct termp *termp; /* Ephemeral. */
};
-struct termseq {
- const char *enc;
- int sym;
-};
-
-dead_pre void punt(struct nroffopt *, char *) dead_post;
+__dead void punt(struct nroffopt *, char *);
static int option(void *, int, char *);
static int optsopt(struct termp *, char *);
static void body(struct termp *,
@@ -66,125 +61,8 @@ static void nescape(struct termp *,
static void chara(struct termp *, char);
static void stringa(struct termp *,
const char *, size_t);
-static void symbola(struct termp *, enum tsym);
static void sanity(const struct mdoc_node *);
-#ifdef __linux__
-extern size_t strlcat(char *, const char *, size_t);
-extern size_t strlcpy(char *, const char *, size_t);
-#endif
-
-static struct termseq termenc1[] = {
- { "\\", TERMSYM_SLASH },
- { "\'", TERMSYM_RSQUOTE },
- { "`", TERMSYM_LSQUOTE },
- { "-", TERMSYM_HYPHEN },
- { " ", TERMSYM_SPACE },
- { ".", TERMSYM_PERIOD },
- { "&", TERMSYM_BREAK },
- { "e", TERMSYM_SLASH },
- { "q", TERMSYM_DQUOTE },
- { "|", TERMSYM_BREAK },
- { NULL, 0 }
-};
-
-static struct termseq termenc2[] = {
- { "rC", TERMSYM_RBRACE },
- { "lC", TERMSYM_LBRACE },
- { "rB", TERMSYM_RBRACK },
- { "lB", TERMSYM_LBRACK },
- { "ra", TERMSYM_RANGLE },
- { "la", TERMSYM_LANGLE },
- { "Lq", TERMSYM_LDQUOTE },
- { "lq", TERMSYM_LDQUOTE },
- { "Rq", TERMSYM_RDQUOTE },
- { "rq", TERMSYM_RDQUOTE },
- { "oq", TERMSYM_LSQUOTE },
- { "aq", TERMSYM_RSQUOTE },
-
- { "<-", TERMSYM_LARROW },
- { "->", TERMSYM_RARROW },
- { "ua", TERMSYM_UARROW },
- { "da", TERMSYM_DARROW },
-
- { "bu", TERMSYM_BULLET },
- { "Ba", TERMSYM_BAR },
- { "ba", TERMSYM_BAR },
- { "co", TERMSYM_COPY },
- { "Am", TERMSYM_AMP },
-
- { "Le", TERMSYM_LE },
- { "<=", TERMSYM_LE },
- { "Ge", TERMSYM_GE },
- { ">=", TERMSYM_GE },
- { "==", TERMSYM_EQ },
- { "Ne", TERMSYM_NEQ },
- { "!=", TERMSYM_NEQ },
- { "Pm", TERMSYM_PLUSMINUS },
- { "+-", TERMSYM_PLUSMINUS },
- { "If", TERMSYM_INF2 },
- { "if", TERMSYM_INF },
- { "Na", TERMSYM_NAN },
- { "na", TERMSYM_NAN },
- { "**", TERMSYM_ASTERISK },
- { "Gt", TERMSYM_GT },
- { "Lt", TERMSYM_LT },
-
- { "aa", TERMSYM_ACUTE },
- { "ga", TERMSYM_GRAVE },
-
- { "en", TERMSYM_EN },
- { "em", TERMSYM_EM },
-
- { "Pi", TERMSYM_PI },
- { NULL, 0 }
-};
-
-/* FIXME: abstract to dynamically-compiled table. */
-static struct termsym termsym_ascii[TERMSYM_MAX] = {
- { "]", 1 }, /* TERMSYM_RBRACK */
- { "[", 1 }, /* TERMSYM_LBRACK */
- { "<-", 2 }, /* TERMSYM_LARROW */
- { "->", 2 }, /* TERMSYM_RARROW */
- { "^", 1 }, /* TERMSYM_UARROW */
- { "v", 1 }, /* TERMSYM_DARROW */
- { "`", 1 }, /* TERMSYM_LSQUOTE */
- { "\'", 1 }, /* TERMSYM_RSQUOTE */
- { "\'", 1 }, /* TERMSYM_SQUOTE */
- { "``", 2 }, /* TERMSYM_LDQUOTE */
- { "\'\'", 2 }, /* TERMSYM_RDQUOTE */
- { "\"", 1 }, /* TERMSYM_DQUOTE */
- { "<", 1 }, /* TERMSYM_LT */
- { ">", 1 }, /* TERMSYM_GT */
- { "<=", 2 }, /* TERMSYM_LE */
- { ">=", 2 }, /* TERMSYM_GE */
- { "==", 2 }, /* TERMSYM_EQ */
- { "!=", 2 }, /* TERMSYM_NEQ */
- { "\'", 1 }, /* TERMSYM_ACUTE */
- { "`", 1 }, /* TERMSYM_GRAVE */
- { "pi", 2 }, /* TERMSYM_PI */
- { "+=", 2 }, /* TERMSYM_PLUSMINUS */
- { "oo", 2 }, /* TERMSYM_INF */
- { "infinity", 8 }, /* TERMSYM_INF2 */
- { "NaN", 3 }, /* TERMSYM_NAN */
- { "|", 1 }, /* TERMSYM_BAR */
- { "o", 1 }, /* TERMSYM_BULLET */
- { "&", 1 }, /* TERMSYM_AMP */
- { "--", 2 }, /* TERMSYM_EM */
- { "-", 1 }, /* TERMSYM_EN */
- { "(C)", 3 }, /* TERMSYM_COPY */
- { "*", 1 }, /* TERMSYM_ASTERISK */
- { "\\", 1 }, /* TERMSYM_SLASH */
- { "-", 1 }, /* TERMSYM_HYPHEN */
- { " ", 1 }, /* TERMSYM_SPACE */
- { ".", 1 }, /* TERMSYM_PERIOD */
- { "", 0 }, /* TERMSYM_BREAK */
- { "<", 1 }, /* TERMSYM_LANGLE */
- { ">", 1 }, /* TERMSYM_RANGLE */
- { "{", 1 }, /* TERMSYM_LBRACE */
- { "}", 1 }, /* TERMSYM_RBRACE */
-};
-
int
main(int argc, char *argv[])
{
@@ -200,9 +78,8 @@ main(int argc, char *argv[])
termp.maxrmargin = termp.rmargin = 78; /* FIXME */
termp.maxcols = 1024; /* FIXME */
- termp.offset = termp.col = 0;
termp.flags = TERMP_NOSPACE;
- termp.symtab = termsym_ascii;
+ termp.symtab = ascii2htab();
nroff.termp = &termp;
@@ -374,7 +251,7 @@ flushln(struct termp *p)
/* LINTED */
for (j = i, vsz = 0; j < p->col; j++) {
- if (isspace((u_char)p->buf[j]))
+ if (' ' == p->buf[j])
break;
else if (8 == p->buf[j])
j += 1;
@@ -420,7 +297,7 @@ flushln(struct termp *p)
*/
for ( ; i < p->col; i++) {
- if (isspace((u_char)p->buf[i]))
+ if (' ' == p->buf[i])
break;
putchar(p->buf[i]);
}
@@ -523,14 +400,13 @@ word(struct termp *p, const char *word)
/* LINTED */
for (j = i = 0; i < len; i++) {
- if ( ! isspace((u_char)word[i])) {
+ if (' ' != word[i]) {
j++;
continue;
}
/* Escaped spaces don't delimit... */
- if (i > 0 && isspace((u_char)word[i]) &&
- '\\' == word[i - 1]) {
+ if (i && ' ' == word[i] && '\\' == word[i - 1]) {
j++;
continue;
}
@@ -737,27 +613,15 @@ header(struct termp *p, const struct mdoc_meta *meta)
static void
nescape(struct termp *p, const char *word, size_t len)
{
- struct termseq *enc;
+ const char *rhs;
+ size_t sz;
- switch (len) {
- case (1):
- enc = termenc1;
- break;
- case (2):
- enc = termenc2;
- break;
- default:
+ if (NULL == (rhs = a2ascii(p->symtab, word, len, &sz))) {
warnx("unsupported %zu-byte escape sequence", len);
return;
}
- for ( ; enc->enc; enc++)
- if (0 == memcmp(enc->enc, word, len)) {
- symbola(p, enc->sym);
- return;
- }
-
- warnx("unsupported %zu-byte escape sequence", len);
+ stringa(p, rhs, sz);
}
@@ -871,18 +735,6 @@ pword(struct termp *p, const char *word, size_t len)
/*
- * Add a symbol to the output line buffer.
- */
-static void
-symbola(struct termp *p, enum tsym sym)
-{
-
- assert(p->symtab[sym].sym);
- stringa(p, p->symtab[sym].sym, p->symtab[sym].sz);
-}
-
-
-/*
* Like chara() but for arbitrary-length buffers. Resize the buffer by
* a factor of two (if the buffer is less than that) or the buffer's
* size.
@@ -1039,7 +891,7 @@ sanity(const struct mdoc_node *n)
}
-dead_pre void
+__dead void
punt(struct nroffopt *nroff, char *in)
{
char *args[32];
diff --git a/mmain.c b/mmain.c
index 645c9acd..df70a2ee 100644
--- a/mmain.c
+++ b/mmain.c
@@ -1,4 +1,4 @@
- /* $Id: mmain.c,v 1.12 2009/03/15 07:08:53 kristaps Exp $ */
+ /* $Id: mmain.c,v 1.13 2009/03/16 22:19:19 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -58,13 +58,6 @@ static int msg_err(void *, int, int, const char *);
static int msg_warn(void *, int, int,
enum mdoc_warn, const char *);
-#ifdef __linux__
-extern int getsubopt(char **, char *const *, char **);
-extern size_t strlcpy(char *, const char *, size_t);
-extern size_t strlcat(char *, const char *, size_t);
-#endif
-
-
/*
* Print our and our caller's usage message.
*/
@@ -176,7 +169,7 @@ mmain_free(struct mmain *p)
}
-dead_pre void
+__dead void
mmain_exit(struct mmain *p, int code)
{
diff --git a/mmain.h b/mmain.h
index 3fe7b580..2f79d178 100644
--- a/mmain.h
+++ b/mmain.h
@@ -1,4 +1,4 @@
-/* $Id: mmain.h,v 1.5 2009/03/15 07:08:53 kristaps Exp $ */
+/* $Id: mmain.h,v 1.6 2009/03/16 22:19:19 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -28,24 +28,12 @@
#include "mdoc.h"
-/* Rules for "dead" functions: */
-#if defined(__NetBSD__)
-#define dead_pre __dead
-#define dead_post __attribute__((__noreturn__))
-#elif defined(__OpenBSD__)
-#define dead_pre __dead
-#define dead_post /* Nothing. */
-#else
-#define dead_pre /* Nothing. */
-#define dead_post __attribute__((__noreturn__))
-#endif
-
__BEGIN_DECLS
struct mmain;
struct mmain *mmain_alloc(void);
-dead_pre void mmain_exit(struct mmain *, int) dead_post;
+__dead void mmain_exit(struct mmain *, int);
int mmain_getopt(struct mmain *, int, char *[],
const char *, const char *,
const char *, void *,
diff --git a/msec.c b/msec.c
new file mode 100644
index 00000000..af22911c
--- /dev/null
+++ b/msec.c
@@ -0,0 +1,34 @@
+/* $Id: msec.c,v 1.1 2009/03/16 22:19:19 kristaps Exp $ */
+/*
+ * Copyright (c) 2009 Kristaps Dzonsons <kristaps@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 <stdlib.h>
+#include <string.h>
+
+#include "private.h"
+
+#define LINE(x, y) \
+ if (0 == strcmp(p, x)) return(y);
+
+const char *
+mdoc_a2msec(const char *p)
+{
+
+#include "msec.in"
+
+ return(NULL);
+}
diff --git a/msec.in b/msec.in
index 97ac2069..b9bcd333 100644
--- a/msec.in
+++ b/msec.in
@@ -1,24 +1,42 @@
-# $Id: msec.in,v 1.2 2009/03/06 14:24:49 kristaps Exp $
-#
-# This file defines the `.Dt' macro 'volume' argument. Lines are
-# composed of tab-delimited fields -- multiple tabs may delimit fields.
-# Comment lines begin with '#'; blank lines are also ok.
-#
-# These were last grok'd from OpenBSD-4.4's mdoc.samples(7).
+/* $Id: msec.in,v 1.3 2009/03/16 22:19:19 kristaps Exp $ */
+/*
+ * Copyright (c) 2009 Kristaps Dzonsons <kristaps@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.
+ */
-1 General Commands Manual
-2 System Calls Manual
-3 Library Functions Manual
-3p Perl Library Functions Manual
-4 Kernel Interfaces Manual
-5 File Formats Manual
-6 Games Manual
-7 Miscellaneous Information Manual
-8 System Manager\'s Manual
-9 Kernel Developer\'s Manual
-X11 X11 Developer\'s Manual
-X11R6 X11 Developer\'s Manual
-unass Unassociated
-local Local
-draft Draft
-paper Paper
+/*
+ * These are all possible manual-section macros and what they correspond
+ * to when rendered as the volume title.
+ *
+ * Be sure to escape strings.
+ */
+
+LINE("1", "General Commands Manual")
+LINE("2", "System Calls Manual")
+LINE("3", "Library Functions Manual")
+LINE("3p", "Perl Library Functions Manual")
+LINE("4", "Kernel Interfaces Manual")
+LINE("5", "File Formats Manual")
+LINE("6", "Games Manual")
+LINE("7", "Miscellaneous Information Manual")
+LINE("8", "System Manager\'s Manual")
+LINE("9", "Kernel Developer\'s Manual")
+LINE("X11", "X11 Developer\'s Manual")
+LINE("X11R6", "X11 Developer\'s Manual")
+LINE("unass", "Unassociated")
+LINE("local", "Local")
+LINE("draft", "Draft")
+LINE("paper", "Paper")
diff --git a/private.h b/private.h
index fe48bb99..597f6370 100644
--- a/private.h
+++ b/private.h
@@ -1,4 +1,4 @@
-/* $Id: private.h,v 1.88 2009/03/08 19:47:40 kristaps Exp $ */
+/* $Id: private.h,v 1.89 2009/03/16 22:19:19 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -53,6 +53,8 @@ struct mdoc_macro {
#define MDOC_PARSED (1 << 1)
#define MDOC_EXPLICIT (1 << 2)
#define MDOC_PROLOGUE (1 << 3)
+#define MDOC_IGNDELIM (1 << 4)
+ /* Reserved words in arguments treated as text. */
};
#define mdoc_nwarn(mdoc, node, type, fmt, ...) \
diff --git a/st.c b/st.c
new file mode 100644
index 00000000..e1447c93
--- /dev/null
+++ b/st.c
@@ -0,0 +1,34 @@
+/* $Id: st.c,v 1.1 2009/03/16 22:19:19 kristaps Exp $ */
+/*
+ * Copyright (c) 2009 Kristaps Dzonsons <kristaps@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 <stdlib.h>
+#include <string.h>
+
+#include "private.h"
+
+#define LINE(x, y) \
+ if (0 == strcmp(p, x)) return(y);
+
+const char *
+mdoc_a2st(const char *p)
+{
+
+#include "st.in"
+
+ return(NULL);
+}
diff --git a/st.in b/st.in
index f8168056..b546c3b8 100644
--- a/st.in
+++ b/st.in
@@ -1,45 +1,48 @@
-# $Id: st.in,v 1.2 2009/03/06 14:24:49 kristaps Exp $
-#
-# This file defines the `.St' macro arguments. Lines are composed of
-# tab-delimited fields -- multiple tabs may delimit fields. Comment
-# lines begin with '#'; blank lines are also ok.
-#
-# These were last grok'd from OpenBSD-4.4's mdoc.samples(7).
+/* $Id: st.in,v 1.3 2009/03/16 22:19:19 kristaps Exp $ */
--p1003.1-88 IEEE Std 1003.1-1988 (\\\\(lqPOSIX\\\\(rq)
--p1003.1-90 IEEE Std 1003.1-1990 (\\\\(lqPOSIX\\\\(rq)
--p1003.1-96 ISO/IEC 9945-1:1996 (\\\\(lqPOSIX\\\\(rq)
--p1003.1-2001 IEEE Std 1003.1-2001 (\\\\(lqPOSIX\\\\(rq)
--p1003.1-2004 IEEE Std 1003.1-2004 (\\\\(lqPOSIX\\\\(rq)
--p1003.1 IEEE Std 1003.1 (\\\\(lqPOSIX\\\\(rq)
--p1003.1b IEEE Std 1003.1b (\\\\(lqPOSIX\\\\(rq)
--p1003.1b-93 IEEE Std 1003.1b-1993 (\\\\(lqPOSIX\\\\(rq)
--p1003.1c-95 IEEE Std 1003.1c-1995 (\\\\(lqPOSIX\\\\(rq)
--p1003.1g-2000 IEEE Std 1003.1g-2000 (\\\\(lqPOSIX\\\\(rq)
--p1003.2-92 IEEE Std 1003.2-1992 (\\\\(lqPOSIX.2\\\\(rq)
--p1387.2-95 IEEE Std 1387.2-1995 (\\\\(lqPOSIX.7.2\\\\(rq)
--p1003.2 IEEE Std 1003.2 (\\\\(lqPOSIX.2\\\\(rq)
--p1387.2 IEEE Std 1387.2 (\\\\(lqPOSIX.7.2\\\\(rq)
--isoC-90 ISO/IEC 9899:1990 (\\\\(lqISO C90\\\\(rq)
--isoC-amd1 ISO/IEC 9899/AMD1:1995 (\\\\(lqISO C90\\\\(rq)
--isoC-tcor1 ISO/IEC 9899/TCOR1:1994 (\\\\(lqISO C90\\\\(rq)
--isoC-tcor2 ISO/IEC 9899/TCOR2:1995 (\\\\(lqISO C90\\\\(rq)
--isoC-99 ISO/IEC 9899:1999 (\\\\(lqISO C99\\\\(rq)
--ansiC ANSI X3.159-1989 (\\\\(lqANSI C\\\\(rq)
--ansiC-89 ANSI X3.159-1989 (\\\\(lqANSI C\\\\(rq)
--ansiC-99 ANSI/ISO/IEC 9899-1999 (\\\\(lqANSI C99\\\\(rq)
--ieee754 IEEE Std 754-1985
--iso8802-3 ISO 8802-3: 1989
--xpg3 X/Open Portability Guide Issue 3 (\\\\(lqXPG3\\\\(rq)
--xpg4 X/Open Portability Guide Issue 4 (\\\\(lqXPG4\\\\(rq)
--xpg4.2 X/Open Portability Guide Issue 4.2 (\\\\(lqXPG4.2\\\\(rq)
--xpg4.3 X/Open Portability Guide Issue 4.3 (\\\\(lqXPG4.3\\\\(rq)
--xbd5 X/Open System Interface Definitions Issue 5 (\\\\(lqXBD5\\\\(rq)
--xcu5 X/Open Commands and Utilities Issue 5 (\\\\(lqXCU5\\\\(rq)
--xsh5 X/Open System Interfaces and Headers Issue 5 (\\\\(lqXSH5\\\\(rq)
--xns5 X/Open Networking Services Issue 5 (\\\\(lqXNS5\\\\(rq)
--xns5.2d2.0 X/Open Networking Services Issue 5.2 Draft 2.0 (\\\\(lqXNS5.2D2.0\\\\(rq)
--xcurses4.2 X/Open Curses Issue 4 Version 2 (\\\\(lqXCURSES4.2\\\\(rq)
--susv2 Version 2 of the Single UNIX Specification
--susv3 Version 3 of the Single UNIX Specification
--svid4 System V Interface Definition, Fourth Edition (\\\\(lqSVID4\\\\(rq)
+/*
+ * This file defines the .St macro arguments. If you add a new
+ * standard, make sure that the left-and side corresponds to the .St
+ * argument (like .St -p1003.1) and the right-hand side corresponds to
+ * the formatted output string.
+ *
+ * Be sure to escape strings.
+ */
+
+LINE("-p1003.1-88", "IEEE Std 1003.1-1988 (\\(lqPOSIX\\(rq)")
+LINE("-p1003.1-90", "IEEE Std 1003.1-1990 (\\(lqPOSIX\\(rq)")
+LINE("-p1003.1-96", "ISO/IEC 9945-1:1996 (\\(lqPOSIX\\(rq)")
+LINE("-p1003.1-2001", "IEEE Std 1003.1-2001 (\\(lqPOSIX\\(rq)")
+LINE("-p1003.1-2004", "IEEE Std 1003.1-2004 (\\(lqPOSIX\\(rq)")
+LINE("-p1003.1", "IEEE Std 1003.1 (\\(lqPOSIX\\(rq)")
+LINE("-p1003.1b", "IEEE Std 1003.1b (\\(lqPOSIX\\(rq)")
+LINE("-p1003.1b-93", "IEEE Std 1003.1b-1993 (\\(lqPOSIX\\(rq)")
+LINE("-p1003.1c-95", "IEEE Std 1003.1c-1995 (\\(lqPOSIX\\(rq)")
+LINE("-p1003.1g-2000", "IEEE Std 1003.1g-2000 (\\(lqPOSIX\\(rq)")
+LINE("-p1003.2-92", "IEEE Std 1003.2-1992 (\\(lqPOSIX.2\\(rq)")
+LINE("-p1387.2-95", "IEEE Std 1387.2-1995 (\\(lqPOSIX.7.2\\(rq)")
+LINE("-p1003.2", "IEEE Std 1003.2 (\\(lqPOSIX.2\\(rq)")
+LINE("-p1387.2", "IEEE Std 1387.2 (\\(lqPOSIX.7.2\\(rq)")
+LINE("-isoC-90", "ISO/IEC 9899:1990 (\\(lqISO C90\\(rq)")
+LINE("-isoC-amd1", "ISO/IEC 9899/AMD1:1995 (\\(lqISO C90\\(rq)")
+LINE("-isoC-tcor1", "ISO/IEC 9899/TCOR1:1994 (\\(lqISO C90\\(rq)")
+LINE("-isoC-tcor2", "ISO/IEC 9899/TCOR2:1995 (\\(lqISO C90\\(rq)")
+LINE("-isoC-99", "ISO/IEC 9899:1999 (\\(lqISO C99\\(rq)")
+LINE("-ansiC", "ANSI X3.159-1989 (\\(lqANSI C\\(rq)")
+LINE("-ansiC-89", "ANSI X3.159-1989 (\\(lqANSI C\\(rq)")
+LINE("-ansiC-99", "ANSI/ISO/IEC 9899-1999 (\\(lqANSI C99\\(rq)")
+LINE("-ieee754", "IEEE Std 754-1985")
+LINE("-iso8802-3", "ISO 8802-3: 1989")
+LINE("-xpg3", "X/Open Portability Guide Issue 3 (\\(lqXPG3\\(rq)")
+LINE("-xpg4", "X/Open Portability Guide Issue 4 (\\(lqXPG4\\(rq)")
+LINE("-xpg4.2", "X/Open Portability Guide Issue 4.2 (\\(lqXPG4.2\\(rq)")
+LINE("-xpg4.3", "X/Open Portability Guide Issue 4.3 (\\(lqXPG4.3\\(rq)")
+LINE("-xbd5", "X/Open System Interface Definitions Issue 5 (\\(lqXBD5\\(rq)")
+LINE("-xcu5", "X/Open Commands and Utilities Issue 5 (\\(lqXCU5\\(rq)")
+LINE("-xsh5", "X/Open System Interfaces and Headers Issue 5 (\\(lqXSH5\\(rq)")
+LINE("-xns5", "X/Open Networking Services Issue 5 (\\(lqXNS5\\(rq)")
+LINE("-xns5.2d2.0", "X/Open Networking Services Issue 5.2 Draft 2.0 (\\(lqXNS5.2D2.0\\(rq)")
+LINE("-xcurses4.2", "X/Open Curses Issue 4 Version 2 (\\(lqXCURSES4.2\\(rq)")
+LINE("-susv2", "Version 2 of the Single UNIX Specification")
+LINE("-susv3", "Version 3 of the Single UNIX Specification")
+LINE("-svid4", "System V Interface Definition, Fourth Edition (\\(lqSVID4\\(rq)")
diff --git a/strings.sh b/strings.sh
deleted file mode 100644
index 54a00d4e..00000000
--- a/strings.sh
+++ /dev/null
@@ -1,89 +0,0 @@
-#! /bin/sh
-# $Id: strings.sh,v 1.3 2009/03/08 19:32:03 kristaps Exp $
-
-# strings.sh [-o output] name input
-#
-# Generate the file of strings. This will contain the following
-# function:
-#
-# const char *
-# mdoc_a2NAME(const char *);
-#
-# The input file must be tab-delimited as follows:
-#
-# attnam0 A longer description
-# attnam1 Another longer description
-
-input=
-output=
-args=`getopt o: $*`
-
-if [ $? -ne 0 ]; then
- echo "usage: $0 [-o output] name input" 1>&2
- exit 1
-fi
-
-set -- $args
-
-while [ $# -ge 0 ]
-do
- case "$1" in
- -o)
- output="$2" ; shift; shift ;;
- --)
- shift ; break ;;
- esac
-done
-
-name=$1
-
-if [ -z "$name" ]; then
- echo "usage: $0 [-o output] name input" 1>&2
- exit 1
-fi
-
-input=$2
-
-if [ "$output" ]; then
- exec >$output
-fi
-
-if [ "$input" ]; then
- exec <$input
-fi
-
-cat <<!
-/*
- * DO NOT EDIT! Automatically generated by $0.
- */
-#include <stdlib.h>
-
-#include "private.h"
-
-const char *
-mdoc_a2${name}(const char *p)
-{
-
-!
-
-while read in ; do
- if [ -z "$in" ]; then
- continue
- fi
- if [ "#" = `echo "$in" | cut -c1` ]; then
- continue
- fi
- key=`printf "%s\n" "$in" | cut -f 1`
- val=`printf "%s\n" "$in" | cut -f 2- | sed 's!^[ ]*!!'`
- cat <<!
- if (xstrcmp(p, "$key"))
- return("$val");
-!
-done
-
-cat <<!
-
- /* No keys found. */
- return(NULL);
-}
-!
diff --git a/term.c b/term.c
index 06d4bc3f..6a81765a 100644
--- a/term.c
+++ b/term.c
@@ -1,4 +1,4 @@
-/* $Id: term.c,v 1.59 2009/03/14 12:35:02 kristaps Exp $ */
+/* $Id: term.c,v 1.60 2009/03/16 22:19:19 kristaps Exp $ */
/*
* Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -296,6 +296,8 @@ const struct termact __termacts[MDOC_MAX] = {
{ termp_brq_pre, termp_brq_post }, /* Bro */
{ NULL, NULL }, /* Brc */
{ NULL, NULL }, /* %C */
+ { NULL, NULL }, /* Es */
+ { NULL, NULL }, /* En */
};
const struct termact *termacts = __termacts;
diff --git a/term.h b/term.h
index 92993942..ff1c1173 100644
--- a/term.h
+++ b/term.h
@@ -1,4 +1,4 @@
-/* $Id: term.h,v 1.24 2009/03/15 10:34:11 kristaps Exp $ */
+/* $Id: term.h,v 1.25 2009/03/16 22:19:19 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -21,60 +21,12 @@
#include "mdoc.h"
+/* XXX - clean up tabs. */
+
#define INDENT 6
__BEGIN_DECLS
-enum tsym {
- TERMSYM_RBRACK = 0,
- TERMSYM_LBRACK = 1,
- TERMSYM_LARROW = 2,
- TERMSYM_RARROW = 3,
- TERMSYM_UARROW = 4,
- TERMSYM_DARROW = 5,
- TERMSYM_LSQUOTE = 6,
- TERMSYM_RSQUOTE = 7,
- TERMSYM_SQUOTE = 8,
- TERMSYM_LDQUOTE = 9,
- TERMSYM_RDQUOTE = 10,
- TERMSYM_DQUOTE = 11,
- TERMSYM_LT = 12,
- TERMSYM_GT = 13,
- TERMSYM_LE = 14,
- TERMSYM_GE = 15,
- TERMSYM_EQ = 16,
- TERMSYM_NEQ = 17,
- TERMSYM_ACUTE = 18,
- TERMSYM_GRAVE = 19,
- TERMSYM_PI = 20,
- TERMSYM_PLUSMINUS = 21,
- TERMSYM_INF = 22,
- TERMSYM_INF2 = 23,
- TERMSYM_NAN = 24,
- TERMSYM_BAR = 25,
- TERMSYM_BULLET = 26,
- TERMSYM_AMP = 27,
- TERMSYM_EM = 28,
- TERMSYM_EN = 29,
- TERMSYM_COPY = 30,
- TERMSYM_ASTERISK = 31,
- TERMSYM_SLASH = 32,
- TERMSYM_HYPHEN = 33,
- TERMSYM_SPACE = 34,
- TERMSYM_PERIOD = 35,
- TERMSYM_BREAK = 36,
- TERMSYM_LANGLE = 37,
- TERMSYM_RANGLE = 38,
- TERMSYM_LBRACE = 39,
- TERMSYM_RBRACE = 40,
- TERMSYM_MAX = 41
-};
-
-struct termsym {
- const char *sym;
- size_t sz;
-};
-
struct termp {
size_t rmargin;
size_t maxrmargin;
@@ -95,9 +47,11 @@ struct termp {
#define TERMP_BOLD (1 << 8) /* Styles... */
#define TERMP_UNDER (1 << 9)
char *buf;
- struct termsym *symtab; /* Special-symbol table. */
+ void *symtab;
};
+/* XXX - clean this up. */
+
struct termpair {
struct termpair *ppair;
int type;
@@ -117,26 +71,24 @@ struct termpair {
} while (0)
struct termact {
- int (*pre)(struct termp *,
- struct termpair *,
- const struct mdoc_meta *,
- const struct mdoc_node *);
- void (*post)(struct termp *,
- struct termpair *,
- const struct mdoc_meta *,
- const struct mdoc_node *);
+ int (*pre)(struct termp *, struct termpair *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
+ void (*post)(struct termp *, struct termpair *,
+ const struct mdoc_meta *,
+ const struct mdoc_node *);
};
-void newln(struct termp *);
-void vspace(struct termp *);
-void word(struct termp *, const char *);
-void flushln(struct termp *);
-void transcode(struct termp *,
- const char *, size_t);
-void subtree(struct termp *,
- const struct mdoc_meta *,
- const struct mdoc_node *);
+void *ascii2htab(void);
+const char *a2ascii(void *, const char *, size_t, size_t *);
+void newln(struct termp *);
+void vspace(struct termp *);
+void word(struct termp *, const char *);
+void flushln(struct termp *);
+void transcode(struct termp *, const char *, size_t);
+void subtree(struct termp *, const struct mdoc_meta *,
+ const struct mdoc_node *);
const struct termact *termacts;
diff --git a/validate.c b/validate.c
index a7f4065b..58b4aa57 100644
--- a/validate.c
+++ b/validate.c
@@ -1,4 +1,4 @@
-/* $Id: validate.c,v 1.83 2009/03/13 13:56:13 kristaps Exp $ */
+/* $Id: validate.c,v 1.84 2009/03/16 22:19:19 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -40,6 +40,7 @@
#define POST_ARGS struct mdoc *mdoc
enum merr {
+ EPRINT,
ENODATA,
ENOPROLOGUE,
ELINE,
@@ -81,16 +82,13 @@ struct valids {
/* Utility checks. */
-static int nwarn(struct mdoc *,
- const struct mdoc_node *, enum mwarn);
-static int nerr(struct mdoc *,
- const struct mdoc_node *, enum merr);
+static int pwarn(struct mdoc *, int, int, enum mwarn);
+static int perr(struct mdoc *, int, int, enum merr);
static int check_parent(PRE_ARGS, int, enum mdoc_type);
static int check_msec(PRE_ARGS, ...);
static int check_sec(PRE_ARGS, ...);
static int check_stdarg(PRE_ARGS);
-static int check_text(struct mdoc *,
- int, int, const char *);
+static int check_text(struct mdoc *, int, int, const char *);
static int check_argv(struct mdoc *,
const struct mdoc_node *,
const struct mdoc_argv *);
@@ -151,6 +149,11 @@ static int post_sh_body(POST_ARGS);
static int post_sh_head(POST_ARGS);
static int post_st(POST_ARGS);
+#define mwarn(m, t) nwarn((m), (m)->last, (t))
+#define merr(m, t) nerr((m), (m)->last, (t))
+#define nwarn(m, n, t) pwarn((m), (n)->line, (n)->pos, (t))
+#define nerr(m, n, t) perr((m), (n)->line, (n)->pos, (t))
+
static v_pre pres_an[] = { pre_an, NULL };
static v_pre pres_bd[] = { pre_display, pre_bd, NULL };
static v_pre pres_bl[] = { pre_bl, NULL };
@@ -310,30 +313,32 @@ const struct valids mdoc_valids[MDOC_MAX] = {
{ NULL, NULL }, /* Bro */
{ NULL, NULL }, /* Brc */
{ NULL, posts_text }, /* %C */
+ { NULL, NULL }, /* Es */
+ { NULL, NULL }, /* En */
};
int
mdoc_valid_pre(struct mdoc *mdoc,
- const struct mdoc_node *node)
+ const struct mdoc_node *n)
{
v_pre *p;
int line, pos;
const char *tp;
- if (MDOC_TEXT == node->type) {
- tp = node->string;
- line = node->line;
- pos = node->pos;
+ if (MDOC_TEXT == n->type) {
+ tp = n->string;
+ line = n->line;
+ pos = n->pos;
return(check_text(mdoc, line, pos, tp));
}
- if ( ! check_args(mdoc, node))
+ if ( ! check_args(mdoc, n))
return(0);
- if (NULL == mdoc_valids[node->tok].pre)
+ if (NULL == mdoc_valids[n->tok].pre)
return(1);
- for (p = mdoc_valids[node->tok].pre; *p; p++)
- if ( ! (*p)(mdoc, node))
+ for (p = mdoc_valids[n->tok].pre; *p; p++)
+ if ( ! (*p)(mdoc, n))
return(0);
return(1);
}
@@ -371,15 +376,16 @@ mdoc_valid_post(struct mdoc *mdoc)
}
-#define merr(m, t) nerr((m), (m)->last, (t))
static int
-nerr(struct mdoc *m, const struct mdoc_node *n, enum merr type)
+perr(struct mdoc *m, int line, int pos, enum merr type)
{
char *p;
p = NULL;
-
switch (type) {
+ case (EPRINT):
+ p = "invalid character";
+ break;
case (ENESTDISP):
p = "displays may not be nested";
break;
@@ -417,22 +423,19 @@ nerr(struct mdoc *m, const struct mdoc_node *n, enum merr type)
p = "default name not yet set";
break;
}
-
assert(p);
- return(mdoc_nerr(m, n, p));
+ return(mdoc_perr(m, line, pos, p));
}
-#define mwarn(m, t) nwarn((m), (m)->last, (t))
static int
-nwarn(struct mdoc *m, const struct mdoc_node *n, enum mwarn type)
+pwarn(struct mdoc *m, int line, int pos, enum mwarn type)
{
char *p;
enum mdoc_warn c;
c = WARN_SYNTAX;
p = NULL;
-
switch (type) {
case (WBADMSEC):
p = "inappropriate manual section";
@@ -484,7 +487,7 @@ nwarn(struct mdoc *m, const struct mdoc_node *n, enum mwarn type)
break;
}
assert(p);
- return(mdoc_nwarn(m, n, c, p));
+ return(mdoc_pwarn(m, line, pos, c, p));
}
@@ -685,12 +688,12 @@ check_text(struct mdoc *mdoc, int line, int pos, const char *p)
{
size_t c;
- /* XXX - indicate deprecated escapes \*(xx and \*x. */
+ /* FIXME: indicate deprecated escapes \*(xx and \*x. */
+ /* FIXME: don't allow tabs unless in literal mode. */
for ( ; *p; p++) {
- if ( ! isprint((u_char)*p) && '\t' != *p)
- return(mdoc_perr(mdoc, line, pos,
- "invalid non-printing character"));
+ if ('\t' != *p && ! isprint((u_char)*p))
+ return(perr(mdoc, line, pos, EPRINT));
if ('\\' != *p)
continue;
if ((c = mdoc_isescape(p))) {
diff --git a/vol.c b/vol.c
new file mode 100644
index 00000000..56e915b2
--- /dev/null
+++ b/vol.c
@@ -0,0 +1,34 @@
+/* $Id: vol.c,v 1.1 2009/03/16 22:19:19 kristaps Exp $ */
+/*
+ * Copyright (c) 2009 Kristaps Dzonsons <kristaps@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 <stdlib.h>
+#include <string.h>
+
+#include "private.h"
+
+#define LINE(x, y) \
+ if (0 == strcmp(p, x)) return(y);
+
+const char *
+mdoc_a2vol(const char *p)
+{
+
+#include "vol.in"
+
+ return(NULL);
+}
diff --git a/vol.in b/vol.in
index 2681cd2c..fe22141c 100644
--- a/vol.in
+++ b/vol.in
@@ -1,20 +1,37 @@
-# $Id: vol.in,v 1.2 2009/03/06 14:24:49 kristaps Exp $
-#
-# This file defines the `.Dt' macro 'volume' argument. Lines are
-# composed of tab-delimited fields -- multiple tabs may delimit fields.
-# Comment lines begin with '#'; blank lines are also ok.
-#
-# These were last grok'd from OpenBSD-4.4's mdoc.samples(7).
+/* $Id: vol.in,v 1.3 2009/03/16 22:19:19 kristaps Exp $ */
+/*
+ * Copyright (c) 2009 Kristaps Dzonsons <kristaps@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.
+ */
-USD User's Supplementary Documents
-PS1 Programmer's Supplementary Documents
-AMD Ancestral Manual Documents
-SMM System Manager's Manual
-URM User's Reference Manual
-PRM Programmer's Manual
-KM Kernel Manual
-IND Manual Master Index
-MMI Manual Master Index
-LOCAL Local Manual
-LOC Local Manual
-CON Contributed Software Manual
+/*
+ * This file defines volume titles for .Dt.
+ *
+ * Be sure to escape strings.
+ */
+
+LINE("USD", "User\'s Supplementary Documents")
+LINE("PS1", "Programmer\'s Supplementary Documents")
+LINE("AMD", "Ancestral Manual Documents")
+LINE("SMM", "System Manager\'s Manual")
+LINE("URM", "User\'s Reference Manual")
+LINE("PRM", "Programmer\'s Manual")
+LINE("KM", "Kernel Manual")
+LINE("IND", "Manual Master Index")
+LINE("MMI", "Manual Master Index")
+LINE("LOCAL", "Local Manual")
+LINE("LOC", "Local Manual")
+LINE("CON", "Contributed Software Manual")
diff --git a/xstd.c b/xstd.c
index 8b2ec4e9..383653bb 100644
--- a/xstd.c
+++ b/xstd.c
@@ -1,4 +1,4 @@
-/* $Id: xstd.c,v 1.9 2009/03/08 19:47:41 kristaps Exp $ */
+/* $Id: xstd.c,v 1.10 2009/03/16 22:19:19 kristaps Exp $ */
/*
* Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
*
@@ -28,12 +28,6 @@
* usage throughout this codebase.
*/
-#ifdef __linux__
-extern size_t strlcat(char *, const char *, size_t);
-extern size_t strlcpy(char *, const char *, size_t);
-#endif
-
-
int
xstrcmp(const char *p1, const char *p2)
{
@@ -105,81 +99,3 @@ xstrlcpys(char *buf, const struct mdoc_node *n, size_t sz)
return(1);
}
-
-#ifdef __linux__
-/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */
-
-/*
- * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/types.h>
-#include <string.h>
-
-
-size_t
-strlcat(char *dst, const char *src, size_t siz)
-{
- char *d = dst;
- const char *s = src;
- size_t n = siz;
- size_t dlen;
-
- /* Find the end of dst and adjust bytes left but don't go past end */
- while (n-- != 0 && *d != '\0')
- d++;
- dlen = d - dst;
- n = siz - dlen;
-
- if (n == 0)
- return(dlen + strlen(s));
- while (*s != '\0') {
- if (n != 1) {
- *d++ = *s;
- n--;
- }
- s++;
- }
- *d = '\0';
-
- return(dlen + (s - src)); /* count does not include NUL */
-}
-
-size_t
-strlcpy(char *dst, const char *src, size_t siz)
-{
- char *d = dst;
- const char *s = src;
- size_t n = siz;
-
- /* Copy as many bytes as will fit */
- if (n != 0) {
- while (--n != 0) {
- if ((*d++ = *s++) == '\0')
- break;
- }
- }
-
- /* Not enough room in dst, add NUL and traverse rest of src */
- if (n == 0) {
- if (siz != 0)
- *d = '\0'; /* NUL-terminate dst */
- while (*s++)
- ;
- }
-
- return(s - src - 1); /* count does not include NUL */
-}
-#endif