To better see what is happening inside each rule,
rerun *sendmail* with a `-d21.12`

debugging command-line
switch:

%

./sendmail -Cclient.cf -d21.12 -bt

The `-d21.12`

switch tells *sendmail* to print each
rule as it is processed. Run *sendmail* again with
this new switch. This time, when you feed in a
nested address, you get considerably more output:

>`rewrite: ruleset 3 input: < a < b > c > ---trying rule: $* < > $* --- rule fails ---trying rule: $* < $* < $* > $* > $* ---rule matches: $2 < $3 > $4 rewritten as: a < b > c ---trying rule: $* < $* < $* > $* > $* --- rule fails ---trying rule: $* < $* > $* ---rule matches: $2 rewritten as: b ---trying rule: $* < $* > $* --- rule fails rewrite: ruleset 3 returns: b`

3 <a<b>c>

This output may appear complicated, but it is really fairly straightforward.
The first two lines and last line are what you have been seeing
all along (when you *didn't* use the `-d21.12`

switch):

>`rewrite: ruleset 3 input: < a < b > c > rewrite: ruleset 3 returns: b`

3 <a<b>c>

Everything in between those lines is new output caused by the `-d21.12`

switch.
That new output shows each rule in rule set 3 being called and
processed in turn.
The first rule looks for empty angle brackets:

R$* <> $* $n handle <> error address

The workspace (tokenized from the input of `<a<b>c>`

)
is compared to the LHS of this rule:

---trying rule: $* < > $* --- rule fails

The LHS doesn't match (the rule fails) because the angle brackets of the workspace are not empty. Consequently, the RHS of the first rule is not called, and the workspace is unchanged.

The second rule is the de-nesting one:

R$* < $* < $* > $* > $* $2<$3>$4 de-nest brackets

The workspace (still `<a<b>c>`

) is compared to the LHS of this rule.

---trying rule: $* < $* < $* > $* > $*

The LHS matches the workspace, so the workspace is rewritten on the basis of the RHS of that rule, and the extra angle brackets are stripped away:

---rule matches: $2 < $3 > $4 rewritten as: a < b > c

The new workspace is then compared to the LHS of the same rule
*once again* - that is, to the rule that just did the rewriting.
If it were to match again, it would be rewritten again. This
property (which in error can continue forever) can be useful in solving many
configuration problems. We'll cover this property more fully in the
next chapter.

So the rewritten workspace is compared once again to the second rule. The workspace (having been rewritten by the second rule) now contains

a < b > c

This time the comparison fails:

---trying rule: $* < $* < $* > $* > $* --- rule fails

The last of the three rules then gets a crack at the workspace. That rule is

R$* < $* > $* $2 basic RFC822 parsing

That workspace is still

a < b > c

The workspace is once again matched, so it is rewritten again on the basis of the RHS of the third rule:

---trying rule: $* < $* > $* ---rule matches: $2 rewritten as: b

After the third rule rewrites the workspace, it again tries to match that rewritten workspace and fails:

---trying rule: $* < $* > $* --- rule fails

As you can see, the `-d21.12`

debugging switch can be
very useful. It shows you exactly what each rule is trying
to do. It shows you each rewrite of the workspace, and it
shows you the order in which rules are being applied.
(Note that in real rule sets, this output can easily span many screens.)