<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">package SGMLS::Refs;

use Carp;

$version = '$Id: Refs.pm,v 1.5 1995/12/03 21:28:36 david Exp $';

=head1 NAME

SGMLS::Refs

=head1 SYNOPSIS

  use SGMLS::Refs;

To create a new reference-manager object using the file "foo.refs":

  my $refs = new SGMLS::Refs("foo.refs");

To create a new reference-manager object using the file "foo.refs" and
logging changes to the file "foo.log":

  my $refs = new SGMLS::Refs("foo.refs","foo.log");

To record a reference:

  $refs-&gt;put("document title",$title);

To retrieve a reference:

  $title = $refs-&gt;get("document title");

To return the number of references changed since the last run:

  $num = $refs-&gt;changed;

To print a LaTeX-like warning if any references have changed:

  $refs-&gt;warn;

=head1 DESCRIPTION

This library can be used together with the B&lt;SGMLS&gt; package to keep
track of forward references from one run to another, like the B&lt;LaTeX&gt;
C&lt;.aux&gt; files.  Each reference manager is an object which reads and
then rewrites a file of perl source, with the file name provided by
the caller.

Example:

  # Start up the reference manager before the parse.
  sgml('start', sub { $refs = new SGMLS::Refs("foo.refs"); });

  # Warn about any changed references at the end.
  sgml('end', sub { $refs-&gt;warn; });

  # Look up the title from the last parse, if available.
  sgml('&lt;div&gt;', sub { 
    my $element = shift;
    my $id = $element-&gt;attribute(ID)-&gt;value;
    my $title = $refs-&gt;get("title:$id") || "[no title available]";

    $current_div_id = $id;

    output "\\section{$title}\n\n";
  });


  # Save the title for the next parse.
  sgml('&lt;head&gt;', sub { push_output('string'); });
  sgml('&lt;/head&gt;', sub {
    my $title = pop_output();
    my $id = $current_div_id;

    $refs-&gt;put("title:$id",$title);
  });
  

=head1 AUTHOR AND COPYRIGHT

Copyright 1994 and 1995 by David Megginson,
C&lt;dmeggins@aix1.uottawa.ca&gt;.  Distributed under the terms of the Gnu
General Public License (version 2, 1991) -- see the file C&lt;COPYING&gt;
which is included in the B&lt;SGMLS.pm&gt; distribution.


=head1 SEE ALSO:

L&lt;SGMLS&gt;, L&lt;SGMLS::Output&gt;.

=cut

#
# Create a new instance of a reference manager.  The first argument is
# the filename for the database, and the second (if present) is a
# filename for logging changes.
#
sub new {
    my ($class,$filename,$logname) = (@_);
    my $self = {};
    my $handle = generate_handle();
    my $loghandle = generate_handle() if $logname;
    my $oldRS = $/;		# Save old record separator.

    # Read the current contents of the reference file (if any).
    if (open($handle,"&lt;$filename")) {
	$/ = 0777;
	$self-&gt;{'refs'} = eval &lt;$handle&gt; || {};
	close $handle;
    } else {
	$self-&gt;{'refs'} = {};
    }

    # Open the reference file.
    open($handle,"&gt;$filename") || croak $@;

    # Open the log file, if any.
    if ($logname) {
	open($loghandle,"&gt;$logname") || croak $@;
    }

    # Note pertinent information.
    $self-&gt;{'change_count'} = 0;
    $self-&gt;{'handle'} = $handle;
    $self-&gt;{'loghandle'} = $loghandle;
    $self-&gt;{'filename'} = $filename;
    $self-&gt;{'logname'} = $logname;

    $/ = $oldRS;		# Restore old record separator.
    return bless $self;
}

#
# Set a reference's value.  If the value is unchanged, don't do anything;
# otherwise, note the change by counting it and (optionally) logging it
# to the file handle provided when the object was created.
#
sub put {
    my ($self,$key,$value) = (@_);
    my $loghandle = $self-&gt;{'loghandle'};
    my $oldvalue = $self-&gt;{'refs'}-&gt;{$key};
    
    if ($oldvalue ne $value) {
	$self-&gt;{'change_count'}++;
	if ($loghandle) {
	    print $loghandle "\"$key\" changed from " .
	      
	      "\"$oldvalue\" to \"$value\".\n";
	}
	$self-&gt;{'refs'}-&gt;{$key} = $value;
    }

    return $oldvalue;
}

#
# Grab the value of a reference.
#
sub get {
    my ($self,$key) = (@_);

    return $self-&gt;{'refs'}-&gt;{$key};
}

#
# Return the number of changed references.
#
sub changed {
    my $self = shift;
    return $self-&gt;{'changed_count'};
}

#
# Print a warning if any references have
# changed (a la LaTeX -- so that the user knows that another pass is
# necessary).  Return 1 if a warning has been printed, or 0 if it
# was unnecessary.
#
sub warn {
    my $self = shift;
    my $count = $self-&gt;{'change_count'};
    my $filename = $self-&gt;{'filename'};
    my $plural = "references have";

    $plural = "reference has" if $count == 1;
    if ($count &gt; 0) {
	warn "SGMLS::Refs ($filename): $count $plural changed.\n";
	return 1;
    }
    return 0;
}

sub DESTROY {
    my $self = shift;
    my $handle = $self-&gt;{'handle'};

    close $self-&gt;{'loghandle'};

    print $handle "{\n";
    foreach $key (keys %{$self-&gt;{'refs'}}) {
	my $value = $self-&gt;{'refs'}-&gt;{$key};
	$key =~ s/\\/\\\\/g;
	$key =~ s/'/\\'/g;
	$value =~ s/\\/\\\\/g;
	$value =~ s/'/\\'/g;
	print $handle "  '$key' =&gt; '$value',\n";
    }
    print $handle "  '' =&gt; ''\n}\n";
}

$handle_counter = 1;
sub generate_handle {
    return "Handle" . $handle_counter++;
}

1;

</pre></body></html>