source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* mdocml: Implement the roff(7) .rn (rename macro or string) request.
@ 2017-06-07  0:51 schwarze
  0 siblings, 0 replies; only message in thread
From: schwarze @ 2017-06-07  0:51 UTC (permalink / raw)
  To: source

Log Message:
-----------
Implement the roff(7) .rn (rename macro or string) request.
Renaming a user-defined macro is very simple: just copy
the definition to the new name and delete the old name.
Renaming high-level macros is a bit tricky: use a dedicated
key-value-table, with non-standard names as keys and standard
names as values.  When a macro is found that is not user-defined,
look it up in the "renamed" table and translate it back to the
standard name before passing it on to the high-level parsers.

Modified Files:
--------------
    mdocml:
        roff.7
        roff.c
        roff.h

Revision Data
-------------
Index: roff.h
===================================================================
RCS file: /home/cvs/mdocml/mdocml/roff.h,v
retrieving revision 1.50
retrieving revision 1.51
diff -Lroff.h -Lroff.h -u -p -r1.50 -r1.51
--- roff.h
+++ roff.h
@@ -309,6 +309,7 @@ enum	roff_tok {
 	ROFF_writem,
 	ROFF_xflag,
 	ROFF_cblock,
+	ROFF_RENAMED,
 	ROFF_USERDEF,
 	TOKEN_NONE,
 	MDOC_Dd,
Index: roff.7
===================================================================
RCS file: /home/cvs/mdocml/mdocml/roff.7,v
retrieving revision 1.85
retrieving revision 1.86
diff -Lroff.7 -Lroff.7 -u -p -r1.85 -r1.86
--- roff.7
+++ roff.7
@@ -530,7 +530,7 @@ input lines without filling.
 .Ar N
 defaults to 1.
 An argument of 0 or less ends centering.
-Currently, high level macros abort certering.
+Currently, high level macros abort centering.
 .It Ic \&cf Ar filename
 Output the contents of a file.
 Ignored because insecure.
@@ -1482,7 +1482,16 @@ Currently ignored.
 Remove a request, macro or string.
 .It Ic \&rn Ar oldname newname
 Rename a request, macro, diversion, or string.
-Currently unsupported.
+In
+.Xr mandoc 1 ,
+user-defined macros,
+.Xr mdoc 7
+and
+.Xr man 7
+macros, and user-defined strings can be renamed, but renaming of
+predefined strings and of
+.Nm
+requests is not supported, and diversions are not implemented at all.
 .It Ic \&rnn Ar oldname newname
 Rename a number register.
 Currently unsupported.
Index: roff.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/roff.c,v
retrieving revision 1.305
retrieving revision 1.306
diff -Lroff.c -Lroff.c -u -p -r1.305 -r1.306
--- roff.c
+++ roff.c
@@ -83,6 +83,7 @@ struct	roff {
 	struct ohash	*reqtab; /* request lookup table */
 	struct roffreg	*regtab; /* number registers */
 	struct roffkv	*strtab; /* user-defined strings & macros */
+	struct roffkv	*rentab; /* renamed strings & macros */
 	struct roffkv	*xmbtab; /* multi-byte trans table (`tr') */
 	struct roffstr	*xtab; /* single-byte trans table (`tr') */
 	const char	*current_string; /* value of last called user macro */
@@ -175,6 +176,8 @@ static	int		 roff_getregn(const struct r
 				const char *, size_t);
 static	int		 roff_getregro(const struct roff *,
 				const char *name);
+static	const char	*roff_getrenn(const struct roff *,
+				const char *, size_t);
 static	const char	*roff_getstrn(const struct roff *,
 				const char *, size_t);
 static	int		 roff_hasregn(const struct roff *,
@@ -191,8 +194,10 @@ static	enum roff_tok	 roff_parse(struct 
 				int, int);
 static	enum rofferr	 roff_parsetext(struct roff *, struct buf *,
 				int, int *);
+static	enum rofferr	 roff_renamed(ROFF_ARGS);
 static	enum rofferr	 roff_res(struct roff *, struct buf *, int, int);
 static	enum rofferr	 roff_rm(ROFF_ARGS);
+static	enum rofferr	 roff_rn(ROFF_ARGS);
 static	enum rofferr	 roff_rr(ROFF_ARGS);
 static	void		 roff_setstr(struct roff *,
 				const char *, const char *, int);
@@ -278,7 +283,7 @@ const char *__roff_name[MAN_MAX + 1] = {
 	"warnscale",	"watch",	"watchlength",	"watchn",
 	"wh",		"while",	"write",	"writec",
 	"writem",	"xflag",	".",		NULL,
-	"text",
+	NULL,		"text",
 	"Dd",		"Dt",		"Os",		"Sh",
 	"Ss",		"Pp",		"D1",		"Dl",
 	"Bd",		"Ed",		"Bl",		"El",
@@ -508,7 +513,7 @@ static	struct roffmac	 roffs[TOKEN_NONE]
 	{ roff_line_ignore, NULL, NULL, 0 },  /* rhang */
 	{ roff_line_ignore, NULL, NULL, 0 },  /* rj */
 	{ roff_rm, NULL, NULL, 0 },  /* rm */
-	{ roff_unsupp, NULL, NULL, 0 },  /* rn */
+	{ roff_rn, NULL, NULL, 0 },  /* rn */
 	{ roff_unsupp, NULL, NULL, 0 },  /* rnn */
 	{ roff_rr, NULL, NULL, 0 },  /* rr */
 	{ roff_line_ignore, NULL, NULL, 0 },  /* rs */
@@ -564,6 +569,7 @@ static	struct roffmac	 roffs[TOKEN_NONE]
 	{ roff_insec, NULL, NULL, 0 },  /* writem */
 	{ roff_line_ignore, NULL, NULL, 0 },  /* xflag */
 	{ roff_cblock, NULL, NULL, 0 },  /* . */
+	{ roff_renamed, NULL, NULL, 0 },
 	{ roff_userdef, NULL, NULL, 0 }
 };
 
@@ -743,8 +749,9 @@ roff_free1(struct roff *r)
 	r->regtab = NULL;
 
 	roff_freestr(r->strtab);
+	roff_freestr(r->rentab);
 	roff_freestr(r->xmbtab);
-	r->strtab = r->xmbtab = NULL;
+	r->strtab = r->rentab = r->xmbtab = NULL;
 
 	if (r->xtab)
 		for (i = 0; i < 128; i++)
@@ -1614,8 +1621,10 @@ roff_parse(struct roff *r, char *buf, in
 	mac = cp;
 	maclen = roff_getname(r, &cp, ln, ppos);
 
-	t = (r->current_string = roff_getstrn(r, mac, maclen))
-	    ? ROFF_USERDEF : roffhash_find(r->reqtab, mac, maclen);
+	t = (r->current_string = roff_getstrn(r, mac, maclen)) ?
+	    ROFF_USERDEF :
+	    (r->current_string = roff_getrenn(r, mac, maclen)) ?
+	    ROFF_RENAMED : roffhash_find(r->reqtab, mac, maclen);
 
 	if (t != TOKEN_NONE)
 		*pos = cp - buf;
@@ -3058,6 +3067,56 @@ roff_tr(ROFF_ARGS)
 }
 
 static enum rofferr
+roff_rn(ROFF_ARGS)
+{
+	const char	*value;
+	char		*oldn, *newn, *end;
+	size_t		 oldsz, newsz;
+
+	oldn = newn = buf->buf + pos;
+	if (*oldn == '\0')
+		return ROFF_IGN;
+
+	oldsz = roff_getname(r, &newn, ln, pos);
+	if (oldn[oldsz] == '\\' || *newn == '\0')
+		return ROFF_IGN;
+
+	end = newn;
+	newsz = roff_getname(r, &end, ln, newn - buf->buf);
+	if (newsz == 0)
+		return ROFF_IGN;
+
+	/*
+	 * Rename a user-defined macro bearing the old name,
+	 * overriding an existing renamed high-level macro
+	 * bearing the new name, if that exists.
+	 */
+
+	if ((value = roff_getstrn(r, oldn, oldsz)) != NULL) {
+		roff_setstrn(&r->strtab, newn, newsz, value, strlen(value), 0);
+		roff_setstrn(&r->strtab, oldn, oldsz, NULL, 0, 0);
+		roff_setstrn(&r->rentab, newn, newsz, NULL, 0, 0);
+		return ROFF_IGN;
+	}
+
+	/*
+	 * Rename a high-level macro bearing the old name,
+	 * either renaming it a second time if it was already
+	 * renamed before, or renaming it for the first time.
+	 * In both cases, override an existing user-defined
+	 * macro bearing the new name, if that exists.
+	 */
+
+	if ((value = roff_getrenn(r, oldn, oldsz)) != NULL) {
+		roff_setstrn(&r->rentab, newn, newsz, value, strlen(value), 0);
+		roff_setstrn(&r->rentab, oldn, oldsz, NULL, 0, 0);
+	} else
+		roff_setstrn(&r->rentab, newn, newsz, oldn, oldsz, 0);
+	roff_setstrn(&r->strtab, newn, newsz, NULL, 0, 0);
+	return ROFF_IGN;
+}
+
+static enum rofferr
 roff_so(ROFF_ARGS)
 {
 	char *name, *cp;
@@ -3231,6 +3290,22 @@ roff_userdef(ROFF_ARGS)
 	   ROFF_REPARSE : ROFF_APPEND;
 }
 
+/*
+ * Calling a high-level macro that was renamed with .rn.
+ * r->current_string has already been set up by roff_parse().
+ */
+static enum rofferr
+roff_renamed(ROFF_ARGS)
+{
+	char	*nbuf;
+
+	buf->sz = mandoc_asprintf(&nbuf, ".%s %s", r->current_string,
+	    buf->buf + pos) + 1;
+	free(buf->buf);
+	buf->buf = nbuf;
+	return ROFF_CONT;
+}
+
 static size_t
 roff_getname(struct roff *r, char **cpp, int ln, int pos)
 {
@@ -3372,6 +3447,23 @@ roff_getstrn(const struct roff *r, const
 		if (0 == strncmp(name, predefs[i].name, len) &&
 				'\0' == predefs[i].name[(int)len])
 			return predefs[i].str;
+
+	return NULL;
+}
+
+/*
+ * Check whether *name is the renamed name of a high-level macro.
+ * Return the standard name, or NULL if it is not.
+ */
+static const char *
+roff_getrenn(const struct roff *r, const char *name, size_t len)
+{
+	const struct roffkv *n;
+
+	for (n = r->rentab; n; n = n->next)
+		if (0 == strncmp(name, n->key.p, len) &&
+		    '\0' == n->key.p[(int)len])
+			return n->val.p;
 
 	return NULL;
 }
--
 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:[~2017-06-07  0:51 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-07  0:51 mdocml: Implement the roff(7) .rn (rename macro or string) request schwarze

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).