=================================================================== RCS file: /cvs/mandoc/eqn.c,v retrieving revision 1.55 retrieving revision 1.64 diff -u -p -r1.55 -r1.64 --- mandoc/eqn.c 2014/10/25 14:35:37 1.55 +++ mandoc/eqn.c 2017/06/21 18:04:34 1.64 @@ -1,7 +1,7 @@ -/* $Id: eqn.c,v 1.55 2014/10/25 14:35:37 schwarze Exp $ */ +/* $Id: eqn.c,v 1.64 2017/06/21 18:04:34 schwarze Exp $ */ /* * Copyright (c) 2011, 2014 Kristaps Dzonsons - * Copyright (c) 2014 Ingo Schwarze + * Copyright (c) 2014, 2015, 2017 Ingo Schwarze * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -31,8 +31,6 @@ #include "libmandoc.h" #include "libroff.h" -#define EQN_MSG(t, x) \ - mandoc_msg((t), (x)->parse, (x)->eqn.ln, (x)->eqn.pos, NULL) #define EQN_NEST_MAX 128 /* maximum nesting of defines */ #define STRNEQ(p1, sz1, p2, sz2) \ ((sz1) == (sz2) && 0 == strncmp((p1), (p2), (sz1))) @@ -82,9 +80,10 @@ enum eqn_tok { EQN_TOK_TDEFINE, EQN_TOK_NDEFINE, EQN_TOK_UNDEF, - EQN_TOK_EOF, EQN_TOK_ABOVE, - EQN_TOK__MAX + EQN_TOK__MAX, + EQN_TOK_FUNC, + EQN_TOK_EOF }; static const char *eqn_toks[EQN_TOK__MAX] = { @@ -132,10 +131,16 @@ static const char *eqn_toks[EQN_TOK__MAX] = { "tdefine", /* EQN_TOK_TDEFINE */ "ndefine", /* EQN_TOK_NDEFINE */ "undef", /* EQN_TOK_UNDEF */ - NULL, /* EQN_TOK_EOF */ "above", /* EQN_TOK_ABOVE */ }; +static const char *const eqn_func[] = { + "acos", "acsc", "and", "arc", "asec", "asin", "atan", + "cos", "cosh", "coth", "csc", "det", "exp", "for", + "if", "lim", "ln", "log", "max", "min", + "sec", "sin", "sinh", "tan", "tanh", "Im", "Re", +}; + enum eqn_symt { EQNSYM_alpha, EQNSYM_beta, @@ -196,6 +201,7 @@ enum eqn_symt { EQNSYM_equiv, EQNSYM_lessequal, EQNSYM_moreequal, + EQNSYM_minus, EQNSYM__MAX }; @@ -251,7 +257,7 @@ static const struct eqnsym eqnsyms[EQNSYM__MAX] = { { "cdot", "pc" }, /* EQNSYM_cdot */ { "nothing", "&" }, /* EQNSYM_nothing */ { "approx", "~~" }, /* EQNSYM_approx */ - { "prime", "aq" }, /* EQNSYM_prime */ + { "prime", "fm" }, /* EQNSYM_prime */ { "half", "12" }, /* EQNSYM_half */ { "partial", "pd" }, /* EQNSYM_partial */ { "inf", "if" }, /* EQNSYM_inf */ @@ -264,8 +270,24 @@ static const struct eqnsym eqnsyms[EQNSYM__MAX] = { { "==", "==" }, /* EQNSYM_equiv */ { "<=", "<=" }, /* EQNSYM_lessequal */ { ">=", ">=" }, /* EQNSYM_moreequal */ + { "-", "mi" }, /* EQNSYM_minus */ }; +static struct eqn_box *eqn_box_alloc(struct eqn_node *, struct eqn_box *); +static void eqn_box_free(struct eqn_box *); +static struct eqn_box *eqn_box_makebinary(struct eqn_node *, + enum eqn_post, struct eqn_box *); +static void eqn_def(struct eqn_node *); +static struct eqn_def *eqn_def_find(struct eqn_node *, const char *, size_t); +static void eqn_delim(struct eqn_node *); +static const char *eqn_next(struct eqn_node *, char, size_t *, int); +static const char *eqn_nextrawtok(struct eqn_node *, size_t *); +static const char *eqn_nexttok(struct eqn_node *, size_t *); +static enum rofferr eqn_parse(struct eqn_node *, struct eqn_box *); +static enum eqn_tok eqn_tok_parse(struct eqn_node *, char **); +static void eqn_undef(struct eqn_node *); + + enum rofferr eqn_read(struct eqn_node **epp, int ln, const char *p, int pos, int *offs) @@ -287,10 +309,10 @@ eqn_read(struct eqn_node **epp, int ln, while (' ' == *p || '\t' == *p) p++; if ('\0' == *p) - return(er); + return er; mandoc_vmsg(MANDOCERR_ARG_SKIP, ep->parse, ln, pos, "EN %s", p); - return(er); + return er; } /* @@ -309,7 +331,7 @@ eqn_read(struct eqn_node **epp, int ln, ep->sz += sz; strlcat(ep->data, p + pos, ep->sz + 1); strlcat(ep->data, " ", ep->sz + 1); - return(ROFF_IGN); + return ROFF_IGN; } struct eqn_node * @@ -324,7 +346,7 @@ eqn_alloc(int pos, int line, struct mparse *parse) p->eqn.pos = pos; p->gsize = EQN_DEFSIZE; - return(p); + return p; } /* @@ -338,9 +360,9 @@ eqn_def_find(struct eqn_node *ep, const char *key, siz 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 &ep->defs[i]; - return(NULL); + return NULL; } /* @@ -351,22 +373,27 @@ eqn_def_find(struct eqn_node *ep, const char *key, siz static const char * eqn_next(struct eqn_node *ep, char quote, size_t *sz, int repl) { + static size_t last_len; + static int lim; + char *start, *next; - int q, diff, lim; + int q, diff; size_t ssz, dummy; struct eqn_def *def; if (NULL == sz) sz = &dummy; - lim = 0; + if (ep->cur >= last_len) + lim = 0; ep->rew = ep->cur; again: /* Prevent self-definitions. */ if (lim >= EQN_NEST_MAX) { - EQN_MSG(MANDOCERR_ROFFLOOP, ep); - return(NULL); + mandoc_msg(MANDOCERR_ROFFLOOP, ep->parse, + ep->eqn.ln, ep->eqn.pos, NULL); + return NULL; } ep->cur = ep->rew; @@ -374,7 +401,7 @@ again: q = 0; if ('\0' == *start) - return(NULL); + return NULL; if (quote == *start) { ep->cur++; @@ -406,7 +433,8 @@ again: ep->cur++; } else { if (q) - EQN_MSG(MANDOCERR_ARG_QUOTE, ep); + mandoc_msg(MANDOCERR_ARG_QUOTE, ep->parse, + ep->eqn.ln, ep->eqn.pos, NULL); next = strchr(start, '\0'); *sz = (size_t)(next - start); ep->cur += *sz; @@ -415,7 +443,7 @@ again: /* Quotes aren't expanded for values. */ if (q || ! repl) - return(start); + return start; if (NULL != (def = eqn_def_find(ep, start, *sz))) { diff = def->valsz - *sz; @@ -431,10 +459,12 @@ again: memmove(start + *sz + diff, start + *sz, (strlen(start) - *sz) + 1); memcpy(start, def->val, def->valsz); + last_len = start - ep->data + def->valsz; + lim++; goto again; } - return(start); + return start; } /* @@ -445,7 +475,7 @@ static const char * eqn_nexttok(struct eqn_node *ep, size_t *sz) { - return(eqn_next(ep, '"', sz, 1)); + return eqn_next(ep, '"', sz, 1); } /* @@ -455,7 +485,7 @@ static const char * eqn_nextrawtok(struct eqn_node *ep, size_t *sz) { - return(eqn_next(ep, '"', sz, 0)); + return eqn_next(ep, '"', sz, 0); } /* @@ -475,31 +505,32 @@ eqn_tok_parse(struct eqn_node *ep, char **p) size_t i, sz; int quoted; - if (NULL != p) + if (p != NULL) *p = NULL; quoted = ep->data[ep->cur] == '"'; - if (NULL == (start = eqn_nexttok(ep, &sz))) - return(EQN_TOK_EOF); + if ((start = eqn_nexttok(ep, &sz)) == NULL) + return EQN_TOK_EOF; if (quoted) { if (p != NULL) *p = mandoc_strndup(start, sz); - return(EQN_TOK__MAX); + return EQN_TOK__MAX; } - for (i = 0; i < EQN_TOK__MAX; i++) { - if (NULL == eqn_toks[i]) - continue; + for (i = 0; i < EQN_TOK__MAX; i++) if (STRNEQ(start, sz, eqn_toks[i], strlen(eqn_toks[i]))) - break; - } + return i; - if (i == EQN_TOK__MAX && NULL != p) + if (p != NULL) *p = mandoc_strndup(start, sz); - return(i); + for (i = 0; i < sizeof(eqn_func)/sizeof(*eqn_func); i++) + if (STRNEQ(start, sz, eqn_func[i], strlen(eqn_func[i]))) + return EQN_TOK_FUNC; + + return EQN_TOK__MAX; } static void @@ -540,7 +571,7 @@ eqn_box_alloc(struct eqn_node *ep, struct eqn_box *par parent->first = bp; parent->last = bp; - return(bp); + return bp; } /* @@ -570,7 +601,7 @@ eqn_box_makebinary(struct eqn_node *ep, newb->first = newb->last = b; newb->first->next = NULL; b->parent = newb; - return(newb); + return newb; } /* @@ -600,23 +631,27 @@ eqn_delim(struct eqn_node *ep) /* * Undefine a previously-defined string. */ -static int +static void eqn_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); + if ((start = eqn_nextrawtok(ep, &sz)) == NULL) { + mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse, + ep->eqn.ln, ep->eqn.pos, "undef"); + return; + } + if ((def = eqn_def_find(ep, start, sz)) == NULL) + return; + free(def->key); + free(def->val); + def->key = def->val = NULL; + def->keysz = def->valsz = 0; } -static int +static void eqn_def(struct eqn_node *ep) { const char *start; @@ -624,9 +659,10 @@ eqn_def(struct eqn_node *ep) struct eqn_def *def; int i; - if (NULL == (start = eqn_nextrawtok(ep, &sz))) { - EQN_MSG(MANDOCERR_EQNEOF, ep); - return(0); + if ((start = eqn_nextrawtok(ep, &sz)) == NULL) { + mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse, + ep->eqn.ln, ep->eqn.pos, "define"); + return; } /* @@ -646,87 +682,90 @@ eqn_def(struct eqn_node *ep) 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]; + def = ep->defs + i; + free(def->key); + def->key = mandoc_strndup(start, sz); + def->keysz = sz; } start = eqn_next(ep, ep->data[(int)ep->cur], &sz, 0); - - if (NULL == start) { - EQN_MSG(MANDOCERR_EQNEOF, ep); - return(-1); + if (start == NULL) { + mandoc_vmsg(MANDOCERR_REQ_EMPTY, ep->parse, + ep->eqn.ln, ep->eqn.pos, "define %s", def->key); + free(def->key); + free(def->val); + def->key = def->val = NULL; + def->keysz = def->valsz = 0; + return; } - + free(def->val); + def->val = mandoc_strndup(start, sz); def->valsz = sz; - def->val = mandoc_realloc(def->val, sz + 1); - memcpy(def->val, start, sz); - def->val[(int)sz] = '\0'; - return(1); } /* * Recursively parse an eqn(7) expression. */ -static int +static enum rofferr eqn_parse(struct eqn_node *ep, struct eqn_box *parent) { + char sym[64]; + struct eqn_box *cur; + const char *start; char *p; + size_t i, sz; enum eqn_tok tok, subtok; enum eqn_post pos; - struct eqn_box *cur; - int rc, size; - size_t i, sz; - char sym[64]; - const char *start; + int size; - assert(NULL != parent); + assert(parent != NULL); + /* + * Empty equation. + * Do not add it to the high-level syntax tree. + */ + + if (ep->data == NULL) + return ROFF_IGN; + next_tok: tok = eqn_tok_parse(ep, &p); this_tok: switch (tok) { - case (EQN_TOK_UNDEF): - if ((rc = eqn_undef(ep)) <= 0) - return(rc); + case EQN_TOK_UNDEF: + eqn_undef(ep); break; - case (EQN_TOK_NDEFINE): - case (EQN_TOK_DEFINE): - if ((rc = eqn_def(ep)) <= 0) - return(rc); + case EQN_TOK_NDEFINE: + case EQN_TOK_DEFINE: + eqn_def(ep); break; - case (EQN_TOK_TDEFINE): - 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); + case EQN_TOK_TDEFINE: + if (eqn_nextrawtok(ep, NULL) == NULL || + eqn_next(ep, ep->data[(int)ep->cur], NULL, 0) == NULL) + mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse, + ep->eqn.ln, ep->eqn.pos, "tdefine"); break; - case (EQN_TOK_DELIM): + case EQN_TOK_DELIM: eqn_delim(ep); break; - case (EQN_TOK_GFONT): + case EQN_TOK_GFONT: if (eqn_nextrawtok(ep, NULL) == NULL) mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse, ep->eqn.ln, ep->eqn.pos, eqn_toks[tok]); break; - case (EQN_TOK_MARK): - case (EQN_TOK_LINEUP): + case EQN_TOK_MARK: + case EQN_TOK_LINEUP: /* Ignore these. */ break; - case (EQN_TOK_DYAD): - case (EQN_TOK_VEC): - case (EQN_TOK_UNDER): - case (EQN_TOK_BAR): - case (EQN_TOK_TILDE): - case (EQN_TOK_HAT): - case (EQN_TOK_DOT): - case (EQN_TOK_DOTDOT): + case EQN_TOK_DYAD: + case EQN_TOK_VEC: + case EQN_TOK_UNDER: + case EQN_TOK_BAR: + case EQN_TOK_TILDE: + case EQN_TOK_HAT: + case EQN_TOK_DOT: + case EQN_TOK_DOTDOT: if (parent->last == NULL) { mandoc_msg(MANDOCERR_EQN_NOBOX, ep->parse, ep->eqn.ln, ep->eqn.pos, eqn_toks[tok]); @@ -738,28 +777,28 @@ this_tok: parent->type = EQN_LISTONE; parent->expectargs = 1; switch (tok) { - case (EQN_TOK_DOTDOT): + case EQN_TOK_DOTDOT: strlcpy(sym, "\\[ad]", sizeof(sym)); break; - case (EQN_TOK_VEC): + case EQN_TOK_VEC: strlcpy(sym, "\\[->]", sizeof(sym)); break; - case (EQN_TOK_DYAD): + case EQN_TOK_DYAD: strlcpy(sym, "\\[<>]", sizeof(sym)); break; - case (EQN_TOK_TILDE): + case EQN_TOK_TILDE: strlcpy(sym, "\\[a~]", sizeof(sym)); break; - case (EQN_TOK_UNDER): + case EQN_TOK_UNDER: strlcpy(sym, "\\[ul]", sizeof(sym)); break; - case (EQN_TOK_BAR): + case EQN_TOK_BAR: strlcpy(sym, "\\[rl]", sizeof(sym)); break; - case (EQN_TOK_DOT): + case EQN_TOK_DOT: strlcpy(sym, "\\[a.]", sizeof(sym)); break; - case (EQN_TOK_HAT): + case EQN_TOK_HAT: strlcpy(sym, "\\[ha]", sizeof(sym)); break; default: @@ -767,16 +806,16 @@ this_tok: } switch (tok) { - case (EQN_TOK_DOTDOT): - case (EQN_TOK_VEC): - case (EQN_TOK_DYAD): - case (EQN_TOK_TILDE): - case (EQN_TOK_BAR): - case (EQN_TOK_DOT): - case (EQN_TOK_HAT): + case EQN_TOK_DOTDOT: + case EQN_TOK_VEC: + case EQN_TOK_DYAD: + case EQN_TOK_TILDE: + case EQN_TOK_BAR: + case EQN_TOK_DOT: + case EQN_TOK_HAT: parent->top = mandoc_strdup(sym); break; - case (EQN_TOK_UNDER): + case EQN_TOK_UNDER: parent->bottom = mandoc_strdup(sym); break; default: @@ -784,10 +823,10 @@ this_tok: } parent = parent->parent; break; - case (EQN_TOK_FWD): - case (EQN_TOK_BACK): - case (EQN_TOK_DOWN): - case (EQN_TOK_UP): + case EQN_TOK_FWD: + case EQN_TOK_BACK: + case EQN_TOK_DOWN: + case EQN_TOK_UP: subtok = eqn_tok_parse(ep, NULL); if (subtok != EQN_TOK__MAX) { mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse, @@ -796,10 +835,10 @@ this_tok: goto this_tok; } break; - case (EQN_TOK_FAT): - case (EQN_TOK_ROMAN): - case (EQN_TOK_ITALIC): - case (EQN_TOK_BOLD): + case EQN_TOK_FAT: + case EQN_TOK_ROMAN: + case EQN_TOK_ITALIC: + case EQN_TOK_BOLD: while (parent->args == parent->expectargs) parent = parent->parent; /* @@ -811,24 +850,24 @@ this_tok: parent->type = EQN_LISTONE; parent->expectargs = 1; switch (tok) { - case (EQN_TOK_FAT): + case EQN_TOK_FAT: parent->font = EQNFONT_FAT; break; - case (EQN_TOK_ROMAN): + case EQN_TOK_ROMAN: parent->font = EQNFONT_ROMAN; break; - case (EQN_TOK_ITALIC): + case EQN_TOK_ITALIC: parent->font = EQNFONT_ITALIC; break; - case (EQN_TOK_BOLD): + case EQN_TOK_BOLD: parent->font = EQNFONT_BOLD; break; default: abort(); } break; - case (EQN_TOK_SIZE): - case (EQN_TOK_GSIZE): + case EQN_TOK_SIZE: + case EQN_TOK_GSIZE: /* Accept two values: integral size and a single. */ if (NULL == (start = eqn_nexttok(ep, &sz))) { mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse, @@ -850,10 +889,10 @@ this_tok: parent->expectargs = 1; parent->size = size; break; - case (EQN_TOK_FROM): - case (EQN_TOK_TO): - case (EQN_TOK_SUB): - case (EQN_TOK_SUP): + case EQN_TOK_FROM: + case EQN_TOK_TO: + case EQN_TOK_SUB: + case EQN_TOK_SUP: /* * We have a left-right-associative expression. * Repivot under a positional node, open a child scope @@ -878,16 +917,16 @@ this_tok: break; } switch (tok) { - case (EQN_TOK_FROM): + case EQN_TOK_FROM: pos = EQNPOS_FROM; break; - case (EQN_TOK_TO): + case EQN_TOK_TO: pos = EQNPOS_TO; break; - case (EQN_TOK_SUP): + case EQN_TOK_SUP: pos = EQNPOS_SUP; break; - case (EQN_TOK_SUB): + case EQN_TOK_SUB: pos = EQNPOS_SUB; break; default: @@ -895,7 +934,7 @@ this_tok: } parent = eqn_box_makebinary(ep, pos, parent); break; - case (EQN_TOK_SQRT): + case EQN_TOK_SQRT: while (parent->args == parent->expectargs) parent = parent->parent; /* @@ -908,7 +947,7 @@ this_tok: parent->pos = EQNPOS_SQRT; parent->expectargs = 1; break; - case (EQN_TOK_OVER): + case EQN_TOK_OVER: /* * We have a right-left-associative fraction. * Close out anything that's currently open, then @@ -925,8 +964,8 @@ this_tok: parent = parent->parent; parent = eqn_box_makebinary(ep, EQNPOS_OVER, parent); break; - case (EQN_TOK_RIGHT): - case (EQN_TOK_BRACE_CLOSE): + case EQN_TOK_RIGHT: + case EQN_TOK_BRACE_CLOSE: /* * Close out the existing brace. * FIXME: this is a shitty sentinel: we should really @@ -961,7 +1000,7 @@ this_tok: parent->right = mandoc_strndup(start, sz); } parent = parent->parent; - if (EQN_TOK_BRACE_CLOSE == tok && parent && + if (tok == EQN_TOK_BRACE_CLOSE && (parent->type == EQN_PILE || parent->type == EQN_MATRIX)) parent = parent->parent; @@ -970,8 +1009,8 @@ this_tok: parent->args == parent->expectargs) parent = parent->parent; break; - case (EQN_TOK_BRACE_OPEN): - case (EQN_TOK_LEFT): + case EQN_TOK_BRACE_OPEN: + case EQN_TOK_LEFT: /* * If we already have something in the stack and we're * in an expression, then rewind til we're not any more @@ -998,20 +1037,20 @@ this_tok: parent->left = mandoc_strndup(start, sz); } break; - case (EQN_TOK_PILE): - case (EQN_TOK_LPILE): - case (EQN_TOK_RPILE): - case (EQN_TOK_CPILE): - case (EQN_TOK_CCOL): - case (EQN_TOK_LCOL): - case (EQN_TOK_RCOL): + case EQN_TOK_PILE: + case EQN_TOK_LPILE: + case EQN_TOK_RPILE: + case EQN_TOK_CPILE: + case EQN_TOK_CCOL: + case EQN_TOK_LCOL: + case EQN_TOK_RCOL: while (parent->args == parent->expectargs) parent = parent->parent; parent = eqn_box_alloc(ep, parent); parent->type = EQN_PILE; parent->expectargs = 1; break; - case (EQN_TOK_ABOVE): + case EQN_TOK_ABOVE: for (cur = parent; cur != NULL; cur = cur->parent) if (cur->type == EQN_PILE) break; @@ -1023,28 +1062,39 @@ this_tok: parent = eqn_box_alloc(ep, cur); parent->type = EQN_LIST; break; - case (EQN_TOK_MATRIX): + case EQN_TOK_MATRIX: while (parent->args == parent->expectargs) parent = parent->parent; parent = eqn_box_alloc(ep, parent); parent->type = EQN_MATRIX; parent->expectargs = 1; break; - case (EQN_TOK_EOF): + case EQN_TOK_EOF: /* * End of file! * TODO: make sure we're not in an open subexpression. */ - return(0); - default: - assert(tok == EQN_TOK__MAX); - assert(NULL != p); + return ROFF_EQN; + case EQN_TOK_FUNC: + case EQN_TOK__MAX: + assert(p != NULL); /* * If we already have something in the stack and we're * in an expression, then rewind til we're not any more. */ while (parent->args == parent->expectargs) parent = parent->parent; + if (tok == EQN_TOK_FUNC) { + for (cur = parent; cur != NULL; cur = cur->parent) + if (cur->font != EQNFONT_NONE) + break; + if (cur == NULL || cur->font != EQNFONT_ROMAN) { + parent = eqn_box_alloc(ep, parent); + parent->type = EQN_LISTONE; + parent->font = EQNFONT_ROMAN; + parent->expectargs = 1; + } + } cur = eqn_box_alloc(ep, parent); cur->type = EQN_TEXT; for (i = 0; i < EQNSYM__MAX; i++) @@ -1065,6 +1115,8 @@ this_tok: parent->args == parent->expectargs) parent = parent->parent; break; + default: + abort(); } goto next_tok; } @@ -1079,7 +1131,7 @@ eqn_end(struct eqn_node **epp) ep->eqn.root = mandoc_calloc(1, sizeof(struct eqn_box)); ep->eqn.root->expectargs = UINT_MAX; - return(0 == eqn_parse(ep, ep->eqn.root) ? ROFF_EQN : ROFF_IGN); + return eqn_parse(ep, ep->eqn.root); } void