tech@mandoc.bsd.lv
 help / color / mirror / Atom feed
* TERMP_NOLPAD r.i.p.
       [not found] ` <4E765AFE.9070302@bsd.lv>
@ 2011-09-19 21:39   ` Ingo Schwarze
  2011-09-19 21:58     ` Kristaps Dzonsons
  0 siblings, 1 reply; 8+ messages in thread
From: Ingo Schwarze @ 2011-09-19 21:39 UTC (permalink / raw)
  To: tech

Hi,

Kristaps drew my attention to the fact that the popt(3) manual
is badly broken:

> .HP
> .nf
> .BI "int poptReadDefaultConfig(poptContext " con ", int " flags ");"
> .fi
> 
> This looks fine in `ul', but on the raw screen it prints out lots of
> blank space due to the flush.  Of course, it's because rmargin is
> set to TERM_MAXMARGIN and the TERMP_NOBREAK goes nuts (in
> print_man_node()). This can be hacked around by NOT setting rmargin
> and only setting maxrmargin, but it still looks crappy.  Any
> thoughts?

Yes, i have come up with the following diff which might be one of the
most beautiful i have written for mandoc so far:  I suggest to
enhance functionality and squash bugs - by removing a flag!

Specifically, as long as we have TERMP_NOLPAD, the problem at hand
is very hard to solve, in particular in the following variant:

  .nf
  .HP 12n
  This is a very long tag.
  .fi
  This is the indented text; it is of considerable length as well.

With TERMP_NOLPAD, while rendering the first line of the .HP,
term_flushln() - yes, once again my favourite function -
overruns the column, breaks the line, and pads to the indent.
After that, the .fi breaks the already padded line - ouch.

To improve this, we should not pad until we know that we want
to write actual content to a line, but let the next call to
term_flushln() do the padding instead; which means that we don't
need TERMP_NOLPAD any longer.

Some of the chunks are non-obvious:

 * term.c chunk @@ -130,9 +126,10 @@:
   Always calculate the padding before starting a new line.
   No more TERMP_NOLPAD.
 * term.c chunk @@ -232,10 +229,14 @@:
   An independent bugfix.  Backspace has negative length.
   Without this, indentation does not get right.
 * term.c chunk @@ -244,7 +245,8 @@:
   Handle the edge case of an empty input string:
   In that case, vis is still zero, and there is no need to go back.
   This occurs e.g. in man(7) page headers and footers.
 * term.c chunk @@ -269,25 +271,18 @@:
   This is the main point.
   No more padding at the end of term_flushln().
 * Most other chunks just drop the obsolete flag.
 * man_term.c chunk @@ -241,6 +241,18 @@:
   That's the main fix for .HP indentation containing .fi/.nf,
   and the only ugly chunk in this diff.
   See the comment in the code what it does.
 * man_term.c chunk @@ -452,8 +464,11 @@:
   This adjusts the indentation width to what groff does.
 * man_term.c chunk @@ -878,7 +889,7 @@:
   The right margin must not be unlimited in literal mode
   when TERMP_NOBREAK is in effect.  That avoids the long string
   of blank characters.

This patch is -65 +50 :).

It reduces groff/mandoc differences in base by nearly 20%,
from 89k to 72k lines of diffs.

I see no regressions.

OK?
  Ingo


Index: term.h
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/term.h,v
retrieving revision 1.31
diff -u -p -r1.31 term.h
--- term.h	18 Sep 2011 10:25:28 -0000	1.31
+++ term.h	19 Sep 2011 21:29:38 -0000
@@ -64,7 +64,6 @@ struct	termp {
 	int		  flags;
 #define	TERMP_SENTENCE	 (1 << 1)	/* Space before a sentence. */
 #define	TERMP_NOSPACE	 (1 << 2)	/* No space before words. */
-#define	TERMP_NOLPAD	 (1 << 3)	/* See term_flushln(). */
 #define	TERMP_NOBREAK	 (1 << 4)	/* See term_flushln(). */
 #define	TERMP_IGNDELIM	 (1 << 6)	/* Delims like regulars. */
 #define	TERMP_NONOSPACE	 (1 << 7)	/* No space (no autounset). */
Index: term.c
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/term.c,v
retrieving revision 1.60
diff -u -p -r1.60 term.c
--- term.c	18 Sep 2011 20:38:02 -0000	1.60
+++ term.c	19 Sep 2011 21:29:38 -0000
@@ -75,22 +75,18 @@ term_end(struct termp *p)
  *
  * The following flags may be specified:
  *
- *  - TERMP_NOLPAD: when beginning to write the line, don't left-pad the
- *    offset value.  This is useful when doing columnar lists where the
- *    prior column has right-padded.
- *
  *  - TERMP_NOBREAK: this is the most important and is used when making
- *    columns.  In short: don't print a newline and instead pad to the
- *    right margin.  Used in conjunction with TERMP_NOLPAD.
+ *    columns.  In short: don't print a newline and instead expect the
+ *    next call to do the padding up to the start of the next column.
  *
- *  - TERMP_TWOSPACE: when padding, make sure there are at least two
- *    space characters of padding.  Otherwise, rather break the line.
+ *  - TERMP_TWOSPACE: make sure there is room for at least two space
+ *    characters of padding.  Otherwise, rather break the line.
  *
  *  - TERMP_DANGLE: don't newline when TERMP_NOBREAK is specified and
  *    the line is overrun, and don't pad-right if it's underrun.
  *
  *  - TERMP_HANG: like TERMP_DANGLE, but doesn't newline when
- *    overruning, instead save the position and continue at that point
+ *    overrunning, instead save the position and continue at that point
  *    when the next invocation.
  *
  *  In-line line breaking:
@@ -130,9 +126,10 @@ term_flushln(struct termp *p)
 	bp = TERMP_NOBREAK & p->flags ? mmax : maxvis;
 
 	/*
-	 * Indent the first line of a paragraph.
+	 * Calculate the required amount of padding.
 	 */
-	vbl = p->flags & TERMP_NOLPAD ? (size_t)0 : p->offset;
+	vbl = p->offset + p->overstep > p->viscol ?
+	      p->offset + p->overstep - p->viscol : 0;
 
 	vis = vend = 0;
 	i = 0;
@@ -232,10 +229,14 @@ term_flushln(struct termp *p)
 			if (ASCII_HYPH == p->buf[i]) {
 				(*p->letter)(p, '-');
 				p->viscol += (*p->width)(p, '-');
-			} else {
-				(*p->letter)(p, p->buf[i]);
-				p->viscol += (*p->width)(p, p->buf[i]);
+				continue;
 			}
+
+			(*p->letter)(p, p->buf[i]);
+			if (8 == p->buf[i])
+				p->viscol -= (*p->width)(p, p->buf[i-1]);
+			else 
+				p->viscol += (*p->width)(p, p->buf[i]);
 		}
 		vis = vend;
 	}
@@ -244,7 +245,8 @@ term_flushln(struct termp *p)
 	 * If there was trailing white space, it was not printed;
 	 * so reset the cursor position accordingly.
 	 */
-	vis -= vbl;
+	if (vis)
+		vis -= vbl;
 
 	p->col = 0;
 	p->overstep = 0;
@@ -269,25 +271,18 @@ term_flushln(struct termp *p)
 		 * move it one step LEFT and flag the rest of the line
 		 * to be longer.
 		 */
-		if (p->overstep >= -1) {
-			assert((int)maxvis + p->overstep >= 0);
-			maxvis += (size_t)p->overstep;
-		} else
+		if (p->overstep < -1)
 			p->overstep = 0;
+		return;
 
 	} else if (TERMP_DANGLE & p->flags)
 		return;
 
-	/* Right-pad. */
-	if (maxvis > vis +
+	/* If the column was overrun, break the line. */
+	if (maxvis <= vis +
 	    ((TERMP_TWOSPACE & p->flags) ? (*p->width)(p, ' ') : 0)) {
-		p->viscol += maxvis - vis;
-		(*p->advance)(p, maxvis - vis);
-		vis += (maxvis - vis);
-	} else {	/* ...or newline break. */
 		(*p->endline)(p);
-		p->viscol = p->rmargin;
-		(*p->advance)(p, p->rmargin);
+		p->viscol = 0;
 	}
 }
 
@@ -302,12 +297,8 @@ term_newln(struct termp *p)
 {
 
 	p->flags |= TERMP_NOSPACE;
-	if (0 == p->col && 0 == p->viscol) {
-		p->flags &= ~TERMP_NOLPAD;
-		return;
-	}
-	term_flushln(p);
-	p->flags &= ~TERMP_NOLPAD;
+	if (p->col || p->viscol)
+		term_flushln(p);
 }
 
 
Index: mdoc_term.c
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/mdoc_term.c,v
retrieving revision 1.135
diff -u -p -r1.135 mdoc_term.c
--- mdoc_term.c	18 Sep 2011 10:25:28 -0000	1.135
+++ mdoc_term.c	19 Sep 2011 21:29:38 -0000
@@ -431,7 +431,7 @@ print_mdoc_foot(struct termp *p, const v
 
 	p->offset = p->rmargin;
 	p->rmargin = p->maxrmargin - term_strlen(p, m->os);
-	p->flags |= TERMP_NOLPAD | TERMP_NOSPACE;
+	p->flags |= TERMP_NOSPACE;
 
 	term_word(p, m->date);
 	term_flushln(p);
@@ -439,7 +439,7 @@ print_mdoc_foot(struct termp *p, const v
 	p->offset = p->rmargin;
 	p->rmargin = p->maxrmargin;
 	p->flags &= ~TERMP_NOBREAK;
-	p->flags |= TERMP_NOLPAD | TERMP_NOSPACE;
+	p->flags |= TERMP_NOSPACE;
 
 	term_word(p, m->os);
 	term_flushln(p);
@@ -495,7 +495,7 @@ print_mdoc_head(struct termp *p, const v
 
 	p->offset = p->rmargin;
 	p->rmargin = p->maxrmargin - term_strlen(p, title);
-	p->flags |= TERMP_NOLPAD | TERMP_NOSPACE;
+	p->flags |= TERMP_NOSPACE;
 
 	term_word(p, buf);
 	term_flushln(p);
@@ -503,7 +503,7 @@ print_mdoc_head(struct termp *p, const v
 	p->offset = p->rmargin;
 	p->rmargin = p->maxrmargin;
 	p->flags &= ~TERMP_NOBREAK;
-	p->flags |= TERMP_NOLPAD | TERMP_NOSPACE;
+	p->flags |= TERMP_NOSPACE;
 
 	term_word(p, title);
 	term_flushln(p);
@@ -783,16 +783,11 @@ termp_it_pre(DECL_ARGS)
 	case (LIST_hyphen):
 		if (MDOC_HEAD == n->type)
 			p->flags |= TERMP_NOBREAK;
-		else
-			p->flags |= TERMP_NOLPAD;
 		break;
 	case (LIST_hang):
 		if (MDOC_HEAD == n->type)
 			p->flags |= TERMP_NOBREAK;
 		else
-			p->flags |= TERMP_NOLPAD;
-
-		if (MDOC_HEAD != n->type)
 			break;
 
 		/*
@@ -803,17 +798,14 @@ termp_it_pre(DECL_ARGS)
 		 */
 		if (n->next->child && 
 				(MDOC_Bl == n->next->child->tok ||
-				 MDOC_Bd == n->next->child->tok)) {
+				 MDOC_Bd == n->next->child->tok))
 			p->flags &= ~TERMP_NOBREAK;
-			p->flags &= ~TERMP_NOLPAD;
-		} else
+		else
 			p->flags |= TERMP_HANG;
 		break;
 	case (LIST_tag):
 		if (MDOC_HEAD == n->type)
 			p->flags |= TERMP_NOBREAK | TERMP_TWOSPACE;
-		else
-			p->flags |= TERMP_NOLPAD;
 
 		if (MDOC_HEAD != n->type)
 			break;
@@ -829,10 +821,6 @@ termp_it_pre(DECL_ARGS)
 		else
 			p->flags |= TERMP_NOBREAK;
 
-		assert(n->prev);
-		if (MDOC_BODY == n->prev->type) 
-			p->flags |= TERMP_NOLPAD;
-
 		break;
 	case (LIST_diag):
 		if (MDOC_HEAD == n->type)
@@ -989,7 +977,6 @@ termp_it_post(DECL_ARGS)
 	p->flags &= ~TERMP_DANGLE;
 	p->flags &= ~TERMP_NOBREAK;
 	p->flags &= ~TERMP_TWOSPACE;
-	p->flags &= ~TERMP_NOLPAD;
 	p->flags &= ~TERMP_HANG;
 }
 
@@ -1005,7 +992,7 @@ termp_nm_pre(DECL_ARGS)
 	if (MDOC_BODY == n->type) {
 		if (NULL == n->child)
 			return(0);
-		p->flags |= TERMP_NOLPAD | TERMP_NOSPACE;
+		p->flags |= TERMP_NOSPACE;
 		p->offset += term_len(p, 1) +
 		    (NULL == n->prev->child ? term_strlen(p, m->name) :
 		     MDOC_TEXT == n->prev->child->type ?
@@ -1050,10 +1037,8 @@ termp_nm_post(DECL_ARGS)
 	if (MDOC_HEAD == n->type && n->next->child) {
 		term_flushln(p);
 		p->flags &= ~(TERMP_NOBREAK | TERMP_HANG);
-	} else if (MDOC_BODY == n->type && n->child) {
+	} else if (MDOC_BODY == n->type && n->child)
 		term_flushln(p);
-		p->flags &= ~TERMP_NOLPAD;
-	}
 }
 
 		
Index: man_term.c
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/man_term.c,v
retrieving revision 1.71
diff -u -p -r1.71 man_term.c
--- man_term.c	18 Sep 2011 10:25:28 -0000	1.71
+++ man_term.c	19 Sep 2011 21:29:38 -0000
@@ -241,6 +241,18 @@ pre_literal(DECL_ARGS)
 	else
 		mt->fl &= ~MANT_LITERAL;
 
+	/*
+	 * Unlike .IP and .TP, .HP does not have a HEAD.
+	 * So in case a second call to term_flushln() is needed,
+	 * indentation has to be set up explicitly.
+	 */
+	if (MAN_HP == n->parent->tok && p->rmargin < p->maxrmargin) {
+		p->offset = p->rmargin + 1;
+		p->rmargin = p->maxrmargin;
+		p->flags &= ~(TERMP_NOBREAK | TERMP_TWOSPACE);
+		p->flags |= TERMP_NOSPACE;
+	}
+
 	return(0);
 }
 
@@ -427,7 +439,7 @@ pre_sp(DECL_ARGS)
 static int
 pre_HP(DECL_ARGS)
 {
-	size_t			 len;
+	size_t			 len, one;
 	int			 ival;
 	const struct man_node	*nn;
 
@@ -452,8 +464,11 @@ pre_HP(DECL_ARGS)
 		if ((ival = a2width(p, nn->string)) >= 0)
 			len = (size_t)ival;
 
-	if (0 == len)
-		len = term_len(p, 1);
+	one = term_len(p, 1);
+	if (len > one)
+		len -= one;
+	else
+		len = one;
 
 	p->offset = mt->offset;
 	p->rmargin = mt->offset + len;
@@ -516,7 +531,6 @@ pre_IP(DECL_ARGS)
 
 	switch (n->type) {
 	case (MAN_BODY):
-		p->flags |= TERMP_NOLPAD;
 		p->flags |= TERMP_NOSPACE;
 		break;
 	case (MAN_HEAD):
@@ -587,7 +601,6 @@ post_IP(DECL_ARGS)
 		break;
 	case (MAN_BODY):
 		term_newln(p);
-		p->flags &= ~TERMP_NOLPAD;
 		break;
 	default:
 		break;
@@ -608,7 +621,6 @@ pre_TP(DECL_ARGS)
 		p->flags |= TERMP_NOBREAK;
 		break;
 	case (MAN_BODY):
-		p->flags |= TERMP_NOLPAD;
 		p->flags |= TERMP_NOSPACE;
 		break;
 	case (MAN_BLOCK):
@@ -677,7 +689,6 @@ post_TP(DECL_ARGS)
 		break;
 	case (MAN_BODY):
 		term_newln(p);
-		p->flags &= ~TERMP_NOLPAD;
 		break;
 	default:
 		break;
@@ -878,7 +889,7 @@ print_man_node(DECL_ARGS)
 		 * -man doesn't have nested macros, we don't need to be
 		 * more specific than this.
 		 */
-		if (MANT_LITERAL & mt->fl && 
+		if (MANT_LITERAL & mt->fl && ! (TERMP_NOBREAK & p->flags) &&
 				(NULL == n->next || 
 				 n->next->line > n->line)) {
 			rm = p->rmargin;
@@ -886,7 +897,6 @@ print_man_node(DECL_ARGS)
 			p->rmargin = p->maxrmargin = TERM_MAXMARGIN;
 			p->flags |= TERMP_NOSPACE;
 			term_flushln(p);
-			p->flags &= ~TERMP_NOLPAD;
 			p->rmargin = rm;
 			p->maxrmargin = rmax;
 		}
@@ -968,7 +978,7 @@ print_man_foot(struct termp *p, const vo
 		term_word(p, "");
 	term_flushln(p);
 
-	p->flags |= TERMP_NOLPAD | TERMP_NOSPACE;
+	p->flags |= TERMP_NOSPACE;
 	p->offset = p->rmargin;
 	p->rmargin = p->maxrmargin;
 	p->flags &= ~TERMP_NOBREAK;
@@ -1015,7 +1025,7 @@ print_man_head(struct termp *p, const vo
 	term_word(p, title);
 	term_flushln(p);
 
-	p->flags |= TERMP_NOLPAD | TERMP_NOSPACE;
+	p->flags |= TERMP_NOSPACE;
 	p->offset = p->rmargin;
 	p->rmargin = p->offset + buflen + titlen < p->maxrmargin ?
 	    p->maxrmargin - titlen : p->maxrmargin;
@@ -1025,7 +1035,7 @@ print_man_head(struct termp *p, const vo
 
 	p->flags &= ~TERMP_NOBREAK;
 	if (p->rmargin + titlen <= p->maxrmargin) {
-		p->flags |= TERMP_NOLPAD | TERMP_NOSPACE;
+		p->flags |= TERMP_NOSPACE;
 		p->offset = p->rmargin;
 		p->rmargin = p->maxrmargin;
 		term_word(p, title);
--
 To unsubscribe send an email to tech+unsubscribe@mdocml.bsd.lv

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: TERMP_NOLPAD r.i.p.
  2011-09-19 21:39   ` TERMP_NOLPAD r.i.p Ingo Schwarze
@ 2011-09-19 21:58     ` Kristaps Dzonsons
  2011-09-20 11:12       ` Kristaps Dzonsons
  0 siblings, 1 reply; 8+ messages in thread
From: Kristaps Dzonsons @ 2011-09-19 21:58 UTC (permalink / raw)
  To: tech

> Kristaps drew my attention to the fact that the popt(3) manual
> is badly broken:
>
>> .HP
>> .nf
>> .BI "int poptReadDefaultConfig(poptContext " con ", int " flags ");"
>> .fi
>>
>> This looks fine in `ul', but on the raw screen it prints out lots of
>> blank space due to the flush.  Of course, it's because rmargin is
>> set to TERM_MAXMARGIN and the TERMP_NOBREAK goes nuts (in
>> print_man_node()). This can be hacked around by NOT setting rmargin
>> and only setting maxrmargin, but it still looks crappy.  Any
>> thoughts?
>
> Yes, i have come up with the following diff which might be one of the
> most beautiful i have written for mandoc so far:  I suggest to
> enhance functionality and squash bugs - by removing a flag!
>
> Specifically, as long as we have TERMP_NOLPAD, the problem at hand
> is very hard to solve, in particular in the following variant:
>
>    .nf
>    .HP 12n
>    This is a very long tag.
>    .fi
>    This is the indented text; it is of considerable length as well.
>
> With TERMP_NOLPAD, while rendering the first line of the .HP,
> term_flushln() - yes, once again my favourite function -
> overruns the column, breaks the line, and pads to the indent.
> After that, the .fi breaks the already padded line - ouch.
>
> To improve this, we should not pad until we know that we want
> to write actual content to a line, but let the next call to
> term_flushln() do the padding instead; which means that we don't
> need TERMP_NOLPAD any longer.
>
> Some of the chunks are non-obvious:
>
>   * term.c chunk @@ -130,9 +126,10 @@:
>     Always calculate the padding before starting a new line.
>     No more TERMP_NOLPAD.
>   * term.c chunk @@ -232,10 +229,14 @@:
>     An independent bugfix.  Backspace has negative length.
>     Without this, indentation does not get right.
>   * term.c chunk @@ -244,7 +245,8 @@:
>     Handle the edge case of an empty input string:
>     In that case, vis is still zero, and there is no need to go back.
>     This occurs e.g. in man(7) page headers and footers.
>   * term.c chunk @@ -269,25 +271,18 @@:
>     This is the main point.
>     No more padding at the end of term_flushln().
>   * Most other chunks just drop the obsolete flag.
>   * man_term.c chunk @@ -241,6 +241,18 @@:
>     That's the main fix for .HP indentation containing .fi/.nf,
>     and the only ugly chunk in this diff.
>     See the comment in the code what it does.
>   * man_term.c chunk @@ -452,8 +464,11 @@:
>     This adjusts the indentation width to what groff does.
>   * man_term.c chunk @@ -878,7 +889,7 @@:
>     The right margin must not be unlimited in literal mode
>     when TERMP_NOBREAK is in effect.  That avoids the long string
>     of blank characters.
>
> This patch is -65 +50 :).
>
> It reduces groff/mandoc differences in base by nearly 20%,
> from 89k to 72k lines of diffs.
>
> I see no regressions.

Ingo, wow, that's a beautiful patch!  Check it in as soon as you can. 
Tomorrow morning I'll run my own regression tests to see if I can trip 
it up and look at the code itself more carefully (I assume you did the 
usual super-long lines and so on).  But a quick lookover tonight didn't 
show anything that would concern---on the contrary, the code is much 
more readable now.  (Why didn't we do this earlier?  Meh!)

Side note: can you quickly verify that -Tps and/or -Tpdf look froody 
with the change?  They're sensitive to spacing violations.

Thanks again!

Kristaps
--
 To unsubscribe send an email to tech+unsubscribe@mdocml.bsd.lv

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: TERMP_NOLPAD r.i.p.
  2011-09-19 21:58     ` Kristaps Dzonsons
@ 2011-09-20 11:12       ` Kristaps Dzonsons
  2011-09-20 11:14         ` Kristaps Dzonsons
  2011-09-20 12:14         ` Ingo Schwarze
  0 siblings, 2 replies; 8+ messages in thread
From: Kristaps Dzonsons @ 2011-09-20 11:12 UTC (permalink / raw)
  To: tech

Ingo,

This last checkin raised an assertion failure when run over NetBSD's 
manuals.  One can reproduce the failure as follows (cut from 
slapo-retcode.5):

.TH SLAPO-RETCODE 5 "2010/06/30" "OpenLDAP 2.4.23"
.SH NAME
slapo\-retcode \- return code overlay to slapd
.SH DESCRIPTION
This directive defines the parent DN where dynamically generated
entries reside.
If not defined, the suffix of the database is used.
.HP
.hy 0
.B retcode\-item <RDN> <errCode> [op=<oplist>] [text=<message>]
.B [ref=<referral>] [sleeptime=<sec>] [matched=<DN>]
.B [unsolicited=<OID>[:<data>]] [flags=[{pre|post}\-]disconnect[,...]]
.RS
A dynamically generated entry, located below \fBretcode\-parent\fP.

Take care,

Kristaps
--
 To unsubscribe send an email to tech+unsubscribe@mdocml.bsd.lv

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: TERMP_NOLPAD r.i.p.
  2011-09-20 11:12       ` Kristaps Dzonsons
@ 2011-09-20 11:14         ` Kristaps Dzonsons
  2011-09-20 12:14         ` Ingo Schwarze
  1 sibling, 0 replies; 8+ messages in thread
From: Kristaps Dzonsons @ 2011-09-20 11:14 UTC (permalink / raw)
  To: tech

[-- Attachment #1: Type: text/plain, Size: 47 bytes --]

The original file enclosed for completeness...

[-- Attachment #2: slapo-retcode.5 --]
[-- Type: text/plain, Size: 8085 bytes --]

.TH SLAPO-RETCODE 5 "2010/06/30" "OpenLDAP 2.4.23"
.\" Copyright 1998-2010 The OpenLDAP Foundation, All Rights Reserved.
.\" Copying restrictions apply.  See the COPYRIGHT file.
.\" Copyright 2001, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
.\" OpenLDAP: pkg/ldap/doc/man/man5/slapo-retcode.5,v 1.9.2.10 2010/04/13 20:22:44 kurt Exp
.SH NAME
slapo\-retcode \- return code overlay to slapd
.SH SYNOPSIS
/etc/openldap/slapd.conf
.SH DESCRIPTION
The
.B retcode
overlay to
.BR slapd (8)
is useful to test the behavior of clients when server-generated erroneous
and/or unusual responses occur, e.g. error codes, referrals, 
excessive response times and so on.

The error responses are generated according to different strategies.
.LP
In the first case, all operations targeted at a specific configurable
subtree cause the object related to the request DN to be looked up
and checked for return code data: a response code, plus an optional
textual message, an optional configurable delay, an optional matched DN
field, and, when the response code is "referral", a (list of) referral(s).
.LP
Well-known response codes from standard track documents are provided
in \fBretcode.conf\fP, which can be included after instantiating
the overlay.
.LP
In the second case, objects of classes inherited from 
the \fBerrAbsObject\fP, like \fBerrObject\fP or \fBerrAuxObject\fP,
when returned as intermediate responses of a search request, are changed
into the response dictated by their content.
.LP
A third mode causes objects to be looked up from the underlying database 
to discover if their class inherits from \fBerrABsObject\fP;
in that case, their content is used to compute the corresponding response.
.LP
The behavior is disabled by using the \fBmanageDSAit\fP control (RFC 3296);
in that case, the resulting object, either present in the directory 
or dynamically generated by the overlay, or contained in the request,
is handled as usual.
.LP 
The config directives that are specific to the
.B retcode
overlay must be prefixed by
.BR retcode\- ,
to avoid conflicts with directives specific to the underlying database
or to other stacked overlays.  The following specific directives 
can be used to configure the retcode overlay: 
.TP
.B retcode\-parent <DN>
This directive defines the parent DN where dynamically generated
entries reside.
If not defined, the suffix of the database is used.
.HP
.hy 0
.B retcode\-item <RDN> <errCode> [op=<oplist>] [text=<message>]
.B [ref=<referral>] [sleeptime=<sec>] [matched=<DN>]
.B [unsolicited=<OID>[:<data>]] [flags=[{pre|post}\-]disconnect[,...]]
.RS
A dynamically generated entry, located below \fBretcode\-parent\fP.
The \fBerrCode\fP is the number of the response code;
it can be in any format supported by
.BR strtol (3).
The optional \fBoplist\fP is a list of operations that cause
response code generation; if absent, all operations are affected.
The \fBmatched\fP field is the matched DN that is returned
along with the error, while the \fBtext\fP field is an optional
diagnostics message.
The \fBref\fP field is only allowed for the \fBreferral\fP 
response code.
The \fBsleeptime\fP field causes
.BR slapd (8)
to sleep the specified number of seconds before proceeding 
with the operation.
The \fBunsolicited\fP field can be used to cause the return
of an RFC 4511 unsolicited response message; if \fBOID\fP
is not "0", an extended response is generated, with the optional
\fBdata\fP appended.
If \fBflags\fP contains \fBdisconnect\fP, or \fBpre\-disconnect\fP,
.BR slapd (8)
disconnects abruptly, without notice; \fBpost\-disconnect\fP
causes disconnection right after sending response as appropriate.
.RE
.TP
.B retcode\-indir
Enables exploitation of in-directory stored errAbsObject.
May result in a lot of unnecessary overhead.
.TP
.B retcode\-sleep [\-]<n>
Defines a sleep time in seconds that is spent before actually handling
any operation.
If negative, a random time between 0 and the absolute value of the argument
is used.

.SH SCHEMA
The
.B retcode
overlay utilizes the "return code" schema described herein. 
This schema is specifically designed for use with this
overlay and is not intended to be used otherwise.
It is also noted that the schema described here is
.I a work in
.IR progress ,
and hence subject to change without notice.
The schema is loaded automatically by the overlay.

The schema includes a number of object classes and associated
attribute types as described below.

.LP
The error code:
.RS 4
(  1.3.6.1.4.1.4203.666.11.4.1.1
    NAME ( 'errCode' )
    DESC 'LDAP error code'
    EQUALITY integerMatch
    ORDERING integerOrderingMatch
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
    SINGLE\-VALUE )
.RE
.LP
The operations that trigger the response code:
.RS 4
( 1.3.6.1.4.1.4203.666.11.4.1.2
    NAME ( 'errOp' )
    DESC 'Operations the errObject applies to'
    EQUALITY caseIgnoreMatch
    SUBSTR caseIgnoreSubstringsMatch
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
.RE
.LP
The text message:
.RS 4
( 1.3.6.1.4.1.4203.666.11.4.1.3
    NAME ( 'errText' )
    DESC 'LDAP error textual description'
    EQUALITY caseIgnoreMatch
    SUBSTR caseIgnoreSubstringsMatch
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
    SINGLE\-VALUE )
.RE
.LP
The sleep time before the response is actually returned to the client:
.RS 4
( 1.3.6.1.4.1.4203.666.11.4.1.4
    NAME ( 'errSleepTime' )
    DESC 'Time to wait before returning the error'
    EQUALITY integerMatch
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
    SINGLE\-VALUE )
.RE
.LP
The matched DN returned to the client:
.RS 4
( 1.3.6.1.4.1.4203.666.11.4.1.5
    NAME ( 'errMatchedDN' )
    DESC 'Value to be returned as matched DN'
    EQUALITY distinguishedNameMatch
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
    SINGLE\-VALUE )
.RE
.LP
The OID to be returned as extended response OID
in RFC 4511 unsolicited responses
("0" generates a regular response with msgid set to 0):
.RS 4
( 1.3.6.1.4.1.4203.666.11.4.1.6
    NAME ( 'errUnsolicitedOID' )
    DESC 'OID to be returned within unsolicited response'
    EQUALITY objectIdentifierMatch
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.38
    SINGLE\-VALUE )
.RE
.LP
The octet string to be returned as extended response data
in RFC 4511 unsolicited response:
.RS 4
( 1.3.6.1.4.1.4203.666.11.4.1.7
    NAME ( 'errUnsolicitedData' )
    DESC 'Data to be returned within unsolicited response'
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
    SINGLE\-VALUE )
.RE
.LP
If TRUE,
.BR slapd (8)
disconnects abruptly without notice; if FALSE, it disconnects
after sending response as appropriate:
.RS 4
( 1.3.6.1.4.1.4203.666.11.4.1.8
    NAME ( 'errDisconnect' )
    DESC 'Disconnect without notice'
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
    SINGLE\-VALUE )
.RE
.LP
The abstract class that triggers the overlay:
.RS 4
( 1.3.6.1.4.1.4203.666.11.4.3.0
    NAME ( 'errAbsObject' )
    SUP top ABSTRACT
    MUST ( errCode )
    MAY ( cn $ description $ errOp $ errText $ errSleepTime
        $ errMatchedDN ) )
.RE
.LP
The standalone structural objectclass for specifically created data:
.RS 4
( 1.3.6.1.4.1.4203.666.11.4.3.1
    NAME ( 'errObject' )
    SUP errAbsObject STRUCTURAL )
.RE
.LP
The auxiliary objectclass to alter the behavior of existing objects:
.RS 4
( 1.3.6.1.4.1.4203.666.11.4.3.2
    NAME ( 'errAuxObject' )
    SUP errAbsObject AUXILIARY )
.RE

.SH EXAMPLE
.LP
.RS
.nf
overlay         retcode
retcode\-parent  "ou=RetCodes,dc=example,dc=com"

# retcode.conf is found in tests/data/ of the source tree
include         ./retcode.conf

# Wait 10 seconds, then return success (0x00)
retcode\-item    "cn=Success after 10 seconds" 0x00 sleeptime=10
# Wait 10 seconds, then return timelimitExceeded (0x03)
retcode\-item    "cn=Timelimit after 10 seconds" 0x03 sleeptime=10
.fi
.RE
.LP
.LP

.SH FILES
.TP
/etc/openldap/slapd.conf
default slapd configuration file
.SH SEE ALSO
.BR slapd.conf (5),
.BR slapd\-config (5),
.BR slapd (8).
The
.BR slapo\-retcode (5)
overlay supports dynamic configuration via
.BR back-config .
.SH ACKNOWLEDGEMENTS
.P
This module was written in 2005 by Pierangelo Masarati for SysNet s.n.c.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: TERMP_NOLPAD r.i.p.
  2011-09-20 11:12       ` Kristaps Dzonsons
  2011-09-20 11:14         ` Kristaps Dzonsons
@ 2011-09-20 12:14         ` Ingo Schwarze
  2011-09-20 12:26           ` Kristaps Dzonsons
  1 sibling, 1 reply; 8+ messages in thread
From: Ingo Schwarze @ 2011-09-20 12:14 UTC (permalink / raw)
  To: tech

Hi Kristaps,

Kristaps Dzonsons wrote on Tue, Sep 20, 2011 at 01:12:29PM +0200:

> This last checkin raised an assertion failure when run over NetBSD's
> manuals.  One can reproduce the failure as follows (cut from
> slapo-retcode.5):
> 
> .TH SLAPO-RETCODE 5 "2010/06/30" "OpenLDAP 2.4.23"
> .SH NAME
> slapo\-retcode \- return code overlay to slapd
> .SH DESCRIPTION
> This directive defines the parent DN where dynamically generated
> entries reside.
> If not defined, the suffix of the database is used.
> .HP
> .hy 0
> .B retcode\-item <RDN> <errCode> [op=<oplist>] [text=<message>]
> .B [ref=<referral>] [sleeptime=<sec>] [matched=<DN>]
> .B [unsolicited=<OID>[:<data>]] [flags=[{pre|post}\-]disconnect[,...]]
> .RS
> A dynamically generated entry, located below \fBretcode\-parent\fP.

Looks like that is an unrelated bug in pre_RS, merely uncovered
by the changes.  When changing the output offset, .RS neglects
to reset the right margin to the default, and it also neglects
to check whether the offset fits into the margin.

The following fixes the (ugly!) test page, and i see no
regressions.

OK?
  Ingo


Index: man_term.c
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/man_term.c,v
retrieving revision 1.73
diff -u -p -r1.73 man_term.c
--- man_term.c	20 Sep 2011 09:02:18 -0000	1.73
+++ man_term.c	20 Sep 2011 12:04:15 -0000
@@ -822,7 +822,8 @@ pre_RS(DECL_ARGS)
 			sz = (size_t)ival;
 
 	mt->offset += sz;
-	p->offset = mt->offset;
+	p->rmargin = p->maxrmargin;
+	p->offset = mt->offset < p->rmargin ? mt->offset : p->rmargin;
 
 	if (++mt->lmarginsz < MAXMARGINS)
 		mt->lmargincur = mt->lmarginsz;
--
 To unsubscribe send an email to tech+unsubscribe@mdocml.bsd.lv

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: TERMP_NOLPAD r.i.p.
  2011-09-20 12:14         ` Ingo Schwarze
@ 2011-09-20 12:26           ` Kristaps Dzonsons
  2011-09-20 13:34             ` Ingo Schwarze
  0 siblings, 1 reply; 8+ messages in thread
From: Kristaps Dzonsons @ 2011-09-20 12:26 UTC (permalink / raw)
  To: tech

[-- Attachment #1: Type: text/plain, Size: 288 bytes --]

That indeed fixes it!  But another takes its place... The relevant file 
is enclosed.

Attached is also, by the way, is a tiny patch to make compilation with 
-Wallpossibilities (or whatever the correct combination is).  Still 
haven't had time to play with this new mode... :(

Kristaps

[-- Attachment #2: groff_hdtbl.man --]
[-- Type: application/x-troff-man, Size: 17744 bytes --]

[-- Attachment #3: patch.txt --]
[-- Type: text/plain, Size: 511 bytes --]

Index: mdoc_man.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/mdoc_man.c,v
retrieving revision 1.1
diff -u -r1.1 mdoc_man.c
--- mdoc_man.c	17 Sep 2011 15:00:51 -0000	1.1
+++ mdoc_man.c	20 Sep 2011 12:26:00 -0000
@@ -31,8 +31,8 @@
 	int		(*cond)(DECL_ARGS);
 	int		(*pre)(DECL_ARGS);
 	void		(*post)(DECL_ARGS);
-	char		 *prefix;
-	char		 *suffix;
+	const char	 *prefix;
+	const char	 *suffix;
 };
 
 static	void	  print_word(const char *);

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: TERMP_NOLPAD r.i.p.
  2011-09-20 12:26           ` Kristaps Dzonsons
@ 2011-09-20 13:34             ` Ingo Schwarze
  2011-09-20 14:05               ` Kristaps Dzonsons
  0 siblings, 1 reply; 8+ messages in thread
From: Ingo Schwarze @ 2011-09-20 13:34 UTC (permalink / raw)
  To: tech

Hi Kristaps,

Kristaps Dzonsons wrote on Tue, Sep 20, 2011 at 02:26:16PM +0200:

> That indeed fixes it!  But another takes its place... The relevant
> file is enclosed.

I have no idea why this pops up only now, but let's fix it
anyway.

The problem is that groff_hdtbl(7) is doing something like

  .de OUCH
  .TP
  .BI
  ..
  .OUCH

tricking the .TP macro and its *next-line* head argument
onto the *same* input line.  So .TP is not allowed to assume
that a head argument being on the same line is indeed a same-line
argument.

I don't see any other similar case in this source file,
and i don't see any regressions.

OK?
  Ingo


P.S.:
Of course, the fix only fixes the segfault.
This raises a more serious question:
In the view of macros, our use of the source line
for semantic purposes is fundamentally broken.
We do that at several places.

P.P.S.:
Mandoc is definitely not the right tool to process groff_hdtbl(7),
but at least it shouldn't segfault.


Index: man_term.c
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/man_term.c,v
retrieving revision 1.74
diff -u -p -r1.74 man_term.c
--- man_term.c	20 Sep 2011 13:13:21 -0000	1.74
+++ man_term.c	20 Sep 2011 13:16:41 -0000
@@ -636,7 +636,7 @@ pre_TP(DECL_ARGS)
 	/* Calculate offset. */
 
 	if (NULL != (nn = n->parent->head->child))
-		if (nn->parent->line == nn->line)
+		if (nn->string && nn->parent->line == nn->line)
 			if ((ival = a2width(p, nn->string)) >= 0)
 				len = (size_t)ival;
 
--
 To unsubscribe send an email to tech+unsubscribe@mdocml.bsd.lv

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: TERMP_NOLPAD r.i.p.
  2011-09-20 13:34             ` Ingo Schwarze
@ 2011-09-20 14:05               ` Kristaps Dzonsons
  0 siblings, 0 replies; 8+ messages in thread
From: Kristaps Dzonsons @ 2011-09-20 14:05 UTC (permalink / raw)
  To: tech

> I have no idea why this pops up only now, but let's fix it
> anyway.
>
> The problem is that groff_hdtbl(7) is doing something like
>
>    .de OUCH
>    .TP
>    .BI
>    ..
>    .OUCH
>
> tricking the .TP macro and its *next-line* head argument
> onto the *same* input line.  So .TP is not allowed to assume
> that a head argument being on the same line is indeed a same-line
> argument.
>
> I don't see any other similar case in this source file,
> and i don't see any regressions.
>
> OK?
>    Ingo
>
>
> P.S.:
> Of course, the fix only fixes the segfault.
> This raises a more serious question:
> In the view of macros, our use of the source line
> for semantic purposes is fundamentally broken.
> We do that at several places.
>
> P.P.S.:
> Mandoc is definitely not the right tool to process groff_hdtbl(7),
> but at least it shouldn't segfault.

Ingo,

I agree on all [P]+S's and note that this fixes the assertion.  I'm now 
able to run through all manuals in all base BSDs without any errors.

Thanks again!

Kristaps
--
 To unsubscribe send an email to tech+unsubscribe@mdocml.bsd.lv

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2011-09-20 14:05 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20110918161317.GE29692@iris.usta.de>
     [not found] ` <4E765AFE.9070302@bsd.lv>
2011-09-19 21:39   ` TERMP_NOLPAD r.i.p Ingo Schwarze
2011-09-19 21:58     ` Kristaps Dzonsons
2011-09-20 11:12       ` Kristaps Dzonsons
2011-09-20 11:14         ` Kristaps Dzonsons
2011-09-20 12:14         ` Ingo Schwarze
2011-09-20 12:26           ` Kristaps Dzonsons
2011-09-20 13:34             ` Ingo Schwarze
2011-09-20 14:05               ` Kristaps Dzonsons

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