#!/usr/local/bin/perl -w
#
# $Id$
#
# Go through an SGML document looking for <!ENTITY ... > entries.
#
# After finding one do our best to 'neutralise' it. The neutralising
# is to try and make SGML parsers ignore the ENTITY when they find it
# in documents that use it. Do this by making the entity resolve to
# it's own name.
#
# For example,
#
#    <!ENTITY foo "This is some text">
#
# will be converted to
#
#    <!ENTITY foo CDATA "&foo;" -- "This is some text" -->
#
# and
#
#    <!ENTITY foo SYSTEM "name_of_file.sgml">
#
# becomes
#
#    <!ENTITY foo CDATA "-entity-foo;" -- SYSTEM "name_of_file.sgml" -->
#
# Ignores parameter entities.
#
# The flag '-r' will reverse the effects of this script (hopefully)
# The flag '-m' is used for files with <!ENTITY ... > lines over multiple lines

use strict;
use Getopt::Std;

use vars qw($opt_r $opt_m);

getopts('rm');

if(defined $opt_m) {
    $/ = "\n\n";
} else {
    $/ = "\n";
}


if(! defined $opt_r) {			     # Do the work
    while(<>) {
	chomp;
	  
	s/(<!ENTITY[^%]*>)/neutralise($1)/iseg;

	print $_, $/;   
    }
} else {				     # Reverse the process
    while(<>) {
	chomp;
	
	s/(<!ENTITY[^%]*?--.*?-->)/activate($1)/iseg;
	
	print $_, $/;
    }
}
    
exit 0;

# ------------------------------------------------------------------------

    
sub neutralise {
    my $entity = shift;

    # Comment out the text of the entity (as well as it's type definition,
    # if any) and put  'CDATA "-entity-entity_name;"' in front of it.
    $entity =~
      m/<!ENTITY			     # <!ENTITY
	\s+				     # Aribtrary whitespace
	(.*?)				     # Entity name ($1)
	\s+				     # Arbitrary whitespace
	(.*)				     # Rest of entity definition ($2)
	>/xsi;

    return "<!ENTITY $1 CDATA \"-entity-$1;\" -- $2 -->";
}

sub activate {
    my $entity = shift;

    # Replace the entity definition with the commented out version. Assume
    # the commented out version was put there by a previous invocation
    # of this program

    # If the entity doesn't match what we're looking for then return
    # it unchanged.
    return $entity
      if $entity !~ /<!ENTITY (.*?) CDATA ".*?" -- (.*?) -->/si;

    return "<!ENTITY $1 $2>";
}
