From: schwarze Date: Wed, 7 Jun 2017 00:50:30 +0000 (+0000) Subject: Implement the roff(7) .rn (rename macro or string) request. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=7e291f1051df7bf8b70f441d8d90fb37d65b9e24;p=openbsd 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. --- diff --git a/share/man/man7/roff.7 b/share/man/man7/roff.7 index c0c30372de7..b3fe9f571e5 100644 --- a/share/man/man7/roff.7 +++ b/share/man/man7/roff.7 @@ -1,4 +1,4 @@ -.\" $OpenBSD: roff.7,v 1.65 2017/06/06 15:00:56 schwarze Exp $ +.\" $OpenBSD: roff.7,v 1.66 2017/06/07 00:50:30 schwarze Exp $ .\" .\" Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons .\" Copyright (c) 2010,2011,2013-2015,2017 Ingo Schwarze @@ -15,7 +15,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: June 6 2017 $ +.Dd $Mdocdate: June 7 2017 $ .Dt ROFF 7 .Os .Sh NAME @@ -528,7 +528,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. @@ -1480,7 +1480,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. diff --git a/usr.bin/mandoc/roff.c b/usr.bin/mandoc/roff.c index 253586382f3..d1b83cbb867 100644 --- a/usr.bin/mandoc/roff.c +++ b/usr.bin/mandoc/roff.c @@ -1,4 +1,4 @@ -/* $OpenBSD: roff.c,v 1.177 2017/06/06 15:00:56 schwarze Exp $ */ +/* $OpenBSD: roff.c,v 1.178 2017/06/07 00:50:30 schwarze Exp $ */ /* * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons * Copyright (c) 2010-2015, 2017 Ingo Schwarze @@ -81,6 +81,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 */ @@ -173,6 +174,8 @@ static int roff_getregn(const struct roff *, 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 *, @@ -189,8 +192,10 @@ static enum roff_tok roff_parse(struct roff *, char *, int *, 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); @@ -276,7 +281,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", @@ -506,7 +511,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 */ @@ -562,6 +567,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 } }; @@ -741,8 +747,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++) @@ -1612,8 +1619,10 @@ roff_parse(struct roff *r, char *buf, int *pos, int ln, int ppos) 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; @@ -3055,6 +3064,56 @@ roff_tr(ROFF_ARGS) return ROFF_IGN; } +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) { @@ -3229,6 +3288,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) { @@ -3374,6 +3449,23 @@ roff_getstrn(const struct roff *r, const char *name, size_t len) 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; +} + static void roff_freestr(struct roffkv *r) { diff --git a/usr.bin/mandoc/roff.h b/usr.bin/mandoc/roff.h index 24816e5e4a2..c1ce3b281a4 100644 --- a/usr.bin/mandoc/roff.h +++ b/usr.bin/mandoc/roff.h @@ -1,4 +1,4 @@ -/* $OpenBSD: roff.h,v 1.32 2017/06/06 15:00:56 schwarze Exp $ */ +/* $OpenBSD: roff.h,v 1.33 2017/06/07 00:50:30 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons * Copyright (c) 2013, 2014, 2015, 2017 Ingo Schwarze @@ -309,6 +309,7 @@ enum roff_tok { ROFF_writem, ROFF_xflag, ROFF_cblock, + ROFF_RENAMED, ROFF_USERDEF, TOKEN_NONE, MDOC_Dd,