-/* $Id: eqn.c,v 1.77 2017/07/14 18:18:26 schwarze Exp $ */
+/* $Id: eqn.c,v 1.84 2020/01/08 12:16:24 schwarze Exp $ */
/*
* Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2014,2015,2017,2018,2020 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
#include "mandoc_aux.h"
#include "mandoc.h"
#include "roff.h"
+#include "eqn.h"
#include "libmandoc.h"
-#include "libroff.h"
+#include "eqn_parse.h"
#define EQN_NEST_MAX 128 /* maximum nesting of defines */
#define STRNEQ(p1, sz1, p2, sz2) \
MODE_TOK
};
+struct eqn_def {
+ char *key;
+ size_t keysz;
+ char *val;
+ size_t valsz;
+};
+
static struct eqn_box *eqn_box_alloc(struct eqn_node *, struct eqn_box *);
static struct eqn_box *eqn_box_makebinary(struct eqn_node *,
struct eqn_box *);
struct eqn_node *
-eqn_alloc(struct mparse *parse)
+eqn_alloc(void)
{
struct eqn_node *ep;
ep = mandoc_calloc(1, sizeof(*ep));
- ep->parse = parse;
ep->gsize = EQN_DEFSIZE;
return ep;
}
case '"':
quoted = 1;
break;
+ case ' ':
+ case '\t':
+ case '~':
+ case '^':
+ if (quoted)
+ break;
+ ep->start++;
+ continue;
default:
break;
}
ep->end = strchr(ep->start + 1, *ep->start);
ep->start++; /* Skip opening quote. */
if (ep->end == NULL) {
- mandoc_msg(MANDOCERR_ARG_QUOTE, ep->parse,
+ mandoc_msg(MANDOCERR_ARG_QUOTE,
ep->node->line, ep->node->pos, NULL);
ep->end = strchr(ep->start, '\0');
}
if ((def = eqn_def_find(ep)) == NULL)
break;
if (++lim > EQN_NEST_MAX) {
- mandoc_msg(MANDOCERR_ROFFLOOP, ep->parse,
+ mandoc_msg(MANDOCERR_ROFFLOOP,
ep->node->line, ep->node->pos, NULL);
return EQN_TOK_EOF;
}
void
eqn_box_free(struct eqn_box *bp)
{
+ if (bp == NULL)
+ return;
if (bp->first)
eqn_box_free(bp->first);
free(bp);
}
+struct eqn_box *
+eqn_box_new(void)
+{
+ struct eqn_box *bp;
+
+ bp = mandoc_calloc(1, sizeof(*bp));
+ bp->expectargs = UINT_MAX;
+ return bp;
+}
+
/*
* Allocate a box as the last child of the parent node.
*/
{
struct eqn_box *bp;
- bp = mandoc_calloc(1, sizeof(struct eqn_box));
+ bp = eqn_box_new();
bp->parent = parent;
bp->parent->args++;
- bp->expectargs = UINT_MAX;
bp->font = bp->parent->font;
bp->size = ep->gsize;
eqn_delim(struct eqn_node *ep)
{
if (ep->end[0] == '\0' || ep->end[1] == '\0') {
- mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,
+ mandoc_msg(MANDOCERR_REQ_EMPTY,
ep->node->line, ep->node->pos, "delim");
if (ep->end[0] != '\0')
ep->end++;
struct eqn_def *def;
if (eqn_next(ep, MODE_NOSUB) == EQN_TOK_EOF) {
- mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,
+ mandoc_msg(MANDOCERR_REQ_EMPTY,
ep->node->line, ep->node->pos, "undef");
return;
}
int i;
if (eqn_next(ep, MODE_NOSUB) == EQN_TOK_EOF) {
- mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,
+ mandoc_msg(MANDOCERR_REQ_EMPTY,
ep->node->line, ep->node->pos, "define");
return;
}
}
if (eqn_next(ep, MODE_QUOTED) == EQN_TOK_EOF) {
- mandoc_vmsg(MANDOCERR_REQ_EMPTY, ep->parse,
+ mandoc_msg(MANDOCERR_REQ_EMPTY,
ep->node->line, ep->node->pos, "define %s", def->key);
free(def->key);
free(def->val);
if (ep->data == NULL)
return;
- ep->start = ep->end = ep->data + strspn(ep->data, " ^~");
+ ep->start = ep->end = ep->data;
next_tok:
tok = eqn_next(ep, MODE_TOK);
case EQN_TOK_TDEFINE:
if (eqn_next(ep, MODE_NOSUB) == EQN_TOK_EOF ||
eqn_next(ep, MODE_QUOTED) == EQN_TOK_EOF)
- mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,
+ mandoc_msg(MANDOCERR_REQ_EMPTY,
ep->node->line, ep->node->pos, "tdefine");
break;
case EQN_TOK_DELIM:
break;
case EQN_TOK_GFONT:
if (eqn_next(ep, MODE_SUB) == EQN_TOK_EOF)
- mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,
- ep->node->line, ep->node->pos, eqn_toks[tok]);
+ mandoc_msg(MANDOCERR_REQ_EMPTY, ep->node->line,
+ ep->node->pos, "%s", eqn_toks[tok]);
break;
case EQN_TOK_MARK:
case EQN_TOK_LINEUP:
case EQN_TOK_DOT:
case EQN_TOK_DOTDOT:
if (parent->last == NULL) {
- mandoc_msg(MANDOCERR_EQN_NOBOX, ep->parse,
- ep->node->line, ep->node->pos, eqn_toks[tok]);
+ mandoc_msg(MANDOCERR_EQN_NOBOX, ep->node->line,
+ ep->node->pos, "%s", eqn_toks[tok]);
cur = eqn_box_alloc(ep, parent);
cur->type = EQN_TEXT;
cur->text = mandoc_strdup("");
parent->bottom = mandoc_strdup("\\[ul]");
break;
case EQN_TOK_BAR:
- parent->top = mandoc_strdup("\\[rl]");
+ parent->top = mandoc_strdup("\\[rn]");
break;
case EQN_TOK_DOT:
parent->top = mandoc_strdup("\\[a.]");
case EQN_TOK_DOWN:
case EQN_TOK_UP:
if (eqn_next(ep, MODE_SUB) == EQN_TOK_EOF)
- mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,
- ep->node->line, ep->node->pos, eqn_toks[tok]);
+ mandoc_msg(MANDOCERR_REQ_EMPTY, ep->node->line,
+ ep->node->pos, "%s", eqn_toks[tok]);
break;
case EQN_TOK_FAT:
case EQN_TOK_ROMAN:
case EQN_TOK_GSIZE:
/* Accept two values: integral size and a single. */
if (eqn_next(ep, MODE_SUB) == EQN_TOK_EOF) {
- mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,
- ep->node->line, ep->node->pos, eqn_toks[tok]);
+ mandoc_msg(MANDOCERR_REQ_EMPTY, ep->node->line,
+ ep->node->pos, "%s", eqn_toks[tok]);
break;
}
size = mandoc_strntoi(ep->start, ep->toksz, 10);
if (-1 == size) {
- mandoc_msg(MANDOCERR_IT_NONUM, ep->parse,
- ep->node->line, ep->node->pos, eqn_toks[tok]);
+ mandoc_msg(MANDOCERR_IT_NONUM, ep->node->line,
+ ep->node->pos, "%s", eqn_toks[tok]);
break;
}
if (EQN_TOK_GSIZE == tok) {
* and keep on reading.
*/
if (parent->last == NULL) {
- mandoc_msg(MANDOCERR_EQN_NOBOX, ep->parse,
- ep->node->line, ep->node->pos, eqn_toks[tok]);
+ mandoc_msg(MANDOCERR_EQN_NOBOX, ep->node->line,
+ ep->node->pos, "%s", eqn_toks[tok]);
cur = eqn_box_alloc(ep, parent);
cur->type = EQN_TEXT;
cur->text = mandoc_strdup("");
* rebalance and continue reading.
*/
if (parent->last == NULL) {
- mandoc_msg(MANDOCERR_EQN_NOBOX, ep->parse,
- ep->node->line, ep->node->pos, eqn_toks[tok]);
+ mandoc_msg(MANDOCERR_EQN_NOBOX, ep->node->line,
+ ep->node->pos, "%s", eqn_toks[tok]);
cur = eqn_box_alloc(ep, parent);
cur->type = EQN_TEXT;
cur->text = mandoc_strdup("");
cur->left != NULL))
break;
if (cur == NULL) {
- mandoc_msg(MANDOCERR_BLK_NOTOPEN, ep->parse,
- ep->node->line, ep->node->pos, eqn_toks[tok]);
+ mandoc_msg(MANDOCERR_BLK_NOTOPEN, ep->node->line,
+ ep->node->pos, "%s", eqn_toks[tok]);
break;
}
parent = cur;
if (EQN_TOK_RIGHT == tok) {
if (eqn_next(ep, MODE_SUB) == EQN_TOK_EOF) {
mandoc_msg(MANDOCERR_REQ_EMPTY,
- ep->parse, ep->node->line,
- ep->node->pos, eqn_toks[tok]);
+ ep->node->line, ep->node->pos,
+ "%s", eqn_toks[tok]);
break;
}
/* Handling depends on right/left. */
parent = parent->parent;
if (EQN_TOK_LEFT == tok &&
eqn_next(ep, MODE_SUB) == EQN_TOK_EOF) {
- mandoc_msg(MANDOCERR_REQ_EMPTY, ep->parse,
- ep->node->line, ep->node->pos, eqn_toks[tok]);
+ mandoc_msg(MANDOCERR_REQ_EMPTY, ep->node->line,
+ ep->node->pos, "%s", eqn_toks[tok]);
break;
}
parent = eqn_box_alloc(ep, parent);
if (cur->type == EQN_PILE)
break;
if (cur == NULL) {
- mandoc_msg(MANDOCERR_IT_STRAY, ep->parse,
- ep->node->line, ep->node->pos, eqn_toks[tok]);
+ mandoc_msg(MANDOCERR_IT_STRAY, ep->node->line,
+ ep->node->pos, "%s", eqn_toks[tok]);
break;
}
parent = eqn_box_alloc(ep, cur);
{
int i;
+ if (p == NULL)
+ return;
+
for (i = 0; i < (int)p->defsz; i++) {
free(p->defs[i].key);
free(p->defs[i].val);