diff options
Diffstat (limited to 'Master/texmf-dist/doc/latex/latex-web-companion/ch7/SGMLS/Refs.pm')
-rw-r--r-- | Master/texmf-dist/doc/latex/latex-web-companion/ch7/SGMLS/Refs.pm | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/Master/texmf-dist/doc/latex/latex-web-companion/ch7/SGMLS/Refs.pm b/Master/texmf-dist/doc/latex/latex-web-companion/ch7/SGMLS/Refs.pm new file mode 100644 index 00000000000..3e3f563770c --- /dev/null +++ b/Master/texmf-dist/doc/latex/latex-web-companion/ch7/SGMLS/Refs.pm @@ -0,0 +1,216 @@ +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->put("document title",$title); + +To retrieve a reference: + + $title = $refs->get("document title"); + +To return the number of references changed since the last run: + + $num = $refs->changed; + +To print a LaTeX-like warning if any references have changed: + + $refs->warn; + +=head1 DESCRIPTION + +This library can be used together with the B<SGMLS> package to keep +track of forward references from one run to another, like the B<LaTeX> +C<.aux> 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->warn; }); + + # Look up the title from the last parse, if available. + sgml('<div>', sub { + my $element = shift; + my $id = $element->attribute(ID)->value; + my $title = $refs->get("title:$id") || "[no title available]"; + + $current_div_id = $id; + + output "\\section{$title}\n\n"; + }); + + + # Save the title for the next parse. + sgml('<head>', sub { push_output('string'); }); + sgml('</head>', sub { + my $title = pop_output(); + my $id = $current_div_id; + + $refs->put("title:$id",$title); + }); + + +=head1 AUTHOR AND COPYRIGHT + +Copyright 1994 and 1995 by David Megginson, +C<dmeggins@aix1.uottawa.ca>. Distributed under the terms of the Gnu +General Public License (version 2, 1991) -- see the file C<COPYING> +which is included in the B<SGMLS.pm> distribution. + + +=head1 SEE ALSO: + +L<SGMLS>, L<SGMLS::Output>. + +=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,"<$filename")) { + $/ = 0777; + $self->{'refs'} = eval <$handle> || {}; + close $handle; + } else { + $self->{'refs'} = {}; + } + + # Open the reference file. + open($handle,">$filename") || croak $@; + + # Open the log file, if any. + if ($logname) { + open($loghandle,">$logname") || croak $@; + } + + # Note pertinent information. + $self->{'change_count'} = 0; + $self->{'handle'} = $handle; + $self->{'loghandle'} = $loghandle; + $self->{'filename'} = $filename; + $self->{'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->{'loghandle'}; + my $oldvalue = $self->{'refs'}->{$key}; + + if ($oldvalue ne $value) { + $self->{'change_count'}++; + if ($loghandle) { + print $loghandle "\"$key\" changed from " . + + "\"$oldvalue\" to \"$value\".\n"; + } + $self->{'refs'}->{$key} = $value; + } + + return $oldvalue; +} + +# +# Grab the value of a reference. +# +sub get { + my ($self,$key) = (@_); + + return $self->{'refs'}->{$key}; +} + +# +# Return the number of changed references. +# +sub changed { + my $self = shift; + return $self->{'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->{'change_count'}; + my $filename = $self->{'filename'}; + my $plural = "references have"; + + $plural = "reference has" if $count == 1; + if ($count > 0) { + warn "SGMLS::Refs ($filename): $count $plural changed.\n"; + return 1; + } + return 0; +} + +sub DESTROY { + my $self = shift; + my $handle = $self->{'handle'}; + + close $self->{'loghandle'}; + + print $handle "{\n"; + foreach $key (keys %{$self->{'refs'}}) { + my $value = $self->{'refs'}->{$key}; + $key =~ s/\\/\\\\/g; + $key =~ s/'/\\'/g; + $value =~ s/\\/\\\\/g; + $value =~ s/'/\\'/g; + print $handle " '$key' => '$value',\n"; + } + print $handle " '' => ''\n}\n"; +} + +$handle_counter = 1; +sub generate_handle { + return "Handle" . $handle_counter++; +} + +1; + |