source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* 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).