* mdocml: Provide implementations of `define', `set', and `unset'.
@ 2011-07-17 14:08 kristaps
0 siblings, 0 replies; only message in thread
From: kristaps @ 2011-07-17 14:08 UTC (permalink / raw)
To: source
Log Message:
-----------
Provide implementations of `define', `set', and `unset'.
Tie them into the stream of data.
Document these appropriate, bringing in the grammar as defined by the
original eqn manual (Kernighan/Richie).
Modified Files:
--------------
mdocml:
eqn.7
eqn.c
mandoc.h
read.c
Revision Data
-------------
Index: eqn.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/eqn.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -Leqn.c -Leqn.c -u -p -r1.7 -r1.8
--- eqn.c
+++ eqn.c
@@ -28,18 +28,46 @@
#include "libmandoc.h"
#include "libroff.h"
-static const char *eqn_nexttok(struct mparse *, int, int,
+#define EQN_ARGS struct eqn_node *ep, \
+ int ln, \
+ int pos, \
+ const char **end
+
+struct eqnpart {
+ const char *name;
+ size_t sz;
+ int (*fp)(EQN_ARGS);
+};
+
+enum eqnpartt {
+ EQN_DEFINE = 0,
+ EQN_SET,
+ EQN_UNDEF,
+ EQN__MAX
+};
+
+static int eqn_do_define(EQN_ARGS);
+static int eqn_do_set(EQN_ARGS);
+static int eqn_do_undef(EQN_ARGS);
+static const char *eqn_nexttok(struct mparse *, int, int,
const char **, size_t *);
+static const struct eqnpart eqnparts[EQN__MAX] = {
+ { "define", 6, eqn_do_define }, /* EQN_DEFINE */
+ { "set", 3, eqn_do_set }, /* EQN_SET */
+ { "undef", 5, eqn_do_undef }, /* EQN_UNDEF */
+};
+
/* ARGSUSED */
enum rofferr
eqn_read(struct eqn_node **epp, int ln,
const char *p, int pos, int *offs)
{
- size_t sz;
- struct eqn_node *ep;
- const char *start, *end;
- int i;
+ size_t sz;
+ struct eqn_node *ep;
+ struct mparse *mp;
+ const char *start, *end;
+ int i, c;
if (0 == strcmp(p, ".EN")) {
*epp = NULL;
@@ -47,70 +75,59 @@ eqn_read(struct eqn_node **epp, int ln,
}
ep = *epp;
+ mp = ep->parse;
end = p + pos;
- start = eqn_nexttok(ep->parse, ln, pos, &end, &sz);
- if (NULL == start)
+ if (NULL == (start = eqn_nexttok(mp, ln, pos, &end, &sz)))
return(ROFF_IGN);
- if (6 == sz && 0 == strncmp("define", start, 6)) {
- if (end && '"' == *end)
- mandoc_msg(MANDOCERR_EQNQUOTE,
- ep->parse, ln, pos, NULL);
-
- start = eqn_nexttok(ep->parse, ln, pos, &end, &sz);
-
- for (i = 0; i < (int)ep->defsz; i++) {
- if (ep->defs[i].keysz != sz)
- continue;
- if (0 == strncmp(ep->defs[i].key, start, sz))
- break;
- }
+ for (i = 0; i < (int)EQN__MAX; i++) {
+ if (eqnparts[i].sz != sz)
+ continue;
+ if (strncmp(eqnparts[i].name, start, sz))
+ continue;
+
+ if ((c = (*eqnparts[i].fp)(ep, ln, pos, &end)) < 0)
+ return(ROFF_ERR);
+ else if (0 == c || '\0' == *end)
+ return(ROFF_IGN);
- /*
- * TODO: merge this code with roff_getstr().
+ /*
+ * Re-calculate offset and rerun, if trailing text.
+ * This allows multiple definitions (say) on each line.
*/
- if (i == (int)ep->defsz) {
- ep->defsz++;
- ep->defs = mandoc_realloc
- (ep->defs, ep->defsz *
- sizeof(struct eqn_def));
- ep->defs[i].keysz = sz;
- ep->defs[i].key = mandoc_malloc(sz + 1);
- memcpy(ep->defs[i].key, start, sz);
- ep->defs[i].key[(int)sz] = '\0';
- ep->defs[i].val = NULL;
- ep->defs[i].valsz = 0;
- }
-
- start = eqn_nexttok(ep->parse, ln, pos, &end, &sz);
-
- ep->defs[i].valsz = sz;
- ep->defs[i].val = mandoc_realloc
- (ep->defs[i].val, sz + 1);
- memcpy(ep->defs[i].val, start, sz);
- ep->defs[i].val[(int)sz] = '\0';
+ *offs = end - (p + pos);
+ return(ROFF_RERUN);
+ }
- if ('\0' == *end)
- return(ROFF_IGN);
+ end = p + pos;
+ while (NULL != (start = eqn_nexttok(mp, ln, pos, &end, &sz))) {
+ if (0 == sz)
+ continue;
- *offs = end - (p + pos);
- assert(*offs > 0);
+ for (i = 0; i < (int)ep->defsz; i++) {
+ if (0 == ep->defs[i].keysz)
+ continue;
+ if (ep->defs[i].keysz != sz)
+ continue;
+ if (strncmp(ep->defs[i].key, start, sz))
+ continue;
+ start = ep->defs[i].val;
+ sz = ep->defs[i].valsz;
+ break;
+ }
- return(ROFF_RERUN);
- } else
- end = p + pos;
+ ep->eqn.data = mandoc_realloc
+ (ep->eqn.data, ep->eqn.sz + sz + 1);
- if (0 == (sz = strlen(end)))
- return(ROFF_IGN);
+ if (0 == ep->eqn.sz)
+ *ep->eqn.data = '\0';
- ep->eqn.data = mandoc_realloc(ep->eqn.data, ep->eqn.sz + sz + 1);
- if (0 == ep->eqn.sz)
- *ep->eqn.data = '\0';
+ ep->eqn.sz += sz;
+ strlcat(ep->eqn.data, start, ep->eqn.sz + 1);
+ }
- ep->eqn.sz += sz;
- strlcat(ep->eqn.data, end, ep->eqn.sz + 1);
return(ROFF_IGN);
}
@@ -197,4 +214,128 @@ eqn_nexttok(struct mparse *mp, int ln, i
}
return(start);
+}
+
+static int
+eqn_do_set(struct eqn_node *ep, int ln, int pos, const char **end)
+{
+ const char *start;
+ struct mparse *mp;
+ size_t sz;
+
+ mp = ep->parse;
+
+ start = eqn_nexttok(ep->parse, ln, pos, end, &sz);
+ if (NULL == start || 0 == sz) {
+ mandoc_msg(MANDOCERR_EQNARGS, mp, ln, pos, NULL);
+ return(0);
+ }
+
+ start = eqn_nexttok(ep->parse, ln, pos, end, &sz);
+ if (NULL == start || 0 == sz) {
+ mandoc_msg(MANDOCERR_EQNARGS, mp, ln, pos, NULL);
+ return(0);
+ }
+
+ return(1);
+}
+
+static int
+eqn_do_define(struct eqn_node *ep, int ln, int pos, const char **end)
+{
+ const char *start;
+ struct mparse *mp;
+ size_t sz;
+ int i;
+
+ mp = ep->parse;
+
+ start = eqn_nexttok(mp, ln, pos, end, &sz);
+ if (NULL == start || 0 == sz) {
+ mandoc_msg(MANDOCERR_EQNARGS, mp, ln, pos, NULL);
+ return(0);
+ }
+
+ /* TODO: merge this code with roff_getstr(). */
+
+ /*
+ * Search for a key that already exists.
+ * Note that the string array can have "holes" (null key).
+ */
+
+ for (i = 0; i < (int)ep->defsz; i++) {
+ if (0 == ep->defs[i].keysz || ep->defs[i].keysz != sz)
+ continue;
+ if (0 == strncmp(ep->defs[i].key, start, sz))
+ break;
+ }
+
+ /* Create a new key. */
+
+ if (i == (int)ep->defsz) {
+ /* Find holes in string array. */
+ for (i = 0; i < (int)ep->defsz; i++)
+ if (0 == ep->defs[i].keysz)
+ break;
+
+ if (i == (int)ep->defsz) {
+ ep->defsz++;
+ ep->defs = mandoc_realloc
+ (ep->defs, ep->defsz *
+ sizeof(struct eqn_def));
+ }
+
+ 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';
+ ep->defs[i].val = NULL;
+ ep->defs[i].valsz = 0;
+ }
+
+ start = eqn_nexttok(mp, ln, pos, end, &sz);
+
+ if (NULL == start || 0 == sz) {
+ ep->defs[i].keysz = 0;
+ mandoc_msg(MANDOCERR_EQNARGS, mp, ln, pos, NULL);
+ return(0);
+ }
+
+ ep->defs[i].valsz = sz;
+ ep->defs[i].val = mandoc_realloc
+ (ep->defs[i].val, sz + 1);
+ memcpy(ep->defs[i].val, start, sz);
+ ep->defs[i].val[(int)sz] = '\0';
+
+ return(sz ? 1 : 0);
+}
+
+static int
+eqn_do_undef(struct eqn_node *ep, int ln, int pos, const char **end)
+{
+ const char *start;
+ struct mparse *mp;
+ size_t sz;
+ int i;
+
+ mp = ep->parse;
+
+ start = eqn_nexttok(mp, ln, pos, end, &sz);
+ if (NULL == start || 0 == sz) {
+ mandoc_msg(MANDOCERR_EQNARGS, mp, ln, pos, NULL);
+ return(0);
+ }
+
+ for (i = 0; i < (int)ep->defsz; i++) {
+ if (0 == ep->defs[i].keysz || ep->defs[i].keysz != sz)
+ continue;
+ if (strncmp(ep->defs[i].key, start, sz))
+ continue;
+ ep->defs[i].keysz = 0;
+ break;
+ }
+
+ return(1);
}
Index: mandoc.h
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/mandoc.h,v
retrieving revision 1.79
retrieving revision 1.80
diff -Lmandoc.h -Lmandoc.h -u -p -r1.79 -r1.80
--- mandoc.h
+++ mandoc.h
@@ -109,6 +109,9 @@ enum mandocerr {
MANDOCERR_ERROR, /* ===== start of errors ===== */
+ /* related to equations */
+ MANDOCERR_EQNARGS, /* bad equation macro arguments */
+
/* related to tables */
MANDOCERR_TBL, /* bad table syntax */
MANDOCERR_TBLOPT, /* bad table option */
Index: eqn.7
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/eqn.7,v
retrieving revision 1.2
retrieving revision 1.3
diff -Leqn.7 -Leqn.7 -u -p -r1.2 -r1.3
--- eqn.7
+++ eqn.7
@@ -40,26 +40,69 @@ Equations within
.Xr mdoc 7
or
.Xr man 7
-are enclosed by the
-.Sq EQ
+documents are enclosed by the standalone
+.Sq \&.EQ
and
-.Sq EN
-macro tags, whose precise syntax is documented in
-.Xr roff 7 .
-Equations consist of multi-line equation data.
-.Pp
-For the time being,
-.Xr mandoc 1
-reproduces the contents of
-.Nm
-equations verbatim in its output.
+.Sq \&.EN
+tags.
+Equations are multi-line blocks consisting of formulas and control
+statements.
+.Sh EQUATION STRUCTURE
+Each equation is bracketed by
+.Sq \&.EQ
+and
+.Sq \&.EN
+strings.
+.Em Note :
+these are not the same as
+.Xr roff 7
+macros, and may only be invoked as
+.Sq \&.EQ .
+.Pp
+The equation grammar is as follows:
+.Bd -literal -offset indent
+eqn : box | eqn box
+box : text
+ | DEFINE text text
+ | SET text text
+ | UNDEF text
+text : TEXT
+.Ed
+.Pp
+Data in TEXT form is a non-empty sequence of non-space characters or a
+non-empty quoted string.
+White-space (and enclosing literal quote pairs) is thrown away and
+productions may not be broken by newlines.
.Pp
-The
+The following control statements are available:
+.Bl -tag -width Ds
+.It Cm define
+Replace all occurances of a key with a value.
+Its syntax is as follows:
+.Pp
+.D1 define Ar key val
+.Pp
+It is an error to have an empty
+.Ar key or
+.Ar value .
+Note that a quoted
+.Ar key
+causes errors in some
.Nm
-implementation in
-.Xr mandoc 1
-is
-.Ud
+implementations and should not be considered portable.
+.It Cm set
+Set an equation mode.
+Both arguments are thrown away.
+.It Cm undef
+Unset a previously-defined key.
+Its syntax is as follows:
+.Pp
+.D1 define Ar key
+.Pp
+Once invoked, the definition for
+.Ar key
+is discarded.
+.El
.Sh SEE ALSO
.Xr mandoc 1 ,
.Xr man 7 ,
Index: read.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/read.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -Lread.c -Lread.c -u -p -r1.16 -r1.17
--- read.c
+++ read.c
@@ -152,6 +152,9 @@ static const char * const mandocerrs[MAN
"generic error",
+ /* related to equations */
+ "bad equation macro syntax",
+
/* related to tables */
"bad table syntax",
"bad table option",
--
To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2011-07-17 14:08 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-17 14:08 mdocml: Provide implementations of `define', `set', and `unset' kristaps
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).