Beispiel #1
0
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);
}
Beispiel #2
0
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);
}
Beispiel #3
0
void
term_eqn(struct termp *p, const struct eqn_box *bp)
{

	eqn_box(p, bp);
	p->flags &= ~TERMP_NOSPACE;
}
Beispiel #4
0
void
term_eqn(struct termp *p, const struct eqn *ep)
{

	eqn_box(p, ep->root);
	p->flags &= ~TERMP_NOSPACE;
}
Beispiel #5
0
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;
}
Beispiel #6
0
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;

	while (EQN_OK == (c = eqn_box(ep, bp)))
		/* Spin! */ ;

	return(c);
}
Beispiel #7
0
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_MATH, 1, &tag);

	p->flags |= HTML_NONOSPACE;
	eqn_box(p, ep->root);
	p->flags &= ~HTML_NONOSPACE;

	print_tagq(p, t);
}
Beispiel #8
0
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);
}
Beispiel #9
0
static void
eqn_box(struct html *p, const struct eqn_box *bp)
{
	struct tag	*post, *row, *cell, *t;
	struct htmlpair	 tag[2];
	const struct eqn_box *child, *parent;
	size_t		 i, j, rows;

	if (NULL == bp)
		return;

	post = NULL;

	/*
	 * Special handling for a matrix, which is presented to us in
	 * column order, but must be printed in row-order.
	 */
	if (EQN_MATRIX == bp->type) {
		if (NULL == bp->first)
			goto out;
		if (EQN_LIST != bp->first->type) {
			eqn_box(p, bp->first);
			goto out;
		}
		if (NULL == (parent = bp->first->first))
			goto out;
		/* Estimate the number of rows, first. */
		if (NULL == (child = parent->first))
			goto out;
		for (rows = 0; NULL != child; rows++)
			child = child->next;
		/* Print row-by-row. */
		post = print_otag(p, TAG_MTABLE, 0, NULL);
		for (i = 0; i < rows; i++) {
			parent = bp->first->first;
			row = print_otag(p, TAG_MTR, 0, NULL);
			while (NULL != parent) {
				child = parent->first;
				for (j = 0; j < i; j++) {
					if (NULL == child)
						break;
					child = child->next;
				}
				cell = print_otag
					(p, TAG_MTD, 0, NULL);
				/*
				 * If we have no data for this
				 * particular cell, then print a
				 * placeholder and continue--don't puke.
				 */
				if (NULL != child)
					eqn_box(p, child->first);
				print_tagq(p, cell);
				parent = parent->next;
			}
			print_tagq(p, row);
		}
		goto out;
	}

	switch (bp->pos) {
	case (EQNPOS_TO):
		post = print_otag(p, TAG_MOVER, 0, NULL);
		break;
	case (EQNPOS_SUP):
		post = print_otag(p, TAG_MSUP, 0, NULL);
		break;
	case (EQNPOS_FROM):
		post = print_otag(p, TAG_MUNDER, 0, NULL);
		break;
	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_FROMTO):
		post = print_otag(p, TAG_MUNDEROVER, 0, NULL);
		break;
	case (EQNPOS_SUBSUP):
		post = print_otag(p, TAG_MSUBSUP, 0, NULL);
		break;
	case (EQNPOS_SQRT):
		post = print_otag(p, TAG_MSQRT, 0, NULL);
		break;
	default:
		break;
	}

	if (bp->top || bp->bottom) {
		assert(NULL == post);
		if (bp->top && NULL == bp->bottom)
			post = print_otag(p, TAG_MOVER, 0, NULL);
		else if (bp->top && bp->bottom)
			post = print_otag(p, TAG_MUNDEROVER, 0, NULL);
		else if (bp->bottom)
			post = print_otag(p, TAG_MUNDER, 0, NULL);
	}

	if (EQN_PILE == bp->type) {
		assert(NULL == post);
		if (bp->first != NULL && bp->first->type == EQN_LIST)
			post = print_otag(p, TAG_MTABLE, 0, NULL);
	} else if (bp->type == EQN_LIST &&
	    bp->parent && bp->parent->type == EQN_PILE) {
		assert(NULL == post);
		post = print_otag(p, TAG_MTR, 0, NULL);
		print_otag(p, TAG_MTD, 0, NULL);
	}

	if (NULL != bp->text) {
		assert(NULL == post);
		post = print_otag(p, TAG_MI, 0, NULL);
		print_text(p, bp->text);
	} else if (NULL == post) {
		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);
			post = print_otag(p, TAG_MFENCED, 2, tag);
		}
		if (NULL == post)
			post = print_otag(p, TAG_MROW, 0, NULL);
		else
			print_otag(p, TAG_MROW, 0, NULL);
	}

	eqn_box(p, bp->first);

out:
	if (NULL != bp->bottom) {
		t = print_otag(p, TAG_MO, 0, NULL);
		print_text(p, bp->bottom);
		print_tagq(p, t);
	}
	if (NULL != bp->top) {
		t = print_otag(p, TAG_MO, 0, NULL);
		print_text(p, bp->top);
		print_tagq(p, t);
	}

	if (NULL != post)
		print_tagq(p, post);

	eqn_box(p, bp->next);
}
Beispiel #10
0
static void
eqn_box(struct termp *p, const struct eqn_box *bp)
{
	const struct eqn_box *child;
	const char *cp;
	int delim;

	/* Delimiters around this box? */

	if ((bp->type == EQN_LIST && bp->expectargs > 1) ||
	    (bp->type == EQN_PILE && (bp->prev || bp->next)) ||
	    (bp->parent != NULL && (bp->parent->pos == EQNPOS_SQRT ||
	    /* Diacritic followed by ^ or _. */
	    ((bp->top != NULL || bp->bottom != NULL) &&
	     bp->parent->type == EQN_SUBEXPR &&
	     bp->parent->pos != EQNPOS_OVER && bp->next != NULL) ||
	    /* Nested over, sub, sup, from, to. */
	    (bp->type == EQN_SUBEXPR && bp->pos != EQNPOS_SQRT &&
	     ((bp->parent->type == EQN_LIST && bp->expectargs == 1) ||
	      (bp->parent->type == EQN_SUBEXPR &&
	       bp->pos != EQNPOS_SQRT)))))) {
		if ((bp->parent->type == EQN_SUBEXPR && bp->prev != NULL) ||
		    (bp->type == EQN_LIST &&
		     bp->first != NULL &&
		     bp->first->type != EQN_PILE &&
		     bp->first->type != EQN_MATRIX &&
		     bp->prev != NULL &&
		     (bp->prev->type == EQN_LIST ||
		      (bp->prev->type == EQN_TEXT &&
		       (*bp->prev->text == '\\' ||
		        isalpha((unsigned char)*bp->prev->text))))))
			p->flags |= TERMP_NOSPACE;
		term_word(p, bp->left != NULL ? bp->left : "(");
		p->flags |= TERMP_NOSPACE;
		delim = 1;
	} else
		delim = 0;

	/* Handle Fonts and text. */

	if (bp->font != EQNFONT_NONE)
		term_fontpush(p, fontmap[(int)bp->font]);

	if (bp->text != NULL) {
		if (strchr("!\"'),.:;?]}", *bp->text) != NULL)
			p->flags |= TERMP_NOSPACE;
		term_word(p, bp->text);
		if ((cp = strchr(bp->text, '\0')) > bp->text &&
		    (strchr("\"'([{", cp[-1]) != NULL ||
		     (bp->prev == NULL && (cp[-1] == '-' ||
		      (cp >= bp->text + 5 &&
		       strcmp(cp - 5, "\\[mi]") == 0)))))
			p->flags |= TERMP_NOSPACE;
	}

	/* Special box types. */

	if (bp->pos == EQNPOS_SQRT) {
		term_word(p, "\\(sr");
		if (bp->first != NULL) {
			p->flags |= TERMP_NOSPACE;
			eqn_box(p, bp->first);
		}
	} else if (bp->type == EQN_SUBEXPR) {
		child = bp->first;
		eqn_box(p, child);
		p->flags |= TERMP_NOSPACE;
		term_word(p, bp->pos == EQNPOS_OVER ? "/" :
		    (bp->pos == EQNPOS_SUP ||
		     bp->pos == EQNPOS_TO) ? "^" : "_");
		child = child->next;
		if (child != NULL) {
			p->flags |= TERMP_NOSPACE;
			eqn_box(p, child);
			if (bp->pos == EQNPOS_FROMTO ||
			    bp->pos == EQNPOS_SUBSUP) {
				p->flags |= TERMP_NOSPACE;
				term_word(p, "^");
				p->flags |= TERMP_NOSPACE;
				child = child->next;
				if (child != NULL)
					eqn_box(p, child);
			}
		}
	} else {
		child = bp->first;
		if (bp->type == EQN_MATRIX &&
		    child != NULL &&
		    child->type == EQN_LIST &&
		    child->expectargs > 1)
			child = child->first;
		while (child != NULL) {
			eqn_box(p,
			    bp->type == EQN_PILE &&
			    child->type == EQN_LIST &&
			    child->expectargs > 1 &&
			    child->args == 1 ?
			    child->first : child);
			child = child->next;
		}
	}

	/* Handle Fonts and diacritics. */

	if (bp->font != EQNFONT_NONE)
		term_fontpop(p);
	if (bp->top != NULL) {
		p->flags |= TERMP_NOSPACE;
		term_word(p, bp->top);
	}
	if (bp->bottom != NULL) {
		p->flags |= TERMP_NOSPACE;
		term_word(p, "_");
	}

	/* Right delimiter after this box? */

	if (delim) {
		p->flags |= TERMP_NOSPACE;
		term_word(p, bp->right != NULL ? bp->right : ")");
		if (bp->parent->type == EQN_SUBEXPR && bp->next != NULL)
			p->flags |= TERMP_NOSPACE;
	}
}
Beispiel #11
0
static void
eqn_box(struct termp *p, const struct eqn_box *bp)
{
	const struct eqn_box *child;

	if (bp->type == EQN_LIST ||
	    (bp->type == EQN_PILE && (bp->prev || bp->next)) ||
	    (bp->parent != NULL && bp->parent->pos == EQNPOS_SQRT)) {
		if (bp->parent->type == EQN_SUBEXPR && bp->prev != NULL)
			p->flags |= TERMP_NOSPACE;
		term_word(p, bp->left != NULL ? bp->left : "(");
		p->flags |= TERMP_NOSPACE;
	}
	if (bp->font != EQNFONT_NONE)
		term_fontpush(p, fontmap[(int)bp->font]);

	if (bp->text != NULL)
		term_word(p, bp->text);

	if (bp->pos == EQNPOS_SQRT) {
		term_word(p, "sqrt");
		p->flags |= TERMP_NOSPACE;
		eqn_box(p, bp->first);
	} else if (bp->type == EQN_SUBEXPR) {
		child = bp->first;
		eqn_box(p, child);
		p->flags |= TERMP_NOSPACE;
		term_word(p, bp->pos == EQNPOS_OVER ? "/" :
		    (bp->pos == EQNPOS_SUP ||
		     bp->pos == EQNPOS_TO) ? "^" : "_");
		p->flags |= TERMP_NOSPACE;
		child = child->next;
		eqn_box(p, child);
		if (bp->pos == EQNPOS_FROMTO ||
		    bp->pos == EQNPOS_SUBSUP) {
			p->flags |= TERMP_NOSPACE;
			term_word(p, "^");
			p->flags |= TERMP_NOSPACE;
			child = child->next;
			eqn_box(p, child);
		}
	} else {
		child = bp->first;
		if (bp->type == EQN_MATRIX && child->type == EQN_LIST)
			child = child->first;
		while (child != NULL) {
			eqn_box(p,
			    bp->type == EQN_PILE &&
			    child->type == EQN_LIST &&
			    child->args == 1 ?
			    child->first : child);
			child = child->next;
		}
	}

	if (bp->font != EQNFONT_NONE)
		term_fontpop(p);
	if (bp->type == EQN_LIST ||
	    (bp->type == EQN_PILE && (bp->prev || bp->next)) ||
	    (bp->parent != NULL && bp->parent->pos == EQNPOS_SQRT)) {
		p->flags |= TERMP_NOSPACE;
		term_word(p, bp->right != NULL ? bp->right : ")");
		if (bp->parent->type == EQN_SUBEXPR && bp->next != NULL)
			p->flags |= TERMP_NOSPACE;
	}

	if (bp->top != NULL) {
		p->flags |= TERMP_NOSPACE;
		term_word(p, bp->top);
	}
	if (bp->bottom != NULL) {
		p->flags |= TERMP_NOSPACE;
		term_word(p, "_");
	}
}
Beispiel #12
0
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);
}