summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@cvs.openbsd.org>2011-09-18 10:25:29 +0000
committerIngo Schwarze <schwarze@cvs.openbsd.org>2011-09-18 10:25:29 +0000
commit4f50809e67b9f55a658e7971ff3fdb7315acd3d7 (patch)
tree8313e9c25a5e5ecc27954763967407abdb8ce6e2
parenta7ddd4c92498f0e8d565f15959dc99a464ec51a1 (diff)
sync to version 1.11.5:
adding an implementation of the eqn(7) language by kristaps@ So far, only .EQ/.EN blocks are handled, in-line equations are not, and rendering is not yet very pretty, but the parser is fairly complete.
-rw-r--r--usr.bin/mandoc/Makefile9
-rw-r--r--usr.bin/mandoc/chars.c8
-rw-r--r--usr.bin/mandoc/chars.in5
-rw-r--r--usr.bin/mandoc/eqn.c907
-rw-r--r--usr.bin/mandoc/eqn_html.c81
-rw-r--r--usr.bin/mandoc/eqn_term.c76
-rw-r--r--usr.bin/mandoc/html.h3
-rw-r--r--usr.bin/mandoc/libman.h4
-rw-r--r--usr.bin/mandoc/libmandoc.h48
-rw-r--r--usr.bin/mandoc/libmdoc.h4
-rw-r--r--usr.bin/mandoc/libroff.h28
-rw-r--r--usr.bin/mandoc/man.c10
-rw-r--r--usr.bin/mandoc/man_html.c7
-rw-r--r--usr.bin/mandoc/man_term.c4
-rw-r--r--usr.bin/mandoc/mandoc.18
-rw-r--r--usr.bin/mandoc/mandoc.c23
-rw-r--r--usr.bin/mandoc/mandoc.h97
-rw-r--r--usr.bin/mandoc/mandocdb.87
-rw-r--r--usr.bin/mandoc/mdoc.c70
-rw-r--r--usr.bin/mandoc/mdoc_html.c7
-rw-r--r--usr.bin/mandoc/mdoc_term.c4
-rw-r--r--usr.bin/mandoc/mdoc_validate.c4
-rw-r--r--usr.bin/mandoc/read.c25
-rw-r--r--usr.bin/mandoc/roff.c103
-rw-r--r--usr.bin/mandoc/tbl.c8
-rw-r--r--usr.bin/mandoc/term.h3
-rw-r--r--usr.bin/mandoc/tree.c89
27 files changed, 1460 insertions, 182 deletions
diff --git a/usr.bin/mandoc/Makefile b/usr.bin/mandoc/Makefile
index 0769e25dcbe..e66a47e56f1 100644
--- a/usr.bin/mandoc/Makefile
+++ b/usr.bin/mandoc/Makefile
@@ -1,9 +1,8 @@
-# $OpenBSD: Makefile,v 1.58 2011/09/17 14:45:22 schwarze Exp $
+# $OpenBSD: Makefile,v 1.59 2011/09/18 10:25:28 schwarze Exp $
.include <bsd.own.mk>
-VERSION=1.11.4
-CFLAGS+=-DVERSION=\"${VERSION}\"
+CFLAGS+=-DVERSION=\"1.11.5\"
CFLAGS+=-W -Wall -Wstrict-prototypes
.if ${COMPILER_VERSION:L} == "gcc3" || ${COMPILER_VERSION:L} == "gcc4"
@@ -15,9 +14,9 @@ SRCS+= mdoc_macro.c mdoc.c mdoc_hash.c \
mdoc_argv.c mdoc_validate.c lib.c att.c \
arch.c vol.c msec.c st.c
SRCS+= man_macro.c man.c man_hash.c man_validate.c
-SRCS+= main.c mdoc_term.c chars.c term.c tree.c man_term.c
+SRCS+= main.c mdoc_term.c chars.c term.c tree.c man_term.c eqn_term.c
SRCS+= mdoc_man.c
-SRCS+= html.c mdoc_html.c man_html.c out.c
+SRCS+= html.c mdoc_html.c man_html.c out.c eqn_html.c
SRCS+= term_ps.c term_ascii.c tbl_term.c tbl_html.c
PROG= mandoc
diff --git a/usr.bin/mandoc/chars.c b/usr.bin/mandoc/chars.c
index ce451027d28..8e0acdc58ff 100644
--- a/usr.bin/mandoc/chars.c
+++ b/usr.bin/mandoc/chars.c
@@ -1,4 +1,4 @@
-/* $Id: chars.c,v 1.21 2011/07/08 16:59:50 schwarze Exp $ */
+/* $Id: chars.c,v 1.22 2011/09/18 10:25:28 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -33,7 +33,7 @@ struct ln {
int unicode;
};
-#define LINES_MAX 325
+#define LINES_MAX 328
#define CHAR(in, ch, code) \
{ NULL, (in), (ch), (code) },
@@ -107,7 +107,7 @@ mchars_num2char(const char *p, size_t sz)
{
int i;
- if ((i = mandoc_strntou(p, sz, 10)) < 0)
+ if ((i = mandoc_strntoi(p, sz, 10)) < 0)
return('\0');
return(i > 0 && i < 256 && isprint(i) ? i : '\0');
}
@@ -117,7 +117,7 @@ mchars_num2uc(const char *p, size_t sz)
{
int i;
- if ((i = mandoc_strntou(p, sz, 16)) < 0)
+ if ((i = mandoc_strntoi(p, sz, 16)) < 0)
return('\0');
/* FIXME: make sure we're not in a bogus range. */
return(i > 0x80 && i <= 0x10FFFF ? i : '\0');
diff --git a/usr.bin/mandoc/chars.in b/usr.bin/mandoc/chars.in
index e4b2c65aa2d..357f7dba95a 100644
--- a/usr.bin/mandoc/chars.in
+++ b/usr.bin/mandoc/chars.in
@@ -1,4 +1,4 @@
-/* $Id: chars.in,v 1.16 2011/05/29 21:22:18 schwarze Exp $ */
+/* $Id: chars.in,v 1.17 2011/09/18 10:25:28 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -312,6 +312,9 @@ CHAR("Im", "I", 8465)
CHAR("Re", "R", 8476)
CHAR("pd", "a", 8706)
CHAR("-h", "/h", 8463)
+CHAR("12", "1/2", 189)
+CHAR("14", "1/4", 188)
+CHAR("34", "3/4", 190)
/* Ligatures. */
CHAR("ff", "ff", 64256)
diff --git a/usr.bin/mandoc/eqn.c b/usr.bin/mandoc/eqn.c
index 0d5bccdea9e..37ed4db0889 100644
--- a/usr.bin/mandoc/eqn.c
+++ b/usr.bin/mandoc/eqn.c
@@ -1,4 +1,4 @@
-/* $Id: eqn.c,v 1.3 2011/04/24 16:22:02 schwarze Exp $ */
+/* $Id: eqn.c,v 1.4 2011/09/18 10:25:28 schwarze Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -19,6 +19,8 @@
#endif
#include <assert.h>
+#include <limits.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -26,54 +28,921 @@
#include "libmandoc.h"
#include "libroff.h"
+#define EQN_NEST_MAX 128 /* maximum nesting of defines */
+#define EQN_MSG(t, x) mandoc_msg((t), (x)->parse, (x)->eqn.ln, (x)->eqn.pos, NULL)
+
+enum eqn_rest {
+ EQN_DESCOPE,
+ EQN_ERR,
+ EQN_OK,
+ EQN_EOF
+};
+
+enum eqn_symt {
+ EQNSYM_alpha,
+ EQNSYM_beta,
+ EQNSYM_chi,
+ EQNSYM_delta,
+ EQNSYM_epsilon,
+ EQNSYM_eta,
+ EQNSYM_gamma,
+ EQNSYM_iota,
+ EQNSYM_kappa,
+ EQNSYM_lambda,
+ EQNSYM_mu,
+ EQNSYM_nu,
+ EQNSYM_omega,
+ EQNSYM_omicron,
+ EQNSYM_phi,
+ EQNSYM_pi,
+ EQNSYM_ps,
+ EQNSYM_rho,
+ EQNSYM_sigma,
+ EQNSYM_tau,
+ EQNSYM_theta,
+ EQNSYM_upsilon,
+ EQNSYM_xi,
+ EQNSYM_zeta,
+ EQNSYM_DELTA,
+ EQNSYM_GAMMA,
+ EQNSYM_LAMBDA,
+ EQNSYM_OMEGA,
+ EQNSYM_PHI,
+ EQNSYM_PI,
+ EQNSYM_PSI,
+ EQNSYM_SIGMA,
+ EQNSYM_THETA,
+ EQNSYM_UPSILON,
+ EQNSYM_XI,
+ EQNSYM_inter,
+ EQNSYM_union,
+ EQNSYM_prod,
+ EQNSYM_int,
+ EQNSYM_sum,
+ EQNSYM_grad,
+ EQNSYM_del,
+ EQNSYM_times,
+ EQNSYM_cdot,
+ EQNSYM_nothing,
+ EQNSYM_approx,
+ EQNSYM_prime,
+ EQNSYM_half,
+ EQNSYM_partial,
+ EQNSYM_inf,
+ EQNSYM_muchgreat,
+ EQNSYM_muchless,
+ EQNSYM_larrow,
+ EQNSYM_rarrow,
+ EQNSYM_pm,
+ EQNSYM_nequal,
+ EQNSYM_equiv,
+ EQNSYM_lessequal,
+ EQNSYM_moreequal,
+ EQNSYM__MAX
+};
+
+enum eqnpartt {
+ EQN_DEFINE = 0,
+ EQN_NDEFINE,
+ EQN_TDEFINE,
+ EQN_SET,
+ EQN_UNDEF,
+ EQN_GFONT,
+ EQN_GSIZE,
+ EQN_BACK,
+ EQN_FWD,
+ EQN_UP,
+ EQN_DOWN,
+ EQN__MAX
+};
+
+struct eqnstr {
+ const char *name;
+ size_t sz;
+};
+
+#define STRNEQ(p1, sz1, p2, sz2) \
+ ((sz1) == (sz2) && 0 == strncmp((p1), (p2), (sz1)))
+#define EQNSTREQ(x, p, sz) \
+ STRNEQ((x)->name, (x)->sz, (p), (sz))
+
+struct eqnpart {
+ struct eqnstr str;
+ int (*fp)(struct eqn_node *);
+};
+
+struct eqnsym {
+ struct eqnstr str;
+ const char *sym;
+};
+
+
+static enum eqn_rest eqn_box(struct eqn_node *, struct eqn_box *);
+static struct eqn_box *eqn_box_alloc(struct eqn_node *,
+ struct eqn_box *);
+static void eqn_box_free(struct eqn_box *);
+static struct eqn_def *eqn_def_find(struct eqn_node *,
+ const char *, size_t);
+static int eqn_do_gfont(struct eqn_node *);
+static int eqn_do_gsize(struct eqn_node *);
+static int eqn_do_define(struct eqn_node *);
+static int eqn_do_ign1(struct eqn_node *);
+static int eqn_do_ign2(struct eqn_node *);
+static int eqn_do_tdefine(struct eqn_node *);
+static int eqn_do_undef(struct eqn_node *);
+static enum eqn_rest eqn_eqn(struct eqn_node *, struct eqn_box *);
+static enum eqn_rest eqn_list(struct eqn_node *, struct eqn_box *);
+static enum eqn_rest eqn_matrix(struct eqn_node *, struct eqn_box *);
+static const char *eqn_nexttok(struct eqn_node *, size_t *);
+static const char *eqn_nextrawtok(struct eqn_node *, size_t *);
+static const char *eqn_next(struct eqn_node *,
+ char, size_t *, int);
+static void eqn_rewind(struct eqn_node *);
+
+static const struct eqnpart eqnparts[EQN__MAX] = {
+ { { "define", 6 }, eqn_do_define }, /* EQN_DEFINE */
+ { { "ndefine", 7 }, eqn_do_define }, /* EQN_NDEFINE */
+ { { "tdefine", 7 }, eqn_do_tdefine }, /* EQN_TDEFINE */
+ { { "set", 3 }, eqn_do_ign2 }, /* EQN_SET */
+ { { "undef", 5 }, eqn_do_undef }, /* EQN_UNDEF */
+ { { "gfont", 5 }, eqn_do_gfont }, /* EQN_GFONT */
+ { { "gsize", 5 }, eqn_do_gsize }, /* EQN_GSIZE */
+ { { "back", 4 }, eqn_do_ign1 }, /* EQN_BACK */
+ { { "fwd", 3 }, eqn_do_ign1 }, /* EQN_FWD */
+ { { "up", 2 }, eqn_do_ign1 }, /* EQN_UP */
+ { { "down", 4 }, eqn_do_ign1 }, /* EQN_DOWN */
+};
+
+static const struct eqnstr eqnmarks[EQNMARK__MAX] = {
+ { "", 0 }, /* EQNMARK_NONE */
+ { "dot", 3 }, /* EQNMARK_DOT */
+ { "dotdot", 6 }, /* EQNMARK_DOTDOT */
+ { "hat", 3 }, /* EQNMARK_HAT */
+ { "tilde", 5 }, /* EQNMARK_TILDE */
+ { "vec", 3 }, /* EQNMARK_VEC */
+ { "dyad", 4 }, /* EQNMARK_DYAD */
+ { "bar", 3 }, /* EQNMARK_BAR */
+ { "under", 5 }, /* EQNMARK_UNDER */
+};
+
+static const struct eqnstr eqnfonts[EQNFONT__MAX] = {
+ { "", 0 }, /* EQNFONT_NONE */
+ { "roman", 5 }, /* EQNFONT_ROMAN */
+ { "bold", 4 }, /* EQNFONT_BOLD */
+ { "fat", 3 }, /* EQNFONT_FAT */
+ { "italic", 6 }, /* EQNFONT_ITALIC */
+};
+
+static const struct eqnstr eqnposs[EQNPOS__MAX] = {
+ { "", 0 }, /* EQNPOS_NONE */
+ { "over", 4 }, /* EQNPOS_OVER */
+ { "sup", 3 }, /* EQNPOS_SUP */
+ { "sub", 3 }, /* EQNPOS_SUB */
+ { "to", 2 }, /* EQNPOS_TO */
+ { "from", 4 }, /* EQNPOS_FROM */
+};
+
+static const struct eqnstr eqnpiles[EQNPILE__MAX] = {
+ { "", 0 }, /* EQNPILE_NONE */
+ { "pile", 4 }, /* EQNPILE_PILE */
+ { "cpile", 5 }, /* EQNPILE_CPILE */
+ { "rpile", 5 }, /* EQNPILE_RPILE */
+ { "lpile", 5 }, /* EQNPILE_LPILE */
+ { "col", 3 }, /* EQNPILE_COL */
+ { "ccol", 4 }, /* EQNPILE_CCOL */
+ { "rcol", 4 }, /* EQNPILE_RCOL */
+ { "lcol", 4 }, /* EQNPILE_LCOL */
+};
+
+static const struct eqnsym eqnsyms[EQNSYM__MAX] = {
+ { { "alpha", 5 }, "*a" }, /* EQNSYM_alpha */
+ { { "beta", 4 }, "*b" }, /* EQNSYM_beta */
+ { { "chi", 3 }, "*x" }, /* EQNSYM_chi */
+ { { "delta", 5 }, "*d" }, /* EQNSYM_delta */
+ { { "epsilon", 7 }, "*e" }, /* EQNSYM_epsilon */
+ { { "eta", 3 }, "*y" }, /* EQNSYM_eta */
+ { { "gamma", 5 }, "*g" }, /* EQNSYM_gamma */
+ { { "iota", 4 }, "*i" }, /* EQNSYM_iota */
+ { { "kappa", 5 }, "*k" }, /* EQNSYM_kappa */
+ { { "lambda", 6 }, "*l" }, /* EQNSYM_lambda */
+ { { "mu", 2 }, "*m" }, /* EQNSYM_mu */
+ { { "nu", 2 }, "*n" }, /* EQNSYM_nu */
+ { { "omega", 5 }, "*w" }, /* EQNSYM_omega */
+ { { "omicron", 7 }, "*o" }, /* EQNSYM_omicron */
+ { { "phi", 3 }, "*f" }, /* EQNSYM_phi */
+ { { "pi", 2 }, "*p" }, /* EQNSYM_pi */
+ { { "psi", 2 }, "*q" }, /* EQNSYM_psi */
+ { { "rho", 3 }, "*r" }, /* EQNSYM_rho */
+ { { "sigma", 5 }, "*s" }, /* EQNSYM_sigma */
+ { { "tau", 3 }, "*t" }, /* EQNSYM_tau */
+ { { "theta", 5 }, "*h" }, /* EQNSYM_theta */
+ { { "upsilon", 7 }, "*u" }, /* EQNSYM_upsilon */
+ { { "xi", 2 }, "*c" }, /* EQNSYM_xi */
+ { { "zeta", 4 }, "*z" }, /* EQNSYM_zeta */
+ { { "DELTA", 5 }, "*D" }, /* EQNSYM_DELTA */
+ { { "GAMMA", 5 }, "*G" }, /* EQNSYM_GAMMA */
+ { { "LAMBDA", 6 }, "*L" }, /* EQNSYM_LAMBDA */
+ { { "OMEGA", 5 }, "*W" }, /* EQNSYM_OMEGA */
+ { { "PHI", 3 }, "*F" }, /* EQNSYM_PHI */
+ { { "PI", 2 }, "*P" }, /* EQNSYM_PI */
+ { { "PSI", 3 }, "*Q" }, /* EQNSYM_PSI */
+ { { "SIGMA", 5 }, "*S" }, /* EQNSYM_SIGMA */
+ { { "THETA", 5 }, "*H" }, /* EQNSYM_THETA */
+ { { "UPSILON", 7 }, "*U" }, /* EQNSYM_UPSILON */
+ { { "XI", 2 }, "*C" }, /* EQNSYM_XI */
+ { { "inter", 5 }, "ca" }, /* EQNSYM_inter */
+ { { "union", 5 }, "cu" }, /* EQNSYM_union */
+ { { "prod", 4 }, "product" }, /* EQNSYM_prod */
+ { { "int", 3 }, "integral" }, /* EQNSYM_int */
+ { { "sum", 3 }, "sum" }, /* EQNSYM_sum */
+ { { "grad", 4 }, "gr" }, /* EQNSYM_grad */
+ { { "del", 3 }, "gr" }, /* EQNSYM_del */
+ { { "times", 5 }, "mu" }, /* EQNSYM_times */
+ { { "cdot", 4 }, "pc" }, /* EQNSYM_cdot */
+ { { "nothing", 7 }, "&" }, /* EQNSYM_nothing */
+ { { "approx", 6 }, "~~" }, /* EQNSYM_approx */
+ { { "prime", 5 }, "aq" }, /* EQNSYM_prime */
+ { { "half", 4 }, "12" }, /* EQNSYM_half */
+ { { "partial", 7 }, "pd" }, /* EQNSYM_partial */
+ { { "inf", 3 }, "if" }, /* EQNSYM_inf */
+ { { ">>", 2 }, ">>" }, /* EQNSYM_muchgreat */
+ { { "<<", 2 }, "<<" }, /* EQNSYM_muchless */
+ { { "<-", 2 }, "<-" }, /* EQNSYM_larrow */
+ { { "->", 2 }, "->" }, /* EQNSYM_rarrow */
+ { { "+-", 2 }, "+-" }, /* EQNSYM_pm */
+ { { "!=", 2 }, "!=" }, /* EQNSYM_nequal */
+ { { "==", 2 }, "==" }, /* EQNSYM_equiv */
+ { { "<=", 2 }, "<=" }, /* EQNSYM_lessequal */
+ { { ">=", 2 }, ">=" }, /* EQNSYM_moreequal */
+};
+
/* ARGSUSED */
enum rofferr
-eqn_read(struct eqn_node **epp, int ln, const char *p, int offs)
+eqn_read(struct eqn_node **epp, int ln,
+ const char *p, int pos, int *offs)
{
size_t sz;
struct eqn_node *ep;
+ enum rofferr er;
+
+ ep = *epp;
- if (0 == strcmp(p, ".EN")) {
- *epp = NULL;
- return(ROFF_EQN);
+ /*
+ * If we're the terminating mark, unset our equation status and
+ * validate the full equation.
+ */
+
+ if (0 == strncmp(p, ".EN", 3)) {
+ er = eqn_end(epp);
+ p += 3;
+ while (' ' == *p || '\t' == *p)
+ p++;
+ if ('\0' == *p)
+ return(er);
+ mandoc_msg(MANDOCERR_ARGSLOST, ep->parse, ln, pos, NULL);
+ return(er);
}
- ep = *epp;
+ /*
+ * Build up the full string, replacing all newlines with regular
+ * whitespace.
+ */
+
+ sz = strlen(p + pos) + 1;
+ ep->data = mandoc_realloc(ep->data, ep->sz + sz + 1);
- sz = strlen(&p[offs]);
- ep->eqn.data = mandoc_realloc(ep->eqn.data, ep->eqn.sz + sz + 1);
- if (0 == ep->eqn.sz)
- *ep->eqn.data = '\0';
+ /* First invocation: nil terminate the string. */
- ep->eqn.sz += sz;
- strlcat(ep->eqn.data, &p[offs], ep->eqn.sz + 1);
+ if (0 == ep->sz)
+ *ep->data = '\0';
+
+ ep->sz += sz;
+ strlcat(ep->data, p + pos, ep->sz + 1);
+ strlcat(ep->data, " ", ep->sz + 1);
return(ROFF_IGN);
}
struct eqn_node *
-eqn_alloc(int pos, int line)
+eqn_alloc(const char *name, int pos, int line, struct mparse *parse)
{
struct eqn_node *p;
+ size_t sz;
+ const char *end;
p = mandoc_calloc(1, sizeof(struct eqn_node));
- p->eqn.line = line;
+
+ if (name && '\0' != *name) {
+ sz = strlen(name);
+ assert(sz);
+ do {
+ sz--;
+ end = name + (int)sz;
+ } while (' ' == *end || '\t' == *end);
+ p->eqn.name = mandoc_strndup(name, sz + 1);
+ }
+
+ p->parse = parse;
+ p->eqn.ln = line;
p->eqn.pos = pos;
+ p->gsize = EQN_DEFSIZE;
return(p);
}
-/* ARGSUSED */
-void
-eqn_end(struct eqn_node *e)
+enum rofferr
+eqn_end(struct eqn_node **epp)
+{
+ struct eqn_node *ep;
+ struct eqn_box *root;
+ enum eqn_rest c;
+
+ ep = *epp;
+ *epp = NULL;
+
+ ep->eqn.root = mandoc_calloc(1, sizeof(struct eqn_box));
+
+ root = ep->eqn.root;
+ root->type = EQN_ROOT;
+
+ if (0 == ep->sz)
+ return(ROFF_IGN);
+
+ if (EQN_DESCOPE == (c = eqn_eqn(ep, root))) {
+ EQN_MSG(MANDOCERR_EQNNSCOPE, ep);
+ c = EQN_ERR;
+ }
+
+ return(EQN_EOF == c ? ROFF_EQN : ROFF_IGN);
+}
+
+static enum eqn_rest
+eqn_eqn(struct eqn_node *ep, struct eqn_box *last)
{
+ struct eqn_box *bp;
+ enum eqn_rest c;
+
+ bp = eqn_box_alloc(ep, last);
+ bp->type = EQN_SUBEXPR;
- /* Nothing to do. */
+ while (EQN_OK == (c = eqn_box(ep, bp)))
+ /* Spin! */ ;
+
+ return(c);
+}
+
+static enum eqn_rest
+eqn_matrix(struct eqn_node *ep, struct eqn_box *last)
+{
+ struct eqn_box *bp;
+ const char *start;
+ size_t sz;
+ enum eqn_rest c;
+
+ bp = eqn_box_alloc(ep, last);
+ bp->type = EQN_MATRIX;
+
+ if (NULL == (start = eqn_nexttok(ep, &sz))) {
+ EQN_MSG(MANDOCERR_EQNEOF, ep);
+ return(EQN_ERR);
+ }
+ if ( ! STRNEQ(start, sz, "{", 1)) {
+ EQN_MSG(MANDOCERR_EQNSYNT, ep);
+ return(EQN_ERR);
+ }
+
+ while (EQN_OK == (c = eqn_box(ep, bp)))
+ switch (bp->last->pile) {
+ case (EQNPILE_LCOL):
+ /* FALLTHROUGH */
+ case (EQNPILE_CCOL):
+ /* FALLTHROUGH */
+ case (EQNPILE_RCOL):
+ continue;
+ default:
+ EQN_MSG(MANDOCERR_EQNSYNT, ep);
+ return(EQN_ERR);
+ };
+
+ if (EQN_DESCOPE != c) {
+ if (EQN_EOF == c)
+ EQN_MSG(MANDOCERR_EQNEOF, ep);
+ return(EQN_ERR);
+ }
+
+ eqn_rewind(ep);
+ start = eqn_nexttok(ep, &sz);
+ assert(start);
+ if (STRNEQ(start, sz, "}", 1))
+ return(EQN_OK);
+
+ EQN_MSG(MANDOCERR_EQNBADSCOPE, ep);
+ return(EQN_ERR);
+}
+
+static enum eqn_rest
+eqn_list(struct eqn_node *ep, struct eqn_box *last)
+{
+ struct eqn_box *bp;
+ const char *start;
+ size_t sz;
+ enum eqn_rest c;
+
+ bp = eqn_box_alloc(ep, last);
+ bp->type = EQN_LIST;
+
+ if (NULL == (start = eqn_nexttok(ep, &sz))) {
+ EQN_MSG(MANDOCERR_EQNEOF, ep);
+ return(EQN_ERR);
+ }
+ if ( ! STRNEQ(start, sz, "{", 1)) {
+ EQN_MSG(MANDOCERR_EQNSYNT, ep);
+ return(EQN_ERR);
+ }
+
+ while (EQN_DESCOPE == (c = eqn_eqn(ep, bp))) {
+ eqn_rewind(ep);
+ start = eqn_nexttok(ep, &sz);
+ assert(start);
+ if ( ! STRNEQ(start, sz, "above", 5))
+ break;
+ }
+
+ if (EQN_DESCOPE != c) {
+ if (EQN_ERR != c)
+ EQN_MSG(MANDOCERR_EQNSCOPE, ep);
+ return(EQN_ERR);
+ }
+
+ eqn_rewind(ep);
+ start = eqn_nexttok(ep, &sz);
+ assert(start);
+ if (STRNEQ(start, sz, "}", 1))
+ return(EQN_OK);
+
+ EQN_MSG(MANDOCERR_EQNBADSCOPE, ep);
+ return(EQN_ERR);
+}
+
+static enum eqn_rest
+eqn_box(struct eqn_node *ep, struct eqn_box *last)
+{
+ size_t sz;
+ const char *start;
+ char *left;
+ char sym[64];
+ enum eqn_rest c;
+ int i, size;
+ struct eqn_box *bp;
+
+ if (NULL == (start = eqn_nexttok(ep, &sz)))
+ return(EQN_EOF);
+
+ if (STRNEQ(start, sz, "}", 1))
+ return(EQN_DESCOPE);
+ else if (STRNEQ(start, sz, "right", 5))
+ return(EQN_DESCOPE);
+ else if (STRNEQ(start, sz, "above", 5))
+ return(EQN_DESCOPE);
+ else if (STRNEQ(start, sz, "mark", 4))
+ return(EQN_OK);
+ else if (STRNEQ(start, sz, "lineup", 6))
+ return(EQN_OK);
+
+ for (i = 0; i < (int)EQN__MAX; i++) {
+ if ( ! EQNSTREQ(&eqnparts[i].str, start, sz))
+ continue;
+ return((*eqnparts[i].fp)(ep) ?
+ EQN_OK : EQN_ERR);
+ }
+
+ if (STRNEQ(start, sz, "{", 1)) {
+ if (EQN_DESCOPE != (c = eqn_eqn(ep, last))) {
+ if (EQN_ERR != c)
+ EQN_MSG(MANDOCERR_EQNSCOPE, ep);
+ return(EQN_ERR);
+ }
+ eqn_rewind(ep);
+ start = eqn_nexttok(ep, &sz);
+ assert(start);
+ if (STRNEQ(start, sz, "}", 1))
+ return(EQN_OK);
+ EQN_MSG(MANDOCERR_EQNBADSCOPE, ep);
+ return(EQN_ERR);
+ }
+
+ for (i = 0; i < (int)EQNPILE__MAX; i++) {
+ if ( ! EQNSTREQ(&eqnpiles[i], start, sz))
+ continue;
+ if (EQN_OK == (c = eqn_list(ep, last)))
+ last->last->pile = (enum eqn_pilet)i;
+ return(c);
+ }
+
+ if (STRNEQ(start, sz, "matrix", 6))
+ return(eqn_matrix(ep, last));
+
+ if (STRNEQ(start, sz, "left", 4)) {
+ if (NULL == (start = eqn_nexttok(ep, &sz))) {
+ EQN_MSG(MANDOCERR_EQNEOF, ep);
+ return(EQN_ERR);
+ }
+ left = mandoc_strndup(start, sz);
+ c = eqn_eqn(ep, last);
+ if (last->last)
+ last->last->left = left;
+ else
+ free(left);
+ if (EQN_DESCOPE != c)
+ return(c);
+ assert(last->last);
+ eqn_rewind(ep);
+ start = eqn_nexttok(ep, &sz);
+ assert(start);
+ if ( ! STRNEQ(start, sz, "right", 5))
+ return(EQN_DESCOPE);
+ if (NULL == (start = eqn_nexttok(ep, &sz))) {
+ EQN_MSG(MANDOCERR_EQNEOF, ep);
+ return(EQN_ERR);
+ }
+ last->last->right = mandoc_strndup(start, sz);
+ return(EQN_OK);
+ }
+
+ for (i = 0; i < (int)EQNPOS__MAX; i++) {
+ if ( ! EQNSTREQ(&eqnposs[i], start, sz))
+ continue;
+ if (NULL == last->last) {
+ EQN_MSG(MANDOCERR_EQNSYNT, ep);
+ return(EQN_ERR);
+ }
+ last->last->pos = (enum eqn_post)i;
+ if (EQN_EOF == (c = eqn_box(ep, last))) {
+ EQN_MSG(MANDOCERR_EQNEOF, ep);
+ return(EQN_ERR);
+ }
+ return(c);
+ }
+
+ for (i = 0; i < (int)EQNMARK__MAX; i++) {
+ if ( ! EQNSTREQ(&eqnmarks[i], start, sz))
+ continue;
+ if (NULL == last->last) {
+ EQN_MSG(MANDOCERR_EQNSYNT, ep);
+ return(EQN_ERR);
+ }
+ last->last->mark = (enum eqn_markt)i;
+ if (EQN_EOF == (c = eqn_box(ep, last))) {
+ EQN_MSG(MANDOCERR_EQNEOF, ep);
+ return(EQN_ERR);
+ }
+ return(c);
+ }
+
+ for (i = 0; i < (int)EQNFONT__MAX; i++) {
+ if ( ! EQNSTREQ(&eqnfonts[i], start, sz))
+ continue;
+ if (EQN_EOF == (c = eqn_box(ep, last))) {
+ EQN_MSG(MANDOCERR_EQNEOF, ep);
+ return(EQN_ERR);
+ } else if (EQN_OK == c)
+ last->last->font = (enum eqn_fontt)i;
+ return(c);
+ }
+
+ if (STRNEQ(start, sz, "size", 4)) {
+ if (NULL == (start = eqn_nexttok(ep, &sz))) {
+ EQN_MSG(MANDOCERR_EQNEOF, ep);
+ return(EQN_ERR);
+ }
+ size = mandoc_strntoi(start, sz, 10);
+ if (EQN_EOF == (c = eqn_box(ep, last))) {
+ EQN_MSG(MANDOCERR_EQNEOF, ep);
+ return(EQN_ERR);
+ } else if (EQN_OK != c)
+ return(c);
+ last->last->size = size;
+ }
+
+ bp = eqn_box_alloc(ep, last);
+ bp->type = EQN_TEXT;
+ for (i = 0; i < (int)EQNSYM__MAX; i++)
+ if (EQNSTREQ(&eqnsyms[i].str, start, sz)) {
+ sym[63] = '\0';
+ snprintf(sym, 62, "\\[%s]", eqnsyms[i].sym);
+ bp->text = mandoc_strdup(sym);
+ return(EQN_OK);
+ }
+
+ bp->text = mandoc_strndup(start, sz);
+ return(EQN_OK);
}
void
eqn_free(struct eqn_node *p)
{
+ int i;
+
+ eqn_box_free(p->eqn.root);
+
+ for (i = 0; i < (int)p->defsz; i++) {
+ free(p->defs[i].key);
+ free(p->defs[i].val);
+ }
- free(p->eqn.data);
+ free(p->eqn.name);
+ free(p->data);
+ free(p->defs);
free(p);
}
+
+static struct eqn_box *
+eqn_box_alloc(struct eqn_node *ep, struct eqn_box *parent)
+{
+ struct eqn_box *bp;
+
+ bp = mandoc_calloc(1, sizeof(struct eqn_box));
+ bp->parent = parent;
+ bp->size = ep->gsize;
+
+ if (NULL == parent->first)
+ parent->first = bp;
+ else
+ parent->last->next = bp;
+
+ parent->last = bp;
+ return(bp);
+}
+
+static void
+eqn_box_free(struct eqn_box *bp)
+{
+
+ if (bp->first)
+ eqn_box_free(bp->first);
+ if (bp->next)
+ eqn_box_free(bp->next);
+
+ free(bp->text);
+ free(bp->left);
+ free(bp->right);
+ free(bp);
+}
+
+static const char *
+eqn_nextrawtok(struct eqn_node *ep, size_t *sz)
+{
+
+ return(eqn_next(ep, '"', sz, 0));
+}
+
+static const char *
+eqn_nexttok(struct eqn_node *ep, size_t *sz)
+{
+
+ return(eqn_next(ep, '"', sz, 1));
+}
+
+static void
+eqn_rewind(struct eqn_node *ep)
+{
+
+ ep->cur = ep->rew;
+}
+
+static const char *
+eqn_next(struct eqn_node *ep, char quote, size_t *sz, int repl)
+{
+ char *start, *next;
+ int q, diff, lim;
+ size_t ssz, dummy;
+ struct eqn_def *def;
+
+ if (NULL == sz)
+ sz = &dummy;
+
+ lim = 0;
+ ep->rew = ep->cur;
+again:
+ /* Prevent self-definitions. */
+
+ if (lim >= EQN_NEST_MAX) {
+ EQN_MSG(MANDOCERR_ROFFLOOP, ep);
+ return(NULL);
+ }
+
+ ep->cur = ep->rew;
+ start = &ep->data[(int)ep->cur];
+ q = 0;
+
+ if ('\0' == *start)
+ return(NULL);
+
+ if (quote == *start) {
+ ep->cur++;
+ q = 1;
+ }
+
+ start = &ep->data[(int)ep->cur];
+
+ if ( ! q) {
+ if ('{' == *start || '}' == *start)
+ ssz = 1;
+ else
+ ssz = strcspn(start + 1, " ^~\"{}\t") + 1;
+ next = start + (int)ssz;
+ if ('\0' == *next)
+ next = NULL;
+ } else
+ next = strchr(start, quote);
+
+ if (NULL != next) {
+ *sz = (size_t)(next - start);
+ ep->cur += *sz;
+ if (q)
+ ep->cur++;
+ while (' ' == ep->data[(int)ep->cur] ||
+ '\t' == ep->data[(int)ep->cur] ||
+ '^' == ep->data[(int)ep->cur] ||
+ '~' == ep->data[(int)ep->cur])
+ ep->cur++;
+ } else {
+ if (q)
+ EQN_MSG(MANDOCERR_BADQUOTE, ep);
+ next = strchr(start, '\0');
+ *sz = (size_t)(next - start);
+ ep->cur += *sz;
+ }
+
+ /* Quotes aren't expanded for values. */
+
+ if (q || ! repl)
+ return(start);
+
+ if (NULL != (def = eqn_def_find(ep, start, *sz))) {
+ diff = def->valsz - *sz;
+
+ if (def->valsz > *sz) {
+ ep->sz += diff;
+ ep->data = mandoc_realloc(ep->data, ep->sz + 1);
+ ep->data[ep->sz] = '\0';
+ start = &ep->data[(int)ep->rew];
+ }
+
+ diff = def->valsz - *sz;
+ memmove(start + *sz + diff, start + *sz,
+ (strlen(start) - *sz) + 1);
+ memcpy(start, def->val, def->valsz);
+ goto again;
+ }
+
+ return(start);
+}
+
+static int
+eqn_do_ign1(struct eqn_node *ep)
+{
+
+ if (NULL == eqn_nextrawtok(ep, NULL))
+ EQN_MSG(MANDOCERR_EQNEOF, ep);
+ else
+ return(1);
+
+ return(0);
+}
+
+static int
+eqn_do_ign2(struct eqn_node *ep)
+{
+
+ if (NULL == eqn_nextrawtok(ep, NULL))
+ EQN_MSG(MANDOCERR_EQNEOF, ep);
+ else if (NULL == eqn_nextrawtok(ep, NULL))
+ EQN_MSG(MANDOCERR_EQNEOF, ep);
+ else
+ return(1);
+
+ return(0);
+}
+
+static int
+eqn_do_tdefine(struct eqn_node *ep)
+{
+
+ if (NULL == eqn_nextrawtok(ep, NULL))
+ EQN_MSG(MANDOCERR_EQNEOF, ep);
+ else if (NULL == eqn_next(ep, ep->data[(int)ep->cur], NULL, 0))
+ EQN_MSG(MANDOCERR_EQNEOF, ep);
+ else
+ return(1);
+
+ return(0);
+}
+
+static int
+eqn_do_define(struct eqn_node *ep)
+{
+ const char *start;
+ size_t sz;
+ struct eqn_def *def;
+ int i;
+
+ if (NULL == (start = eqn_nextrawtok(ep, &sz))) {
+ EQN_MSG(MANDOCERR_EQNEOF, ep);
+ return(0);
+ }
+
+ /*
+ * Search for a key that already exists.
+ * Create a new key if none is found.
+ */
+
+ if (NULL == (def = eqn_def_find(ep, start, sz))) {
+ /* Find holes in string array. */
+ for (i = 0; i < (int)ep->defsz; i++)
+ if (0 == ep->defs[i].keysz)
+ break;
+
+ if (i == (int)ep->defsz) {
+ ep->defsz++;
+ ep->defs = mandoc_realloc
+ (ep->defs, ep->defsz *
+ sizeof(struct eqn_def));
+ ep->defs[i].key = ep->defs[i].val = NULL;
+ }
+
+ ep->defs[i].keysz = sz;
+ ep->defs[i].key = mandoc_realloc
+ (ep->defs[i].key, sz + 1);
+
+ memcpy(ep->defs[i].key, start, sz);
+ ep->defs[i].key[(int)sz] = '\0';
+ def = &ep->defs[i];
+ }
+
+ start = eqn_next(ep, ep->data[(int)ep->cur], &sz, 0);
+
+ if (NULL == start) {
+ EQN_MSG(MANDOCERR_EQNEOF, ep);
+ return(0);
+ }
+
+ def->valsz = sz;
+ def->val = mandoc_realloc(def->val, sz + 1);
+ memcpy(def->val, start, sz);
+ def->val[(int)sz] = '\0';
+ return(1);
+}
+
+static int
+eqn_do_gfont(struct eqn_node *ep)
+{
+
+ if (NULL == eqn_nextrawtok(ep, NULL)) {
+ EQN_MSG(MANDOCERR_EQNEOF, ep);
+ return(0);
+ }
+ return(1);
+}
+
+static int
+eqn_do_gsize(struct eqn_node *ep)
+{
+ const char *start;
+ size_t sz;
+
+ if (NULL == (start = eqn_nextrawtok(ep, &sz))) {
+ EQN_MSG(MANDOCERR_EQNEOF, ep);
+ return(0);
+ }
+ ep->gsize = mandoc_strntoi(start, sz, 10);
+ return(1);
+}
+
+static int
+eqn_do_undef(struct eqn_node *ep)
+{
+ const char *start;
+ struct eqn_def *def;
+ size_t sz;
+
+ if (NULL == (start = eqn_nextrawtok(ep, &sz))) {
+ EQN_MSG(MANDOCERR_EQNEOF, ep);
+ return(0);
+ } else if (NULL != (def = eqn_def_find(ep, start, sz)))
+ def->keysz = 0;
+
+ return(1);
+}
+
+static struct eqn_def *
+eqn_def_find(struct eqn_node *ep, const char *key, size_t sz)
+{
+ int i;
+
+ for (i = 0; i < (int)ep->defsz; i++)
+ if (ep->defs[i].keysz && STRNEQ(ep->defs[i].key,
+ ep->defs[i].keysz, key, sz))
+ return(&ep->defs[i]);
+
+ return(NULL);
+}
diff --git a/usr.bin/mandoc/eqn_html.c b/usr.bin/mandoc/eqn_html.c
new file mode 100644
index 00000000000..0ca6e4a8574
--- /dev/null
+++ b/usr.bin/mandoc/eqn_html.c
@@ -0,0 +1,81 @@
+/* $Id: eqn_html.c,v 1.1 2011/09/18 10:25:28 schwarze Exp $ */
+/*
+ * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mandoc.h"
+#include "out.h"
+#include "html.h"
+
+static const enum htmltag fontmap[EQNFONT__MAX] = {
+ TAG_SPAN, /* EQNFONT_NONE */
+ TAG_SPAN, /* EQNFONT_ROMAN */
+ TAG_B, /* EQNFONT_BOLD */
+ TAG_B, /* EQNFONT_FAT */
+ TAG_I /* EQNFONT_ITALIC */
+};
+
+
+static void eqn_box(struct html *, const struct eqn_box *);
+
+void
+print_eqn(struct html *p, const struct eqn *ep)
+{
+ struct htmlpair tag;
+ struct tag *t;
+
+ PAIR_CLASS_INIT(&tag, "eqn");
+ t = print_otag(p, TAG_SPAN, 1, &tag);
+
+ p->flags |= HTML_NONOSPACE;
+ eqn_box(p, ep->root);
+ p->flags &= ~HTML_NONOSPACE;
+
+ print_tagq(p, t);
+}
+
+static void
+eqn_box(struct html *p, const struct eqn_box *bp)
+{
+ struct tag *t;
+
+ t = EQNFONT_NONE == bp->font ? NULL :
+ print_otag(p, fontmap[(int)bp->font], 0, NULL);
+
+ if (bp->left)
+ print_text(p, bp->left);
+
+ if (bp->text)
+ print_text(p, bp->text);
+
+ if (bp->first)
+ eqn_box(p, bp->first);
+
+ if (NULL != t)
+ print_tagq(p, t);
+ if (bp->right)
+ print_text(p, bp->right);
+
+ if (bp->next)
+ eqn_box(p, bp->next);
+}
diff --git a/usr.bin/mandoc/eqn_term.c b/usr.bin/mandoc/eqn_term.c
new file mode 100644
index 00000000000..0f0d53f8fb1
--- /dev/null
+++ b/usr.bin/mandoc/eqn_term.c
@@ -0,0 +1,76 @@
+/* $Id: eqn_term.c,v 1.1 2011/09/18 10:25:28 schwarze Exp $ */
+/*
+ * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mandoc.h"
+#include "out.h"
+#include "term.h"
+
+static const enum termfont fontmap[EQNFONT__MAX] = {
+ TERMFONT_NONE, /* EQNFONT_NONE */
+ TERMFONT_NONE, /* EQNFONT_ROMAN */
+ TERMFONT_BOLD, /* EQNFONT_BOLD */
+ TERMFONT_BOLD, /* EQNFONT_FAT */
+ TERMFONT_UNDER /* EQNFONT_ITALIC */
+};
+
+static void eqn_box(struct termp *, const struct eqn_box *);
+
+void
+term_eqn(struct termp *p, const struct eqn *ep)
+{
+
+ p->flags |= TERMP_NONOSPACE;
+ eqn_box(p, ep->root);
+ term_word(p, " ");
+ p->flags &= ~TERMP_NONOSPACE;
+}
+
+static void
+eqn_box(struct termp *p, const struct eqn_box *bp)
+{
+
+ if (EQNFONT_NONE != bp->font)
+ term_fontpush(p, fontmap[(int)bp->font]);
+ if (bp->left)
+ term_word(p, bp->left);
+ if (EQN_SUBEXPR == bp->type)
+ term_word(p, "(");
+
+ if (bp->text)
+ term_word(p, bp->text);
+
+ if (bp->first)
+ eqn_box(p, bp->first);
+
+ if (EQN_SUBEXPR == bp->type)
+ term_word(p, ")");
+ if (bp->right)
+ term_word(p, bp->right);
+ if (EQNFONT_NONE != bp->font)
+ term_fontpop(p);
+
+ if (bp->next)
+ eqn_box(p, bp->next);
+}
diff --git a/usr.bin/mandoc/html.h b/usr.bin/mandoc/html.h
index 10f9a3a5787..8e86973f2b0 100644
--- a/usr.bin/mandoc/html.h
+++ b/usr.bin/mandoc/html.h
@@ -1,4 +1,4 @@
-/* $Id: html.h,v 1.16 2011/05/29 21:22:18 schwarze Exp $ */
+/* $Id: html.h,v 1.17 2011/09/18 10:25:28 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -141,6 +141,7 @@ void print_stagq(struct html *, const struct tag *);
void print_text(struct html *, const char *);
void print_tblclose(struct html *);
void print_tbl(struct html *, const struct tbl_span *);
+void print_eqn(struct html *, const struct eqn *);
void bufcat_fmt(struct html *, const char *, ...);
void bufcat(struct html *, const char *);
diff --git a/usr.bin/mandoc/libman.h b/usr.bin/mandoc/libman.h
index 1d86d1026ef..e9ecec7da65 100644
--- a/usr.bin/mandoc/libman.h
+++ b/usr.bin/mandoc/libman.h
@@ -1,4 +1,4 @@
-/* $Id: libman.h,v 1.29 2011/04/24 16:22:02 schwarze Exp $ */
+/* $Id: libman.h,v 1.30 2011/09/18 10:25:28 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -36,7 +36,7 @@ struct man {
struct man_node *last; /* the last parsed node */
struct man_node *first; /* the first parsed node */
struct man_meta meta; /* document meta-data */
- struct regset *regs; /* registers */
+ struct roff *roff;
};
#define MACRO_PROT_ARGS struct man *m, \
diff --git a/usr.bin/mandoc/libmandoc.h b/usr.bin/mandoc/libmandoc.h
index 62cecdb63a2..4378c6391ed 100644
--- a/usr.bin/mandoc/libmandoc.h
+++ b/usr.bin/mandoc/libmandoc.h
@@ -1,4 +1,4 @@
-/* $Id: libmandoc.h,v 1.13 2011/09/17 13:45:28 schwarze Exp $ */
+/* $Id: libmandoc.h,v 1.14 2011/09/18 10:25:28 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -34,35 +34,6 @@ enum regs {
REG__MAX
};
-/*
- * A register (struct reg) can consist of many types: this consists of
- * normalised types from the original string form. For the time being,
- * there's only an unsigned integer type.
- */
-union regval {
- unsigned u; /* unsigned integer */
-};
-
-/*
- * A single register entity. If "set" is zero, the value of the
- * register should be the default one, which is per-register. It's
- * assumed that callers know which type in "v" corresponds to which
- * register value.
- */
-struct reg {
- int set; /* whether set or not */
- union regval v; /* parsed data */
-};
-
-/*
- * The primary interface to setting register values is in libroff,
- * although libmdoc and libman from time to time will manipulate
- * registers (such as `.Sh SYNOPSIS' enabling REG_nS).
- */
-struct regset {
- struct reg regs[REG__MAX];
-};
-
__BEGIN_DECLS
struct roff;
@@ -78,10 +49,10 @@ char *mandoc_normdate(struct mparse *, char *, int, int);
int mandoc_eos(const char *, size_t, int);
int mandoc_hyph(const char *, const char *);
int mandoc_getcontrol(const char *, int *);
-int mandoc_strntou(const char *, size_t, int);
+int mandoc_strntoi(const char *, size_t, int);
void mdoc_free(struct mdoc *);
-struct mdoc *mdoc_alloc(struct regset *, struct mparse *);
+struct mdoc *mdoc_alloc(struct roff *, struct mparse *);
void mdoc_reset(struct mdoc *);
int mdoc_parseln(struct mdoc *, int, char *, int);
int mdoc_endparse(struct mdoc *);
@@ -89,7 +60,7 @@ int mdoc_addspan(struct mdoc *, const struct tbl_span *);
int mdoc_addeqn(struct mdoc *, const struct eqn *);
void man_free(struct man *);
-struct man *man_alloc(struct regset *, struct mparse *);
+struct man *man_alloc(struct roff *, struct mparse *);
void man_reset(struct man *);
int man_parseln(struct man *, int, char *, int);
int man_endparse(struct man *);
@@ -97,11 +68,20 @@ int man_addspan(struct man *, const struct tbl_span *);
int man_addeqn(struct man *, const struct eqn *);
void roff_free(struct roff *);
-struct roff *roff_alloc(struct regset *, struct mparse *);
+struct roff *roff_alloc(struct mparse *);
void roff_reset(struct roff *);
enum rofferr roff_parseln(struct roff *, int,
char **, size_t *, int, int *);
void roff_endparse(struct roff *);
+int roff_regisset(const struct roff *, enum regs);
+unsigned int roff_regget(const struct roff *, enum regs);
+void roff_regunset(struct roff *, enum regs);
+#if 0
+char roff_eqndelim(const struct roff *);
+void roff_openeqn(struct roff *, const char *,
+ int, int, const char *);
+int roff_closeeqn(struct roff *);
+#endif
const struct tbl_span *roff_span(const struct roff *);
const struct eqn *roff_eqn(const struct roff *);
diff --git a/usr.bin/mandoc/libmdoc.h b/usr.bin/mandoc/libmdoc.h
index ee99633aa61..1bdc1ab4ccf 100644
--- a/usr.bin/mandoc/libmdoc.h
+++ b/usr.bin/mandoc/libmdoc.h
@@ -1,4 +1,4 @@
-/* $Id: libmdoc.h,v 1.46 2011/05/29 21:22:18 schwarze Exp $ */
+/* $Id: libmdoc.h,v 1.47 2011/09/18 10:25:28 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -39,7 +39,7 @@ struct mdoc {
struct mdoc_meta meta; /* document meta-data */
enum mdoc_sec lastnamed;
enum mdoc_sec lastsec;
- struct regset *regs; /* registers */
+ struct roff *roff;
};
#define MACRO_PROT_ARGS struct mdoc *m, \
diff --git a/usr.bin/mandoc/libroff.h b/usr.bin/mandoc/libroff.h
index 5769f31e105..efbb0da6521 100644
--- a/usr.bin/mandoc/libroff.h
+++ b/usr.bin/mandoc/libroff.h
@@ -1,4 +1,4 @@
-/* $Id: libroff.h,v 1.4 2011/04/24 16:22:02 schwarze Exp $ */
+/* $Id: libroff.h,v 1.5 2011/09/18 10:25:28 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -43,8 +43,23 @@ struct tbl_node {
};
struct eqn_node {
+ struct eqn_def *defs;
+ size_t defsz;
+ char *data;
+ size_t rew;
+ size_t cur;
+ size_t sz;
+ int gsize;
struct eqn eqn;
- struct eqn_node *next;
+ struct mparse *parse;
+ struct eqn_node *next;
+};
+
+struct eqn_def {
+ char *key;
+ size_t keysz;
+ char *val;
+ size_t valsz;
};
struct tbl_node *tbl_alloc(int, int, struct mparse *);
@@ -57,11 +72,12 @@ int tbl_layout(struct tbl_node *, int, const char *);
int tbl_data(struct tbl_node *, int, const char *);
int tbl_cdata(struct tbl_node *, int, const char *);
const struct tbl_span *tbl_span(struct tbl_node *);
-void tbl_end(struct tbl_node *);
-struct eqn_node *eqn_alloc(int, int);
-void eqn_end(struct eqn_node *);
+void tbl_end(struct tbl_node **);
+struct eqn_node *eqn_alloc(const char *, int, int, struct mparse *);
+enum rofferr eqn_end(struct eqn_node **);
void eqn_free(struct eqn_node *);
-enum rofferr eqn_read(struct eqn_node **, int, const char *, int);
+enum rofferr eqn_read(struct eqn_node **, int,
+ const char *, int, int *);
__END_DECLS
diff --git a/usr.bin/mandoc/man.c b/usr.bin/mandoc/man.c
index e0d4bb26ddb..85d213099dd 100644
--- a/usr.bin/mandoc/man.c
+++ b/usr.bin/mandoc/man.c
@@ -1,4 +1,4 @@
-/* $Id: man.c,v 1.59 2011/04/24 16:22:02 schwarze Exp $ */
+/* $Id: man.c,v 1.60 2011/09/18 10:25:28 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -92,7 +92,7 @@ man_free(struct man *man)
struct man *
-man_alloc(struct regset *regs, struct mparse *parse)
+man_alloc(struct roff *roff, struct mparse *parse)
{
struct man *p;
@@ -100,7 +100,7 @@ man_alloc(struct regset *regs, struct mparse *parse)
man_hash_init();
p->parse = parse;
- p->regs = regs;
+ p->roff = roff;
man_alloc1(p);
return(p);
@@ -367,14 +367,14 @@ man_addeqn(struct man *m, const struct eqn *ep)
assert( ! (MAN_HALT & m->flags));
- n = man_node_alloc(m, ep->line, ep->pos, MAN_EQN, MAN_MAX);
+ n = man_node_alloc(m, ep->ln, ep->pos, MAN_EQN, MAN_MAX);
n->eqn = ep;
if ( ! man_node_append(m, n))
return(0);
m->next = MAN_NEXT_SIBLING;
- return(man_descope(m, ep->line, ep->pos));
+ return(man_descope(m, ep->ln, ep->pos));
}
int
diff --git a/usr.bin/mandoc/man_html.c b/usr.bin/mandoc/man_html.c
index 0dea648b2bc..1dcfe5aea61 100644
--- a/usr.bin/mandoc/man_html.c
+++ b/usr.bin/mandoc/man_html.c
@@ -1,4 +1,4 @@
-/* $Id: man_html.c,v 1.40 2011/07/08 17:47:54 schwarze Exp $ */
+/* $Id: man_html.c,v 1.41 2011/09/18 10:25:28 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -197,7 +197,6 @@ print_man_node(MAN_ARGS)
{
int child;
struct tag *t;
- struct htmlpair tag;
child = 1;
t = h->tags.head;
@@ -225,9 +224,7 @@ print_man_node(MAN_ARGS)
print_text(h, n->string);
return;
case (MAN_EQN):
- PAIR_CLASS_INIT(&tag, "eqn");
- print_otag(h, TAG_SPAN, 1, &tag);
- print_text(h, n->eqn->data);
+ print_eqn(h, n->eqn);
break;
case (MAN_TBL):
/*
diff --git a/usr.bin/mandoc/man_term.c b/usr.bin/mandoc/man_term.c
index faff17aa3d2..f976892aaa6 100644
--- a/usr.bin/mandoc/man_term.c
+++ b/usr.bin/mandoc/man_term.c
@@ -1,4 +1,4 @@
-/* $Id: man_term.c,v 1.70 2011/07/07 21:10:48 schwarze Exp $ */
+/* $Id: man_term.c,v 1.71 2011/09/18 10:25:28 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -895,7 +895,7 @@ print_man_node(DECL_ARGS)
p->flags |= TERMP_SENTENCE;
return;
case (MAN_EQN):
- term_word(p, n->eqn->data);
+ term_eqn(p, n->eqn);
return;
case (MAN_TBL):
/*
diff --git a/usr.bin/mandoc/mandoc.1 b/usr.bin/mandoc/mandoc.1
index 5d5d6ab9ecc..79737196d9b 100644
--- a/usr.bin/mandoc/mandoc.1
+++ b/usr.bin/mandoc/mandoc.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: mandoc.1,v 1.46 2011/09/17 14:45:22 schwarze Exp $
+.\" $OpenBSD: mandoc.1,v 1.47 2011/09/18 10:25:28 schwarze Exp $
.\"
.\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: September 17 2011 $
+.Dd $Mdocdate: September 18 2011 $
.Dt MANDOC 1
.Os
.Sh NAME
@@ -578,6 +578,7 @@ and
lists render similarly.
.El
.Sh SEE ALSO
+.Xr eqn 7 ,
.Xr man 7 ,
.Xr mandoc_char 7 ,
.Xr mdoc 7 ,
@@ -587,7 +588,8 @@ lists render similarly.
The
.Nm
utility was written by
-.An Kristaps Dzonsons Aq kristaps@bsd.lv .
+.An Kristaps Dzonsons ,
+.Mt kristaps@bsd.lv .
.Sh CAVEATS
In
.Fl T Ns Cm html
diff --git a/usr.bin/mandoc/mandoc.c b/usr.bin/mandoc/mandoc.c
index b9ec46283e8..20ddc72def4 100644
--- a/usr.bin/mandoc/mandoc.c
+++ b/usr.bin/mandoc/mandoc.c
@@ -1,4 +1,4 @@
-/* $Id: mandoc.c,v 1.26 2011/05/29 21:22:18 schwarze Exp $ */
+/* $Id: mandoc.c,v 1.27 2011/09/18 10:25:28 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -428,6 +428,16 @@ mandoc_realloc(void *ptr, size_t size)
return(ptr);
}
+char *
+mandoc_strndup(const char *ptr, size_t sz)
+{
+ char *p;
+
+ p = mandoc_malloc(sz + 1);
+ memcpy(p, ptr, sz);
+ p[(int)sz] = '\0';
+ return(p);
+}
char *
mandoc_strdup(const char *ptr)
@@ -694,7 +704,7 @@ mandoc_getcontrol(const char *cp, int *ppos)
* If the string is invalid, or is less than 0, return -1.
*/
int
-mandoc_strntou(const char *p, size_t sz, int base)
+mandoc_strntoi(const char *p, size_t sz, int base)
{
char buf[32];
char *ep;
@@ -712,11 +722,10 @@ mandoc_strntou(const char *p, size_t sz, int base)
if (buf[0] == '\0' || *ep != '\0')
return(-1);
- if ((errno == ERANGE &&
- (v == LONG_MAX || v == LONG_MIN)) ||
- (v > INT_MAX || v < 0))
- return(-1);
+ if (v > INT_MAX)
+ v = INT_MAX;
+ if (v < INT_MIN)
+ v = INT_MIN;
return((int)v);
}
-
diff --git a/usr.bin/mandoc/mandoc.h b/usr.bin/mandoc/mandoc.h
index 8633fb35e2c..473d80253f1 100644
--- a/usr.bin/mandoc/mandoc.h
+++ b/usr.bin/mandoc/mandoc.h
@@ -1,4 +1,4 @@
-/* $Id: mandoc.h,v 1.39 2011/09/17 13:45:28 schwarze Exp $ */
+/* $Id: mandoc.h,v 1.40 2011/09/18 10:25:28 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -104,8 +104,18 @@ enum mandocerr {
MANDOCERR_BADESCAPE, /* unknown escape sequence */
MANDOCERR_BADQUOTE, /* unterminated quoted string */
+ /* related to equations */
+ MANDOCERR_EQNQUOTE, /* unexpected literal in equation */
+
MANDOCERR_ERROR, /* ===== start of errors ===== */
+ /* related to equations */
+ MANDOCERR_EQNNSCOPE, /* unexpected equation scope closure*/
+ MANDOCERR_EQNSCOPE, /* equation scope open on exit */
+ MANDOCERR_EQNBADSCOPE, /* overlapping equation scopes */
+ MANDOCERR_EQNEOF, /* unexpected end of equation */
+ MANDOCERR_EQNSYNT, /* equation syntax error */
+
/* related to tables */
MANDOCERR_TBL, /* bad table syntax */
MANDOCERR_TBLOPT, /* bad table option */
@@ -270,10 +280,88 @@ struct tbl_span {
struct tbl_span *next;
};
+enum eqn_boxt {
+ EQN_ROOT, /* root of parse tree */
+ EQN_TEXT, /* text (number, variable, whatever) */
+ EQN_SUBEXPR, /* nested `eqn' subexpression */
+ EQN_LIST, /* subexpressions list */
+ EQN_MATRIX /* matrix subexpression */
+};
+
+enum eqn_markt {
+ EQNMARK_NONE = 0,
+ EQNMARK_DOT,
+ EQNMARK_DOTDOT,
+ EQNMARK_HAT,
+ EQNMARK_TILDE,
+ EQNMARK_VEC,
+ EQNMARK_DYAD,
+ EQNMARK_BAR,
+ EQNMARK_UNDER,
+ EQNMARK__MAX
+};
+
+enum eqn_fontt {
+ EQNFONT_NONE = 0,
+ EQNFONT_ROMAN,
+ EQNFONT_BOLD,
+ EQNFONT_FAT,
+ EQNFONT_ITALIC,
+ EQNFONT__MAX
+};
+
+enum eqn_post {
+ EQNPOS_NONE = 0,
+ EQNPOS_OVER,
+ EQNPOS_SUP,
+ EQNPOS_SUB,
+ EQNPOS_TO,
+ EQNPOS_FROM,
+ EQNPOS__MAX
+};
+
+enum eqn_pilet {
+ EQNPILE_NONE = 0,
+ EQNPILE_PILE,
+ EQNPILE_CPILE,
+ EQNPILE_RPILE,
+ EQNPILE_LPILE,
+ EQNPILE_COL,
+ EQNPILE_CCOL,
+ EQNPILE_RCOL,
+ EQNPILE_LCOL,
+ EQNPILE__MAX
+};
+
+ /*
+ * A "box" is a parsed mathematical expression as defined by the eqn.7
+ * grammar.
+ */
+struct eqn_box {
+ int size; /* font size of expression */
+#define EQN_DEFSIZE INT_MIN
+ enum eqn_boxt type; /* type of node */
+ struct eqn_box *first; /* first child node */
+ struct eqn_box *last; /* last child node */
+ struct eqn_box *next; /* node sibling */
+ struct eqn_box *parent; /* node sibling */
+ char *text; /* text (or NULL) */
+ char *left;
+ char *right;
+ enum eqn_post pos; /* position of next box */
+ enum eqn_markt mark; /* a mark about the box */
+ enum eqn_fontt font; /* font of box */
+ enum eqn_pilet pile; /* equation piling */
+};
+
+/*
+ * An equation consists of a tree of expressions starting at a given
+ * line and position.
+ */
struct eqn {
- size_t sz;
- char *data;
- int line; /* invocation line */
+ char *name; /* identifier (or NULL) */
+ struct eqn_box *root; /* root mathematical expression */
+ int ln; /* invocation line */
int pos; /* invocation position */
};
@@ -325,6 +413,7 @@ void *mandoc_calloc(size_t, size_t);
void *mandoc_malloc(size_t);
void *mandoc_realloc(void *, size_t);
char *mandoc_strdup(const char *);
+char *mandoc_strndup(const char *, size_t);
enum mandoc_esc mandoc_escape(const char **, const char **, int *);
diff --git a/usr.bin/mandoc/mandocdb.8 b/usr.bin/mandoc/mandocdb.8
index dda691a6e4b..12602b648fa 100644
--- a/usr.bin/mandoc/mandocdb.8
+++ b/usr.bin/mandoc/mandocdb.8
@@ -1,4 +1,4 @@
-.\" $Id: mandocdb.8,v 1.2 2011/09/17 13:45:28 schwarze Exp $
+.\" $Id: mandocdb.8,v 1.3 2011/09/18 10:25:28 schwarze Exp $
.\"
.\" Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: September 17 2011 $
+.Dd $Mdocdate: September 18 2011 $
.Dt MANDOCDB 8
.Os
.Sh NAME
@@ -197,4 +197,5 @@ The output databases are corrupt and should be removed .
The
.Nm
utility was written by
-.An Kristaps Dzonsons Aq kristaps@bsd.lv .
+.An Kristaps Dzonsons ,
+.Mt kristaps@bsd.lv .
diff --git a/usr.bin/mandoc/mdoc.c b/usr.bin/mandoc/mdoc.c
index c63a93a3130..6946e04fcf0 100644
--- a/usr.bin/mandoc/mdoc.c
+++ b/usr.bin/mandoc/mdoc.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc.c,v 1.83 2011/04/24 16:22:02 schwarze Exp $ */
+/* $Id: mdoc.c,v 1.84 2011/09/18 10:25:28 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
@@ -93,6 +93,9 @@ static struct mdoc_node *node_alloc(struct mdoc *, int, int,
enum mdoct, enum mdoc_type);
static int node_append(struct mdoc *,
struct mdoc_node *);
+#if 0
+static int mdoc_preptext(struct mdoc *, int, char *, int);
+#endif
static int mdoc_ptext(struct mdoc *, int, char *, int);
static int mdoc_pmacro(struct mdoc *, int, char *, int);
@@ -189,14 +192,14 @@ mdoc_free(struct mdoc *mdoc)
* Allocate volatile and non-volatile parse resources.
*/
struct mdoc *
-mdoc_alloc(struct regset *regs, struct mparse *parse)
+mdoc_alloc(struct roff *roff, struct mparse *parse)
{
struct mdoc *p;
p = mandoc_calloc(1, sizeof(struct mdoc));
p->parse = parse;
- p->regs = regs;
+ p->roff = roff;
mdoc_hash_init();
mdoc_alloc1(p);
@@ -229,11 +232,11 @@ mdoc_addeqn(struct mdoc *m, const struct eqn *ep)
/* No text before an initial macro. */
if (SEC_NONE == m->lastnamed) {
- mdoc_pmsg(m, ep->line, ep->pos, MANDOCERR_NOTEXT);
+ mdoc_pmsg(m, ep->ln, ep->pos, MANDOCERR_NOTEXT);
return(1);
}
- n = node_alloc(m, ep->line, ep->pos, MDOC_MAX, MDOC_EQN);
+ n = node_alloc(m, ep->ln, ep->pos, MDOC_MAX, MDOC_EQN);
n->eqn = ep;
if ( ! node_append(m, n))
@@ -286,8 +289,8 @@ mdoc_parseln(struct mdoc *m, int ln, char *buf, int offs)
* whether this mode is on or off.
* Note that this mode is also switched by the Sh macro.
*/
- if (m->regs->regs[(int)REG_nS].set) {
- if (m->regs->regs[(int)REG_nS].v.u)
+ if (roff_regisset(m->roff, REG_nS)) {
+ if (roff_regget(m->roff, REG_nS))
m->flags |= MDOC_SYNOPSIS;
else
m->flags &= ~MDOC_SYNOPSIS;
@@ -646,6 +649,59 @@ mdoc_node_delete(struct mdoc *m, struct mdoc_node *p)
mdoc_node_free(p);
}
+#if 0
+/*
+ * Pre-treat a text line.
+ * Text lines can consist of equations, which must be handled apart from
+ * the regular text.
+ * Thus, use this function to step through a line checking if it has any
+ * equations embedded in it.
+ * This must handle multiple equations AND equations that do not end at
+ * the end-of-line, i.e., will re-enter in the next roff parse.
+ */
+static int
+mdoc_preptext(struct mdoc *m, int line, char *buf, int offs)
+{
+ char *start, *end;
+ char delim;
+
+ while ('\0' != buf[offs]) {
+ /* Mark starting position if eqn is set. */
+ start = NULL;
+ if ('\0' != (delim = roff_eqndelim(m->roff)))
+ if (NULL != (start = strchr(buf + offs, delim)))
+ *start++ = '\0';
+
+ /* Parse text as normal. */
+ if ( ! mdoc_ptext(m, line, buf, offs))
+ return(0);
+
+ /* Continue only if an equation exists. */
+ if (NULL == start)
+ break;
+
+ /* Read past the end of the equation. */
+ offs += start - (buf + offs);
+ assert(start == &buf[offs]);
+ if (NULL != (end = strchr(buf + offs, delim))) {
+ *end++ = '\0';
+ while (' ' == *end)
+ end++;
+ }
+
+ /* Parse the equation itself. */
+ roff_openeqn(m->roff, NULL, line, offs, buf);
+
+ /* Process a finished equation? */
+ if (roff_closeeqn(m->roff))
+ if ( ! mdoc_addeqn(m, roff_eqn(m->roff)))
+ return(0);
+ offs += (end - (buf + offs));
+ }
+
+ return(1);
+}
+#endif
/*
* Parse free-form text, that is, a line that does not begin with the
diff --git a/usr.bin/mandoc/mdoc_html.c b/usr.bin/mandoc/mdoc_html.c
index 76609267fcc..c9fa7a4fa16 100644
--- a/usr.bin/mandoc/mdoc_html.c
+++ b/usr.bin/mandoc/mdoc_html.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_html.c,v 1.59 2011/07/05 04:12:41 schwarze Exp $ */
+/* $Id: mdoc_html.c,v 1.60 2011/09/18 10:25:28 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -403,7 +403,6 @@ print_mdoc_node(MDOC_ARGS)
{
int child;
struct tag *t;
- struct htmlpair tag;
child = 1;
t = h->tags.head;
@@ -430,9 +429,7 @@ print_mdoc_node(MDOC_ARGS)
h->flags |= HTML_NOSPACE;
return;
case (MDOC_EQN):
- PAIR_CLASS_INIT(&tag, "eqn");
- print_otag(h, TAG_SPAN, 1, &tag);
- print_text(h, n->eqn->data);
+ print_eqn(h, n->eqn);
break;
case (MDOC_TBL):
/*
diff --git a/usr.bin/mandoc/mdoc_term.c b/usr.bin/mandoc/mdoc_term.c
index 2d621badd0f..be0b13560cb 100644
--- a/usr.bin/mandoc/mdoc_term.c
+++ b/usr.bin/mandoc/mdoc_term.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_term.c,v 1.134 2011/07/05 04:12:41 schwarze Exp $ */
+/* $Id: mdoc_term.c,v 1.135 2011/09/18 10:25:28 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
@@ -347,7 +347,7 @@ print_mdoc_node(DECL_ARGS)
p->flags |= TERMP_NOSPACE;
break;
case (MDOC_EQN):
- term_word(p, n->eqn->data);
+ term_eqn(p, n->eqn);
break;
case (MDOC_TBL):
term_tbl(p, n->span);
diff --git a/usr.bin/mandoc/mdoc_validate.c b/usr.bin/mandoc/mdoc_validate.c
index 1c08e614a80..5a8dc53c275 100644
--- a/usr.bin/mandoc/mdoc_validate.c
+++ b/usr.bin/mandoc/mdoc_validate.c
@@ -1,4 +1,4 @@
-/* $Id: mdoc_validate.c,v 1.93 2011/05/29 21:22:18 schwarze Exp $ */
+/* $Id: mdoc_validate.c,v 1.94 2011/09/18 10:25:28 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -895,7 +895,7 @@ pre_sh(PRE_ARGS)
if (MDOC_BLOCK != n->type)
return(1);
- mdoc->regs->regs[(int)REG_nS].set = 0;
+ roff_regunset(mdoc->roff, REG_nS);
return(check_parent(mdoc, n, MDOC_MAX, MDOC_ROOT));
}
diff --git a/usr.bin/mandoc/read.c b/usr.bin/mandoc/read.c
index aa491c9fe34..1f31b7b27bb 100644
--- a/usr.bin/mandoc/read.c
+++ b/usr.bin/mandoc/read.c
@@ -1,4 +1,4 @@
-/* $Id: read.c,v 1.2 2011/05/29 21:22:18 schwarze Exp $ */
+/* $Id: read.c,v 1.3 2011/09/18 10:25:28 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -49,7 +49,6 @@ struct mparse {
struct man *man; /* man parser */
struct mdoc *mdoc; /* mdoc parser */
struct roff *roff; /* roff parser (!NULL) */
- struct regset regs; /* roff registers */
int reparse_count; /* finite interp. stack */
mandocmsg mmsg; /* warning/error message handler */
void *arg; /* argument to mmsg */
@@ -136,9 +135,19 @@ static const char * const mandocerrs[MANDOCERR_MAX] = {
"bad comment style",
"bad escape sequence",
"unterminated quoted string",
+
+ /* related to equations */
+ "unexpected literal in equation",
"generic error",
+ /* related to equations */
+ "unexpected equation scope closure",
+ "equation scope open on exit",
+ "overlapping equation scopes",
+ "unexpected end of equation",
+ "equation syntax error",
+
/* related to tables */
"bad table syntax",
"bad table option",
@@ -227,13 +236,13 @@ pset(const char *buf, int pos, struct mparse *curp)
switch (curp->inttype) {
case (MPARSE_MDOC):
if (NULL == curp->pmdoc)
- curp->pmdoc = mdoc_alloc(&curp->regs, curp);
+ curp->pmdoc = mdoc_alloc(curp->roff, curp);
assert(curp->pmdoc);
curp->mdoc = curp->pmdoc;
return;
case (MPARSE_MAN):
if (NULL == curp->pman)
- curp->pman = man_alloc(&curp->regs, curp);
+ curp->pman = man_alloc(curp->roff, curp);
assert(curp->pman);
curp->man = curp->pman;
return;
@@ -243,14 +252,14 @@ pset(const char *buf, int pos, struct mparse *curp)
if (pos >= 3 && 0 == memcmp(buf, ".Dd", 3)) {
if (NULL == curp->pmdoc)
- curp->pmdoc = mdoc_alloc(&curp->regs, curp);
+ curp->pmdoc = mdoc_alloc(curp->roff, curp);
assert(curp->pmdoc);
curp->mdoc = curp->pmdoc;
return;
}
if (NULL == curp->pman)
- curp->pman = man_alloc(&curp->regs, curp);
+ curp->pman = man_alloc(curp->roff, curp);
assert(curp->pman);
curp->man = curp->pman;
}
@@ -667,7 +676,7 @@ mparse_alloc(enum mparset inttype, enum mandoclevel wlevel, mandocmsg mmsg, void
curp->arg = arg;
curp->inttype = inttype;
- curp->roff = roff_alloc(&curp->regs, curp);
+ curp->roff = roff_alloc(curp);
return(curp);
}
@@ -675,8 +684,6 @@ void
mparse_reset(struct mparse *curp)
{
- memset(&curp->regs, 0, sizeof(struct regset));
-
roff_reset(curp->roff);
if (curp->mdoc)
diff --git a/usr.bin/mandoc/roff.c b/usr.bin/mandoc/roff.c
index 5cc504e3eee..9efb8fd385b 100644
--- a/usr.bin/mandoc/roff.c
+++ b/usr.bin/mandoc/roff.c
@@ -1,4 +1,4 @@
-/* $Id: roff.c,v 1.40 2011/07/31 14:11:48 schwarze Exp $ */
+/* $Id: roff.c,v 1.41 2011/09/18 10:25:28 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -67,6 +67,16 @@ enum roffrule {
ROFFRULE_DENY
};
+/*
+ * A single register entity. If "set" is zero, the value of the
+ * register should be the default one, which is per-register.
+ * Registers are assumed to be unsigned ints for now.
+ */
+struct reg {
+ int set; /* whether set or not */
+ unsigned int u; /* unsigned integer */
+};
+
struct roffstr {
char *name; /* key of symbol */
char *string; /* current value */
@@ -78,7 +88,7 @@ struct roff {
struct roffnode *last; /* leaf of stack */
enum roffrule rstack[RSTACK_MAX]; /* stack of !`ie' rules */
int rstackpos; /* position in rstack */
- struct regset *regs; /* read/writable registers */
+ struct reg regs[REG__MAX];
struct roffstr *first_string; /* user-defined strings & macros */
const char *current_string; /* value of last called user macro */
struct tbl_node *first_tbl; /* first table parsed */
@@ -145,6 +155,8 @@ static const char *roff_getstrn(const struct roff *,
const char *, size_t);
static enum rofferr roff_line_ignore(ROFF_ARGS);
static enum rofferr roff_nr(ROFF_ARGS);
+static void roff_openeqn(struct roff *, const char *,
+ int, int, const char *);
static int roff_res(struct roff *,
char **, size_t *, int, int);
static enum rofferr roff_rm(ROFF_ARGS);
@@ -347,6 +359,8 @@ roff_reset(struct roff *r)
roff_free1(r);
+ memset(&r->regs, 0, sizeof(struct reg) * REG__MAX);
+
for (i = 0; i < PREDEFS_MAX; i++)
roff_setstr(r, predefs[i].name, predefs[i].str, 0);
}
@@ -362,13 +376,12 @@ roff_free(struct roff *r)
struct roff *
-roff_alloc(struct regset *regs, struct mparse *parse)
+roff_alloc(struct mparse *parse)
{
struct roff *r;
int i;
r = mandoc_calloc(1, sizeof(struct roff));
- r->regs = regs;
r->parse = parse;
r->rstackpos = -1;
@@ -515,18 +528,18 @@ roff_parseln(struct roff *r, int ln, char **bufp,
if (ROFF_CONT != e)
return(e);
if (r->eqn)
- return(eqn_read(&r->eqn, ln, *bufp, pos));
+ return(eqn_read(&r->eqn, ln, *bufp, pos, offs));
if (r->tbl)
return(tbl_read(r->tbl, ln, *bufp, pos));
return(ROFF_CONT);
} else if ( ! ctl) {
if (r->eqn)
- return(eqn_read(&r->eqn, ln, *bufp, pos));
+ return(eqn_read(&r->eqn, ln, *bufp, pos, offs));
if (r->tbl)
return(tbl_read(r->tbl, ln, *bufp, pos));
return(ROFF_CONT);
} else if (r->eqn)
- return(eqn_read(&r->eqn, ln, *bufp, ppos));
+ return(eqn_read(&r->eqn, ln, *bufp, ppos, offs));
/*
* If a scope is open, go to the child handler for that macro,
@@ -568,16 +581,14 @@ roff_endparse(struct roff *r)
if (r->eqn) {
mandoc_msg(MANDOCERR_SCOPEEXIT, r->parse,
- r->eqn->eqn.line, r->eqn->eqn.pos, NULL);
- eqn_end(r->eqn);
- r->eqn = NULL;
+ r->eqn->eqn.ln, r->eqn->eqn.pos, NULL);
+ eqn_end(&r->eqn);
}
if (r->tbl) {
mandoc_msg(MANDOCERR_SCOPEEXIT, r->parse,
r->tbl->line, r->tbl->pos, NULL);
- tbl_end(r->tbl);
- r->tbl = NULL;
+ tbl_end(&r->tbl);
}
}
@@ -1100,6 +1111,26 @@ roff_ds(ROFF_ARGS)
return(ROFF_IGN);
}
+int
+roff_regisset(const struct roff *r, enum regs reg)
+{
+
+ return(r->regs[(int)reg].set);
+}
+
+unsigned int
+roff_regget(const struct roff *r, enum regs reg)
+{
+
+ return(r->regs[(int)reg].u);
+}
+
+void
+roff_regunset(struct roff *r, enum regs reg)
+{
+
+ r->regs[(int)reg].set = 0;
+}
/* ARGSUSED */
static enum rofferr
@@ -1108,18 +1139,16 @@ roff_nr(ROFF_ARGS)
const char *key;
char *val;
int iv;
- struct reg *rg;
val = *bufp + pos;
key = roff_getname(r, &val, ln, pos);
- rg = r->regs->regs;
if (0 == strcmp(key, "nS")) {
- rg[(int)REG_nS].set = 1;
- if ((iv = mandoc_strntou(val, strlen(val), 10)) >= 0)
- rg[REG_nS].v.u = (unsigned)iv;
+ r->regs[(int)REG_nS].set = 1;
+ if ((iv = mandoc_strntoi(val, strlen(val), 10)) >= 0)
+ r->regs[(int)REG_nS].u = (unsigned)iv;
else
- rg[(int)REG_nS].v.u = 0u;
+ r->regs[(int)REG_nS].u = 0u;
}
return(ROFF_IGN);
@@ -1149,9 +1178,8 @@ roff_TE(ROFF_ARGS)
if (NULL == r->tbl)
mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL);
else
- tbl_end(r->tbl);
+ tbl_end(&r->tbl);
- r->tbl = NULL;
return(ROFF_IGN);
}
@@ -1168,14 +1196,24 @@ roff_T_(ROFF_ARGS)
return(ROFF_IGN);
}
-/* ARGSUSED */
-static enum rofferr
-roff_EQ(ROFF_ARGS)
+#if 0
+static int
+roff_closeeqn(struct roff *r)
{
- struct eqn_node *e;
+
+ return(r->eqn && ROFF_EQN == eqn_end(&r->eqn) ? 1 : 0);
+}
+#endif
+
+static void
+roff_openeqn(struct roff *r, const char *name, int line,
+ int offs, const char *buf)
+{
+ struct eqn_node *e;
+ int poff;
assert(NULL == r->eqn);
- e = eqn_alloc(ppos, ln);
+ e = eqn_alloc(name, offs, line, r->parse);
if (r->last_eqn)
r->last_eqn->next = e;
@@ -1183,6 +1221,19 @@ roff_EQ(ROFF_ARGS)
r->first_eqn = r->last_eqn = e;
r->eqn = r->last_eqn = e;
+
+ if (buf) {
+ poff = 0;
+ eqn_read(&r->eqn, line, buf, offs, &poff);
+ }
+}
+
+/* ARGSUSED */
+static enum rofferr
+roff_EQ(ROFF_ARGS)
+{
+
+ roff_openeqn(r, *bufp + pos, ln, ppos, NULL);
return(ROFF_IGN);
}
@@ -1203,7 +1254,7 @@ roff_TS(ROFF_ARGS)
if (r->tbl) {
mandoc_msg(MANDOCERR_SCOPEBROKEN, r->parse, ln, ppos, NULL);
- tbl_end(r->tbl);
+ tbl_end(&r->tbl);
}
t = tbl_alloc(ppos, ln, r->parse);
diff --git a/usr.bin/mandoc/tbl.c b/usr.bin/mandoc/tbl.c
index b708abcb861..203dfe320d6 100644
--- a/usr.bin/mandoc/tbl.c
+++ b/usr.bin/mandoc/tbl.c
@@ -1,4 +1,4 @@
-/* $Id: tbl.c,v 1.6 2011/04/24 16:22:02 schwarze Exp $ */
+/* $Id: tbl.c,v 1.7 2011/09/18 10:25:28 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -150,8 +150,12 @@ tbl_span(struct tbl_node *tbl)
}
void
-tbl_end(struct tbl_node *tbl)
+tbl_end(struct tbl_node **tblp)
{
+ struct tbl_node *tbl;
+
+ tbl = *tblp;
+ *tblp = NULL;
if (NULL == tbl->first_span || NULL == tbl->first_span->first)
mandoc_msg(MANDOCERR_TBLNODATA, tbl->parse,
diff --git a/usr.bin/mandoc/term.h b/usr.bin/mandoc/term.h
index 30d9b70a9d5..22366b29b33 100644
--- a/usr.bin/mandoc/term.h
+++ b/usr.bin/mandoc/term.h
@@ -1,4 +1,4 @@
-/* $Id: term.h,v 1.30 2011/05/29 21:22:18 schwarze Exp $ */
+/* $Id: term.h,v 1.31 2011/09/18 10:25:28 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -96,6 +96,7 @@ struct termp {
struct termp_ps *ps;
};
+void term_eqn(struct termp *, const struct eqn *);
void term_tbl(struct termp *, const struct tbl_span *);
void term_free(struct termp *);
void term_newln(struct termp *);
diff --git a/usr.bin/mandoc/tree.c b/usr.bin/mandoc/tree.c
index 19b91d7f9bd..8d97dfb46e7 100644
--- a/usr.bin/mandoc/tree.c
+++ b/usr.bin/mandoc/tree.c
@@ -1,4 +1,4 @@
-/* $Id: tree.c,v 1.15 2011/04/24 16:22:02 schwarze Exp $ */
+/* $Id: tree.c,v 1.16 2011/09/18 10:25:28 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -15,6 +15,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <assert.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
@@ -24,8 +25,9 @@
#include "man.h"
#include "main.h"
-static void print_mdoc(const struct mdoc_node *, int);
+static void print_box(const struct eqn_box *, int);
static void print_man(const struct man_node *, int);
+static void print_mdoc(const struct mdoc_node *, int);
static void print_span(const struct tbl_span *, int);
@@ -59,6 +61,7 @@ print_mdoc(const struct mdoc_node *n, int indent)
argv = NULL;
argc = sz = 0;
params = NULL;
+ t = p = NULL;
switch (n->type) {
case (MDOC_ROOT):
@@ -86,18 +89,14 @@ print_mdoc(const struct mdoc_node *n, int indent)
t = "text";
break;
case (MDOC_TBL):
- t = "tbl";
- break;
+ /* FALLTHROUGH */
case (MDOC_EQN):
- t = "eqn";
break;
default:
abort();
/* NOTREACHED */
}
- p = NULL;
-
switch (n->type) {
case (MDOC_TEXT):
p = n->string;
@@ -126,9 +125,8 @@ print_mdoc(const struct mdoc_node *n, int indent)
}
break;
case (MDOC_TBL):
- break;
+ /* FALLTHROUGH */
case (MDOC_EQN):
- p = n->eqn->data;
break;
case (MDOC_ROOT):
p = "root";
@@ -139,8 +137,11 @@ print_mdoc(const struct mdoc_node *n, int indent)
}
if (n->span) {
- assert(NULL == p);
+ assert(NULL == p && NULL == t);
print_span(n->span, indent);
+ } else if (n->eqn) {
+ assert(NULL == p && NULL == t);
+ print_box(n->eqn->root, indent);
} else {
for (i = 0; i < indent; i++)
putchar('\t');
@@ -160,11 +161,9 @@ print_mdoc(const struct mdoc_node *n, int indent)
for (i = 0; i < (int)sz; i++)
printf(" [%s]", params[i]);
- printf(" %d:%d", n->line, n->pos);
+ printf(" %d:%d\n", n->line, n->pos);
}
- putchar('\n');
-
if (n->child)
print_mdoc(n->child, indent + 1);
if (n->next)
@@ -178,6 +177,8 @@ print_man(const struct man_node *n, int indent)
const char *p, *t;
int i;
+ t = p = NULL;
+
switch (n->type) {
case (MAN_ROOT):
t = "root";
@@ -201,18 +202,14 @@ print_man(const struct man_node *n, int indent)
t = "block-tail";
break;
case (MAN_TBL):
- t = "tbl";
- break;
+ /* FALLTHROUGH */
case (MAN_EQN):
- t = "eqn";
break;
default:
abort();
/* NOTREACHED */
}
- p = NULL;
-
switch (n->type) {
case (MAN_TEXT):
p = n->string;
@@ -232,9 +229,8 @@ print_man(const struct man_node *n, int indent)
p = "root";
break;
case (MAN_TBL):
- break;
+ /* FALLTHROUGH */
case (MAN_EQN):
- p = n->eqn->data;
break;
default:
abort();
@@ -242,16 +238,17 @@ print_man(const struct man_node *n, int indent)
}
if (n->span) {
- assert(NULL == p);
+ assert(NULL == p && NULL == t);
print_span(n->span, indent);
+ } else if (n->eqn) {
+ assert(NULL == p && NULL == t);
+ print_box(n->eqn->root, indent);
} else {
for (i = 0; i < indent; i++)
putchar('\t');
- printf("%s (%s) %d:%d", p, t, n->line, n->pos);
+ printf("%s (%s) %d:%d\n", p, t, n->line, n->pos);
}
- putchar('\n');
-
if (n->child)
print_man(n->child, indent + 1);
if (n->next)
@@ -259,6 +256,48 @@ print_man(const struct man_node *n, int indent)
}
static void
+print_box(const struct eqn_box *ep, int indent)
+{
+ int i;
+ const char *t;
+
+ if (NULL == ep)
+ return;
+ for (i = 0; i < indent; i++)
+ putchar('\t');
+
+ t = NULL;
+ switch (ep->type) {
+ case (EQN_ROOT):
+ t = "eqn-root";
+ break;
+ case (EQN_LIST):
+ t = "eqn-list";
+ break;
+ case (EQN_SUBEXPR):
+ t = "eqn-expr";
+ break;
+ case (EQN_TEXT):
+ t = "eqn-text";
+ break;
+ case (EQN_MATRIX):
+ t = "eqn-matrix";
+ break;
+ }
+
+ assert(t);
+ printf("%s(%d, %d, %d, %d, %d, \"%s\", \"%s\") %s\n",
+ t, EQN_DEFSIZE == ep->size ? 0 : ep->size,
+ ep->pos, ep->font, ep->mark, ep->pile,
+ ep->left ? ep->left : "",
+ ep->right ? ep->right : "",
+ ep->text ? ep->text : "");
+
+ print_box(ep->first, indent + 1);
+ print_box(ep->next, indent);
+}
+
+static void
print_span(const struct tbl_span *sp, int indent)
{
const struct tbl_dat *dp;
@@ -302,5 +341,5 @@ print_span(const struct tbl_span *sp, int indent)
putchar(' ');
}
- printf("(tbl) %d:1", sp->line);
+ printf("(tbl) %d:1\n", sp->line);
}