summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorschwarze <schwarze@openbsd.org>2014-10-09 15:49:09 +0000
committerschwarze <schwarze@openbsd.org>2014-10-09 15:49:09 +0000
commit933d2e00494223345f40ad103193270db8d73713 (patch)
treecd2796074d2be70d6d64d83e27e5d56889327cc5
parentmore readable eqn(7) -Ttree output; from kristaps@ (diff)
downloadwireguard-openbsd-933d2e00494223345f40ad103193270db8d73713.tar.xz
wireguard-openbsd-933d2e00494223345f40ad103193270db8d73713.zip
initial bits of MathML rendering for eqn(7) -Thtml;
written by kristaps@ during EuroBSDCon
-rw-r--r--usr.bin/mandoc/eqn_html.c172
-rw-r--r--usr.bin/mandoc/html.c17
-rw-r--r--usr.bin/mandoc/html.h17
3 files changed, 182 insertions, 24 deletions
diff --git a/usr.bin/mandoc/eqn_html.c b/usr.bin/mandoc/eqn_html.c
index 1944ed8953f..004b7457cf4 100644
--- a/usr.bin/mandoc/eqn_html.c
+++ b/usr.bin/mandoc/eqn_html.c
@@ -1,6 +1,6 @@
-/* $Id: eqn_html.c,v 1.2 2014/04/20 16:44:44 schwarze Exp $ */
+/* $Id: eqn_html.c,v 1.3 2014/10/09 15:49:09 schwarze Exp $ */
/*
- * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2011, 2014 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
@@ -31,7 +31,8 @@ static const enum htmltag fontmap[EQNFONT__MAX] = {
TAG_I /* EQNFONT_ITALIC */
};
-static void eqn_box(struct html *, const struct eqn_box *);
+static const struct eqn_box *
+ eqn_box(struct html *, const struct eqn_box *, int);
void
@@ -41,37 +42,164 @@ print_eqn(struct html *p, const struct eqn *ep)
struct tag *t;
PAIR_CLASS_INIT(&tag, "eqn");
- t = print_otag(p, TAG_SPAN, 1, &tag);
+ t = print_otag(p, TAG_MATH, 1, &tag);
p->flags |= HTML_NONOSPACE;
- eqn_box(p, ep->root);
+ eqn_box(p, ep->root, 1);
p->flags &= ~HTML_NONOSPACE;
print_tagq(p, t);
}
-static void
-eqn_box(struct html *p, const struct eqn_box *bp)
+/*
+ * This function is fairly brittle.
+ * This is because the eqn syntax doesn't play so nicely with recusive
+ * formats, e.g.,
+ * foo sub bar sub baz
+ * ...needs to resolve into
+ * <msub> foo <msub> bar, baz </msub> </msub>
+ * In other words, we need to embed some recursive work.
+ * FIXME: this does NOT handle right-left associativity or precedence!
+ */
+static const struct eqn_box *
+eqn_box(struct html *p, const struct eqn_box *bp, int next)
{
- struct tag *t;
+ struct tag *post, *pilet, *tmp;
+ struct htmlpair tag[2];
+ int skiptwo;
+
+ if (NULL == bp)
+ return(NULL);
+
+ post = pilet = NULL;
+ skiptwo = 0;
+
+ /*
+ * If we're a "row" under a pile, then open up the piling
+ * context here.
+ * We do this first because the pile surrounds the content of
+ * the contained expression.
+ */
+ if (NULL != bp->parent && bp->parent->pile != EQNPILE_NONE) {
+ pilet = print_otag(p, TAG_MTR, 0, NULL);
+ print_otag(p, TAG_MTD, 0, NULL);
+ }
+
+ /*
+ * If we're establishing a pile, start the table mode now.
+ * If we've already in a pile row, then don't override "pilet",
+ * because we'll be closed out anyway.
+ */
+ if (bp->pile != EQNPILE_NONE) {
+ tmp = print_otag(p, TAG_MTABLE, 0, NULL);
+ pilet = (NULL == pilet) ? tmp : pilet;
+ }
- t = EQNFONT_NONE == bp->font ? NULL :
- print_otag(p, fontmap[(int)bp->font], 0, NULL);
+ /*
+ * Positioning.
+ * This is the most complicated part, and actually doesn't quite
+ * work (FIXME) because it doesn't account for associativity.
+ * Setting "post" will mean that we're only going to process a
+ * single or double following expression.
+ */
+ switch (bp->pos) {
+ case (EQNPOS_SUP):
+ post = print_otag(p, TAG_MSUP, 0, NULL);
+ break;
+ case (EQNPOS_FROM):
+ /* FALLTHROUGH */
+ case (EQNPOS_SUB):
+ post = print_otag(p, TAG_MSUB, 0, NULL);
+ break;
+ case (EQNPOS_OVER):
+ post = print_otag(p, TAG_MFRAC, 0, NULL);
+ break;
+ case (EQNPOS_SUBSUP):
+ /* This requires two elements. */
+ post = print_otag(p, TAG_MSUBSUP, 0, NULL);
+ skiptwo = 1;
+ break;
+ default:
+ break;
+ }
- if (bp->left)
- print_text(p, bp->left);
+ /*t = EQNFONT_NONE == bp->font ? NULL :
+ print_otag(p, fontmap[(int)bp->font], 0, NULL);*/
- if (bp->text)
- print_text(p, bp->text);
+ if (NULL != bp->text) {
+ assert(NULL == bp->first);
+ /*
+ * We have text.
+ * This can be a number, a function, a variable, or
+ * pretty much anything else.
+ * First, check for some known functions.
+ * If we're going to create a structural node (e.g.,
+ * sqrt), then set the "post" variable only if it's not
+ * already set.
+ */
+ if (0 == strcmp(bp->text, "sqrt")) {
+ tmp = print_otag(p, TAG_MSQRT, 0, NULL);
+ post = (NULL == post) ? tmp : post;
+ } else if (0 == strcmp(bp->text, "+") ||
+ 0 == strcmp(bp->text, "-") ||
+ 0 == strcmp(bp->text, "=") ||
+ 0 == strcmp(bp->text, "(") ||
+ 0 == strcmp(bp->text, ")") ||
+ 0 == strcmp(bp->text, "/")) {
+ tmp = print_otag(p, TAG_MO, 0, NULL);
+ print_text(p, bp->text);
+ print_tagq(p, tmp);
+ } else {
+ tmp = print_otag(p, TAG_MI, 0, NULL);
+ print_text(p, bp->text);
+ print_tagq(p, tmp);
+ }
+ } else if (NULL != bp->first) {
+ assert(NULL == bp->text);
+ /*
+ * If we're a "fenced" component (i.e., having
+ * brackets), then process those brackets now.
+ * Otherwise, introduce a dummy row (if we're not
+ * already in a table context).
+ */
+ tmp = NULL;
+ if (NULL != bp->left || NULL != bp->right) {
+ PAIR_INIT(&tag[0], ATTR_OPEN,
+ NULL != bp->left ? bp->left : "");
+ PAIR_INIT(&tag[1], ATTR_CLOSE,
+ NULL != bp->right ? bp->right : "");
+ tmp = print_otag(p, TAG_MFENCED, 2, tag);
+ print_otag(p, TAG_MROW, 0, NULL);
+ } else if (NULL == pilet)
+ tmp = print_otag(p, TAG_MROW, 0, NULL);
+ eqn_box(p, bp->first, 1);
+ if (NULL != tmp)
+ print_tagq(p, tmp);
+ }
- if (bp->first)
- eqn_box(p, bp->first);
+ /*
+ * If a positional context, invoke the "next" context.
+ * This is recursive and will return the end of the recursive
+ * chain of "next" contexts.
+ */
+ if (NULL != post) {
+ bp = eqn_box(p, bp->next, 0);
+ if (skiptwo)
+ bp = eqn_box(p, bp->next, 0);
+ print_tagq(p, post);
+ }
- if (NULL != t)
- print_tagq(p, t);
- if (bp->right)
- print_text(p, bp->right);
+ /*
+ * If we're being piled (either directly, in the table, or
+ * indirectly in a table row), then close that out.
+ */
+ if (NULL != pilet)
+ print_tagq(p, pilet);
- if (bp->next)
- eqn_box(p, bp->next);
+ /*
+ * If we're normally processing, then grab the next node.
+ * If we're in a recursive context, then don't seek to the next
+ * node; further recursion has already been handled.
+ */
+ return(next ? eqn_box(p, bp->next, 1) : bp);
}
diff --git a/usr.bin/mandoc/html.c b/usr.bin/mandoc/html.c
index c5177130d2a..ab0015cbbdd 100644
--- a/usr.bin/mandoc/html.c
+++ b/usr.bin/mandoc/html.c
@@ -1,4 +1,4 @@
-/* $Id: html.c,v 1.42 2014/10/07 18:17:05 schwarze Exp $ */
+/* $Id: html.c,v 1.43 2014/10/09 15:49:09 schwarze Exp $ */
/*
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
@@ -72,6 +72,19 @@ static const struct htmldata htmltags[TAG_MAX] = {
{"code", 0 }, /* TAG_CODE */
{"small", 0 }, /* TAG_SMALL */
{"style", HTML_CLRLINE}, /* TAG_STYLE */
+ {"math", HTML_CLRLINE}, /* TAG_MATH */
+ {"mrow", 0}, /* TAG_MROW */
+ {"mi", 0}, /* TAG_MI */
+ {"mo", 0}, /* TAG_MO */
+ {"msup", 0}, /* TAG_MSUP */
+ {"msub", 0}, /* TAG_MSUB */
+ {"msubsup", 0}, /* TAG_MSUBSUP */
+ {"mfrac", 0}, /* TAG_MFRAC */
+ {"msqrt", 0}, /* TAG_MSQRT */
+ {"mfenced", 0}, /* TAG_MFENCED */
+ {"mtable", 0}, /* TAG_MTABLE */
+ {"mtr", 0}, /* TAG_MTR */
+ {"mtd", 0}, /* TAG_MTD */
};
static const char *const htmlattrs[ATTR_MAX] = {
@@ -85,6 +98,8 @@ static const char *const htmlattrs[ATTR_MAX] = {
"id", /* ATTR_ID */
"colspan", /* ATTR_COLSPAN */
"charset", /* ATTR_CHARSET */
+ "open", /* ATTR_OPEN */
+ "close", /* ATTR_CLOSE */
};
static const char *const roffscales[SCALE_MAX] = {
diff --git a/usr.bin/mandoc/html.h b/usr.bin/mandoc/html.h
index 784992c51dc..f7b97d06f18 100644
--- a/usr.bin/mandoc/html.h
+++ b/usr.bin/mandoc/html.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: html.h,v 1.25 2014/10/07 18:17:05 schwarze Exp $ */
+/* $OpenBSD: html.h,v 1.26 2014/10/09 15:49:09 schwarze Exp $ */
/*
* Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -50,6 +50,19 @@ enum htmltag {
TAG_CODE,
TAG_SMALL,
TAG_STYLE,
+ TAG_MATH,
+ TAG_MROW,
+ TAG_MI,
+ TAG_MO,
+ TAG_MSUP,
+ TAG_MSUB,
+ TAG_MSUBSUP,
+ TAG_MFRAC,
+ TAG_MSQRT,
+ TAG_MFENCED,
+ TAG_MTABLE,
+ TAG_MTR,
+ TAG_MTD,
TAG_MAX
};
@@ -64,6 +77,8 @@ enum htmlattr {
ATTR_ID,
ATTR_COLSPAN,
ATTR_CHARSET,
+ ATTR_OPEN,
+ ATTR_CLOSE,
ATTR_MAX
};