sub trigram
#	Replace each of a list of characters with its hex value, preceded
#	by a key character ID'ing the replacement; eg, replace blank w/%20
#	Functionality duplicates trigram_utils, but latter cannot be
#	easily used if target characters are special to shell
#
#	Takes 3 args: string whose characters are to be replaced
#		      list of characters to replace
#		      ID character (may not be null)
#	Returns 2 strings: status ("OK","NG","WARN")
#			   if NG, diagnostic message
#			   if not NG, string w/replacements
#	If ID character is itself to be replaced, it must be first in
#	replacement list.  If ID character is NOT to be replaced, then
#	its presence in the source string results in a WARN
{
  my ($string,$trigram_list,$trigram_char,$dummy) = @_;
  my ($convert_trigram_char_OK,$trigram_char_in_string,$pos_in_list);

  (defined $trigram_char) || return "NG","missing argument";
  (defined $dummy) && return "NG","extra argument";
#   Code below PROBABLY works w/null trigram_char, but didn't look into it
  ($trigram_char eq "") && return "NG","null trigram character";

  $_ = quotemeta($trigram_char);
  $trigram_char_in_string = ($string =~ /$_/);

  $convert_trigram_char_OK = 0;
  $pos_in_list = 0;

  foreach (split ("",$trigram_list)) {
    if ($_ eq $trigram_char) {
#	If trigram_char is in conversion list, it must be first
#	As a corollary, it can only be converted once (not counting
#	  multiple consec times at the beginning!).  Tolerate multiples
#	  if first time was proper,  but out-of-position is an error
#	We could re-order the list in here, but that is probably more work
#	  than the trigramming.  As coded, all we do is an extra test per
#	  char in trigram_list (plus a couple of statements if we find the
#	  trigram char)
      if ($pos_in_list == 0) {
	$convert_trigram_char_OK = 1;
      } else {
	$convert_trigram_char_OK && next;
	return "NG",
	  "if trigram char is itself to be trigrammed, it must lead list";
      }
    }
    $trigram = $trigram_char . sprintf ("%2.X",ord);
    $_ = quotemeta;
    $string =~ s/$_/$trigram/g;
    $pos_in_list++;
  }
#   Probably trouble if there was a trigram char in the input that didn't
#   itself get trigrammed ... but I'm not REALLY sure it should be an error
#   That's what multiple statuses are for - let the caller worry!
  $status = 
	(   $convert_trigram_char_OK || (! $trigram_char_in_string)    )
				?
	"OK" : "WARN";
  return $status,$string;
}
1
