-/* $Id: eqn.c,v 1.30 2011/07/22 14:59:02 kristaps Exp $ */
+/* $Id: eqn.c,v 1.38 2011/07/25 15:37:00 kristaps Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
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;
const char *sym;
};
-enum eqnpartt {
- EQN_DEFINE = 0,
- EQN_SET,
- EQN_UNDEF,
- EQN_GFONT,
- EQN_GSIZE,
- EQN__MAX
-};
static enum eqn_rest eqn_box(struct eqn_node *, struct eqn_box *);
static struct eqn_box *eqn_box_alloc(struct eqn_node *,
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_set(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 *,
static const struct eqnpart eqnparts[EQN__MAX] = {
{ { "define", 6 }, eqn_do_define }, /* EQN_DEFINE */
- { { "set", 3 }, eqn_do_set }, /* EQN_SET */
+ { { "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 }, /* EQNFONT_NONE */
{ "roman", 5 }, /* EQNFONT_ROMAN */
{ "bold", 4 }, /* EQNFONT_BOLD */
+ { "fat", 3 }, /* EQNFONT_FAT */
{ "italic", 6 }, /* EQNFONT_ITALIC */
};
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] = {
* validate the full equation.
*/
- if (0 == strcmp(p, ".EN")) {
- er = eqn_end(ep);
- *epp = NULL;
+ 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);
}
}
struct eqn_node *
-eqn_alloc(int pos, int line, struct mparse *parse)
+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));
+
+ 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;
}
enum rofferr
-eqn_end(struct eqn_node *ep)
+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;
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)
{
assert(start);
if ( ! STRNEQ(start, sz, "above", 5))
break;
- bp->last->above = 1;
}
if (EQN_DESCOPE != c) {
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);
+ return((*eqnparts[i].fp)(ep) ?
+ EQN_OK : EQN_ERR);
}
if (STRNEQ(start, sz, "{", 1)) {
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);
free(p->defs[i].val);
}
+ free(p->eqn.name);
free(p->data);
free(p->defs);
free(p);
/* Prevent self-definitions. */
if (lim >= EQN_NEST_MAX) {
- EQN_MSG(MANDOCERR_EQNNEST, ep);
+ EQN_MSG(MANDOCERR_ROFFLOOP, ep);
return(NULL);
}
if ('{' == *start || '}' == *start)
ssz = 1;
else
- ssz = strcspn(start + 1, " ~\"{}\t") + 1;
+ ssz = strcspn(start + 1, " ^~\"{}\t") + 1;
next = start + (int)ssz;
if ('\0' == *next)
next = NULL;
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 {
}
static int
-eqn_do_set(struct eqn_node *ep)
+eqn_do_ign1(struct eqn_node *ep)
{
- const char *start;
- if (NULL == (start = eqn_nextrawtok(ep, NULL)))
+ 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 == (start = eqn_nextrawtok(ep, NULL)))
+ else if (NULL == eqn_next(ep, ep->data[(int)ep->cur], NULL, 0))
EQN_MSG(MANDOCERR_EQNEOF, ep);
else
return(1);
static int
eqn_do_gfont(struct eqn_node *ep)
{
- const char *start;
- if (NULL == (start = eqn_nextrawtok(ep, NULL))) {
+ if (NULL == eqn_nextrawtok(ep, NULL)) {
EQN_MSG(MANDOCERR_EQNEOF, ep);
return(0);
}
EQN_MSG(MANDOCERR_EQNEOF, ep);
return(0);
}
-
ep->gsize = mandoc_strntoi(start, sz, 10);
return(1);
}