This file is indexed.

/usr/share/perl5/Biblio/EndnoteStyle.pm is in libbiblio-endnotestyle-perl 0.05-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
# $Id: EndnoteStyle.pm,v 1.10 2007/10/04 00:07:03 mike Exp $

package Biblio::EndnoteStyle;

use 5.006;
use strict;
use warnings;

our $VERSION = 0.05;

=head1 NAME

Biblio::EndnoteStyle - reference formatting using Endnote-like templates

=head1 SYNOPSIS

 use Biblio::EndnoteStyle;
 $style = new Biblio::EndnoteStyle();
 ($text, $errmsg) = $style->format($template, \%fields);

=head1 DESCRIPTION

This small module provides a way of formatting bibliographic
references using style templates similar to those used by the popular
reference management software Endnote (http://www.endnote.com/).  The
API is embarrassingly simple: a formatter object is made using the
class's constructor, the C<new()> method; C<format()> may then be
repeatedly called on this object, using the same or different
templates.

(The sole purpose of the object is to cache compiled templates so that
multiple C<format()> invocations are more efficient than they would
otherwise be.  Apart from that, the API might just as well have been a
single function.)

=head1 METHODS

=head2 new()

 $style = new Biblio::EndnoteStyle();

Creates a new formatter object.  Takes no arguments.

=cut

# The object is vacuous except that it knows its class, so that
# subclasses can be made that override some of the methods.
#
sub new {
    my $class = shift();

    return bless {
	debug => 0,
	compiled => {},		# cache of compiled templates
    }, $class;
}


=head2 debug()

 $olddebug = $style->debug(1);

Turns debugging on or off and returns the old debugging status.  If an
argument is provided, then debugging is turned either on or off
according to whether then argument is true or false.  In any case, the
old value of the debugging status is returned, so that a call with no
argument is a side-effect-free inquiry.

When debugging is turned on, compiled templates are dumped to standard
error.  It is not pretty.

=cut

sub debug {
    my $this = shift();
    my($val) = @_;

    my $old = $this->{debug};
    $this->{debug} = $val if defined $val;
    return $old;
}


=head2 format()

 ($text, $errmsg) = $style->format($template, \%fields);

Formats a reference, consisting of a hash of fields, according to an
Endnote-like template.  The template is a string essentially the same
as those used in Endnote, as documented in the Endnote X User Guide at
http://www.endnote.com/support/helpdocs/EndNoteXWinManual.pdf
pages 390ff.  In particular, pages 415-210 have details of the recipe
format.  Because the templates used in this module are plain text, a
few special characters are used:

=over 4

=item ¬

Link adjacent words.  This is the "non-breaking space"
described on page 418 of the EndNote X

=item |

Forced Seperation of elements that would otherwise be dependent.

=item ^

Separator for singular/plural aternatives.

=cut `

=item `

Used to prevent literal text from being interpreted as a fieldname.

=back

The hash of fields is passed by reference: keys are fieldnames, and
the corresponding values are the data.  PLEASE NOTE AN IMPORTANT
DIFFERENCE.  Keys that do not appear in the hash at all are not
considered to be fields, so that if they appear in the template, they
will be interpreted as literal text; keys that appear in the hash but
whose values are undefined or empty are considered to be fields with
no value, and will be formatted as empty with dependent text omitted.
So for example:

 $style->format(";Author: ", { Author => "Taylor" }) eq ":Taylor: "
 $style->format(";Author: ", { Author => "" }) eq ";"
 $style->format(";Author: ", { xAuthor => "" }) eq ";Author: "

C<format()> returns two values: the formatted reference and an
error-message.  The error message is defined if and only if the
formatted reference is not.

=cut

sub format {
    my $this = shift();
    my($text, $data) = @_;

    #use Data::Dumper; print Dumper($data);
    my $template = $this->{compiled}->{$text};
    if (!defined $template) {
	my $errmsg;
	($template, $errmsg) =
	    Biblio::EndnoteStyle::Template->new($text, $this->{debug});
	return (undef, $errmsg) if !defined $template;
	#print "template '$text'\n", $template->render();
	$this->{compiled}->{$text} = $template;
    }

    return $template->format($data);
}


package Biblio::EndnoteStyle::Template;

sub new {
    my $class = shift();
    my($text, $debug) = @_;

    my @sequences;
    while ($text ne "") {
	if ($text =~ s/^(\s*[^\s|]*\s?)//) {
	    my $sequence = $1;
	    my $obj = Biblio::EndnoteStyle::Sequence->new($sequence);
	    push @sequences, $obj;
	    $text =~ s/^\|//;
	} else {
	    die "unparseable template fragment '$text'";
	}
    }

    my $this = bless {
	text => $text,
	sequences => \@sequences,
    }, $class;
    print STDERR $this->render() if $debug;

    return $this;
}

sub render {
    my $this = shift();

    return join("", map { $_->render() . "\n" } @{ $this->{sequences} });
}

sub format {
    my $this = shift();
    my($data) = @_;

    my $result = "";
    foreach my $sequence (@{ $this->{sequences} }) {
	my($substr, $errmsg) = $sequence->format($data);
	return (undef, $errmsg) if !defined $substr;
	$result .= $substr;
    }

    return $result;
}


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

package Biblio::EndnoteStyle::Sequence;

sub WORD { 290168 }
sub LITERAL { 120368 }
sub typename {
    my($type) = @_;
    return "WORD" if $type == WORD;
    return "LITERAL" if $type == LITERAL;
    return "???";
}

sub new {
    my $class = shift();
    my($text) = @_;

    use Carp;
    confess("new($class) with text undefined") if !defined $text;
    my $tail = $text;
    $tail =~ s/¬/ /g;
    my @tokens;
    while ($tail =~ s/(.*?)([``a-z_0-9]+)//i) {
	my($head, $word) = ($1, $2);
	push @tokens, [ LITERAL, $head ] if $head ne "";
	if ($word =~ s/^`(.*)`$/$1/) {
	    push @tokens, [ LITERAL, $word ];
	} else {
	    push @tokens, [ WORD, $word ];
	}
    }
    push @tokens, [ LITERAL, $tail ] if $tail ne "";

    return bless {
	text => $text,
	tokens => \@tokens,
    }, $class;
}

sub render {
    my $this = shift();

    return (sprintf("%24s: ", ("'" . $this->{text} . "'")) .
	    join(", ", map {
		my($type, $val) = @$_;
		typename($type) . " '$val'";
	    } @{ $this->{tokens} }));
}

sub format {
    my $this = shift();
    my($data) = @_;

    my $gotField = 0;
    my $result = "";
    foreach my $token (@{ $this->{tokens} }) {
	my($type, $val) = @$token;
	if ($type == LITERAL) {
	    $result .= $val;
	} elsif ($type != WORD) {
	    die "unexpected token type '$type'";
	} else {
	    my $dval = $data->{$val};
	    $dval = $data->{lc($val)} if !defined $dval;
	    $dval = "" if !defined $dval && (exists $data->{$val} ||
					     exists $data->{lc($val)});
	    if (!defined $dval) {
		# The word is not a fieldname at all: treat as a literal
		#print "!defined \$dval\n";
		$result .= $val;
	    } elsif (!$gotField && $dval eq "") {
		#print "\$dval is empty\n";
		# Field is empty, so whole dependent sequence is omitted
		return "";
	    } else {
		#print "$dval eq '$dval'\n";
		$gotField = 1;
		# Loathesome but useful special case
		$dval = "http://$dval" if $val eq "URL" && $dval !~ /^[a-z]+:/;
		$result .= $dval;
	    }
	}
    }

    return $result;
}


=head1 AUTHOR

Mike Taylor, E<lt>mike@miketaylor.org.ukE<gt>

=head1 COPYRIGHT AND LICENCE

Copyright (C) 2007 by Mike Taylor.

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.4 or,
at your option, any later version of Perl 5 you may have available.

=cut


1;