From dbface5c83837d76b73a9ba99fde1ccc3afab3d5 Mon Sep 17 00:00:00 2001 From: Kristaps Dzonsons Date: Tue, 12 Jun 2012 20:21:04 +0000 Subject: [PATCH] Add `cc' support. This was reported by espie@ and in the TODO. Caveat: `cc' has buggy behaviour when invoked in groff(1) and followed by a line-breaking control character macro, e.g., in a -man doc, .cc | .B foo 'B foo |cc 'B foo will cause groff(1) to behave properly for `.B' but inline the macro definition for `B' when invoked with the line-breaking macro. --- TODO | 5 +---- libmandoc.h | 5 +++-- man.c | 4 ++-- mandoc.c | 28 +----------------------- mdoc.c | 4 ++-- roff.7 | 14 +++++++++++- roff.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 7 files changed, 81 insertions(+), 40 deletions(-) diff --git a/TODO b/TODO index 6eed3a61..d2c69aa5 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,6 @@ ************************************************************************ * Official mandoc TODO. -* $Id: TODO,v 1.135 2012/06/12 12:47:14 kristaps Exp $ +* $Id: TODO,v 1.136 2012/06/12 20:21:04 kristaps Exp $ ************************************************************************ ************************************************************************ @@ -23,9 +23,6 @@ .ad -- re-enable adjustment without changing the mode Adjustment mode is ignored while in no-fill mode (.nf). -- .cc (change control character) occurs in sqlite3(1) - reported by espie@ Sat, 14 Apr 2012 15:35:38 +0200 - - .it (line traps) occur in mysql(1), yasm_arch(7) generated by DocBook XSL Stylesheets v1.71.1 reported by brad@ Sat, 15 Jan 2011 15:48:18 -0500 diff --git a/libmandoc.h b/libmandoc.h index f75416db..e10a162a 100644 --- a/libmandoc.h +++ b/libmandoc.h @@ -1,4 +1,4 @@ -/* $Id: libmandoc.h,v 1.30 2012/05/27 17:48:57 schwarze Exp $ */ +/* $Id: libmandoc.h,v 1.31 2012/06/12 20:21:04 kristaps Exp $ */ /* * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons * @@ -47,7 +47,6 @@ void mandoc_vmsg(enum mandocerr, struct mparse *, char *mandoc_getarg(struct mparse *, char **, int, int *); char *mandoc_normdate(struct mparse *, char *, int, int); int mandoc_eos(const char *, size_t, int); -int mandoc_getcontrol(const char *, int *); int mandoc_strntoi(const char *, size_t, int); const char *mandoc_a2msec(const char*); @@ -77,6 +76,8 @@ int roff_regisset(const struct roff *, enum regs); unsigned int roff_regget(const struct roff *, enum regs); void roff_regunset(struct roff *, enum regs); char *roff_strdup(const struct roff *, const char *); +int roff_getcontrol(const struct roff *, + const char *, int *); #if 0 char roff_eqndelim(const struct roff *); void roff_openeqn(struct roff *, const char *, diff --git a/man.c b/man.c index ece4868f..d2297251 100644 --- a/man.c +++ b/man.c @@ -1,4 +1,4 @@ -/* $Id: man.c,v 1.116 2012/06/02 20:16:23 schwarze Exp $ */ +/* $Id: man.c,v 1.117 2012/06/12 20:21:04 kristaps Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons * @@ -131,7 +131,7 @@ man_parseln(struct man *m, int ln, char *buf, int offs) assert( ! (MAN_HALT & m->flags)); - return (mandoc_getcontrol(buf, &offs) ? + return (roff_getcontrol(m->roff, buf, &offs) ? man_pmacro(m, ln, buf, offs) : man_ptext(m, ln, buf, offs)); } diff --git a/mandoc.c b/mandoc.c index 3ecf56bb..420e8aa5 100644 --- a/mandoc.c +++ b/mandoc.c @@ -1,4 +1,4 @@ -/* $Id: mandoc.c,v 1.65 2012/05/31 22:38:16 schwarze Exp $ */ +/* $Id: mandoc.c,v 1.66 2012/06/12 20:21:04 kristaps Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons * Copyright (c) 2011, 2012 Ingo Schwarze @@ -603,32 +603,6 @@ mandoc_eos(const char *p, size_t sz, int enclosed) return(found && !enclosed); } -/* - * Find out whether a line is a macro line or not. If it is, adjust the - * current position and return one; if it isn't, return zero and don't - * change the current position. - */ -int -mandoc_getcontrol(const char *cp, int *ppos) -{ - int pos; - - pos = *ppos; - - if ('\\' == cp[pos] && '.' == cp[pos + 1]) - pos += 2; - else if ('.' == cp[pos] || '\'' == cp[pos]) - pos++; - else - return(0); - - while (' ' == cp[pos] || '\t' == cp[pos]) - pos++; - - *ppos = pos; - return(1); -} - /* * Convert a string to a long that may not be <0. * If the string is invalid, or is less than 0, return -1. diff --git a/mdoc.c b/mdoc.c index ee7c36dd..7021c5c6 100644 --- a/mdoc.c +++ b/mdoc.c @@ -1,4 +1,4 @@ -/* $Id: mdoc.c,v 1.197 2012/05/27 17:48:57 schwarze Exp $ */ +/* $Id: mdoc.c,v 1.198 2012/06/12 20:21:04 kristaps Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons * Copyright (c) 2010 Ingo Schwarze @@ -302,7 +302,7 @@ mdoc_parseln(struct mdoc *m, int ln, char *buf, int offs) m->flags &= ~MDOC_SYNOPSIS; } - return(mandoc_getcontrol(buf, &offs) ? + return(roff_getcontrol(m->roff, buf, &offs) ? mdoc_pmacro(m, ln, buf, offs) : mdoc_ptext(m, ln, buf, offs)); } diff --git a/roff.7 b/roff.7 index a89cce8c..22212514 100644 --- a/roff.7 +++ b/roff.7 @@ -1,4 +1,4 @@ -.\" $Id: roff.7,v 1.38 2012/06/12 19:50:50 kristaps Exp $ +.\" $Id: roff.7,v 1.39 2012/06/12 20:21:04 kristaps Exp $ .\" .\" Copyright (c) 2010, 2011 Kristaps Dzonsons .\" Copyright (c) 2010, 2011 Ingo Schwarze @@ -417,6 +417,18 @@ The syntax of this request is the same as that of It is currently ignored by .Xr mandoc 1 , as are its children. +.Ss \&cc +Changes the control character. +Its syntax is as follows: +.Bd -literal -offset indent +.Pf . Cm \&cc Op Ar c +.Ed +.Pp +If +.Ar c +is not specified, the control character is reset to +.Sq \&. . +Trailing characters are ignored. .Ss \&de Define a .Nm diff --git a/roff.c b/roff.c index d5ecfdff..ad9645ee 100644 --- a/roff.c +++ b/roff.c @@ -1,4 +1,4 @@ -/* $Id: roff.c,v 1.173 2012/05/31 22:41:19 schwarze Exp $ */ +/* $Id: roff.c,v 1.174 2012/06/12 20:21:04 kristaps Exp $ */ /* * Copyright (c) 2010, 2011 Kristaps Dzonsons * Copyright (c) 2010, 2011, 2012 Ingo Schwarze @@ -39,6 +39,7 @@ enum rofft { ROFF_am, ROFF_ami, ROFF_am1, + ROFF_cc, ROFF_de, ROFF_dei, ROFF_de1, @@ -105,6 +106,7 @@ struct roff { struct mparse *parse; /* parse point */ struct roffnode *last; /* leaf of stack */ enum roffrule rstack[RSTACK_MAX]; /* stack of !`ie' rules */ + char control; /* control character */ int rstackpos; /* position in rstack */ struct reg regs[REG__MAX]; struct roffkv *strtab; /* user-defined strings & macros */ @@ -169,6 +171,7 @@ static enum rofferr roff_block(ROFF_ARGS); static enum rofferr roff_block_text(ROFF_ARGS); static enum rofferr roff_block_sub(ROFF_ARGS); static enum rofferr roff_cblock(ROFF_ARGS); +static enum rofferr roff_cc(ROFF_ARGS); static enum rofferr roff_ccond(ROFF_ARGS); static enum rofferr roff_cond(ROFF_ARGS); static enum rofferr roff_cond_text(ROFF_ARGS); @@ -215,6 +218,7 @@ static struct roffmac roffs[ROFF_MAX] = { { "am", roff_block, roff_block_text, roff_block_sub, 0, NULL }, { "ami", roff_block, roff_block_text, roff_block_sub, 0, NULL }, { "am1", roff_block, roff_block_text, roff_block_sub, 0, NULL }, + { "cc", roff_cc, NULL, NULL, 0, NULL }, { "de", roff_block, roff_block_text, roff_block_sub, 0, NULL }, { "dei", roff_block, roff_block_text, roff_block_sub, 0, NULL }, { "de1", roff_block, roff_block_text, roff_block_sub, 0, NULL }, @@ -392,6 +396,7 @@ roff_reset(struct roff *r) roff_free1(r); + r->control = 0; memset(&r->regs, 0, sizeof(struct reg) * REG__MAX); for (i = 0; i < PREDEFS_MAX; i++) @@ -611,7 +616,7 @@ roff_parseln(struct roff *r, int ln, char **bufp, assert(ROFF_CONT == e); ppos = pos; - ctl = mandoc_getcontrol(*bufp, &pos); + ctl = roff_getcontrol(r, *bufp, &pos); /* * First, if a scope is open and we're not a macro, pass the @@ -1361,6 +1366,23 @@ roff_TS(ROFF_ARGS) return(ROFF_IGN); } +/* ARGSUSED */ +static enum rofferr +roff_cc(ROFF_ARGS) +{ + const char *p; + + p = *bufp + pos; + + if ('\0' == *p || '.' == (r->control = *p++)) + r->control = 0; + + if ('\0' != *p) + mandoc_msg(MANDOCERR_ARGCOUNT, r->parse, ln, ppos, NULL); + + return(ROFF_IGN); +} + /* ARGSUSED */ static enum rofferr roff_tr(ROFF_ARGS) @@ -1757,3 +1779,38 @@ roff_strdup(const struct roff *r, const char *p) res[(int)ssz] = '\0'; return(res); } + +/* + * Find out whether a line is a macro line or not. + * If it is, adjust the current position and return one; if it isn't, + * return zero and don't change the current position. + * If the control character has been set with `.cc', then let that grain + * precedence. + * This is slighly contrary to groff, where using the non-breaking + * control character when `cc' has been invoked will cause the + * non-breaking macro contents to be printed verbatim. + */ +int +roff_getcontrol(const struct roff *r, const char *cp, int *ppos) +{ + int pos; + + pos = *ppos; + + if (0 != r->control && cp[pos] == r->control) + pos++; + else if (0 != r->control) + return(0); + else if ('\\' == cp[pos] && '.' == cp[pos + 1]) + pos += 2; + else if ('.' == cp[pos] || '\'' == cp[pos]) + pos++; + else + return(0); + + while (' ' == cp[pos] || '\t' == cp[pos]) + pos++; + + *ppos = pos; + return(1); +} -- 2.47.1