When I said,
| >So far the only way I see to do this without an external program is a
| >recursive INCLUDERC, and those things can be vicious.
Philip Guenther responded,
| That sounded like a challenge, so I crafted the following.
Well, ok, I've deconstructed it. (You knew I would.)
G> # Put the regexp of the lines to examine in REGEXP
G> :0
G> * ^Resent-(From|Date|To|Cc|Message-Id):
G> { REGEXP = "^Resent-(To|Cc):" }
G> :0E
G> { REGEXP = "^(To|Cc):" }
So far no quibbles.
G> # Put the string to match against in HEADER
G> :0
G> * ^^\/.*^^
G> { HEADER = $MATCH }
Given that the head will not start out with a match to $REGEXP, let's discard
the initial stuff (From_, Return-Path:, Received:, Message-Id:) right now.
Now, $HEADER will never contain the entire head, so it's a different concept,
which I'll name $HEADERLINES:
# Put the string to match against into $HEADERLINES
:0 # H is implicit
* $ ()\/$REGEXP(.*)$
{ HEADERLINES = $MATCH }
Now, instead of using (and explaining) ${COUNT:-0} in both the main rcfile
and in the recursively called rcfile, let's just preset
COUNT=0
right here. It also takes care of the situation where we may have used
the same variable earlier and it may already have a value that we don't want.
Better yet, since we're going to subtract nineteen anyway,
EXCESS=-19
G> # Count'em
G> INCLUDERC = count_comma_sep.rc
Here's the continuing code in the main rcfile after returning from the
recursion:
G> # Beware: if there were no matches, then COUNT will be unset, so use
G> # ${COUNT:-0} ala Bourne shell.
G> :0
G> * $ ${COUNT:-0}^0
G> * -19^0
G> { EXITCODE=77 HOST }
EXCESS is always set, and the 19 has already been subtracted, so
:0 # count was predefined and prejudiced at -19
* $ $EXCESS^0
{ EXITCODE=77 HOST }
If, for some odd reason, there are no recipients in the head, we shouldn't
use the other rcfile even once. So, then, we have this:
# Put the string to match against into $HEADERLINES
:0 # H is implicit
* $ ()\/$REGEXP(.*)$
{
# Set up the initial run.
HEADERLINES = $MATCH
EXCESS = -19
# Let it rip.
INCLUDERC = count_comma_sep.rc
:0 # count was predefined and prejudiced at -19
* $ $EXCESS^0
{ EXITCODE=77 HOST }
}
Now, to the code in the included rcfile:
G> Then in the file count_comma_sep.rc put:
G>
G> # Goal: count the number of commas separated items in HEADER at the
G> # end of the lines that match $REGEXP. COUNT will keep the running
G> # total.
# Goal: count the number of comma-separated items in $HEADERLINES in
# lines that begin with $REGEXP. EXCESS will keep the running excess
# over 19.
G> # Clear MATCH, then count the items in the first match, if any.
G> MATCH=
G> :0
G> * 1^0 HEADER ?? $ $REGEXP\/.*
G> * 1^1 MATCH ?? ,
G> {
Looks good (though I'd need to change HEADER to HEADERLINES, of course).
G> # Okay, increment COUNT by $=. Beware, COUNT may be unset, so use
G> # ${COUNT:-0} to get it's value if any, or zero if none.
G> :0
G> * $ $=^0
G> * $ ${COUNT:-0}^0
G> { COUNT = $= }
EXCESS won't be unset or null, and personally I like the addends in the other
order (though that part really doesn't matter).
# Okay, increment EXCESS by $=.
:0
* $ $EXCESS^0
* $ $=^0
{ EXCESS = $= }
All right then ... moving onward ...
G> # Now, do we need to recurse? Only if there's more than one
G> # match of $REGEXP.
G> :0
G> * -1^0
G> * 1^1 HEADER ?? $ $REGEXP
G> {
G> # We do. We'll need to reset HEADER to only contain everything
G> # *after* the first match.
G> :0
G> * HEADER ?? $ $REGEXP.*($)\/(.*($)?)*
If there are other lines between the line we just tested and the next one of
any value, we're still keeping them around in $HEADERLINES when we can, lose
them
right now. So let's do this:
* HEADERLINES ?? $ $REGEXP(.*$)*\/$REGEXP(.*$)*
In fact, that can be used as the recursion test as well and makes the
previous scoring unnecessary. I think I'll modify the entire recursion
test below, including the effect on the remaining lines, which were:
G> { HEADER = $MATCH }
G>
G> # Recurse!
G> INCLUDERC = $_
G> }
# Now, do we need to recurse? Only if there's still another
# match to $REGEXP. If so, we reset $HEADERLINES to contain only
# the second match and beyond, and then we take another ride.
:0
* HEADERLINES ?? $ $REGEXP(.*$)*\/$REGEXP(.*$)*
{
HEADERLINES = $MATCH
# Recurse!
INCLUDERC = $_
}
Then let's include the closing brace from Philip's original code:
G> }