Current File : /home/mmdealscpanel/yummmdeals.com/File.zip
PK
W�Z �$?[3[3Glob.pmnu�[���package File::Glob;

use strict;
our($VERSION, @ISA, @EXPORT_OK, @EXPORT_FAIL, %EXPORT_TAGS, $DEFAULT_FLAGS);

require XSLoader;

@ISA = qw(Exporter);

# NOTE: The glob() export is only here for compatibility with 5.6.0.
# csh_glob() should not be used directly, unless you know what you're doing.

%EXPORT_TAGS = (
    'glob' => [ qw(
        GLOB_ABEND
	GLOB_ALPHASORT
        GLOB_ALTDIRFUNC
        GLOB_BRACE
        GLOB_CSH
        GLOB_ERR
        GLOB_ERROR
        GLOB_LIMIT
        GLOB_MARK
        GLOB_NOCASE
        GLOB_NOCHECK
        GLOB_NOMAGIC
        GLOB_NOSORT
        GLOB_NOSPACE
        GLOB_QUOTE
        GLOB_TILDE
        bsd_glob
        glob
    ) ],
);
$EXPORT_TAGS{bsd_glob} = [@{$EXPORT_TAGS{glob}}];
pop @{$EXPORT_TAGS{bsd_glob}}; # no "glob"

@EXPORT_OK   = (@{$EXPORT_TAGS{'glob'}}, 'csh_glob');

$VERSION = '1.28';

sub import {
    require Exporter;
    local $Exporter::ExportLevel = $Exporter::ExportLevel + 1;
    Exporter::import(grep {
        my $passthrough;
        if ($_ eq ':case') {
            $DEFAULT_FLAGS &= ~GLOB_NOCASE()
        }
        elsif ($_ eq ':nocase') {
            $DEFAULT_FLAGS |= GLOB_NOCASE();
        }
        elsif ($_ eq ':globally') {
	    no warnings 'redefine';
	    *CORE::GLOBAL::glob = \&File::Glob::csh_glob;
	}
        elsif ($_ eq ':bsd_glob') {
	    no strict; *{caller."::glob"} = \&bsd_glob_override;
            $passthrough = 1;
	}
	else {
            $passthrough = 1;
        }
        $passthrough;
    } @_);
}

XSLoader::load();

$DEFAULT_FLAGS = GLOB_CSH();
if ($^O =~ /^(?:MSWin32|VMS|os2|dos|riscos)$/) {
    $DEFAULT_FLAGS |= GLOB_NOCASE();
}

# File::Glob::glob() is deprecated because its prototype is different from
# CORE::glob() (use bsd_glob() instead)
sub glob {
    use 5.024;
    use warnings ();
    warnings::warnif (deprecated =>
         "File::Glob::glob() will disappear in perl 5.30. " .
         "Use File::Glob::bsd_glob() instead.") unless state $warned ++;

    splice @_, 1; # no flags
    goto &bsd_glob;
}

1;
__END__

=head1 NAME

File::Glob - Perl extension for BSD glob routine

=head1 SYNOPSIS

  use File::Glob ':bsd_glob';

  @list = bsd_glob('*.[ch]');
  $homedir = bsd_glob('~gnat', GLOB_TILDE | GLOB_ERR);

  if (GLOB_ERROR) {
    # an error occurred reading $homedir
  }

  ## override the core glob (CORE::glob() does this automatically
  ## by default anyway, since v5.6.0)
  use File::Glob ':globally';
  my @sources = <*.{c,h,y}>;

  ## override the core glob, forcing case sensitivity
  use File::Glob qw(:globally :case);
  my @sources = <*.{c,h,y}>;

  ## override the core glob forcing case insensitivity
  use File::Glob qw(:globally :nocase);
  my @sources = <*.{c,h,y}>;

  ## glob on all files in home directory
  use File::Glob ':globally';
  my @sources = <~gnat/*>;

=head1 DESCRIPTION

The glob angle-bracket operator C<< <> >> is a pathname generator that
implements the rules for file name pattern matching used by Unix-like shells
such as the Bourne shell or C shell.

File::Glob::bsd_glob() implements the FreeBSD glob(3) routine, which is
a superset of the POSIX glob() (described in IEEE Std 1003.2 "POSIX.2").
bsd_glob() takes a mandatory C<pattern> argument, and an optional
C<flags> argument, and returns a list of filenames matching the
pattern, with interpretation of the pattern modified by the C<flags>
variable.

Since v5.6.0, Perl's CORE::glob() is implemented in terms of bsd_glob().
Note that they don't share the same prototype--CORE::glob() only accepts
a single argument.  Due to historical reasons, CORE::glob() will also
split its argument on whitespace, treating it as multiple patterns,
whereas bsd_glob() considers them as one pattern.  But see C<:bsd_glob>
under L</EXPORTS>, below.

=head2 META CHARACTERS

  \       Quote the next metacharacter
  []      Character class
  {}      Multiple pattern
  *       Match any string of characters
  ?       Match any single character
  ~       User name home directory

The metanotation C<a{b,c,d}e> is a shorthand for C<abe ace ade>.  Left to
right order is preserved, with results of matches being sorted separately
at a low level to preserve this order.  As a special case C<{>, C<}>, and
C<{}> are passed undisturbed.

=head2 EXPORTS

See also the L</POSIX FLAGS> below, which can be exported individually.

=head3 C<:bsd_glob>

The C<:bsd_glob> export tag exports bsd_glob() and the constants listed
below.  It also overrides glob() in the calling package with one that
behaves like bsd_glob() with regard to spaces (the space is treated as part
of a file name), but supports iteration in scalar context; i.e., it
preserves the core function's feature of returning the next item each time
it is called.

=head3 C<:glob>

The C<:glob> tag, now discouraged, is the old version of C<:bsd_glob>.  It
exports the same constants and functions, but its glob() override does not
support iteration; it returns the last file name in scalar context.  That
means this will loop forever:

    use File::Glob ':glob';
    while (my $file = <* copy.txt>) {
	...
    }

=head3 C<bsd_glob>

This function, which is included in the two export tags listed above,
takes one or two arguments.  The first is the glob pattern.  The
second, if given, is a set of flags ORed together.  The available
flags and the default set of flags are listed below under L</POSIX FLAGS>.

Remember that to use the named constants for flags you must import
them, for example with C<:bsd_glob> described above.  If not imported,
and C<use strict> is not in effect, then the constants will be
treated as bareword strings, which won't do what you what.


=head3 C<:nocase> and C<:case>

These two export tags globally modify the default flags that bsd_glob()
and, except on VMS, Perl's built-in C<glob> operator use.  C<GLOB_NOCASE>
is turned on or off, respectively.

=head3 C<csh_glob>

The csh_glob() function can also be exported, but you should not use it
directly unless you really know what you are doing.  It splits the pattern
into words and feeds each one to bsd_glob().  Perl's own glob() function
uses this internally.

=head2 POSIX FLAGS

If no flags argument is give then C<GLOB_CSH> is set, and on VMS and
Windows systems, C<GLOB_NOCASE> too.  Otherwise the flags to use are
determined solely by the flags argument.  The POSIX defined flags are:

=over 4

=item C<GLOB_ERR>

Force bsd_glob() to return an error when it encounters a directory it
cannot open or read.  Ordinarily bsd_glob() continues to find matches.

=item C<GLOB_LIMIT>

Make bsd_glob() return an error (GLOB_NOSPACE) when the pattern expands
to a size bigger than the system constant C<ARG_MAX> (usually found in
limits.h).  If your system does not define this constant, bsd_glob() uses
C<sysconf(_SC_ARG_MAX)> or C<_POSIX_ARG_MAX> where available (in that
order).  You can inspect these values using the standard C<POSIX>
extension.

=item C<GLOB_MARK>

Each pathname that is a directory that matches the pattern has a slash
appended.

=item C<GLOB_NOCASE>

By default, file names are assumed to be case sensitive; this flag
makes bsd_glob() treat case differences as not significant.

=item C<GLOB_NOCHECK>

If the pattern does not match any pathname, then bsd_glob() returns a list
consisting of only the pattern.  If C<GLOB_QUOTE> is set, its effect
is present in the pattern returned.

=item C<GLOB_NOSORT>

By default, the pathnames are sorted in ascending ASCII order; this
flag prevents that sorting (speeding up bsd_glob()).

=back

The FreeBSD extensions to the POSIX standard are the following flags:

=over 4

=item C<GLOB_BRACE>

Pre-process the string to expand C<{pat,pat,...}> strings like csh(1).
The pattern '{}' is left unexpanded for historical reasons (and csh(1)
does the same thing to ease typing of find(1) patterns).

=item C<GLOB_NOMAGIC>

Same as C<GLOB_NOCHECK> but it only returns the pattern if it does not
contain any of the special characters "*", "?" or "[".  C<NOMAGIC> is
provided to simplify implementing the historic csh(1) globbing
behaviour and should probably not be used anywhere else.

=item C<GLOB_QUOTE>

Use the backslash ('\') character for quoting: every occurrence of a
backslash followed by a character in the pattern is replaced by that
character, avoiding any special interpretation of the character.
(But see below for exceptions on DOSISH systems).

=item C<GLOB_TILDE>

Expand patterns that start with '~' to user name home directories.

=item C<GLOB_CSH>

For convenience, C<GLOB_CSH> is a synonym for
C<GLOB_BRACE | GLOB_NOMAGIC | GLOB_QUOTE | GLOB_TILDE | GLOB_ALPHASORT>.

=back

The POSIX provided C<GLOB_APPEND>, C<GLOB_DOOFFS>, and the FreeBSD
extensions C<GLOB_ALTDIRFUNC>, and C<GLOB_MAGCHAR> flags have not been
implemented in the Perl version because they involve more complex
interaction with the underlying C structures.

The following flag has been added in the Perl implementation for
csh compatibility:

=over 4

=item C<GLOB_ALPHASORT>

If C<GLOB_NOSORT> is not in effect, sort filenames is alphabetical
order (case does not matter) rather than in ASCII order.

=back

=head1 DIAGNOSTICS

bsd_glob() returns a list of matching paths, possibly zero length.  If an
error occurred, &File::Glob::GLOB_ERROR will be non-zero and C<$!> will be
set.  &File::Glob::GLOB_ERROR is guaranteed to be zero if no error occurred,
or one of the following values otherwise:

=over 4

=item C<GLOB_NOSPACE>

An attempt to allocate memory failed.

=item C<GLOB_ABEND>

The glob was stopped because an error was encountered.

=back

In the case where bsd_glob() has found some matching paths, but is
interrupted by an error, it will return a list of filenames B<and>
set &File::Glob::ERROR.

Note that bsd_glob() deviates from POSIX and FreeBSD glob(3) behaviour
by not considering C<ENOENT> and C<ENOTDIR> as errors - bsd_glob() will
continue processing despite those errors, unless the C<GLOB_ERR> flag is
set.

Be aware that all filenames returned from File::Glob are tainted.

=head1 NOTES

=over 4

=item *

If you want to use multiple patterns, e.g. C<bsd_glob("a* b*")>, you should
probably throw them in a set as in C<bsd_glob("{a*,b*}")>.  This is because
the argument to bsd_glob() isn't subjected to parsing by the C shell.
Remember that you can use a backslash to escape things.

=item *

On DOSISH systems, backslash is a valid directory separator character.
In this case, use of backslash as a quoting character (via GLOB_QUOTE)
interferes with the use of backslash as a directory separator.  The
best (simplest, most portable) solution is to use forward slashes for
directory separators, and backslashes for quoting.  However, this does
not match "normal practice" on these systems.  As a concession to user
expectation, therefore, backslashes (under GLOB_QUOTE) only quote the
glob metacharacters '[', ']', '{', '}', '-', '~', and backslash itself.
All other backslashes are passed through unchanged.

=item *

Win32 users should use the real slash.  If you really want to use
backslashes, consider using Sarathy's File::DosGlob, which comes with
the standard Perl distribution.

=back

=head1 SEE ALSO

L<perlfunc/glob>, glob(3)

=head1 AUTHOR

The Perl interface was written by Nathan Torkington E<lt>gnat@frii.comE<gt>,
and is released under the artistic license.  Further modifications were
made by Greg Bacon E<lt>gbacon@cs.uah.eduE<gt>, Gurusamy Sarathy
E<lt>gsar@activestate.comE<gt>, and Thomas Wegner
E<lt>wegner_thomas@yahoo.comE<gt>.  The C glob code has the
following copyright:

Copyright (c) 1989, 1993 The Regents of the University of California.
All rights reserved.

This code is derived from software contributed to Berkeley by
Guido van Rossum.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

=over 4

=item 1.

Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

=item 2.

Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

=item 3.

Neither the name of the University nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.

=back

THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

=cut
PK
W�Z��W::
DosGlob.pmnu�[���#!perl -w

#
# Documentation at the __END__
#

package File::DosGlob;

our $VERSION = '1.12';
use strict;
use warnings;

require XSLoader;
XSLoader::load();

sub doglob {
    my $cond = shift;
    my @retval = ();
    my $fix_drive_relative_paths;
  OUTER:
    for my $pat (@_) {
	my @matched = ();
	my @globdirs = ();
	my $head = '.';
	my $sepchr = '/';
        my $tail;
	next OUTER unless defined $pat and $pat ne '';
	# if arg is within quotes strip em and do no globbing
	if ($pat =~ /^"(.*)"\z/s) {
	    $pat = $1;
	    if ($cond eq 'd') { push(@retval, $pat) if -d $pat }
	    else              { push(@retval, $pat) if -e $pat }
	    next OUTER;
	}
	# wildcards with a drive prefix such as h:*.pm must be changed
	# to h:./*.pm to expand correctly
	if ($pat =~ m|^([A-Za-z]:)[^/\\]|s) {
	    substr($pat,0,2) = $1 . "./";
	    $fix_drive_relative_paths = 1;
	}
	if ($pat =~ m|^(.*)([\\/])([^\\/]*)\z|s) {
	    ($head, $sepchr, $tail) = ($1,$2,$3);
	    push (@retval, $pat), next OUTER if $tail eq '';
	    if ($head =~ /[*?]/) {
		@globdirs = doglob('d', $head);
		push(@retval, doglob($cond, map {"$_$sepchr$tail"} @globdirs)),
		    next OUTER if @globdirs;
	    }
	    $head .= $sepchr if $head eq '' or $head =~ /^[A-Za-z]:\z/s;
	    $pat = $tail;
	}
	#
	# If file component has no wildcards, we can avoid opendir
	unless ($pat =~ /[*?]/) {
	    $head = '' if $head eq '.';
	    $head .= $sepchr unless $head eq '' or substr($head,-1) eq $sepchr;
	    $head .= $pat;
	    if ($cond eq 'd') { push(@retval,$head) if -d $head }
	    else              { push(@retval,$head) if -e $head }
	    next OUTER;
	}
	opendir(D, $head) or next OUTER;
	my @leaves = readdir D;
	closedir D;

	# VMS-format filespecs, especially if they contain extended characters,
	# are unlikely to match patterns correctly, so Unixify them.
	if ($^O eq 'VMS') {
	    require VMS::Filespec;
	    @leaves = map {$_ =~ s/\.$//; VMS::Filespec::unixify($_)} @leaves;
        }
	$head = '' if $head eq '.';
	$head .= $sepchr unless $head eq '' or substr($head,-1) eq $sepchr;

	# escape regex metachars but not glob chars
	$pat =~ s:([].+^\-\${}()[|]):\\$1:g;
	# and convert DOS-style wildcards to regex
	$pat =~ s/\*/.*/g;
	$pat =~ s/\?/.?/g;

	my $matchsub = sub { $_[0] =~ m|^$pat\z|is };
      INNER:
	for my $e (@leaves) {
	    next INNER if $e eq '.' or $e eq '..';
	    next INNER if $cond eq 'd' and ! -d "$head$e";
	    push(@matched, "$head$e"), next INNER if &$matchsub($e);
	    #
	    # [DOS compatibility special case]
	    # Failed, add a trailing dot and try again, but only
	    # if name does not have a dot in it *and* pattern
	    # has a dot *and* name is shorter than 9 chars.
	    #
	    if (index($e,'.') == -1 and length($e) < 9
	        and index($pat,'\\.') != -1) {
		push(@matched, "$head$e"), next INNER if &$matchsub("$e.");
	    }
	}
	push @retval, @matched if @matched;
    }
    if ($fix_drive_relative_paths) {
	s|^([A-Za-z]:)\./|$1| for @retval;
    }
    return @retval;
}

#
# this can be used to override CORE::glob in a specific
# package by saying C<use File::DosGlob 'glob';> in that
# namespace.
#

# context (keyed by second cxix arg provided by core)
our %entries;

sub glob {
    my($pat,$cxix) = ($_[0], _callsite());
    my @pat;

    # glob without args defaults to $_
    $pat = $_ unless defined $pat;

    # if we're just beginning, do it all first
    if (!$entries{$cxix}) {
      # extract patterns
      if ($pat =~ /\s/) {
	require Text::ParseWords;
	@pat = Text::ParseWords::parse_line('\s+',0,$pat);
      }
      else {
	push @pat, $pat;
      }

      # Mike Mestnik: made to do abc{1,2,3} == abc1 abc2 abc3.
      #   abc3 will be the original {3} (and drop the {}).
      #   abc1 abc2 will be put in @appendpat.
      # This was just the easiest way, not nearly the best.
      REHASH: {
	my @appendpat = ();
	for (@pat) {
	    # There must be a "," I.E. abc{efg} is not what we want.
	    while ( /^(.*)(?<!\\)\{(.*?)(?<!\\)\,.*?(?<!\\)\}(.*)$/ ) {
		my ($start, $match, $end) = ($1, $2, $3);
		#print "Got: \n\t$start\n\t$match\n\t$end\n";
		my $tmp = "$start$match$end";
		while ( $tmp =~ s/^(.*?)(?<!\\)\{(?:.*(?<!\\)\,)?(.*\Q$match\E.*?)(?:(?<!\\)\,.*)?(?<!\\)\}(.*)$/$1$2$3/ ) {
		    #  these expansions will be performed by the original,
		    #  when we call REHASH.
		}
		push @appendpat, ("$tmp");
		s/^\Q$start\E(?<!\\)\{\Q$match\E(?<!\\)\,/$start\{/;
		if ( /^\Q$start\E(?<!\\)\{(?!.*?(?<!\\)\,.*?\Q$end\E$)(.*)(?<!\\)\}\Q$end\E$/ ) {
		    $match = $1;
		    #print "GOT: \n\t$start\n\t$match\n\t$end\n\n";
		    $_ = "$start$match$end";
		}
	    }
	    #print "Sould have "GOT" vs "Got"!\n";
		#FIXME: There should be checking for this.
		#  How or what should be done about failure is beyond me.
	}
	if ( $#appendpat != -1
		) {
	    #FIXME: Max loop, no way! :")
	    for ( @appendpat ) {
	        push @pat, $_;
	    }
	    goto REHASH;
	}
      }
      for ( @pat ) {
	s/\\([{},])/$1/g;
      }
 
      $entries{$cxix} = [doglob(1,@pat)];
    }

    # chuck it all out, quick or slow
    if (wantarray) {
	return @{delete $entries{$cxix}};
    }
    else {
	if (scalar @{$entries{$cxix}}) {
	    return shift @{$entries{$cxix}};
	}
	else {
	    # return undef for EOL
	    delete $entries{$cxix};
	    return undef;
	}
    }
}

{
    no strict 'refs';

    sub import {
    my $pkg = shift;
    return unless @_;
    my $sym = shift;
    my $callpkg = ($sym =~ s/^GLOBAL_//s ? 'CORE::GLOBAL' : caller(0));
    *{$callpkg.'::'.$sym} = \&{$pkg.'::'.$sym} if $sym eq 'glob';
    }
}
1;

__END__

=head1 NAME

File::DosGlob - DOS like globbing and then some

=head1 SYNOPSIS

    require 5.004;

    # override CORE::glob in current package
    use File::DosGlob 'glob';

    # override CORE::glob in ALL packages (use with extreme caution!)
    use File::DosGlob 'GLOBAL_glob';

    @perlfiles = glob  "..\\pe?l/*.p?";
    print <..\\pe?l/*.p?>;

    # from the command line (overrides only in main::)
    > perl -MFile::DosGlob=glob -e "print <../pe*/*p?>"

=head1 DESCRIPTION

A module that implements DOS-like globbing with a few enhancements.
It is largely compatible with perlglob.exe (the M$ setargv.obj
version) in all but one respect--it understands wildcards in
directory components.

For example, C<< <..\\l*b\\file/*glob.p?> >> will work as expected (in
that it will find something like '..\lib\File/DosGlob.pm' alright).
Note that all path components are case-insensitive, and that
backslashes and forward slashes are both accepted, and preserved.
You may have to double the backslashes if you are putting them in
literally, due to double-quotish parsing of the pattern by perl.

Spaces in the argument delimit distinct patterns, so
C<glob('*.exe *.dll')> globs all filenames that end in C<.exe>
or C<.dll>.  If you want to put in literal spaces in the glob
pattern, you can escape them with either double quotes, or backslashes.
e.g. C<glob('c:/"Program Files"/*/*.dll')>, or
C<glob('c:/Program\ Files/*/*.dll')>.  The argument is tokenized using
C<Text::ParseWords::parse_line()>, so see L<Text::ParseWords> for details
of the quoting rules used.

Extending it to csh patterns is left as an exercise to the reader.

=head1 EXPORTS (by request only)

glob()

=head1 BUGS

Should probably be built into the core, and needs to stop
pandering to DOS habits.  Needs a dose of optimization too.

=head1 AUTHOR

Gurusamy Sarathy <gsar@activestate.com>

=head1 HISTORY

=over 4

=item *

Support for globally overriding glob() (GSAR 3-JUN-98)

=item *

Scalar context, independent iterator context fixes (GSAR 15-SEP-97)

=item *

A few dir-vs-file optimizations result in glob importation being
10 times faster than using perlglob.exe, and using perlglob.bat is
only twice as slow as perlglob.exe (GSAR 28-MAY-97)

=item *

Several cleanups prompted by lack of compatible perlglob.exe
under Borland (GSAR 27-MAY-97)

=item *

Initial version (GSAR 20-FEB-97)

=back

=head1 SEE ALSO

perl

perlglob.bat

Text::ParseWords

=cut

PK�6�Z��M�^'^'stat.pmnu�[���package File::stat;
use 5.006;

use strict;
use warnings;
use warnings::register;
use Carp;

BEGIN { *warnif = \&warnings::warnif }

our(@EXPORT, @EXPORT_OK, %EXPORT_TAGS);

our $VERSION = '1.07';

my @fields;
BEGIN { 
    use Exporter   ();
    @EXPORT      = qw(stat lstat);
    @fields      = qw( $st_dev	   $st_ino    $st_mode 
		       $st_nlink   $st_uid    $st_gid 
		       $st_rdev    $st_size 
		       $st_atime   $st_mtime  $st_ctime 
		       $st_blksize $st_blocks
		    );
    @EXPORT_OK   = ( @fields, "stat_cando" );
    %EXPORT_TAGS = ( FIELDS => [ @fields, @EXPORT ] );
}
use vars @fields;

use Fcntl qw(S_IRUSR S_IWUSR S_IXUSR);

BEGIN {
    # These constants will croak on use if the platform doesn't define
    # them. It's important to avoid inflicting that on the user.
    no strict 'refs';
    for (qw(suid sgid svtx)) {
        my $val = eval { &{"Fcntl::S_I\U$_"} };
        *{"_$_"} = defined $val ? sub { $_[0] & $val ? 1 : "" } : sub { "" };
    }
    for (qw(SOCK CHR BLK REG DIR LNK)) {
        *{"S_IS$_"} = defined eval { &{"Fcntl::S_IF$_"} }
            ? \&{"Fcntl::S_IS$_"} : sub { "" };
    }
    # FIFO flag and macro don't quite follow the S_IF/S_IS pattern above
    # RT #111638
    *{"S_ISFIFO"} = defined &Fcntl::S_IFIFO
      ? \&Fcntl::S_ISFIFO : sub { "" };
}

# from doio.c
sub _ingroup {
    my ($gid, $eff)   = @_;

    # I am assuming that since VMS doesn't have getgroups(2), $) will
    # always only contain a single entry.
    $^O eq "VMS"    and return $_[0] == $);

    my ($egid, @supp) = split " ", $);
    my ($rgid)        = split " ", $(;

    $gid == ($eff ? $egid : $rgid)  and return 1;
    grep $gid == $_, @supp          and return 1;

    return "";
}

# VMS uses the Unix version of the routine, even though this is very
# suboptimal. VMS has a permissions structure that doesn't really fit
# into struct stat, and unlike on Win32 the normal -X operators respect
# that, but unfortunately by the time we get here we've already lost the
# information we need. It looks to me as though if we were to preserve
# the st_devnam entry of vmsish.h's fake struct stat (which actually
# holds the filename) it might be possible to do this right, but both
# getting that value out of the struct (perl's stat doesn't return it)
# and interpreting it later would require this module to have an XS
# component (at which point we might as well just call Perl_cando and
# have done with it).
    
if (grep $^O eq $_, qw/os2 MSWin32 dos/) {

    # from doio.c
    *cando = sub { ($_[0][2] & $_[1]) ? 1 : "" };
}
else {

    # from doio.c
    *cando = sub {
        my ($s, $mode, $eff) = @_;
        my $uid = $eff ? $> : $<;
        my ($stmode, $stuid, $stgid) = @$s[2,4,5];

        # This code basically assumes that the rwx bits of the mode are
        # the 0777 bits, but so does Perl_cando.

        if ($uid == 0 && $^O ne "VMS") {
            # If we're root on unix
            # not testing for executable status => all file tests are true
            return 1 if !($mode & 0111);
            # testing for executable status =>
            # for a file, any x bit will do
            # for a directory, always true
            return 1 if $stmode & 0111 || S_ISDIR($stmode);
            return "";
        }

        if ($stuid == $uid) {
            $stmode & $mode         and return 1;
        }
        elsif (_ingroup($stgid, $eff)) {
            $stmode & ($mode >> 3)  and return 1;
        }
        else {
            $stmode & ($mode >> 6)  and return 1;
        }
        return "";
    };
}

# alias for those who don't like objects
*stat_cando = \&cando;

my %op = (
    r => sub { cando($_[0], S_IRUSR, 1) },
    w => sub { cando($_[0], S_IWUSR, 1) },
    x => sub { cando($_[0], S_IXUSR, 1) },
    o => sub { $_[0][4] == $>           },

    R => sub { cando($_[0], S_IRUSR, 0) },
    W => sub { cando($_[0], S_IWUSR, 0) },
    X => sub { cando($_[0], S_IXUSR, 0) },
    O => sub { $_[0][4] == $<           },

    e => sub { 1 },
    z => sub { $_[0][7] == 0    },
    s => sub { $_[0][7]         },

    f => sub { S_ISREG ($_[0][2]) },
    d => sub { S_ISDIR ($_[0][2]) },
    l => sub { S_ISLNK ($_[0][2]) },
    p => sub { S_ISFIFO($_[0][2]) },
    S => sub { S_ISSOCK($_[0][2]) },
    b => sub { S_ISBLK ($_[0][2]) },
    c => sub { S_ISCHR ($_[0][2]) },

    u => sub { _suid($_[0][2]) },
    g => sub { _sgid($_[0][2]) },
    k => sub { _svtx($_[0][2]) },

    M => sub { ($^T - $_[0][9] ) / 86400 },
    C => sub { ($^T - $_[0][10]) / 86400 },
    A => sub { ($^T - $_[0][8] ) / 86400 },
);

use constant HINT_FILETEST_ACCESS => 0x00400000;

# we need fallback=>1 or stringifying breaks
use overload 
    fallback => 1,
    -X => sub {
        my ($s, $op) = @_;

        if (index("rwxRWX", $op) >= 0) {
            (caller 0)[8] & HINT_FILETEST_ACCESS
                and warnif("File::stat ignores use filetest 'access'");

            $^O eq "VMS" and warnif("File::stat ignores VMS ACLs");

            # It would be nice to have a warning about using -l on a
            # non-lstat, but that would require an extra member in the
            # object.
        }

        if ($op{$op}) {
            return $op{$op}->($_[0]);
        }
        else {
            croak "-$op is not implemented on a File::stat object";
        }
    };

# Class::Struct forbids use of @ISA
sub import { goto &Exporter::import }

use Class::Struct qw(struct);
struct 'File::stat' => [
     map { $_ => '$' } qw{
	 dev ino mode nlink uid gid rdev size
	 atime mtime ctime blksize blocks
     }
];

sub populate (@) {
    return unless @_;
    my $stob = new();
    @$stob = (
	$st_dev, $st_ino, $st_mode, $st_nlink, $st_uid, $st_gid, $st_rdev,
        $st_size, $st_atime, $st_mtime, $st_ctime, $st_blksize, $st_blocks ) 
	    = @_;
    return $stob;
} 

sub lstat ($)  { populate(CORE::lstat(shift)) }

sub stat ($) {
    my $arg = shift;
    my $st = populate(CORE::stat $arg);
    return $st if defined $st;
	my $fh;
    {
		local $!;
		no strict 'refs';
		require Symbol;
		$fh = \*{ Symbol::qualify( $arg, caller() )};
		return unless defined fileno $fh;
	}
    return populate(CORE::stat $fh);
}

1;
__END__

=head1 NAME

File::stat - by-name interface to Perl's built-in stat() functions

=head1 SYNOPSIS

 use File::stat;
 $st = stat($file) or die "No $file: $!";
 if ( ($st->mode & 0111) && $st->nlink > 1) ) {
     print "$file is executable with lotsa links\n";
 } 

 if ( -x $st ) {
     print "$file is executable\n";
 }

 use Fcntl "S_IRUSR";
 if ( $st->cando(S_IRUSR, 1) ) {
     print "My effective uid can read $file\n";
 }

 use File::stat qw(:FIELDS);
 stat($file) or die "No $file: $!";
 if ( ($st_mode & 0111) && ($st_nlink > 1) ) {
     print "$file is executable with lotsa links\n";
 } 

=head1 DESCRIPTION

This module's default exports override the core stat() 
and lstat() functions, replacing them with versions that return 
"File::stat" objects.  This object has methods that
return the similarly named structure field name from the
stat(2) function; namely,
dev,
ino,
mode,
nlink,
uid,
gid,
rdev,
size,
atime,
mtime,
ctime,
blksize,
and
blocks.  

As of version 1.02 (provided with perl 5.12) the object provides C<"-X">
overloading, so you can call filetest operators (C<-f>, C<-x>, and so
on) on it. It also provides a C<< ->cando >> method, called like

 $st->cando( ACCESS, EFFECTIVE )

where I<ACCESS> is one of C<S_IRUSR>, C<S_IWUSR> or C<S_IXUSR> from the
L<Fcntl|Fcntl> module, and I<EFFECTIVE> indicates whether to use
effective (true) or real (false) ids. The method interprets the C<mode>,
C<uid> and C<gid> fields, and returns whether or not the current process
would be allowed the specified access.

If you don't want to use the objects, you may import the C<< ->cando >>
method into your namespace as a regular function called C<stat_cando>.
This takes an arrayref containing the return values of C<stat> or
C<lstat> as its first argument, and interprets it for you.

You may also import all the structure fields directly into your namespace
as regular variables using the :FIELDS import tag.  (Note that this still
overrides your stat() and lstat() functions.)  Access these fields as
variables named with a preceding C<st_> in front their method names.
Thus, C<$stat_obj-E<gt>dev()> corresponds to $st_dev if you import
the fields.

To access this functionality without the core overrides,
pass the C<use> an empty import list, and then access
function functions with their full qualified names.
On the other hand, the built-ins are still available
via the C<CORE::> pseudo-package.

=head1 BUGS

As of Perl 5.8.0 after using this module you cannot use the implicit
C<$_> or the special filehandle C<_> with stat() or lstat(), trying
to do so leads into strange errors.  The workaround is for C<$_> to
be explicit

    my $stat_obj = stat $_;

and for C<_> to explicitly populate the object using the unexported
and undocumented populate() function with CORE::stat():

    my $stat_obj = File::stat::populate(CORE::stat(_));

=head1 ERRORS

=over 4

=item -%s is not implemented on a File::stat object

The filetest operators C<-t>, C<-T> and C<-B> are not implemented, as
they require more information than just a stat buffer.

=back

=head1 WARNINGS

These can all be disabled with

    no warnings "File::stat";

=over 4

=item File::stat ignores use filetest 'access'

You have tried to use one of the C<-rwxRWX> filetests with C<use
filetest 'access'> in effect. C<File::stat> will ignore the pragma, and
just use the information in the C<mode> member as usual.

=item File::stat ignores VMS ACLs

VMS systems have a permissions structure that cannot be completely
represented in a stat buffer, and unlike on other systems the builtin
filetest operators respect this. The C<File::stat> overloads, however,
do not, since the information required is not available.

=back

=head1 NOTE

While this class is currently implemented using the Class::Struct
module to build a struct-like class, you shouldn't rely upon this.

=head1 AUTHOR

Tom Christiansen
PK�6�Z��H??Copy.pmnu�[���# File/Copy.pm. Written in 1994 by Aaron Sherman <ajs@ajs.com>. This
# source code has been placed in the public domain by the author.
# Please be kind and preserve the documentation.
#
# Additions copyright 1996 by Charles Bailey.  Permission is granted
# to distribute the revised code under the same terms as Perl itself.

package File::Copy;

use 5.006;
use strict;
use warnings; no warnings 'newline';
use File::Spec;
use Config;
# During perl build, we need File::Copy but Scalar::Util might not be built yet
# And then we need these games to avoid loading overload, as that will
# confuse miniperl during the bootstrap of perl.
my $Scalar_Util_loaded = eval q{ require Scalar::Util; require overload; 1 };
our(@ISA, @EXPORT, @EXPORT_OK, $VERSION, $Too_Big, $Syscopy_is_copy);
sub copy;
sub syscopy;
sub cp;
sub mv;

$VERSION = '2.32';

require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(copy move);
@EXPORT_OK = qw(cp mv);

$Too_Big = 1024 * 1024 * 2;

sub croak {
    require Carp;
    goto &Carp::croak;
}

sub carp {
    require Carp;
    goto &Carp::carp;
}

sub _catname {
    my($from, $to) = @_;
    if (not defined &basename) {
	require File::Basename;
	import  File::Basename 'basename';
    }

    return File::Spec->catfile($to, basename($from));
}

# _eq($from, $to) tells whether $from and $to are identical
sub _eq {
    my ($from, $to) = map {
        $Scalar_Util_loaded && Scalar::Util::blessed($_)
	    && overload::Method($_, q{""})
            ? "$_"
            : $_
    } (@_);
    return '' if ( (ref $from) xor (ref $to) );
    return $from == $to if ref $from;
    return $from eq $to;
}

sub copy {
    croak("Usage: copy(FROM, TO [, BUFFERSIZE]) ")
      unless(@_ == 2 || @_ == 3);

    my $from = shift;
    my $to = shift;

    my $size;
    if (@_) {
	$size = shift(@_) + 0;
	croak("Bad buffer size for copy: $size\n") unless ($size > 0);
    }

    my $from_a_handle = (ref($from)
			 ? (ref($from) eq 'GLOB'
			    || UNIVERSAL::isa($from, 'GLOB')
                            || UNIVERSAL::isa($from, 'IO::Handle'))
			 : (ref(\$from) eq 'GLOB'));
    my $to_a_handle =   (ref($to)
			 ? (ref($to) eq 'GLOB'
			    || UNIVERSAL::isa($to, 'GLOB')
                            || UNIVERSAL::isa($to, 'IO::Handle'))
			 : (ref(\$to) eq 'GLOB'));

    if (_eq($from, $to)) { # works for references, too
	carp("'$from' and '$to' are identical (not copied)");
        return 0;
    }

    if (!$from_a_handle && !$to_a_handle && -d $to && ! -d $from) {
	$to = _catname($from, $to);
    }

    if ((($Config{d_symlink} && $Config{d_readlink}) || $Config{d_link}) &&
	!($^O eq 'MSWin32' || $^O eq 'os2')) {
	my @fs = stat($from);
	if (@fs) {
	    my @ts = stat($to);
	    if (@ts && $fs[0] == $ts[0] && $fs[1] == $ts[1] && !-p $from) {
		carp("'$from' and '$to' are identical (not copied)");
                return 0;
	    }
	}
    }
    elsif (_eq($from, $to)) {
	carp("'$from' and '$to' are identical (not copied)");
	return 0;
    }

    if (defined &syscopy && !$Syscopy_is_copy
	&& !$to_a_handle
	&& !($from_a_handle && $^O eq 'os2' )	# OS/2 cannot handle handles
	&& !($from_a_handle && $^O eq 'MSWin32')
	&& !($from_a_handle && $^O eq 'NetWare')
       )
    {
        if ($^O eq 'VMS' && -e $from
            && ! -d $to && ! -d $from) {

            # VMS natively inherits path components from the source of a
            # copy, but we want the Unixy behavior of inheriting from
            # the current working directory.  Also, default in a trailing
            # dot for null file types.

            $to = VMS::Filespec::rmsexpand(VMS::Filespec::vmsify($to), '.');

            # Get rid of the old versions to be like UNIX
            1 while unlink $to;
        }

        return syscopy($from, $to) || 0;
    }

    my $closefrom = 0;
    my $closeto = 0;
    my ($status, $r, $buf);
    local($\) = '';

    my $from_h;
    if ($from_a_handle) {
       $from_h = $from;
    } else {
       open $from_h, "<", $from or goto fail_open1;
       binmode $from_h or die "($!,$^E)";
       $closefrom = 1;
    }

    # Seems most logical to do this here, in case future changes would want to
    # make this croak for some reason.
    unless (defined $size) {
	$size = tied(*$from_h) ? 0 : -s $from_h || 0;
	$size = 1024 if ($size < 512);
	$size = $Too_Big if ($size > $Too_Big);
    }

    my $to_h;
    if ($to_a_handle) {
       $to_h = $to;
    } else {
	$to_h = \do { local *FH }; # XXX is this line obsolete?
	open $to_h, ">", $to or goto fail_open2;
	binmode $to_h or die "($!,$^E)";
	$closeto = 1;
    }

    $! = 0;
    for (;;) {
	my ($r, $w, $t);
       defined($r = sysread($from_h, $buf, $size))
	    or goto fail_inner;
	last unless $r;
	for ($w = 0; $w < $r; $w += $t) {
           $t = syswrite($to_h, $buf, $r - $w, $w)
		or goto fail_inner;
	}
    }

    close($to_h) || goto fail_open2 if $closeto;
    close($from_h) || goto fail_open1 if $closefrom;

    # Use this idiom to avoid uninitialized value warning.
    return 1;

    # All of these contortions try to preserve error messages...
  fail_inner:
    if ($closeto) {
	$status = $!;
	$! = 0;
       close $to_h;
	$! = $status unless $!;
    }
  fail_open2:
    if ($closefrom) {
	$status = $!;
	$! = 0;
       close $from_h;
	$! = $status unless $!;
    }
  fail_open1:
    return 0;
}

sub cp {
    my($from,$to) = @_;
    my(@fromstat) = stat $from;
    my(@tostat) = stat $to;
    my $perm;

    return 0 unless copy(@_) and @fromstat;

    if (@tostat) {
        $perm = $tostat[2];
    } else {
        $perm = $fromstat[2] & ~(umask || 0);
	@tostat = stat $to;
    }
    # Might be more robust to look for S_I* in Fcntl, but we're
    # trying to avoid dependence on any XS-containing modules,
    # since File::Copy is used during the Perl build.
    $perm &= 07777;
    if ($perm & 06000) {
	croak("Unable to check setuid/setgid permissions for $to: $!")
	    unless @tostat;

	if ($perm & 04000 and                     # setuid
	    $fromstat[4] != $tostat[4]) {         # owner must match
	    $perm &= ~06000;
	}

	if ($perm & 02000 && $> != 0) {           # if not root, setgid
	    my $ok = $fromstat[5] == $tostat[5];  # group must match
	    if ($ok) {                            # and we must be in group
                $ok = grep { $_ == $fromstat[5] } split /\s+/, $)
	    }
	    $perm &= ~06000 unless $ok;
	}
    }
    return 0 unless @tostat;
    return 1 if $perm == ($tostat[2] & 07777);
    return eval { chmod $perm, $to; } ? 1 : 0;
}

sub _move {
    croak("Usage: move(FROM, TO) ") unless @_ == 3;

    my($from,$to,$fallback) = @_;

    my($fromsz,$tosz1,$tomt1,$tosz2,$tomt2,$sts,$ossts);

    if (-d $to && ! -d $from) {
	$to = _catname($from, $to);
    }

    ($tosz1,$tomt1) = (stat($to))[7,9];
    $fromsz = -s $from;
    if ($^O eq 'os2' and defined $tosz1 and defined $fromsz) {
      # will not rename with overwrite
      unlink $to;
    }

    if ($^O eq 'VMS' && -e $from
        && ! -d $to && ! -d $from) {

            # VMS natively inherits path components from the source of a
            # copy, but we want the Unixy behavior of inheriting from
            # the current working directory.  Also, default in a trailing
            # dot for null file types.

            $to = VMS::Filespec::rmsexpand(VMS::Filespec::vmsify($to), '.');

            # Get rid of the old versions to be like UNIX
            1 while unlink $to;
    }

    return 1 if rename $from, $to;

    # Did rename return an error even though it succeeded, because $to
    # is on a remote NFS file system, and NFS lost the server's ack?
    return 1 if defined($fromsz) && !-e $from &&           # $from disappeared
                (($tosz2,$tomt2) = (stat($to))[7,9]) &&    # $to's there
                  ((!defined $tosz1) ||			   #  not before or
		   ($tosz1 != $tosz2 or $tomt1 != $tomt2)) &&  #   was changed
                $tosz2 == $fromsz;                         # it's all there

    ($tosz1,$tomt1) = (stat($to))[7,9];  # just in case rename did something

    {
        local $@;
        eval {
            local $SIG{__DIE__};
            $fallback->($from,$to) or die;
            my($atime, $mtime) = (stat($from))[8,9];
            utime($atime, $mtime, $to);
            unlink($from)   or die;
        };
        return 1 unless $@;
    }
    ($sts,$ossts) = ($! + 0, $^E + 0);

    ($tosz2,$tomt2) = ((stat($to))[7,9],0,0) if defined $tomt1;
    unlink($to) if !defined($tomt1) or $tomt1 != $tomt2 or $tosz1 != $tosz2;
    ($!,$^E) = ($sts,$ossts);
    return 0;
}

sub move { _move(@_,\&copy); }
sub mv   { _move(@_,\&cp);   }

# &syscopy is an XSUB under OS/2
unless (defined &syscopy) {
    if ($^O eq 'VMS') {
	*syscopy = \&rmscopy;
    } elsif ($^O eq 'MSWin32' && defined &DynaLoader::boot_DynaLoader) {
	# Win32::CopyFile() fill only work if we can load Win32.xs
	*syscopy = sub {
	    return 0 unless @_ == 2;
	    return Win32::CopyFile(@_, 1);
	};
    } else {
	$Syscopy_is_copy = 1;
	*syscopy = \&copy;
    }
}

1;

__END__

=head1 NAME

File::Copy - Copy files or filehandles

=head1 SYNOPSIS

	use File::Copy;

	copy("sourcefile","destinationfile") or die "Copy failed: $!";
	copy("Copy.pm",\*STDOUT);
	move("/dev1/sourcefile","/dev2/destinationfile");

	use File::Copy "cp";

	$n = FileHandle->new("/a/file","r");
	cp($n,"x");

=head1 DESCRIPTION

The File::Copy module provides two basic functions, C<copy> and
C<move>, which are useful for getting the contents of a file from
one place to another.

=over 4

=item copy
X<copy> X<cp>

The C<copy> function takes two
parameters: a file to copy from and a file to copy to. Either
argument may be a string, a FileHandle reference or a FileHandle
glob. Obviously, if the first argument is a filehandle of some
sort, it will be read from, and if it is a file I<name> it will
be opened for reading. Likewise, the second argument will be
written to. If the second argument does not exist but the parent
directory does exist, then it will be created. Trying to copy
a file into a non-existent directory is an error.
Trying to copy a file on top of itself is also an error.
C<copy> will not overwrite read-only files.

If the destination (second argument) already exists and is a directory,
and the source (first argument) is not a filehandle, then the source
file will be copied into the directory specified by the destination,
using the same base name as the source file.  It's a failure to have a
filehandle as the source when the destination is a directory.

B<Note that passing in
files as handles instead of names may lead to loss of information
on some operating systems; it is recommended that you use file
names whenever possible.>  Files are opened in binary mode where
applicable.  To get a consistent behaviour when copying from a
filehandle to a file, use C<binmode> on the filehandle.

An optional third parameter can be used to specify the buffer
size used for copying. This is the number of bytes from the
first file, that will be held in memory at any given time, before
being written to the second file. The default buffer size depends
upon the file, but will generally be the whole file (up to 2MB), or
1k for filehandles that do not reference files (eg. sockets).

You may use the syntax C<use File::Copy "cp"> to get at the C<cp>
alias for this function. The syntax is I<exactly> the same.  The
behavior is nearly the same as well: as of version 2.15, C<cp> will
preserve the source file's permission bits like the shell utility
C<cp(1)> would do, while C<copy> uses the default permissions for the
target file (which may depend on the process' C<umask>, file
ownership, inherited ACLs, etc.).  If an error occurs in setting
permissions, C<cp> will return 0, regardless of whether the file was
successfully copied.

=item move
X<move> X<mv> X<rename>

The C<move> function also takes two parameters: the current name
and the intended name of the file to be moved.  If the destination
already exists and is a directory, and the source is not a
directory, then the source file will be renamed into the directory
specified by the destination.

If possible, move() will simply rename the file.  Otherwise, it copies
the file to the new location and deletes the original.  If an error occurs
during this copy-and-delete process, you may be left with a (possibly partial)
copy of the file under the destination name.

You may use the C<mv> alias for this function in the same way that
you may use the C<cp> alias for C<copy>.

=item syscopy
X<syscopy>

File::Copy also provides the C<syscopy> routine, which copies the
file specified in the first parameter to the file specified in the
second parameter, preserving OS-specific attributes and file
structure.  For Unix systems, this is equivalent to the simple
C<copy> routine, which doesn't preserve OS-specific attributes.  For
VMS systems, this calls the C<rmscopy> routine (see below).  For OS/2
systems, this calls the C<syscopy> XSUB directly. For Win32 systems,
this calls C<Win32::CopyFile>.

B<Special behaviour if C<syscopy> is defined (OS/2, VMS and Win32)>:

If both arguments to C<copy> are not file handles,
then C<copy> will perform a "system copy" of
the input file to a new output file, in order to preserve file
attributes, indexed file structure, I<etc.>  The buffer size
parameter is ignored.  If either argument to C<copy> is a
handle to an opened file, then data is copied using Perl
operators, and no effort is made to preserve file attributes
or record structure.

The system copy routine may also be called directly under VMS and OS/2
as C<File::Copy::syscopy> (or under VMS as C<File::Copy::rmscopy>, which
is the routine that does the actual work for syscopy).

=item rmscopy($from,$to[,$date_flag])
X<rmscopy>

The first and second arguments may be strings, typeglobs, typeglob
references, or objects inheriting from IO::Handle;
they are used in all cases to obtain the
I<filespec> of the input and output files, respectively.  The
name and type of the input file are used as defaults for the
output file, if necessary.

A new version of the output file is always created, which
inherits the structure and RMS attributes of the input file,
except for owner and protections (and possibly timestamps;
see below).  All data from the input file is copied to the
output file; if either of the first two parameters to C<rmscopy>
is a file handle, its position is unchanged.  (Note that this
means a file handle pointing to the output file will be
associated with an old version of that file after C<rmscopy>
returns, not the newly created version.)

The third parameter is an integer flag, which tells C<rmscopy>
how to handle timestamps.  If it is E<lt> 0, none of the input file's
timestamps are propagated to the output file.  If it is E<gt> 0, then
it is interpreted as a bitmask: if bit 0 (the LSB) is set, then
timestamps other than the revision date are propagated; if bit 1
is set, the revision date is propagated.  If the third parameter
to C<rmscopy> is 0, then it behaves much like the DCL COPY command:
if the name or type of the output file was explicitly specified,
then no timestamps are propagated, but if they were taken implicitly
from the input filespec, then all timestamps other than the
revision date are propagated.  If this parameter is not supplied,
it defaults to 0.

C<rmscopy> is VMS specific and cannot be exported; it must be
referenced by its full name, e.g.:

  File::Copy::rmscopy($from, $to) or die $!;

Like C<copy>, C<rmscopy> returns 1 on success.  If an error occurs,
it sets C<$!>, deletes the output file, and returns 0.

=back

=head1 RETURN

All functions return 1 on success, 0 on failure.
$! will be set if an error was encountered.

=head1 NOTES

Before calling copy() or move() on a filehandle, the caller should
close or flush() the file to avoid writes being lost. Note that this
is the case even for move(), because it may actually copy the file,
depending on the OS-specific inplementation, and the underlying
filesystem(s).

=head1 AUTHOR

File::Copy was written by Aaron Sherman I<E<lt>ajs@ajs.comE<gt>> in 1995,
and updated by Charles Bailey I<E<lt>bailey@newman.upenn.eduE<gt>> in 1996.

=cut

PK�6�Z��CU>=>=
GlobMapper.pmnu�[���package File::GlobMapper;

use strict;
use warnings;
use Carp;

our ($CSH_GLOB);

BEGIN
{
    if ($] < 5.006)
    {
        require File::BSDGlob; import File::BSDGlob qw(:glob) ;
        $CSH_GLOB = File::BSDGlob::GLOB_CSH() ;
        *globber = \&File::BSDGlob::csh_glob;
    }
    else
    {
        require File::Glob; import File::Glob qw(:glob) ;
        $CSH_GLOB = File::Glob::GLOB_CSH() ;
        #*globber = \&File::Glob::bsd_glob;
        *globber = \&File::Glob::csh_glob;
    }
}

our ($Error);

our ($VERSION, @EXPORT_OK);
$VERSION = '1.001';
@EXPORT_OK = qw( globmap );


our ($noPreBS, $metachars, $matchMetaRE, %mapping, %wildCount);
$noPreBS = '(?<!\\\)' ; # no preceding backslash
$metachars = '.*?[](){}';
$matchMetaRE = '[' . quotemeta($metachars) . ']';

%mapping = (
                '*' => '([^/]*)',
                '?' => '([^/])',
                '.' => '\.',
                '[' => '([',
                '(' => '(',
                ')' => ')',
           );

%wildCount = map { $_ => 1 } qw/ * ? . { ( [ /;

sub globmap ($$;)
{
    my $inputGlob = shift ;
    my $outputGlob = shift ;

    my $obj = new File::GlobMapper($inputGlob, $outputGlob, @_)
        or croak "globmap: $Error" ;
    return $obj->getFileMap();
}

sub new
{
    my $class = shift ;
    my $inputGlob = shift ;
    my $outputGlob = shift ;
    # TODO -- flags needs to default to whatever File::Glob does
    my $flags = shift || $CSH_GLOB ;
    #my $flags = shift ;

    $inputGlob =~ s/^\s*\<\s*//;
    $inputGlob =~ s/\s*\>\s*$//;

    $outputGlob =~ s/^\s*\<\s*//;
    $outputGlob =~ s/\s*\>\s*$//;

    my %object =
            (   InputGlob   => $inputGlob,
                OutputGlob  => $outputGlob,
                GlobFlags   => $flags,
                Braces      => 0,
                WildCount   => 0,
                Pairs       => [],
                Sigil       => '#',
            );

    my $self = bless \%object, ref($class) || $class ;

    $self->_parseInputGlob()
        or return undef ;

    $self->_parseOutputGlob()
        or return undef ;

    my @inputFiles = globber($self->{InputGlob}, $flags) ;

    if (GLOB_ERROR)
    {
        $Error = $!;
        return undef ;
    }

    #if (whatever)
    {
        my $missing = grep { ! -e $_ } @inputFiles ;

        if ($missing)
        {
            $Error = "$missing input files do not exist";
            return undef ;
        }
    }

    $self->{InputFiles} = \@inputFiles ;

    $self->_getFiles()
        or return undef ;

    return $self;
}

sub _retError
{
    my $string = shift ;
    $Error = "$string in input fileglob" ;
    return undef ;
}

sub _unmatched
{
    my $delimeter = shift ;

    _retError("Unmatched $delimeter");
    return undef ;
}

sub _parseBit
{
    my $self = shift ;

    my $string = shift ;

    my $out = '';
    my $depth = 0 ;

    while ($string =~ s/(.*?)$noPreBS(,|$matchMetaRE)//)
    {
        $out .= quotemeta($1) ;
        $out .= $mapping{$2} if defined $mapping{$2};

        ++ $self->{WildCount} if $wildCount{$2} ;

        if ($2 eq ',')
        {
            return _unmatched("(")
                if $depth ;

            $out .= '|';
        }
        elsif ($2 eq '(')
        {
            ++ $depth ;
        }
        elsif ($2 eq ')')
        {
            return _unmatched(")")
                if ! $depth ;

            -- $depth ;
        }
        elsif ($2 eq '[')
        {
            # TODO -- quotemeta & check no '/'
            # TODO -- check for \]  & other \ within the []
            $string =~ s#(.*?\])##
                or return _unmatched("[");
            $out .= "$1)" ;
        }
        elsif ($2 eq ']')
        {
            return _unmatched("]");
        }
        elsif ($2 eq '{' || $2 eq '}')
        {
            return _retError("Nested {} not allowed");
        }
    }

    $out .= quotemeta $string;

    return _unmatched("(")
        if $depth ;

    return $out ;
}

sub _parseInputGlob
{
    my $self = shift ;

    my $string = $self->{InputGlob} ;
    my $inGlob = '';

    # Multiple concatenated *'s don't make sense
    #$string =~ s#\*\*+#*# ;

    # TODO -- Allow space to delimit patterns?
    #my @strings = split /\s+/, $string ;
    #for my $str (@strings)
    my $out = '';
    my $depth = 0 ;

    while ($string =~ s/(.*?)$noPreBS($matchMetaRE)//)
    {
        $out .= quotemeta($1) ;
        $out .= $mapping{$2} if defined $mapping{$2};
        ++ $self->{WildCount} if $wildCount{$2} ;

        if ($2 eq '(')
        {
            ++ $depth ;
        }
        elsif ($2 eq ')')
        {
            return _unmatched(")")
                if ! $depth ;

            -- $depth ;
        }
        elsif ($2 eq '[')
        {
            # TODO -- quotemeta & check no '/' or '(' or ')'
            # TODO -- check for \]  & other \ within the []
            $string =~ s#(.*?\])##
                or return _unmatched("[");
            $out .= "$1)" ;
        }
        elsif ($2 eq ']')
        {
            return _unmatched("]");
        }
        elsif ($2 eq '}')
        {
            return _unmatched("}");
        }
        elsif ($2 eq '{')
        {
            # TODO -- check no '/' within the {}
            # TODO -- check for \}  & other \ within the {}

            my $tmp ;
            unless ( $string =~ s/(.*?)$noPreBS\}//)
            {
                return _unmatched("{");
            }
            #$string =~ s#(.*?)\}##;

            #my $alt = join '|',
            #          map { quotemeta $_ }
            #          split "$noPreBS,", $1 ;
            my $alt = $self->_parseBit($1);
            defined $alt or return 0 ;
            $out .= "($alt)" ;

            ++ $self->{Braces} ;
        }
    }

    return _unmatched("(")
        if $depth ;

    $out .= quotemeta $string ;


    $self->{InputGlob} =~ s/$noPreBS[\(\)]//g;
    $self->{InputPattern} = $out ;

    #print "# INPUT '$self->{InputGlob}' => '$out'\n";

    return 1 ;

}

sub _parseOutputGlob
{
    my $self = shift ;

    my $string = $self->{OutputGlob} ;
    my $maxwild = $self->{WildCount};

    if ($self->{GlobFlags} & GLOB_TILDE)
    #if (1)
    {
        $string =~ s{
              ^ ~             # find a leading tilde
              (               # save this in $1
                  [^/]        # a non-slash character
                        *     # repeated 0 or more times (0 means me)
              )
            }{
              $1
                  ? (getpwnam($1))[7]
                  : ( $ENV{HOME} || $ENV{LOGDIR} )
            }ex;

    }

    # max #1 must be == to max no of '*' in input
    while ( $string =~ m/#(\d)/g )
    {
        croak "Max wild is #$maxwild, you tried #$1"
            if $1 > $maxwild ;
    }

    my $noPreBS = '(?<!\\\)' ; # no preceding backslash
    #warn "noPreBS = '$noPreBS'\n";

    #$string =~ s/${noPreBS}\$(\d)/\${$1}/g;
    $string =~ s/${noPreBS}#(\d)/\${$1}/g;
    $string =~ s#${noPreBS}\*#\${inFile}#g;
    $string = '"' . $string . '"';

    #print "OUTPUT '$self->{OutputGlob}' => '$string'\n";
    $self->{OutputPattern} = $string ;

    return 1 ;
}

sub _getFiles
{
    my $self = shift ;

    my %outInMapping = ();
    my %inFiles = () ;

    foreach my $inFile (@{ $self->{InputFiles} })
    {
        next if $inFiles{$inFile} ++ ;

        my $outFile = $inFile ;

        if ( $inFile =~ m/$self->{InputPattern}/ )
        {
            no warnings 'uninitialized';
            eval "\$outFile = $self->{OutputPattern};" ;

            if (defined $outInMapping{$outFile})
            {
                $Error =  "multiple input files map to one output file";
                return undef ;
            }
            $outInMapping{$outFile} = $inFile;
            push @{ $self->{Pairs} }, [$inFile, $outFile];
        }
    }

    return 1 ;
}

sub getFileMap
{
    my $self = shift ;

    return $self->{Pairs} ;
}

sub getHash
{
    my $self = shift ;

    return { map { $_->[0] => $_->[1] } @{ $self->{Pairs} } } ;
}

1;

__END__

=head1 NAME

File::GlobMapper - Extend File Glob to Allow Input and Output Files

=head1 SYNOPSIS

    use File::GlobMapper qw( globmap );

    my $aref = globmap $input => $output
        or die $File::GlobMapper::Error ;

    my $gm = new File::GlobMapper $input => $output
        or die $File::GlobMapper::Error ;


=head1 DESCRIPTION

This module needs Perl5.005 or better.

This module takes the existing C<File::Glob> module as a starting point and
extends it to allow new filenames to be derived from the files matched by
C<File::Glob>.

This can be useful when carrying out batch operations on multiple files that
have both an input filename and output filename and the output file can be
derived from the input filename. Examples of operations where this can be
useful include, file renaming, file copying and file compression.


=head2 Behind The Scenes

To help explain what C<File::GlobMapper> does, consider what code you
would write if you wanted to rename all files in the current directory
that ended in C<.tar.gz> to C<.tgz>. So say these files are in the
current directory

    alpha.tar.gz
    beta.tar.gz
    gamma.tar.gz

and they need renamed to this

    alpha.tgz
    beta.tgz
    gamma.tgz

Below is a possible implementation of a script to carry out the rename
(error cases have been omitted)

    foreach my $old ( glob "*.tar.gz" )
    {
        my $new = $old;
        $new =~ s#(.*)\.tar\.gz$#$1.tgz# ;

        rename $old => $new
            or die "Cannot rename '$old' to '$new': $!\n;
    }

Notice that a file glob pattern C<*.tar.gz> was used to match the
C<.tar.gz> files, then a fairly similar regular expression was used in
the substitute to allow the new filename to be created.

Given that the file glob is just a cut-down regular expression and that it
has already done a lot of the hard work in pattern matching the filenames,
wouldn't it be handy to be able to use the patterns in the fileglob to
drive the new filename?

Well, that's I<exactly> what C<File::GlobMapper> does.

Here is same snippet of code rewritten using C<globmap>

    for my $pair (globmap '<*.tar.gz>' => '<#1.tgz>' )
    {
        my ($from, $to) = @$pair;
        rename $from => $to
            or die "Cannot rename '$old' to '$new': $!\n;
    }

So how does it work?

Behind the scenes the C<globmap> function does a combination of a
file glob to match existing filenames followed by a substitute
to create the new filenames.

Notice how both parameters to C<globmap> are strings that are delimited by <>.
This is done to make them look more like file globs - it is just syntactic
sugar, but it can be handy when you want the strings to be visually
distinctive. The enclosing <> are optional, so you don't have to use them - in
fact the first thing globmap will do is remove these delimiters if they are
present.

The first parameter to C<globmap>, C<*.tar.gz>, is an I<Input File Glob>.
Once the enclosing "< ... >" is removed, this is passed (more or
less) unchanged to C<File::Glob> to carry out a file match.

Next the fileglob C<*.tar.gz> is transformed behind the scenes into a
full Perl regular expression, with the additional step of wrapping each
transformed wildcard metacharacter sequence in parenthesis.

In this case the input fileglob C<*.tar.gz> will be transformed into
this Perl regular expression

    ([^/]*)\.tar\.gz

Wrapping with parenthesis allows the wildcard parts of the Input File
Glob to be referenced by the second parameter to C<globmap>, C<#1.tgz>,
the I<Output File Glob>. This parameter operates just like the replacement
part of a substitute command. The difference is that the C<#1> syntax
is used to reference sub-patterns matched in the input fileglob, rather
than the C<$1> syntax that is used with perl regular expressions. In
this case C<#1> is used to refer to the text matched by the C<*> in the
Input File Glob. This makes it easier to use this module where the
parameters to C<globmap> are typed at the command line.

The final step involves passing each filename matched by the C<*.tar.gz>
file glob through the derived Perl regular expression in turn and
expanding the output fileglob using it.

The end result of all this is a list of pairs of filenames. By default
that is what is returned by C<globmap>. In this example the data structure
returned will look like this

     ( ['alpha.tar.gz' => 'alpha.tgz'],
       ['beta.tar.gz'  => 'beta.tgz' ],
       ['gamma.tar.gz' => 'gamma.tgz']
     )


Each pair is an array reference with two elements - namely the I<from>
filename, that C<File::Glob> has matched, and a I<to> filename that is
derived from the I<from> filename.



=head2 Limitations

C<File::GlobMapper> has been kept simple deliberately, so it isn't intended to
solve all filename mapping operations. Under the hood C<File::Glob> (or for
older versions of Perl, C<File::BSDGlob>) is used to match the files, so you
will never have the flexibility of full Perl regular expression.

=head2 Input File Glob

The syntax for an Input FileGlob is identical to C<File::Glob>, except
for the following

=over 5

=item 1.

No nested {}

=item 2.

Whitespace does not delimit fileglobs.

=item 3.

The use of parenthesis can be used to capture parts of the input filename.

=item 4.

If an Input glob matches the same file more than once, only the first
will be used.

=back

The syntax

=over 5

=item B<~>

=item B<~user>


=item B<.>

Matches a literal '.'.
Equivalent to the Perl regular expression

    \.

=item B<*>

Matches zero or more characters, except '/'. Equivalent to the Perl
regular expression

    [^/]*

=item B<?>

Matches zero or one character, except '/'. Equivalent to the Perl
regular expression

    [^/]?

=item B<\>

Backslash is used, as usual, to escape the next character.

=item  B<[]>

Character class.

=item  B<{,}>

Alternation

=item  B<()>

Capturing parenthesis that work just like perl

=back

Any other character it taken literally.

=head2 Output File Glob

The Output File Glob is a normal string, with 2 glob-like features.

The first is the '*' metacharacter. This will be replaced by the complete
filename matched by the input file glob. So

    *.c *.Z

The second is

Output FileGlobs take the

=over 5

=item "*"

The "*" character will be replaced with the complete input filename.

=item #1

Patterns of the form /#\d/ will be replaced with the

=back

=head2 Returned Data


=head1 EXAMPLES

=head2 A Rename script

Below is a simple "rename" script that uses C<globmap> to determine the
source and destination filenames.

    use File::GlobMapper qw(globmap) ;
    use File::Copy;

    die "rename: Usage rename 'from' 'to'\n"
        unless @ARGV == 2 ;

    my $fromGlob = shift @ARGV;
    my $toGlob   = shift @ARGV;

    my $pairs = globmap($fromGlob, $toGlob)
        or die $File::GlobMapper::Error;

    for my $pair (@$pairs)
    {
        my ($from, $to) = @$pair;
        move $from => $to ;
    }



Here is an example that renames all c files to cpp.

    $ rename '*.c' '#1.cpp'

=head2 A few example globmaps

Below are a few examples of globmaps

To copy all your .c file to a backup directory

    '</my/home/*.c>'    '</my/backup/#1.c>'

If you want to compress all

    '</my/home/*.[ch]>'    '<*.gz>'

To uncompress

    '</my/home/*.[ch].gz>'    '</my/home/#1.#2>'

=head1 SEE ALSO

L<File::Glob|File::Glob>

=head1 AUTHOR

The I<File::GlobMapper> module was written by Paul Marquess, F<pmqs@cpan.org>.

=head1 COPYRIGHT AND LICENSE

Copyright (c) 2005 Paul Marquess. All rights reserved.
This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
PK�6�Z3�w�+�+Basename.pmnu�[���=head1 NAME

File::Basename - Parse file paths into directory, filename and suffix.

=head1 SYNOPSIS

    use File::Basename;

    ($name,$path,$suffix) = fileparse($fullname,@suffixlist);
    $name = fileparse($fullname,@suffixlist);

    $basename = basename($fullname,@suffixlist);
    $dirname  = dirname($fullname);


=head1 DESCRIPTION

These routines allow you to parse file paths into their directory, filename
and suffix.

B<NOTE>: C<dirname()> and C<basename()> emulate the behaviours, and
quirks, of the shell and C functions of the same name.  See each
function's documentation for details.  If your concern is just parsing
paths it is safer to use L<File::Spec>'s C<splitpath()> and
C<splitdir()> methods.

It is guaranteed that

    # Where $path_separator is / for Unix, \ for Windows, etc...
    dirname($path) . $path_separator . basename($path);

is equivalent to the original path for all systems but VMS.


=cut


package File::Basename;

# File::Basename is used during the Perl build, when the re extension may
# not be available, but we only actually need it if running under tainting.
BEGIN {
  if (${^TAINT}) {
    require re;
    re->import('taint');
  }
}


use strict;
use 5.006;
use warnings;
our(@ISA, @EXPORT, $VERSION, $Fileparse_fstype, $Fileparse_igncase);
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(fileparse fileparse_set_fstype basename dirname);
$VERSION = "2.85";

fileparse_set_fstype($^O);


=over 4

=item C<fileparse>
X<fileparse>

    my($filename, $dirs, $suffix) = fileparse($path);
    my($filename, $dirs, $suffix) = fileparse($path, @suffixes);
    my $filename                  = fileparse($path, @suffixes);

The C<fileparse()> routine divides a file path into its $dirs, $filename
and (optionally) the filename $suffix.

$dirs contains everything up to and including the last
directory separator in the $path including the volume (if applicable).
The remainder of the $path is the $filename.

     # On Unix returns ("baz", "/foo/bar/", "")
     fileparse("/foo/bar/baz");

     # On Windows returns ("baz", 'C:\foo\bar\', "")
     fileparse('C:\foo\bar\baz');

     # On Unix returns ("", "/foo/bar/baz/", "")
     fileparse("/foo/bar/baz/");

If @suffixes are given each element is a pattern (either a string or a
C<qr//>) matched against the end of the $filename.  The matching
portion is removed and becomes the $suffix.

     # On Unix returns ("baz", "/foo/bar/", ".txt")
     fileparse("/foo/bar/baz.txt", qr/\.[^.]*/);

If type is non-Unix (see L</fileparse_set_fstype>) then the pattern
matching for suffix removal is performed case-insensitively, since
those systems are not case-sensitive when opening existing files.

You are guaranteed that C<$dirs . $filename . $suffix> will
denote the same location as the original $path.

=cut


sub fileparse {
  my($fullname,@suffices) = @_;

  unless (defined $fullname) {
      require Carp;
      Carp::croak("fileparse(): need a valid pathname");
  }

  my $orig_type = '';
  my($type,$igncase) = ($Fileparse_fstype, $Fileparse_igncase);

  my($taint) = substr($fullname,0,0);  # Is $fullname tainted?

  if ($type eq "VMS" and $fullname =~ m{/} ) {
    # We're doing Unix emulation
    $orig_type = $type;
    $type = 'Unix';
  }

  my($dirpath, $basename);

  if (grep { $type eq $_ } qw(MSDOS DOS MSWin32 Epoc)) {
    ($dirpath,$basename) = ($fullname =~ /^((?:.*[:\\\/])?)(.*)/s);
    $dirpath .= '.\\' unless $dirpath =~ /[\\\/]\z/;
  }
  elsif ($type eq "OS2") {
    ($dirpath,$basename) = ($fullname =~ m#^((?:.*[:\\/])?)(.*)#s);
    $dirpath = './' unless $dirpath;	# Can't be 0
    $dirpath .= '/' unless $dirpath =~ m#[\\/]\z#;
  }
  elsif ($type eq "MacOS") {
    ($dirpath,$basename) = ($fullname =~ /^(.*:)?(.*)/s);
    $dirpath = ':' unless $dirpath;
  }
  elsif ($type eq "AmigaOS") {
    ($dirpath,$basename) = ($fullname =~ /(.*[:\/])?(.*)/s);
    $dirpath = './' unless $dirpath;
  }
  elsif ($type eq 'VMS' ) {
    ($dirpath,$basename) = ($fullname =~ /^(.*[:>\]])?(.*)/s);
    $dirpath ||= '';  # should always be defined
  }
  else { # Default to Unix semantics.
    ($dirpath,$basename) = ($fullname =~ m{^(.*/)?(.*)}s);
    if ($orig_type eq 'VMS' and $fullname =~ m{^(/[^/]+/000000(/|$))(.*)}) {
      # dev:[000000] is top of VMS tree, similar to Unix '/'
      # so strip it off and treat the rest as "normal"
      my $devspec  = $1;
      my $remainder = $3;
      ($dirpath,$basename) = ($remainder =~ m{^(.*/)?(.*)}s);
      $dirpath ||= '';  # should always be defined
      $dirpath = $devspec.$dirpath;
    }
    $dirpath = './' unless $dirpath;
  }
      

  my $tail   = '';
  my $suffix = '';
  if (@suffices) {
    foreach $suffix (@suffices) {
      my $pat = ($igncase ? '(?i)' : '') . "($suffix)\$";
      if ($basename =~ s/$pat//s) {
        $taint .= substr($suffix,0,0);
        $tail = $1 . $tail;
      }
    }
  }

  # Ensure taint is propagated from the path to its pieces.
  $tail .= $taint;
  wantarray ? ($basename .= $taint, $dirpath .= $taint, $tail)
            : ($basename .= $taint);
}



=item C<basename>
X<basename> X<filename>

    my $filename = basename($path);
    my $filename = basename($path, @suffixes);

This function is provided for compatibility with the Unix shell command
C<basename(1)>.  It does B<NOT> always return the file name portion of a
path as you might expect.  To be safe, if you want the file name portion of
a path use C<fileparse()>.

C<basename()> returns the last level of a filepath even if the last
level is clearly directory.  In effect, it is acting like C<pop()> for
paths.  This differs from C<fileparse()>'s behaviour.

    # Both return "bar"
    basename("/foo/bar");
    basename("/foo/bar/");

@suffixes work as in C<fileparse()> except all regex metacharacters are
quoted.

    # These two function calls are equivalent.
    my $filename = basename("/foo/bar/baz.txt",  ".txt");
    my $filename = fileparse("/foo/bar/baz.txt", qr/\Q.txt\E/);

Also note that in order to be compatible with the shell command,
C<basename()> does not strip off a suffix if it is identical to the
remaining characters in the filename.

=cut


sub basename {
  my($path) = shift;

  # From BSD basename(1)
  # The basename utility deletes any prefix ending with the last slash '/'
  # character present in string (after first stripping trailing slashes)
  _strip_trailing_sep($path);

  my($basename, $dirname, $suffix) = fileparse( $path, map("\Q$_\E",@_) );

  # From BSD basename(1)
  # The suffix is not stripped if it is identical to the remaining 
  # characters in string.
  if( length $suffix and !length $basename ) {
      $basename = $suffix;
  }
  
  # Ensure that basename '/' == '/'
  if( !length $basename ) {
      $basename = $dirname;
  }

  return $basename;
}



=item C<dirname>
X<dirname>

This function is provided for compatibility with the Unix shell
command C<dirname(1)> and has inherited some of its quirks.  In spite of
its name it does B<NOT> always return the directory name as you might
expect.  To be safe, if you want the directory name of a path use
C<fileparse()>.

Only on VMS (where there is no ambiguity between the file and directory
portions of a path) and AmigaOS (possibly due to an implementation quirk in
this module) does C<dirname()> work like C<fileparse($path)>, returning just the
$dirs.

    # On VMS and AmigaOS
    my $dirs = dirname($path);

When using Unix or MSDOS syntax this emulates the C<dirname(1)> shell function
which is subtly different from how C<fileparse()> works.  It returns all but
the last level of a file path even if the last level is clearly a directory.
In effect, it is not returning the directory portion but simply the path one
level up acting like C<chop()> for file paths.

Also unlike C<fileparse()>, C<dirname()> does not include a trailing slash on
its returned path.

    # returns /foo/bar.  fileparse() would return /foo/bar/
    dirname("/foo/bar/baz");

    # also returns /foo/bar despite the fact that baz is clearly a 
    # directory.  fileparse() would return /foo/bar/baz/
    dirname("/foo/bar/baz/");

    # returns '.'.  fileparse() would return 'foo/'
    dirname("foo/");

Under VMS, if there is no directory information in the $path, then the
current default device and directory is used.

=cut


sub dirname {
    my $path = shift;

    my($type) = $Fileparse_fstype;

    if( $type eq 'VMS' and $path =~ m{/} ) {
        # Parse as Unix
        local($File::Basename::Fileparse_fstype) = '';
        return dirname($path);
    }

    my($basename, $dirname) = fileparse($path);

    if ($type eq 'VMS') { 
        $dirname ||= $ENV{DEFAULT};
    }
    elsif ($type eq 'MacOS') {
	if( !length($basename) && $dirname !~ /^[^:]+:\z/) {
            _strip_trailing_sep($dirname);
	    ($basename,$dirname) = fileparse $dirname;
	}
	$dirname .= ":" unless $dirname =~ /:\z/;
    }
    elsif (grep { $type eq $_ } qw(MSDOS DOS MSWin32 OS2)) { 
        _strip_trailing_sep($dirname);
        unless( length($basename) ) {
	    ($basename,$dirname) = fileparse $dirname;
	    _strip_trailing_sep($dirname);
	}
    }
    elsif ($type eq 'AmigaOS') {
        if ( $dirname =~ /:\z/) { return $dirname }
        chop $dirname;
        $dirname =~ s{[^:/]+\z}{} unless length($basename);
    }
    else {
        _strip_trailing_sep($dirname);
        unless( length($basename) ) {
	    ($basename,$dirname) = fileparse $dirname;
	    _strip_trailing_sep($dirname);
	}
    }

    $dirname;
}


# Strip the trailing path separator.
sub _strip_trailing_sep  {
    my $type = $Fileparse_fstype;

    if ($type eq 'MacOS') {
        $_[0] =~ s/([^:]):\z/$1/s;
    }
    elsif (grep { $type eq $_ } qw(MSDOS DOS MSWin32 OS2)) { 
        $_[0] =~ s/([^:])[\\\/]*\z/$1/;
    }
    else {
        $_[0] =~ s{(.)/*\z}{$1}s;
    }
}


=item C<fileparse_set_fstype>
X<filesystem>

  my $type = fileparse_set_fstype();
  my $previous_type = fileparse_set_fstype($type);

Normally File::Basename will assume a file path type native to your current
operating system (ie. /foo/bar style on Unix, \foo\bar on Windows, etc...).
With this function you can override that assumption.

Valid $types are "MacOS", "VMS", "AmigaOS", "OS2", "RISCOS",
"MSWin32", "DOS" (also "MSDOS" for backwards bug compatibility),
"Epoc" and "Unix" (all case-insensitive).  If an unrecognized $type is
given "Unix" will be assumed.

If you've selected VMS syntax, and the file specification you pass to
one of these routines contains a "/", they assume you are using Unix
emulation and apply the Unix syntax rules instead, for that function
call only.

=back

=cut


BEGIN {

my @Ignore_Case = qw(MacOS VMS AmigaOS OS2 RISCOS MSWin32 MSDOS DOS Epoc);
my @Types = (@Ignore_Case, qw(Unix));

sub fileparse_set_fstype {
    my $old = $Fileparse_fstype;

    if (@_) {
        my $new_type = shift;

        $Fileparse_fstype = 'Unix';  # default
        foreach my $type (@Types) {
            $Fileparse_fstype = $type if $new_type =~ /^$type/i;
        }

        $Fileparse_igncase = 
          (grep $Fileparse_fstype eq $_, @Ignore_Case) ? 1 : 0;
    }

    return $old;
}

}


1;


=head1 SEE ALSO

L<dirname(1)>, L<basename(1)>, L<File::Spec>
PK�6�Z�J@d�d�Find.pmnu�[���package File::Find;
use 5.006;
use strict;
use warnings;
use warnings::register;
our $VERSION = '1.34';
require Exporter;
require Cwd;

our @ISA = qw(Exporter);
our @EXPORT = qw(find finddepth);


use strict;
my $Is_VMS;
my $Is_Win32;

require File::Basename;
require File::Spec;

# Should ideally be my() not our() but local() currently
# refuses to operate on lexicals

our %SLnkSeen;
our ($wanted_callback, $avoid_nlink, $bydepth, $no_chdir, $follow,
    $follow_skip, $full_check, $untaint, $untaint_skip, $untaint_pat,
    $pre_process, $post_process, $dangling_symlinks);

sub contract_name {
    my ($cdir,$fn) = @_;

    return substr($cdir,0,rindex($cdir,'/')) if $fn eq $File::Find::current_dir;

    $cdir = substr($cdir,0,rindex($cdir,'/')+1);

    $fn =~ s|^\./||;

    my $abs_name= $cdir . $fn;

    if (substr($fn,0,3) eq '../') {
       1 while $abs_name =~ s!/[^/]*/\.\./+!/!;
    }

    return $abs_name;
}

sub PathCombine($$) {
    my ($Base,$Name) = @_;
    my $AbsName;

    if (substr($Name,0,1) eq '/') {
	$AbsName= $Name;
    }
    else {
	$AbsName= contract_name($Base,$Name);
    }

    # (simple) check for recursion
    my $newlen= length($AbsName);
    if ($newlen <= length($Base)) {
	if (($newlen == length($Base) || substr($Base,$newlen,1) eq '/')
	    && $AbsName eq substr($Base,0,$newlen))
	{
	    return undef;
	}
    }
    return $AbsName;
}

sub Follow_SymLink($) {
    my ($AbsName) = @_;

    my ($NewName,$DEV, $INO);
    ($DEV, $INO)= lstat $AbsName;

    while (-l _) {
	if ($SLnkSeen{$DEV, $INO}++) {
	    if ($follow_skip < 2) {
		die "$AbsName is encountered a second time";
	    }
	    else {
		return undef;
	    }
	}
	$NewName= PathCombine($AbsName, readlink($AbsName));
	unless(defined $NewName) {
	    if ($follow_skip < 2) {
		die "$AbsName is a recursive symbolic link";
	    }
	    else {
		return undef;
	    }
	}
	else {
	    $AbsName= $NewName;
	}
	($DEV, $INO) = lstat($AbsName);
	return undef unless defined $DEV;  #  dangling symbolic link
    }

    if ($full_check && defined $DEV && $SLnkSeen{$DEV, $INO}++) {
	if ( ($follow_skip < 1) || ((-d _) && ($follow_skip < 2)) ) {
	    die "$AbsName encountered a second time";
	}
	else {
	    return undef;
	}
    }

    return $AbsName;
}

our($dir, $name, $fullname, $prune);
sub _find_dir_symlnk($$$);
sub _find_dir($$$);

# check whether or not a scalar variable is tainted
# (code straight from the Camel, 3rd ed., page 561)
sub is_tainted_pp {
    my $arg = shift;
    my $nada = substr($arg, 0, 0); # zero-length
    local $@;
    eval { eval "# $nada" };
    return length($@) != 0;
}

sub _find_opt {
    my $wanted = shift;
    return unless @_;
    die "invalid top directory" unless defined $_[0];

    # This function must local()ize everything because callbacks may
    # call find() or finddepth()

    local %SLnkSeen;
    local ($wanted_callback, $avoid_nlink, $bydepth, $no_chdir, $follow,
	$follow_skip, $full_check, $untaint, $untaint_skip, $untaint_pat,
	$pre_process, $post_process, $dangling_symlinks);
    local($dir, $name, $fullname, $prune);
    local *_ = \my $a;

    my $cwd            = $wanted->{bydepth} ? Cwd::fastcwd() : Cwd::getcwd();
    if ($Is_VMS) {
	# VMS returns this by default in VMS format which just doesn't
	# work for the rest of this module.
	$cwd = VMS::Filespec::unixpath($cwd);

	# Apparently this is not expected to have a trailing space.
	# To attempt to make VMS/UNIX conversions mostly reversible,
	# a trailing slash is needed.  The run-time functions ignore the
	# resulting double slash, but it causes the perl tests to fail.
        $cwd =~ s#/\z##;

	# This comes up in upper case now, but should be lower.
	# In the future this could be exact case, no need to change.
    }
    my $cwd_untainted  = $cwd;
    my $check_t_cwd    = 1;
    $wanted_callback   = $wanted->{wanted};
    $bydepth           = $wanted->{bydepth};
    $pre_process       = $wanted->{preprocess};
    $post_process      = $wanted->{postprocess};
    $no_chdir          = $wanted->{no_chdir};
    $full_check        = $Is_Win32 ? 0 : $wanted->{follow};
    $follow            = $Is_Win32 ? 0 :
                             $full_check || $wanted->{follow_fast};
    $follow_skip       = $wanted->{follow_skip};
    $untaint           = $wanted->{untaint};
    $untaint_pat       = $wanted->{untaint_pattern};
    $untaint_skip      = $wanted->{untaint_skip};
    $dangling_symlinks = $wanted->{dangling_symlinks};

    # for compatibility reasons (find.pl, find2perl)
    local our ($topdir, $topdev, $topino, $topmode, $topnlink);

    # a symbolic link to a directory doesn't increase the link count
    $avoid_nlink      = $follow || $File::Find::dont_use_nlink;

    my ($abs_dir, $Is_Dir);

    Proc_Top_Item:
    foreach my $TOP (@_) {
	my $top_item = $TOP;
	$top_item = VMS::Filespec::unixify($top_item) if $Is_VMS;

	($topdev,$topino,$topmode,$topnlink) = $follow ? stat $top_item : lstat $top_item;

	if ($Is_Win32) {
	    $top_item =~ s|[/\\]\z||
	      unless $top_item =~ m{^(?:\w:)?[/\\]$};
	}
	else {
	    $top_item =~ s|/\z|| unless $top_item eq '/';
	}

	$Is_Dir= 0;

	if ($follow) {

	    if (substr($top_item,0,1) eq '/') {
		$abs_dir = $top_item;
	    }
	    elsif ($top_item eq $File::Find::current_dir) {
		$abs_dir = $cwd;
	    }
	    else {  # care about any  ../
		$top_item =~ s/\.dir\z//i if $Is_VMS;
		$abs_dir = contract_name("$cwd/",$top_item);
	    }
	    $abs_dir= Follow_SymLink($abs_dir);
	    unless (defined $abs_dir) {
		if ($dangling_symlinks) {
		    if (ref $dangling_symlinks eq 'CODE') {
			$dangling_symlinks->($top_item, $cwd);
		    } else {
			warnings::warnif "$top_item is a dangling symbolic link\n";
		    }
		}
		next Proc_Top_Item;
	    }

	    if (-d _) {
		$top_item =~ s/\.dir\z//i if $Is_VMS;
		_find_dir_symlnk($wanted, $abs_dir, $top_item);
		$Is_Dir= 1;
	    }
	}
	else { # no follow
	    $topdir = $top_item;
	    unless (defined $topnlink) {
		warnings::warnif "Can't stat $top_item: $!\n";
		next Proc_Top_Item;
	    }
	    if (-d _) {
		$top_item =~ s/\.dir\z//i if $Is_VMS;
		_find_dir($wanted, $top_item, $topnlink);
		$Is_Dir= 1;
	    }
	    else {
		$abs_dir= $top_item;
	    }
	}

	unless ($Is_Dir) {
	    unless (($_,$dir) = File::Basename::fileparse($abs_dir)) {
		($dir,$_) = ('./', $top_item);
	    }

	    $abs_dir = $dir;
	    if (( $untaint ) && (is_tainted($dir) )) {
		( $abs_dir ) = $dir =~ m|$untaint_pat|;
		unless (defined $abs_dir) {
		    if ($untaint_skip == 0) {
			die "directory $dir is still tainted";
		    }
		    else {
			next Proc_Top_Item;
		    }
		}
	    }

	    unless ($no_chdir || chdir $abs_dir) {
		warnings::warnif "Couldn't chdir $abs_dir: $!\n";
		next Proc_Top_Item;
	    }

	    $name = $abs_dir . $_; # $File::Find::name
	    $_ = $name if $no_chdir;

	    { $wanted_callback->() }; # protect against wild "next"

	}

	unless ( $no_chdir ) {
	    if ( ($check_t_cwd) && (($untaint) && (is_tainted($cwd) )) ) {
		( $cwd_untainted ) = $cwd =~ m|$untaint_pat|;
		unless (defined $cwd_untainted) {
		    die "insecure cwd in find(depth)";
		}
		$check_t_cwd = 0;
	    }
	    unless (chdir $cwd_untainted) {
		die "Can't cd to $cwd: $!\n";
	    }
	}
    }
}

# API:
#  $wanted
#  $p_dir :  "parent directory"
#  $nlink :  what came back from the stat
# preconditions:
#  chdir (if not no_chdir) to dir

sub _find_dir($$$) {
    my ($wanted, $p_dir, $nlink) = @_;
    my ($CdLvl,$Level) = (0,0);
    my @Stack;
    my @filenames;
    my ($subcount,$sub_nlink);
    my $SE= [];
    my $dir_name= $p_dir;
    my $dir_pref;
    my $dir_rel = $File::Find::current_dir;
    my $tainted = 0;
    my $no_nlink;

    if ($Is_Win32) {
	$dir_pref
	  = ($p_dir =~ m{^(?:\w:[/\\]?|[/\\])$} ? $p_dir : "$p_dir/" );
    } elsif ($Is_VMS) {

	#	VMS is returning trailing .dir on directories
	#	and trailing . on files and symbolic links
	#	in UNIX syntax.
	#

	$p_dir =~ s/\.(dir)?$//i unless $p_dir eq '.';

	$dir_pref = ($p_dir =~ m/[\]>]+$/ ? $p_dir : "$p_dir/" );
    }
    else {
	$dir_pref= ( $p_dir eq '/' ? '/' : "$p_dir/" );
    }

    local ($dir, $name, $prune, *DIR);

    unless ( $no_chdir || ($p_dir eq $File::Find::current_dir)) {
	my $udir = $p_dir;
	if (( $untaint ) && (is_tainted($p_dir) )) {
	    ( $udir ) = $p_dir =~ m|$untaint_pat|;
	    unless (defined $udir) {
		if ($untaint_skip == 0) {
		    die "directory $p_dir is still tainted";
		}
		else {
		    return;
		}
	    }
	}
	unless (chdir ($Is_VMS && $udir !~ /[\/\[<]+/ ? "./$udir" : $udir)) {
	    warnings::warnif "Can't cd to $udir: $!\n";
	    return;
	}
    }

    # push the starting directory
    push @Stack,[$CdLvl,$p_dir,$dir_rel,-1]  if  $bydepth;

    while (defined $SE) {
	unless ($bydepth) {
	    $dir= $p_dir; # $File::Find::dir
	    $name= $dir_name; # $File::Find::name
	    $_= ($no_chdir ? $dir_name : $dir_rel ); # $_
	    # prune may happen here
	    $prune= 0;
	    { $wanted_callback->() };	# protect against wild "next"
	    next if $prune;
	}

	# change to that directory
	unless ($no_chdir || ($dir_rel eq $File::Find::current_dir)) {
	    my $udir= $dir_rel;
	    if ( ($untaint) && (($tainted) || ($tainted = is_tainted($dir_rel) )) ) {
		( $udir ) = $dir_rel =~ m|$untaint_pat|;
		unless (defined $udir) {
		    if ($untaint_skip == 0) {
			die "directory (" . ($p_dir ne '/' ? $p_dir : '') . "/) $dir_rel is still tainted";
		    } else { # $untaint_skip == 1
			next;
		    }
		}
	    }
	    unless (chdir ($Is_VMS && $udir !~ /[\/\[<]+/ ? "./$udir" : $udir)) {
		warnings::warnif "Can't cd to (" .
		    ($p_dir ne '/' ? $p_dir : '') . "/) $udir: $!\n";
		next;
	    }
	    $CdLvl++;
	}

	$dir= $dir_name; # $File::Find::dir

	# Get the list of files in the current directory.
	unless (opendir DIR, ($no_chdir ? $dir_name : $File::Find::current_dir)) {
	    warnings::warnif "Can't opendir($dir_name): $!\n";
	    next;
	}
	@filenames = readdir DIR;
	closedir(DIR);
	@filenames = $pre_process->(@filenames) if $pre_process;
	push @Stack,[$CdLvl,$dir_name,"",-2]   if $post_process;

	# default: use whatever was specified
        # (if $nlink >= 2, and $avoid_nlink == 0, this will switch back)
        $no_nlink = $avoid_nlink;
        # if dir has wrong nlink count, force switch to slower stat method
        $no_nlink = 1 if ($nlink < 2);

	if ($nlink == 2 && !$no_nlink) {
	    # This dir has no subdirectories.
	    for my $FN (@filenames) {
		if ($Is_VMS) {
		# Big hammer here - Compensate for VMS trailing . and .dir
		# No win situation until this is changed, but this
		# will handle the majority of the cases with breaking the fewest

		    $FN =~ s/\.dir\z//i;
		    $FN =~ s#\.$## if ($FN ne '.');
		}
		next if $FN =~ $File::Find::skip_pattern;
		
		$name = $dir_pref . $FN; # $File::Find::name
		$_ = ($no_chdir ? $name : $FN); # $_
		{ $wanted_callback->() }; # protect against wild "next"
	    }

	}
	else {
	    # This dir has subdirectories.
	    $subcount = $nlink - 2;

	    # HACK: insert directories at this position, so as to preserve
	    # the user pre-processed ordering of files (thus ensuring
	    # directory traversal is in user sorted order, not at random).
            my $stack_top = @Stack;

	    for my $FN (@filenames) {
		next if $FN =~ $File::Find::skip_pattern;
		if ($subcount > 0 || $no_nlink) {
		    # Seen all the subdirs?
		    # check for directoriness.
		    # stat is faster for a file in the current directory
		    $sub_nlink = (lstat ($no_chdir ? $dir_pref . $FN : $FN))[3];

		    if (-d _) {
			--$subcount;
			$FN =~ s/\.dir\z//i if $Is_VMS;
			# HACK: replace push to preserve dir traversal order
			#push @Stack,[$CdLvl,$dir_name,$FN,$sub_nlink];
			splice @Stack, $stack_top, 0,
			         [$CdLvl,$dir_name,$FN,$sub_nlink];
		    }
		    else {
			$name = $dir_pref . $FN; # $File::Find::name
			$_= ($no_chdir ? $name : $FN); # $_
			{ $wanted_callback->() }; # protect against wild "next"
		    }
		}
		else {
		    $name = $dir_pref . $FN; # $File::Find::name
		    $_= ($no_chdir ? $name : $FN); # $_
		    { $wanted_callback->() }; # protect against wild "next"
		}
	    }
	}
    }
    continue {
	while ( defined ($SE = pop @Stack) ) {
	    ($Level, $p_dir, $dir_rel, $nlink) = @$SE;
	    if ($CdLvl > $Level && !$no_chdir) {
		my $tmp;
		if ($Is_VMS) {
		    $tmp = '[' . ('-' x ($CdLvl-$Level)) . ']';
		}
		else {
		    $tmp = join('/',('..') x ($CdLvl-$Level));
		}
		die "Can't cd to $tmp from $dir_name: $!"
		    unless chdir ($tmp);
		$CdLvl = $Level;
	    }

	    if ($Is_Win32) {
		$dir_name = ($p_dir =~ m{^(?:\w:[/\\]?|[/\\])$}
		    ? "$p_dir$dir_rel" : "$p_dir/$dir_rel");
		$dir_pref = "$dir_name/";
	    }
	    elsif ($^O eq 'VMS') {
                if ($p_dir =~ m/[\]>]+$/) {
                    $dir_name = $p_dir;
                    $dir_name =~ s/([\]>]+)$/.$dir_rel$1/;
                    $dir_pref = $dir_name;
                }
                else {
                    $dir_name = "$p_dir/$dir_rel";
                    $dir_pref = "$dir_name/";
                }
	    }
	    else {
		$dir_name = ($p_dir eq '/' ? "/$dir_rel" : "$p_dir/$dir_rel");
		$dir_pref = "$dir_name/";
	    }

	    if ( $nlink == -2 ) {
		$name = $dir = $p_dir; # $File::Find::name / dir
                $_ = $File::Find::current_dir;
		$post_process->();		# End-of-directory processing
	    }
	    elsif ( $nlink < 0 ) {  # must be finddepth, report dirname now
		$name = $dir_name;
		if ( substr($name,-2) eq '/.' ) {
		    substr($name, length($name) == 2 ? -1 : -2) = '';
		}
		$dir = $p_dir;
		$_ = ($no_chdir ? $dir_name : $dir_rel );
		if ( substr($_,-2) eq '/.' ) {
		    substr($_, length($_) == 2 ? -1 : -2) = '';
		}
		{ $wanted_callback->() }; # protect against wild "next"
	     }
	     else {
		push @Stack,[$CdLvl,$p_dir,$dir_rel,-1]  if  $bydepth;
		last;
	    }
	}
    }
}


# API:
#  $wanted
#  $dir_loc : absolute location of a dir
#  $p_dir   : "parent directory"
# preconditions:
#  chdir (if not no_chdir) to dir

sub _find_dir_symlnk($$$) {
    my ($wanted, $dir_loc, $p_dir) = @_; # $dir_loc is the absolute directory
    my @Stack;
    my @filenames;
    my $new_loc;
    my $updir_loc = $dir_loc; # untainted parent directory
    my $SE = [];
    my $dir_name = $p_dir;
    my $dir_pref;
    my $loc_pref;
    my $dir_rel = $File::Find::current_dir;
    my $byd_flag; # flag for pending stack entry if $bydepth
    my $tainted = 0;
    my $ok = 1;

    $dir_pref = ( $p_dir   eq '/' ? '/' : "$p_dir/" );
    $loc_pref = ( $dir_loc eq '/' ? '/' : "$dir_loc/" );

    local ($dir, $name, $fullname, $prune, *DIR);

    unless ($no_chdir) {
	# untaint the topdir
	if (( $untaint ) && (is_tainted($dir_loc) )) {
	    ( $updir_loc ) = $dir_loc =~ m|$untaint_pat|; # parent dir, now untainted
	     # once untainted, $updir_loc is pushed on the stack (as parent directory);
	    # hence, we don't need to untaint the parent directory every time we chdir
	    # to it later
	    unless (defined $updir_loc) {
		if ($untaint_skip == 0) {
		    die "directory $dir_loc is still tainted";
		}
		else {
		    return;
		}
	    }
	}
	$ok = chdir($updir_loc) unless ($p_dir eq $File::Find::current_dir);
	unless ($ok) {
	    warnings::warnif "Can't cd to $updir_loc: $!\n";
	    return;
	}
    }

    push @Stack,[$dir_loc,$updir_loc,$p_dir,$dir_rel,-1]  if  $bydepth;

    while (defined $SE) {

	unless ($bydepth) {
	    # change (back) to parent directory (always untainted)
	    unless ($no_chdir) {
		unless (chdir $updir_loc) {
		    warnings::warnif "Can't cd to $updir_loc: $!\n";
		    next;
		}
	    }
	    $dir= $p_dir; # $File::Find::dir
	    $name= $dir_name; # $File::Find::name
	    $_= ($no_chdir ? $dir_name : $dir_rel ); # $_
	    $fullname= $dir_loc; # $File::Find::fullname
	    # prune may happen here
	    $prune= 0;
	    lstat($_); # make sure  file tests with '_' work
	    { $wanted_callback->() }; # protect against wild "next"
	    next if $prune;
	}

	# change to that directory
	unless ($no_chdir || ($dir_rel eq $File::Find::current_dir)) {
	    $updir_loc = $dir_loc;
	    if ( ($untaint) && (($tainted) || ($tainted = is_tainted($dir_loc) )) ) {
		# untaint $dir_loc, what will be pushed on the stack as (untainted) parent dir
		( $updir_loc ) = $dir_loc =~ m|$untaint_pat|;
		unless (defined $updir_loc) {
		    if ($untaint_skip == 0) {
			die "directory $dir_loc is still tainted";
		    }
		    else {
			next;
		    }
		}
	    }
	    unless (chdir $updir_loc) {
		warnings::warnif "Can't cd to $updir_loc: $!\n";
		next;
	    }
	}

	$dir = $dir_name; # $File::Find::dir

	# Get the list of files in the current directory.
	unless (opendir DIR, ($no_chdir ? $dir_loc : $File::Find::current_dir)) {
	    warnings::warnif "Can't opendir($dir_loc): $!\n";
	    next;
	}
	@filenames = readdir DIR;
	closedir(DIR);

	for my $FN (@filenames) {
	    if ($Is_VMS) {
	    # Big hammer here - Compensate for VMS trailing . and .dir
	    # No win situation until this is changed, but this
	    # will handle the majority of the cases with breaking the fewest.

		$FN =~ s/\.dir\z//i;
		$FN =~ s#\.$## if ($FN ne '.');
	    }
	    next if $FN =~ $File::Find::skip_pattern;

	    # follow symbolic links / do an lstat
	    $new_loc = Follow_SymLink($loc_pref.$FN);

	    # ignore if invalid symlink
	    unless (defined $new_loc) {
	        if (!defined -l _ && $dangling_symlinks) {
                $fullname = undef;
	            if (ref $dangling_symlinks eq 'CODE') {
	                $dangling_symlinks->($FN, $dir_pref);
	            } else {
	                warnings::warnif "$dir_pref$FN is a dangling symbolic link\n";
	            }
	        }
            else {
                $fullname = $loc_pref . $FN;
            }
	        $name = $dir_pref . $FN;
	        $_ = ($no_chdir ? $name : $FN);
	        { $wanted_callback->() };
	        next;
	    }

	    if (-d _) {
		if ($Is_VMS) {
		    $FN =~ s/\.dir\z//i;
		    $FN =~ s#\.$## if ($FN ne '.');
		    $new_loc =~ s/\.dir\z//i;
		    $new_loc =~ s#\.$## if ($new_loc ne '.');
		}
		push @Stack,[$new_loc,$updir_loc,$dir_name,$FN,1];
	    }
	    else {
		$fullname = $new_loc; # $File::Find::fullname
		$name = $dir_pref . $FN; # $File::Find::name
		$_ = ($no_chdir ? $name : $FN); # $_
		{ $wanted_callback->() }; # protect against wild "next"
	    }
	}

    }
    continue {
	while (defined($SE = pop @Stack)) {
	    ($dir_loc, $updir_loc, $p_dir, $dir_rel, $byd_flag) = @$SE;
	    $dir_name = ($p_dir eq '/' ? "/$dir_rel" : "$p_dir/$dir_rel");
	    $dir_pref = "$dir_name/";
	    $loc_pref = "$dir_loc/";
	    if ( $byd_flag < 0 ) {  # must be finddepth, report dirname now
		unless ($no_chdir || ($dir_rel eq $File::Find::current_dir)) {
		    unless (chdir $updir_loc) { # $updir_loc (parent dir) is always untainted
			warnings::warnif "Can't cd to $updir_loc: $!\n";
			next;
		    }
		}
		$fullname = $dir_loc; # $File::Find::fullname
		$name = $dir_name; # $File::Find::name
		if ( substr($name,-2) eq '/.' ) {
		    substr($name, length($name) == 2 ? -1 : -2) = ''; # $File::Find::name
		}
		$dir = $p_dir; # $File::Find::dir
		$_ = ($no_chdir ? $dir_name : $dir_rel); # $_
		if ( substr($_,-2) eq '/.' ) {
		    substr($_, length($_) == 2 ? -1 : -2) = '';
		}

		lstat($_); # make sure file tests with '_' work
		{ $wanted_callback->() }; # protect against wild "next"
	    }
	    else {
		push @Stack,[$dir_loc, $updir_loc, $p_dir, $dir_rel,-1]  if  $bydepth;
		last;
	    }
	}
    }
}


sub wrap_wanted {
    my $wanted = shift;
    if ( ref($wanted) eq 'HASH' ) {
        # RT #122547
        my %valid_options = map {$_ => 1} qw(
            wanted
            bydepth
            preprocess
            postprocess
            follow
            follow_fast
            follow_skip
            dangling_symlinks
            no_chdir
            untaint
            untaint_pattern
            untaint_skip
        );
        my @invalid_options = ();
        for my $v (keys %{$wanted}) {
            push @invalid_options, $v unless exists $valid_options{$v};
        }
        warn "Invalid option(s): @invalid_options" if @invalid_options;

        unless( exists $wanted->{wanted} and ref( $wanted->{wanted} ) eq 'CODE' ) {
            die 'no &wanted subroutine given';
        }
        if ( $wanted->{follow} || $wanted->{follow_fast}) {
            $wanted->{follow_skip} = 1 unless defined $wanted->{follow_skip};
        }
        if ( $wanted->{untaint} ) {
            $wanted->{untaint_pattern} = $File::Find::untaint_pattern
            unless defined $wanted->{untaint_pattern};
            $wanted->{untaint_skip} = 0 unless defined $wanted->{untaint_skip};
        }
        return $wanted;
    }
    elsif( ref( $wanted ) eq 'CODE' ) {
        return { wanted => $wanted };
    }
    else {
       die 'no &wanted subroutine given';
    }
}

sub find {
    my $wanted = shift;
    _find_opt(wrap_wanted($wanted), @_);
}

sub finddepth {
    my $wanted = wrap_wanted(shift);
    $wanted->{bydepth} = 1;
    _find_opt($wanted, @_);
}

# default
$File::Find::skip_pattern    = qr/^\.{1,2}\z/;
$File::Find::untaint_pattern = qr|^([-+@\w./]+)$|;

# These are hard-coded for now, but may move to hint files.
if ($^O eq 'VMS') {
    $Is_VMS = 1;
    $File::Find::dont_use_nlink = 1;
}
elsif ($^O eq 'MSWin32') {
    $Is_Win32 = 1;
}

# this _should_ work properly on all platforms
# where File::Find can be expected to work
$File::Find::current_dir = File::Spec->curdir || '.';

$File::Find::dont_use_nlink = 1
    if $^O eq 'os2' || $^O eq 'dos' || $^O eq 'amigaos' || $Is_Win32 ||
       $^O eq 'interix' || $^O eq 'cygwin' || $^O eq 'qnx' || $^O eq 'nto';

# Set dont_use_nlink in your hint file if your system's stat doesn't
# report the number of links in a directory as an indication
# of the number of files.
# See e.g. hints/haiku.sh for Haiku.
unless ($File::Find::dont_use_nlink) {
    require Config;
    $File::Find::dont_use_nlink = 1 if ($Config::Config{'dont_use_nlink'});
}

# We need a function that checks if a scalar is tainted. Either use the
# Scalar::Util module's tainted() function or our (slower) pure Perl
# fallback is_tainted_pp()
{
    local $@;
    eval { require Scalar::Util };
    *is_tainted = $@ ? \&is_tainted_pp : \&Scalar::Util::tainted;
}

1;

__END__

=head1 NAME

File::Find - Traverse a directory tree.

=head1 SYNOPSIS

    use File::Find;
    find(\&wanted, @directories_to_search);
    sub wanted { ... }

    use File::Find;
    finddepth(\&wanted, @directories_to_search);
    sub wanted { ... }

    use File::Find;
    find({ wanted => \&process, follow => 1 }, '.');

=head1 DESCRIPTION

These are functions for searching through directory trees doing work
on each file found similar to the Unix I<find> command.  File::Find
exports two functions, C<find> and C<finddepth>.  They work similarly
but have subtle differences.

=over 4

=item B<find>

  find(\&wanted,  @directories);
  find(\%options, @directories);

C<find()> does a depth-first search over the given C<@directories> in
the order they are given.  For each file or directory found, it calls
the C<&wanted> subroutine.  (See below for details on how to use the
C<&wanted> function).  Additionally, for each directory found, it will
C<chdir()> into that directory and continue the search, invoking the
C<&wanted> function on each file or subdirectory in the directory.

=item B<finddepth>

  finddepth(\&wanted,  @directories);
  finddepth(\%options, @directories);

C<finddepth()> works just like C<find()> except that it invokes the
C<&wanted> function for a directory I<after> invoking it for the
directory's contents.  It does a postorder traversal instead of a
preorder traversal, working from the bottom of the directory tree up
where C<find()> works from the top of the tree down.

=back

=head2 %options

The first argument to C<find()> is either a code reference to your
C<&wanted> function, or a hash reference describing the operations
to be performed for each file.  The
code reference is described in L</The wanted function> below.

Here are the possible keys for the hash:

=over 3

=item C<wanted>

The value should be a code reference.  This code reference is
described in L</The wanted function> below. The C<&wanted> subroutine is
mandatory.

=item C<bydepth>

Reports the name of a directory only AFTER all its entries
have been reported.  Entry point C<finddepth()> is a shortcut for
specifying C<< { bydepth => 1 } >> in the first argument of C<find()>.

=item C<preprocess>

The value should be a code reference. This code reference is used to
preprocess the current directory. The name of the currently processed
directory is in C<$File::Find::dir>. Your preprocessing function is
called after C<readdir()>, but before the loop that calls the C<wanted()>
function. It is called with a list of strings (actually file/directory
names) and is expected to return a list of strings. The code can be
used to sort the file/directory names alphabetically, numerically,
or to filter out directory entries based on their name alone. When
I<follow> or I<follow_fast> are in effect, C<preprocess> is a no-op.

=item C<postprocess>

The value should be a code reference. It is invoked just before leaving
the currently processed directory. It is called in void context with no
arguments. The name of the current directory is in C<$File::Find::dir>. This
hook is handy for summarizing a directory, such as calculating its disk
usage. When I<follow> or I<follow_fast> are in effect, C<postprocess> is a
no-op.

=item C<follow>

Causes symbolic links to be followed. Since directory trees with symbolic
links (followed) may contain files more than once and may even have
cycles, a hash has to be built up with an entry for each file.
This might be expensive both in space and time for a large
directory tree. See L</follow_fast> and L</follow_skip> below.
If either I<follow> or I<follow_fast> is in effect:

=over 6

=item *

It is guaranteed that an I<lstat> has been called before the user's
C<wanted()> function is called. This enables fast file checks involving C<_>.
Note that this guarantee no longer holds if I<follow> or I<follow_fast>
are not set.

=item *

There is a variable C<$File::Find::fullname> which holds the absolute
pathname of the file with all symbolic links resolved.  If the link is
a dangling symbolic link, then fullname will be set to C<undef>.

=back

This is a no-op on Win32.

=item C<follow_fast>

This is similar to I<follow> except that it may report some files more
than once.  It does detect cycles, however.  Since only symbolic links
have to be hashed, this is much cheaper both in space and time.  If
processing a file more than once (by the user's C<wanted()> function)
is worse than just taking time, the option I<follow> should be used.

This is also a no-op on Win32.

=item C<follow_skip>

C<follow_skip==1>, which is the default, causes all files which are
neither directories nor symbolic links to be ignored if they are about
to be processed a second time. If a directory or a symbolic link
are about to be processed a second time, File::Find dies.

C<follow_skip==0> causes File::Find to die if any file is about to be
processed a second time.

C<follow_skip==2> causes File::Find to ignore any duplicate files and
directories but to proceed normally otherwise.

=item C<dangling_symlinks>

Specifies what to do with symbolic links whose target doesn't exist.
If true and a code reference, will be called with the symbolic link
name and the directory it lives in as arguments.  Otherwise, if true
and warnings are on, a warning of the form C<"symbolic_link_name is a dangling
symbolic link\n"> will be issued.  If false, the dangling symbolic link
will be silently ignored.

=item C<no_chdir>

Does not C<chdir()> to each directory as it recurses. The C<wanted()>
function will need to be aware of this, of course. In this case,
C<$_> will be the same as C<$File::Find::name>.

=item C<untaint>

If find is used in L<taint-mode|perlsec/Taint mode> (-T command line switch or
if EUID != UID or if EGID != GID), then internally directory names have to be
untainted before they can be C<chdir>'d to. Therefore they are checked against
a regular expression I<untaint_pattern>.  Note that all names passed to the
user's C<wanted()> function are still tainted. If this option is used while not
in taint-mode, C<untaint> is a no-op.

=item C<untaint_pattern>

See above. This should be set using the C<qr> quoting operator.
The default is set to C<qr|^([-+@\w./]+)$|>.
Note that the parentheses are vital.

=item C<untaint_skip>

If set, a directory which fails the I<untaint_pattern> is skipped,
including all its sub-directories. The default is to C<die> in such a case.

=back

=head2 The wanted function

The C<wanted()> function does whatever verifications you want on
each file and directory.  Note that despite its name, the C<wanted()>
function is a generic callback function, and does B<not> tell
File::Find if a file is "wanted" or not.  In fact, its return value
is ignored.

The wanted function takes no arguments but rather does its work
through a collection of variables.

=over 4

=item C<$File::Find::dir> is the current directory name,

=item C<$_> is the current filename within that directory

=item C<$File::Find::name> is the complete pathname to the file.

=back

The above variables have all been localized and may be changed without
affecting data outside of the wanted function.

For example, when examining the file F</some/path/foo.ext> you will have:

    $File::Find::dir  = /some/path/
    $_                = foo.ext
    $File::Find::name = /some/path/foo.ext

You are chdir()'d to C<$File::Find::dir> when the function is called,
unless C<no_chdir> was specified. Note that when changing to
directories is in effect, the root directory (F</>) is a somewhat
special case inasmuch as the concatenation of C<$File::Find::dir>,
C<'/'> and C<$_> is not literally equal to C<$File::Find::name>. The
table below summarizes all variants:

              $File::Find::name  $File::Find::dir  $_
 default      /                  /                 .
 no_chdir=>0  /etc               /                 etc
              /etc/x             /etc              x

 no_chdir=>1  /                  /                 /
              /etc               /                 /etc
              /etc/x             /etc              /etc/x


When C<follow> or C<follow_fast> are in effect, there is
also a C<$File::Find::fullname>.  The function may set
C<$File::Find::prune> to prune the tree unless C<bydepth> was
specified.  Unless C<follow> or C<follow_fast> is specified, for
compatibility reasons (find.pl, find2perl) there are in addition the
following globals available: C<$File::Find::topdir>,
C<$File::Find::topdev>, C<$File::Find::topino>,
C<$File::Find::topmode> and C<$File::Find::topnlink>.

This library is useful for the C<find2perl> tool (distributed as part of the
App-find2perl CPAN distribution), which when fed,

  find2perl / -name .nfs\* -mtime +7 \
    -exec rm -f {} \; -o -fstype nfs -prune

produces something like:

 sub wanted {
    /^\.nfs.*\z/s &&
    (($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($_)) &&
    int(-M _) > 7 &&
    unlink($_)
    ||
    ($nlink || (($dev, $ino, $mode, $nlink, $uid, $gid) = lstat($_))) &&
    $dev < 0 &&
    ($File::Find::prune = 1);
 }

Notice the C<_> in the above C<int(-M _)>: the C<_> is a magical
filehandle that caches the information from the preceding
C<stat()>, C<lstat()>, or filetest.

Here's another interesting wanted function.  It will find all symbolic
links that don't resolve:

    sub wanted {
         -l && !-e && print "bogus link: $File::Find::name\n";
    }

Note that you may mix directories and (non-directory) files in the list of 
directories to be searched by the C<wanted()> function.

    find(\&wanted, "./foo", "./bar", "./baz/epsilon");

In the example above, no file in F<./baz/> other than F<./baz/epsilon> will be
evaluated by C<wanted()>.

See also the script C<pfind> on CPAN for a nice application of this
module.

=head1 WARNINGS

If you run your program with the C<-w> switch, or if you use the
C<warnings> pragma, File::Find will report warnings for several weird
situations. You can disable these warnings by putting the statement

    no warnings 'File::Find';

in the appropriate scope. See L<warnings> for more info about lexical
warnings.

=head1 CAVEAT

=over 2

=item $dont_use_nlink

You can set the variable C<$File::Find::dont_use_nlink> to 1 if you want to
force File::Find to always stat directories. This was used for file systems
that do not have an C<nlink> count matching the number of sub-directories.
Examples are ISO-9660 (CD-ROM), AFS, HPFS (OS/2 file system), FAT (DOS file
system) and a couple of others.

You shouldn't need to set this variable, since File::Find should now detect
such file systems on-the-fly and switch itself to using stat. This works even
for parts of your file system, like a mounted CD-ROM.

If you do set C<$File::Find::dont_use_nlink> to 1, you will notice slow-downs.

=item symlinks

Be aware that the option to follow symbolic links can be dangerous.
Depending on the structure of the directory tree (including symbolic
links to directories) you might traverse a given (physical) directory
more than once (only if C<follow_fast> is in effect).
Furthermore, deleting or changing files in a symbolically linked directory
might cause very unpleasant surprises, since you delete or change files
in an unknown directory.

=back

=head1 BUGS AND CAVEATS

Despite the name of the C<finddepth()> function, both C<find()> and
C<finddepth()> perform a depth-first search of the directory
hierarchy.

=head1 HISTORY

File::Find used to produce incorrect results if called recursively.
During the development of perl 5.8 this bug was fixed.
The first fixed version of File::Find was 1.01.

=head1 SEE ALSO

L<find(1)>, find2perl.

=cut
PK�6�Z�tڪ��
Compare.pmnu�[���package File::Compare;

use 5.006;
use strict;
use warnings;
our($VERSION, @ISA, @EXPORT, @EXPORT_OK, $Too_Big);

require Exporter;

$VERSION = '1.1006';
@ISA = qw(Exporter);
@EXPORT = qw(compare);
@EXPORT_OK = qw(cmp compare_text);

$Too_Big = 1024 * 1024 * 2;

sub croak {
    require Carp;
    goto &Carp::croak;
}

sub compare {
    croak("Usage: compare( file1, file2 [, buffersize]) ")
      unless(@_ == 2 || @_ == 3);

    my ($from,$to,$size) = @_;
    my $text_mode = defined($size) && (ref($size) eq 'CODE' || $size < 0);

    my ($fromsize,$closefrom,$closeto);
    local (*FROM, *TO);

    croak("from undefined") unless (defined $from);
    croak("to undefined") unless (defined $to);

    if (ref($from) && 
        (UNIVERSAL::isa($from,'GLOB') || UNIVERSAL::isa($from,'IO::Handle'))) {
	*FROM = *$from;
    } elsif (ref(\$from) eq 'GLOB') {
	*FROM = $from;
    } else {
	open(FROM,"<",$from) or goto fail_open1;
	unless ($text_mode) {
	    binmode FROM;
	    $fromsize = -s FROM;
	}
	$closefrom = 1;
    }

    if (ref($to) &&
        (UNIVERSAL::isa($to,'GLOB') || UNIVERSAL::isa($to,'IO::Handle'))) {
	*TO = *$to;
    } elsif (ref(\$to) eq 'GLOB') {
	*TO = $to;
    } else {
	open(TO,"<",$to) or goto fail_open2;
	binmode TO unless $text_mode;
	$closeto = 1;
    }

    if (!$text_mode && $closefrom && $closeto) {
	# If both are opened files we know they differ if their size differ
	goto fail_inner if $fromsize != -s TO;
    }

    if ($text_mode) {
	local $/ = "\n";
	my ($fline,$tline);
	while (defined($fline = <FROM>)) {
	    goto fail_inner unless defined($tline = <TO>);
	    if (ref $size) {
		# $size contains ref to comparison function
		goto fail_inner if &$size($fline, $tline);
	    } else {
		goto fail_inner if $fline ne $tline;
	    }
	}
	goto fail_inner if defined($tline = <TO>);
    }
    else {
	unless (defined($size) && $size > 0) {
	    $size = $fromsize || -s TO || 0;
	    $size = 1024 if $size < 512;
	    $size = $Too_Big if $size > $Too_Big;
	}

	my ($fr,$tr,$fbuf,$tbuf);
	$fbuf = $tbuf = '';
	while(defined($fr = read(FROM,$fbuf,$size)) && $fr > 0) {
	    unless (defined($tr = read(TO,$tbuf,$fr)) && $tbuf eq $fbuf) {
		goto fail_inner;
	    }
	}
	goto fail_inner if defined($tr = read(TO,$tbuf,$size)) && $tr > 0;
    }

    close(TO) || goto fail_open2 if $closeto;
    close(FROM) || goto fail_open1 if $closefrom;

    return 0;
    
  # All of these contortions try to preserve error messages...
  fail_inner:
    close(TO) || goto fail_open2 if $closeto;
    close(FROM) || goto fail_open1 if $closefrom;

    return 1;

  fail_open2:
    if ($closefrom) {
	my $status = $!;
	$! = 0;
	close FROM;
	$! = $status unless $!;
    }
  fail_open1:
    return -1;
}

sub cmp;
*cmp = \&compare;

sub compare_text {
    my ($from,$to,$cmp) = @_;
    croak("Usage: compare_text( file1, file2 [, cmp-function])")
	unless @_ == 2 || @_ == 3;
    croak("Third arg to compare_text() function must be a code reference")
	if @_ == 3 && ref($cmp) ne 'CODE';

    # Using a negative buffer size puts compare into text_mode too
    $cmp = -1 unless defined $cmp;
    compare($from, $to, $cmp);
}

1;

__END__

=head1 NAME

File::Compare - Compare files or filehandles

=head1 SYNOPSIS

  	use File::Compare;

	if (compare("file1","file2") == 0) {
	    print "They're equal\n";
	}

=head1 DESCRIPTION

The File::Compare::compare function compares the contents of two
sources, each of which can be a file or a file handle.  It is exported
from File::Compare by default.

File::Compare::cmp is a synonym for File::Compare::compare.  It is
exported from File::Compare only by request.

File::Compare::compare_text does a line by line comparison of the two
files. It stops as soon as a difference is detected. compare_text()
accepts an optional third argument: This must be a CODE reference to
a line comparison function, which returns 0 when both lines are considered
equal. For example:

    compare_text($file1, $file2)

is basically equivalent to

    compare_text($file1, $file2, sub {$_[0] ne $_[1]} )

=head1 RETURN

File::Compare::compare and its sibling functions return 0 if the files
are equal, 1 if the files are unequal, or -1 if an error was encountered.

=head1 AUTHOR

File::Compare was written by Nick Ing-Simmons.
Its original documentation was written by Chip Salzenberg.

=cut

PKnc[��##Spec/Epoc.pmnu�[���package File::Spec::Epoc;

use strict;

our $VERSION = '3.74';
$VERSION =~ tr/_//d;

require File::Spec::Unix;
our @ISA = qw(File::Spec::Unix);

=head1 NAME

File::Spec::Epoc - methods for Epoc file specs

=head1 SYNOPSIS

 require File::Spec::Epoc; # Done internally by File::Spec if needed

=head1 DESCRIPTION

See File::Spec::Unix for a documentation of the methods provided
there.  This package overrides the implementation of these methods, not
the semantics.

This package is still a work in progress. ;-)

=cut

sub case_tolerant {
    return 1;
}

=pod

=over 4

=item canonpath()

No physical check on the filesystem, but a logical cleanup of a
path.  On UNIX eliminated successive slashes and successive "/.".

=back

=cut

sub canonpath {
    my ($self,$path) = @_;
    return unless defined $path;

    $path =~ s|/+|/|g;                             # xx////xx  -> xx/xx
    $path =~ s|(/\.)+/|/|g;                        # xx/././xx -> xx/xx
    $path =~ s|^(\./)+||s unless $path eq "./";    # ./xx      -> xx
    $path =~ s|^/(\.\./)+|/|s;                     # /../../xx -> xx
    $path =~  s|/\Z(?!\n)|| unless $path eq "/";          # xx/       -> xx
    return $path;
}

=pod

=head1 AUTHOR

o.flebbe@gmx.de

=head1 COPYRIGHT

Copyright (c) 2004 by the Perl 5 Porters.  All rights reserved.

This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

=head1 SEE ALSO

See L<File::Spec> and L<File::Spec::Unix>.  This package overrides the
implementation of these methods, not the semantics.

=cut

1;
PKnc[�
5mSpec/Cygwin.pmnu�[���package File::Spec::Cygwin;

use strict;
require File::Spec::Unix;

our $VERSION = '3.74';
$VERSION =~ tr/_//d;

our @ISA = qw(File::Spec::Unix);

=head1 NAME

File::Spec::Cygwin - methods for Cygwin file specs

=head1 SYNOPSIS

 require File::Spec::Cygwin; # Done internally by File::Spec if needed

=head1 DESCRIPTION

See L<File::Spec> and L<File::Spec::Unix>.  This package overrides the
implementation of these methods, not the semantics.

This module is still in beta.  Cygwin-knowledgeable folks are invited
to offer patches and suggestions.

=cut

=pod

=over 4

=item canonpath

Any C<\> (backslashes) are converted to C</> (forward slashes),
and then File::Spec::Unix canonpath() is called on the result.

=cut

sub canonpath {
    my($self,$path) = @_;
    return unless defined $path;

    $path =~ s|\\|/|g;

    # Handle network path names beginning with double slash
    my $node = '';
    if ( $path =~ s@^(//[^/]+)(?:/|\z)@/@s ) {
        $node = $1;
    }
    return $node . $self->SUPER::canonpath($path);
}

sub catdir {
    my $self = shift;
    return unless @_;

    # Don't create something that looks like a //network/path
    if ($_[0] and ($_[0] eq '/' or $_[0] eq '\\')) {
        shift;
        return $self->SUPER::catdir('', @_);
    }

    $self->SUPER::catdir(@_);
}

=pod

=item file_name_is_absolute

True is returned if the file name begins with C<drive_letter:>,
and if not, File::Spec::Unix file_name_is_absolute() is called.

=cut


sub file_name_is_absolute {
    my ($self,$file) = @_;
    return 1 if $file =~ m{^([a-z]:)?[\\/]}is; # C:/test
    return $self->SUPER::file_name_is_absolute($file);
}

=item tmpdir (override)

Returns a string representation of the first existing directory
from the following list:

    $ENV{TMPDIR}
    /tmp
    $ENV{'TMP'}
    $ENV{'TEMP'}
    C:/temp

If running under taint mode, and if the environment
variables are tainted, they are not used.

=cut

sub tmpdir {
    my $cached = $_[0]->_cached_tmpdir(qw 'TMPDIR TMP TEMP');
    return $cached if defined $cached;
    $_[0]->_cache_tmpdir(
        $_[0]->_tmpdir(
            $ENV{TMPDIR}, "/tmp", $ENV{'TMP'}, $ENV{'TEMP'}, 'C:/temp'
        ),
        qw 'TMPDIR TMP TEMP'
    );
}

=item case_tolerant

Override Unix. Cygwin case-tolerance depends on managed mount settings and
as with MsWin32 on GetVolumeInformation() $ouFsFlags == FS_CASE_SENSITIVE,
indicating the case significance when comparing file specifications.
Default: 1

=cut

sub case_tolerant {
  return 1 unless $^O eq 'cygwin'
    and defined &Cygwin::mount_flags;

  my $drive = shift;
  if (! $drive) {
      my @flags = split(/,/, Cygwin::mount_flags('/cygwin'));
      my $prefix = pop(@flags);
      if (! $prefix || $prefix eq 'cygdrive') {
          $drive = '/cygdrive/c';
      } elsif ($prefix eq '/') {
          $drive = '/c';
      } else {
          $drive = "$prefix/c";
      }
  }
  my $mntopts = Cygwin::mount_flags($drive);
  if ($mntopts and ($mntopts =~ /,managed/)) {
    return 0;
  }
  eval {
      local @INC = @INC;
      pop @INC if $INC[-1] eq '.';
      require Win32API::File;
  } or return 1;
  my $osFsType = "\0"x256;
  my $osVolName = "\0"x256;
  my $ouFsFlags = 0;
  Win32API::File::GetVolumeInformation($drive, $osVolName, 256, [], [], $ouFsFlags, $osFsType, 256 );
  if ($ouFsFlags & Win32API::File::FS_CASE_SENSITIVE()) { return 0; }
  else { return 1; }
}

=back

=head1 COPYRIGHT

Copyright (c) 2004,2007 by the Perl 5 Porters.  All rights reserved.

This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

=cut

1;
PKnc[�F� >>Spec/Unix.pmnu�[���package File::Spec::Unix;

use strict;
use Cwd ();

our $VERSION = '3.74';
$VERSION =~ tr/_//d;

=head1 NAME

File::Spec::Unix - File::Spec for Unix, base for other File::Spec modules

=head1 SYNOPSIS

 require File::Spec::Unix; # Done automatically by File::Spec

=head1 DESCRIPTION

Methods for manipulating file specifications.  Other File::Spec
modules, such as File::Spec::Mac, inherit from File::Spec::Unix and
override specific methods.

=head1 METHODS

=over 2

=item canonpath()

No physical check on the filesystem, but a logical cleanup of a
path. On UNIX eliminates successive slashes and successive "/.".

    $cpath = File::Spec->canonpath( $path ) ;

Note that this does *not* collapse F<x/../y> sections into F<y>.  This
is by design.  If F</foo> on your system is a symlink to F</bar/baz>,
then F</foo/../quux> is actually F</bar/quux>, not F</quux> as a naive
F<../>-removal would give you.  If you want to do this kind of
processing, you probably want C<Cwd>'s C<realpath()> function to
actually traverse the filesystem cleaning up paths like this.

=cut

sub _pp_canonpath {
    my ($self,$path) = @_;
    return unless defined $path;
    
    # Handle POSIX-style node names beginning with double slash (qnx, nto)
    # (POSIX says: "a pathname that begins with two successive slashes
    # may be interpreted in an implementation-defined manner, although
    # more than two leading slashes shall be treated as a single slash.")
    my $node = '';
    my $double_slashes_special = $^O eq 'qnx' || $^O eq 'nto';


    if ( $double_slashes_special
         && ( $path =~ s{^(//[^/]+)/?\z}{}s || $path =~ s{^(//[^/]+)/}{/}s ) ) {
      $node = $1;
    }
    # This used to be
    # $path =~ s|/+|/|g unless ($^O eq 'cygwin');
    # but that made tests 29, 30, 35, 46, and 213 (as of #13272) to fail
    # (Mainly because trailing "" directories didn't get stripped).
    # Why would cygwin avoid collapsing multiple slashes into one? --jhi
    $path =~ s|/{2,}|/|g;                            # xx////xx  -> xx/xx
    $path =~ s{(?:/\.)+(?:/|\z)}{/}g;                # xx/././xx -> xx/xx
    $path =~ s|^(?:\./)+||s unless $path eq "./";    # ./xx      -> xx
    $path =~ s|^/(?:\.\./)+|/|;                      # /../../xx -> xx
    $path =~ s|^/\.\.$|/|;                         # /..       -> /
    $path =~ s|/\z|| unless $path eq "/";          # xx/       -> xx
    return "$node$path";
}
*canonpath = \&_pp_canonpath unless defined &canonpath;

=item catdir()

Concatenate two or more directory names to form a complete path ending
with a directory. But remove the trailing slash from the resulting
string, because it doesn't look good, isn't necessary and confuses
OS2. Of course, if this is the root directory, don't cut off the
trailing slash :-)

=cut

sub _pp_catdir {
    my $self = shift;

    $self->canonpath(join('/', @_, '')); # '' because need a trailing '/'
}
*catdir = \&_pp_catdir unless defined &catdir;

=item catfile

Concatenate one or more directory names and a filename to form a
complete path ending with a filename

=cut

sub _pp_catfile {
    my $self = shift;
    my $file = $self->canonpath(pop @_);
    return $file unless @_;
    my $dir = $self->catdir(@_);
    $dir .= "/" unless substr($dir,-1) eq "/";
    return $dir.$file;
}
*catfile = \&_pp_catfile unless defined &catfile;

=item curdir

Returns a string representation of the current directory.  "." on UNIX.

=cut

sub curdir { '.' }
use constant _fn_curdir => ".";

=item devnull

Returns a string representation of the null device. "/dev/null" on UNIX.

=cut

sub devnull { '/dev/null' }
use constant _fn_devnull => "/dev/null";

=item rootdir

Returns a string representation of the root directory.  "/" on UNIX.

=cut

sub rootdir { '/' }
use constant _fn_rootdir => "/";

=item tmpdir

Returns a string representation of the first writable directory from
the following list or the current directory if none from the list are
writable:

    $ENV{TMPDIR}
    /tmp

If running under taint mode, and if $ENV{TMPDIR}
is tainted, it is not used.

=cut

my ($tmpdir, %tmpenv);
# Cache and return the calculated tmpdir, recording which env vars
# determined it.
sub _cache_tmpdir {
    @tmpenv{@_[2..$#_]} = @ENV{@_[2..$#_]};
    return $tmpdir = $_[1];
}
# Retrieve the cached tmpdir, checking first whether relevant env vars have
# changed and invalidated the cache.
sub _cached_tmpdir {
    shift;
    local $^W;
    return if grep $ENV{$_} ne $tmpenv{$_}, @_;
    return $tmpdir;
}
sub _tmpdir {
    my $self = shift;
    my @dirlist = @_;
    my $taint = do { no strict 'refs'; ${"\cTAINT"} };
    if ($taint) { # Check for taint mode on perl >= 5.8.0
	require Scalar::Util;
	@dirlist = grep { ! Scalar::Util::tainted($_) } @dirlist;
    }
    elsif ($] < 5.007) { # No ${^TAINT} before 5.8
	@dirlist = grep { !defined($_) || eval { eval('1'.substr $_,0,0) } }
			@dirlist;
    }
    
    foreach (@dirlist) {
	next unless defined && -d && -w _;
	$tmpdir = $_;
	last;
    }
    $tmpdir = $self->curdir unless defined $tmpdir;
    $tmpdir = defined $tmpdir && $self->canonpath($tmpdir);
    if ( !$self->file_name_is_absolute($tmpdir) ) {
        # See [perl #120593] for the full details
        # If possible, return a full path, rather than '.' or 'lib', but
        # jump through some hoops to avoid returning a tainted value.
        ($tmpdir) = grep {
            $taint     ? ! Scalar::Util::tainted($_) :
            $] < 5.007 ? eval { eval('1'.substr $_,0,0) } : 1
        } $self->rel2abs($tmpdir), $tmpdir;
    }
    return $tmpdir;
}

sub tmpdir {
    my $cached = $_[0]->_cached_tmpdir('TMPDIR');
    return $cached if defined $cached;
    $_[0]->_cache_tmpdir($_[0]->_tmpdir( $ENV{TMPDIR}, "/tmp" ), 'TMPDIR');
}

=item updir

Returns a string representation of the parent directory.  ".." on UNIX.

=cut

sub updir { '..' }
use constant _fn_updir => "..";

=item no_upwards

Given a list of file names, strip out those that refer to a parent
directory. (Does not strip symlinks, only '.', '..', and equivalents.)

=cut

sub no_upwards {
    my $self = shift;
    return grep(!/^\.{1,2}\z/s, @_);
}

=item case_tolerant

Returns a true or false value indicating, respectively, that alphabetic
is not or is significant when comparing file specifications.

=cut

sub case_tolerant { 0 }
use constant _fn_case_tolerant => 0;

=item file_name_is_absolute

Takes as argument a path and returns true if it is an absolute path.

This does not consult the local filesystem on Unix, Win32, OS/2 or Mac 
OS (Classic).  It does consult the working environment for VMS (see
L<File::Spec::VMS/file_name_is_absolute>).

=cut

sub file_name_is_absolute {
    my ($self,$file) = @_;
    return scalar($file =~ m:^/:s);
}

=item path

Takes no argument, returns the environment variable PATH as an array.

=cut

sub path {
    return () unless exists $ENV{PATH};
    my @path = split(':', $ENV{PATH});
    foreach (@path) { $_ = '.' if $_ eq '' }
    return @path;
}

=item join

join is the same as catfile.

=cut

sub join {
    my $self = shift;
    return $self->catfile(@_);
}

=item splitpath

    ($volume,$directories,$file) = File::Spec->splitpath( $path );
    ($volume,$directories,$file) = File::Spec->splitpath( $path,
                                                          $no_file );

Splits a path into volume, directory, and filename portions. On systems
with no concept of volume, returns '' for volume. 

For systems with no syntax differentiating filenames from directories, 
assumes that the last file is a path unless $no_file is true or a 
trailing separator or /. or /.. is present. On Unix this means that $no_file
true makes this return ( '', $path, '' ).

The directory portion may or may not be returned with a trailing '/'.

The results can be passed to L</catpath()> to get back a path equivalent to
(usually identical to) the original path.

=cut

sub splitpath {
    my ($self,$path, $nofile) = @_;

    my ($volume,$directory,$file) = ('','','');

    if ( $nofile ) {
        $directory = $path;
    }
    else {
        $path =~ m|^ ( (?: .* / (?: \.\.?\z )? )? ) ([^/]*) |xs;
        $directory = $1;
        $file      = $2;
    }

    return ($volume,$directory,$file);
}


=item splitdir

The opposite of L</catdir()>.

    @dirs = File::Spec->splitdir( $directories );

$directories must be only the directory portion of the path on systems 
that have the concept of a volume or that have path syntax that differentiates
files from directories.

Unlike just splitting the directories on the separator, empty
directory names (C<''>) can be returned, because these are significant
on some OSs.

On Unix,

    File::Spec->splitdir( "/a/b//c/" );

Yields:

    ( '', 'a', 'b', '', 'c', '' )

=cut

sub splitdir {
    return split m|/|, $_[1], -1;  # Preserve trailing fields
}


=item catpath()

Takes volume, directory and file portions and returns an entire path. Under
Unix, $volume is ignored, and directory and file are concatenated.  A '/' is
inserted if needed (though if the directory portion doesn't start with
'/' it is not added).  On other OSs, $volume is significant.

=cut

sub catpath {
    my ($self,$volume,$directory,$file) = @_;

    if ( $directory ne ''                && 
         $file ne ''                     && 
         substr( $directory, -1 ) ne '/' && 
         substr( $file, 0, 1 ) ne '/' 
    ) {
        $directory .= "/$file" ;
    }
    else {
        $directory .= $file ;
    }

    return $directory ;
}

=item abs2rel

Takes a destination path and an optional base path returns a relative path
from the base path to the destination path:

    $rel_path = File::Spec->abs2rel( $path ) ;
    $rel_path = File::Spec->abs2rel( $path, $base ) ;

If $base is not present or '', then L<cwd()|Cwd> is used. If $base is
relative, then it is converted to absolute form using
L</rel2abs()>. This means that it is taken to be relative to
L<cwd()|Cwd>.

On systems that have a grammar that indicates filenames, this ignores the 
$base filename. Otherwise all path components are assumed to be
directories.

If $path is relative, it is converted to absolute form using L</rel2abs()>.
This means that it is taken to be relative to L<cwd()|Cwd>.

No checks against the filesystem are made, so the result may not be correct if
C<$base> contains symbolic links.  (Apply
L<Cwd::abs_path()|Cwd/abs_path> beforehand if that
is a concern.)  On VMS, there is interaction with the working environment, as
logicals and macros are expanded.

Based on code written by Shigio Yamaguchi.

=cut

sub abs2rel {
    my($self,$path,$base) = @_;
    $base = Cwd::getcwd() unless defined $base and length $base;

    ($path, $base) = map $self->canonpath($_), $path, $base;

    my $path_directories;
    my $base_directories;

    if (grep $self->file_name_is_absolute($_), $path, $base) {
	($path, $base) = map $self->rel2abs($_), $path, $base;

	my ($path_volume) = $self->splitpath($path, 1);
	my ($base_volume) = $self->splitpath($base, 1);

	# Can't relativize across volumes
	return $path unless $path_volume eq $base_volume;

	$path_directories = ($self->splitpath($path, 1))[1];
	$base_directories = ($self->splitpath($base, 1))[1];

	# For UNC paths, the user might give a volume like //foo/bar that
	# strictly speaking has no directory portion.  Treat it as if it
	# had the root directory for that volume.
	if (!length($base_directories) and $self->file_name_is_absolute($base)) {
	    $base_directories = $self->rootdir;
	}
    }
    else {
	my $wd= ($self->splitpath(Cwd::getcwd(), 1))[1];
	$path_directories = $self->catdir($wd, $path);
	$base_directories = $self->catdir($wd, $base);
    }

    # Now, remove all leading components that are the same
    my @pathchunks = $self->splitdir( $path_directories );
    my @basechunks = $self->splitdir( $base_directories );

    if ($base_directories eq $self->rootdir) {
      return $self->curdir if $path_directories eq $self->rootdir;
      shift @pathchunks;
      return $self->canonpath( $self->catpath('', $self->catdir( @pathchunks ), '') );
    }

    my @common;
    while (@pathchunks && @basechunks && $self->_same($pathchunks[0], $basechunks[0])) {
        push @common, shift @pathchunks ;
        shift @basechunks ;
    }
    return $self->curdir unless @pathchunks || @basechunks;

    # @basechunks now contains the directories the resulting relative path 
    # must ascend out of before it can descend to $path_directory.  If there
    # are updir components, we must descend into the corresponding directories
    # (this only works if they are no symlinks).
    my @reverse_base;
    while( defined(my $dir= shift @basechunks) ) {
	if( $dir ne $self->updir ) {
	    unshift @reverse_base, $self->updir;
	    push @common, $dir;
	}
	elsif( @common ) {
	    if( @reverse_base && $reverse_base[0] eq $self->updir ) {
		shift @reverse_base;
		pop @common;
	    }
	    else {
		unshift @reverse_base, pop @common;
	    }
	}
    }
    my $result_dirs = $self->catdir( @reverse_base, @pathchunks );
    return $self->canonpath( $self->catpath('', $result_dirs, '') );
}

sub _same {
  $_[1] eq $_[2];
}

=item rel2abs()

Converts a relative path to an absolute path. 

    $abs_path = File::Spec->rel2abs( $path ) ;
    $abs_path = File::Spec->rel2abs( $path, $base ) ;

If $base is not present or '', then L<cwd()|Cwd> is used. If $base is
relative, then it is converted to absolute form using
L</rel2abs()>. This means that it is taken to be relative to
L<cwd()|Cwd>.

On systems that have a grammar that indicates filenames, this ignores
the $base filename. Otherwise all path components are assumed to be
directories.

If $path is absolute, it is cleaned up and returned using L</canonpath()>.

No checks against the filesystem are made.  On VMS, there is
interaction with the working environment, as logicals and
macros are expanded.

Based on code written by Shigio Yamaguchi.

=cut

sub rel2abs {
    my ($self,$path,$base ) = @_;

    # Clean up $path
    if ( ! $self->file_name_is_absolute( $path ) ) {
        # Figure out the effective $base and clean it up.
        if ( !defined( $base ) || $base eq '' ) {
	    $base = Cwd::getcwd();
        }
        elsif ( ! $self->file_name_is_absolute( $base ) ) {
            $base = $self->rel2abs( $base ) ;
        }
        else {
            $base = $self->canonpath( $base ) ;
        }

        # Glom them together
        $path = $self->catdir( $base, $path ) ;
    }

    return $self->canonpath( $path ) ;
}

=back

=head1 COPYRIGHT

Copyright (c) 2004 by the Perl 5 Porters.  All rights reserved.

This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

Please submit bug reports and patches to perlbug@perl.org.

=head1 SEE ALSO

L<File::Spec>

=cut

# Internal method to reduce xx\..\yy -> yy
sub _collapse {
    my($fs, $path) = @_;

    my $updir  = $fs->updir;
    my $curdir = $fs->curdir;

    my($vol, $dirs, $file) = $fs->splitpath($path);
    my @dirs = $fs->splitdir($dirs);
    pop @dirs if @dirs && $dirs[-1] eq '';

    my @collapsed;
    foreach my $dir (@dirs) {
        if( $dir eq $updir              and   # if we have an updir
            @collapsed                  and   # and something to collapse
            length $collapsed[-1]       and   # and its not the rootdir
            $collapsed[-1] ne $updir    and   # nor another updir
            $collapsed[-1] ne $curdir         # nor the curdir
          ) 
        {                                     # then
            pop @collapsed;                   # collapse
        }
        else {                                # else
            push @collapsed, $dir;            # just hang onto it
        }
    }

    return $fs->catpath($vol,
                        $fs->catdir(@collapsed),
                        $file
                       );
}


1;
PKnc[���WWSpec/Mac.pmnu�[���package File::Spec::Mac;

use strict;
use Cwd ();
require File::Spec::Unix;

our $VERSION = '3.74';
$VERSION =~ tr/_//d;

our @ISA = qw(File::Spec::Unix);

sub case_tolerant { 1 }


=head1 NAME

File::Spec::Mac - File::Spec for Mac OS (Classic)

=head1 SYNOPSIS

 require File::Spec::Mac; # Done internally by File::Spec if needed

=head1 DESCRIPTION

Methods for manipulating file specifications.

=head1 METHODS

=over 2

=item canonpath

On Mac OS, there's nothing to be done. Returns what it's given.

=cut

sub canonpath {
    my ($self,$path) = @_;
    return $path;
}

=item catdir()

Concatenate two or more directory names to form a path separated by colons
(":") ending with a directory. Resulting paths are B<relative> by default,
but can be forced to be absolute (but avoid this, see below). Automatically
puts a trailing ":" on the end of the complete path, because that's what's
done in MacPerl's environment and helps to distinguish a file path from a
directory path.

B<IMPORTANT NOTE:> Beginning with version 1.3 of this module, the resulting
path is relative by default and I<not> absolute. This decision was made due
to portability reasons. Since C<File::Spec-E<gt>catdir()> returns relative paths
on all other operating systems, it will now also follow this convention on Mac
OS. Note that this may break some existing scripts.

The intended purpose of this routine is to concatenate I<directory names>.
But because of the nature of Macintosh paths, some additional possibilities
are allowed to make using this routine give reasonable results for some
common situations. In other words, you are also allowed to concatenate
I<paths> instead of directory names (strictly speaking, a string like ":a"
is a path, but not a name, since it contains a punctuation character ":").

So, beside calls like

    catdir("a") = ":a:"
    catdir("a","b") = ":a:b:"
    catdir() = ""                    (special case)

calls like the following

    catdir(":a:") = ":a:"
    catdir(":a","b") = ":a:b:"
    catdir(":a:","b") = ":a:b:"
    catdir(":a:",":b:") = ":a:b:"
    catdir(":") = ":"

are allowed.

Here are the rules that are used in C<catdir()>; note that we try to be as
compatible as possible to Unix:

=over 2

=item 1.

The resulting path is relative by default, i.e. the resulting path will have a
leading colon.

=item 2.

A trailing colon is added automatically to the resulting path, to denote a
directory.

=item 3.

Generally, each argument has one leading ":" and one trailing ":"
removed (if any). They are then joined together by a ":". Special
treatment applies for arguments denoting updir paths like "::lib:",
see (4), or arguments consisting solely of colons ("colon paths"),
see (5).

=item 4.

When an updir path like ":::lib::" is passed as argument, the number
of directories to climb up is handled correctly, not removing leading
or trailing colons when necessary. E.g.

    catdir(":::a","::b","c")    = ":::a::b:c:"
    catdir(":::a::","::b","c")  = ":::a:::b:c:"

=item 5.

Adding a colon ":" or empty string "" to a path at I<any> position
doesn't alter the path, i.e. these arguments are ignored. (When a ""
is passed as the first argument, it has a special meaning, see
(6)). This way, a colon ":" is handled like a "." (curdir) on Unix,
while an empty string "" is generally ignored (see
L<File::Spec::Unix/canonpath()> ). Likewise, a "::" is handled like a ".."
(updir), and a ":::" is handled like a "../.." etc.  E.g.

    catdir("a",":",":","b")   = ":a:b:"
    catdir("a",":","::",":b") = ":a::b:"

=item 6.

If the first argument is an empty string "" or is a volume name, i.e. matches
the pattern /^[^:]+:/, the resulting path is B<absolute>.

=item 7.

Passing an empty string "" as the first argument to C<catdir()> is
like passingC<File::Spec-E<gt>rootdir()> as the first argument, i.e.

    catdir("","a","b")          is the same as

    catdir(rootdir(),"a","b").

This is true on Unix, where C<catdir("","a","b")> yields "/a/b" and
C<rootdir()> is "/". Note that C<rootdir()> on Mac OS is the startup
volume, which is the closest in concept to Unix' "/". This should help
to run existing scripts originally written for Unix.

=item 8.

For absolute paths, some cleanup is done, to ensure that the volume
name isn't immediately followed by updirs. This is invalid, because
this would go beyond "root". Generally, these cases are handled like
their Unix counterparts:

 Unix:
    Unix->catdir("","")                 =  "/"
    Unix->catdir("",".")                =  "/"
    Unix->catdir("","..")               =  "/"        # can't go
                                                      # beyond root
    Unix->catdir("",".","..","..","a")  =  "/a"
 Mac:
    Mac->catdir("","")                  =  rootdir()  # (e.g. "HD:")
    Mac->catdir("",":")                 =  rootdir()
    Mac->catdir("","::")                =  rootdir()  # can't go
                                                      # beyond root
    Mac->catdir("",":","::","::","a")   =  rootdir() . "a:"
                                                    # (e.g. "HD:a:")

However, this approach is limited to the first arguments following
"root" (again, see L<File::Spec::Unix/canonpath()>. If there are more
arguments that move up the directory tree, an invalid path going
beyond root can be created.

=back

As you've seen, you can force C<catdir()> to create an absolute path
by passing either an empty string or a path that begins with a volume
name as the first argument. However, you are strongly encouraged not
to do so, since this is done only for backward compatibility. Newer
versions of File::Spec come with a method called C<catpath()> (see
below), that is designed to offer a portable solution for the creation
of absolute paths.  It takes volume, directory and file portions and
returns an entire path. While C<catdir()> is still suitable for the
concatenation of I<directory names>, you are encouraged to use
C<catpath()> to concatenate I<volume names> and I<directory
paths>. E.g.

    $dir      = File::Spec->catdir("tmp","sources");
    $abs_path = File::Spec->catpath("MacintoshHD:", $dir,"");

yields

    "MacintoshHD:tmp:sources:" .

=cut

sub catdir {
	my $self = shift;
	return '' unless @_;
	my @args = @_;
	my $first_arg;
	my $relative;

	# take care of the first argument

	if ($args[0] eq '')  { # absolute path, rootdir
		shift @args;
		$relative = 0;
		$first_arg = $self->rootdir;

	} elsif ($args[0] =~ /^[^:]+:/) { # absolute path, volume name
		$relative = 0;
		$first_arg = shift @args;
		# add a trailing ':' if need be (may be it's a path like HD:dir)
		$first_arg = "$first_arg:" unless ($first_arg =~ /:\Z(?!\n)/);

	} else { # relative path
		$relative = 1;
		if ( $args[0] =~ /^::+\Z(?!\n)/ ) {
			# updir colon path ('::', ':::' etc.), don't shift
			$first_arg = ':';
		} elsif ($args[0] eq ':') {
			$first_arg = shift @args;
		} else {
			# add a trailing ':' if need be
			$first_arg = shift @args;
			$first_arg = "$first_arg:" unless ($first_arg =~ /:\Z(?!\n)/);
		}
	}

	# For all other arguments,
	# (a) ignore arguments that equal ':' or '',
	# (b) handle updir paths specially:
	#     '::' 			-> concatenate '::'
	#     '::' . '::' 	-> concatenate ':::' etc.
	# (c) add a trailing ':' if need be

	my $result = $first_arg;
	while (@args) {
		my $arg = shift @args;
		unless (($arg eq '') || ($arg eq ':')) {
			if ($arg =~ /^::+\Z(?!\n)/ ) { # updir colon path like ':::'
				my $updir_count = length($arg) - 1;
				while ((@args) && ($args[0] =~ /^::+\Z(?!\n)/) ) { # while updir colon path
					$arg = shift @args;
					$updir_count += (length($arg) - 1);
				}
				$arg = (':' x $updir_count);
			} else {
				$arg =~ s/^://s; # remove a leading ':' if any
				$arg = "$arg:" unless ($arg =~ /:\Z(?!\n)/); # ensure trailing ':'
			}
			$result .= $arg;
		}#unless
	}

	if ( ($relative) && ($result !~ /^:/) ) {
		# add a leading colon if need be
		$result = ":$result";
	}

	unless ($relative) {
		# remove updirs immediately following the volume name
		$result =~ s/([^:]+:)(:*)(.*)\Z(?!\n)/$1$3/;
	}

	return $result;
}

=item catfile

Concatenate one or more directory names and a filename to form a
complete path ending with a filename. Resulting paths are B<relative>
by default, but can be forced to be absolute (but avoid this).

B<IMPORTANT NOTE:> Beginning with version 1.3 of this module, the
resulting path is relative by default and I<not> absolute. This
decision was made due to portability reasons. Since
C<File::Spec-E<gt>catfile()> returns relative paths on all other
operating systems, it will now also follow this convention on Mac OS.
Note that this may break some existing scripts.

The last argument is always considered to be the file portion. Since
C<catfile()> uses C<catdir()> (see above) for the concatenation of the
directory portions (if any), the following with regard to relative and
absolute paths is true:

    catfile("")     = ""
    catfile("file") = "file"

but

    catfile("","")        = rootdir()         # (e.g. "HD:")
    catfile("","file")    = rootdir() . file  # (e.g. "HD:file")
    catfile("HD:","file") = "HD:file"

This means that C<catdir()> is called only when there are two or more
arguments, as one might expect.

Note that the leading ":" is removed from the filename, so that

    catfile("a","b","file")  = ":a:b:file"    and

    catfile("a","b",":file") = ":a:b:file"

give the same answer.

To concatenate I<volume names>, I<directory paths> and I<filenames>,
you are encouraged to use C<catpath()> (see below).

=cut

sub catfile {
    my $self = shift;
    return '' unless @_;
    my $file = pop @_;
    return $file unless @_;
    my $dir = $self->catdir(@_);
    $file =~ s/^://s;
    return $dir.$file;
}

=item curdir

Returns a string representing the current directory. On Mac OS, this is ":".

=cut

sub curdir {
    return ":";
}

=item devnull

Returns a string representing the null device. On Mac OS, this is "Dev:Null".

=cut

sub devnull {
    return "Dev:Null";
}

=item rootdir

Returns the empty string.  Mac OS has no real root directory.

=cut

sub rootdir { '' }

=item tmpdir

Returns the contents of $ENV{TMPDIR}, if that directory exits or the
current working directory otherwise. Under MacPerl, $ENV{TMPDIR} will
contain a path like "MacintoshHD:Temporary Items:", which is a hidden
directory on your startup volume.

=cut

sub tmpdir {
    my $cached = $_[0]->_cached_tmpdir('TMPDIR');
    return $cached if defined $cached;
    $_[0]->_cache_tmpdir($_[0]->_tmpdir( $ENV{TMPDIR} ), 'TMPDIR');
}

=item updir

Returns a string representing the parent directory. On Mac OS, this is "::".

=cut

sub updir {
    return "::";
}

=item file_name_is_absolute

Takes as argument a path and returns true, if it is an absolute path.
If the path has a leading ":", it's a relative path. Otherwise, it's an
absolute path, unless the path doesn't contain any colons, i.e. it's a name
like "a". In this particular case, the path is considered to be relative
(i.e. it is considered to be a filename). Use ":" in the appropriate place
in the path if you want to distinguish unambiguously. As a special case,
the filename '' is always considered to be absolute. Note that with version
1.2 of File::Spec::Mac, this does no longer consult the local filesystem.

E.g.

    File::Spec->file_name_is_absolute("a");         # false (relative)
    File::Spec->file_name_is_absolute(":a:b:");     # false (relative)
    File::Spec->file_name_is_absolute("MacintoshHD:");
                                                    # true (absolute)
    File::Spec->file_name_is_absolute("");          # true (absolute)


=cut

sub file_name_is_absolute {
    my ($self,$file) = @_;
    if ($file =~ /:/) {
	return (! ($file =~ m/^:/s) );
    } elsif ( $file eq '' ) {
        return 1 ;
    } else {
	return 0; # i.e. a file like "a"
    }
}

=item path

Returns the null list for the MacPerl application, since the concept is
usually meaningless under Mac OS. But if you're using the MacPerl tool under
MPW, it gives back $ENV{Commands} suitably split, as is done in
:lib:ExtUtils:MM_Mac.pm.

=cut

sub path {
#
#  The concept is meaningless under the MacPerl application.
#  Under MPW, it has a meaning.
#
    return unless exists $ENV{Commands};
    return split(/,/, $ENV{Commands});
}

=item splitpath

    ($volume,$directories,$file) = File::Spec->splitpath( $path );
    ($volume,$directories,$file) = File::Spec->splitpath( $path,
                                                          $no_file );

Splits a path into volume, directory, and filename portions.

On Mac OS, assumes that the last part of the path is a filename unless
$no_file is true or a trailing separator ":" is present.

The volume portion is always returned with a trailing ":". The directory portion
is always returned with a leading (to denote a relative path) and a trailing ":"
(to denote a directory). The file portion is always returned I<without> a leading ":".
Empty portions are returned as empty string ''.

The results can be passed to C<catpath()> to get back a path equivalent to
(usually identical to) the original path.


=cut

sub splitpath {
    my ($self,$path, $nofile) = @_;
    my ($volume,$directory,$file);

    if ( $nofile ) {
        ( $volume, $directory ) = $path =~ m|^((?:[^:]+:)?)(.*)|s;
    }
    else {
        $path =~
            m|^( (?: [^:]+: )? )
               ( (?: .*: )? )
               ( .* )
             |xs;
        $volume    = $1;
        $directory = $2;
        $file      = $3;
    }

    $volume = '' unless defined($volume);
	$directory = ":$directory" if ( $volume && $directory ); # take care of "HD::dir"
    if ($directory) {
        # Make sure non-empty directories begin and end in ':'
        $directory .= ':' unless (substr($directory,-1) eq ':');
        $directory = ":$directory" unless (substr($directory,0,1) eq ':');
    } else {
	$directory = '';
    }
    $file = '' unless defined($file);

    return ($volume,$directory,$file);
}


=item splitdir

The opposite of C<catdir()>.

    @dirs = File::Spec->splitdir( $directories );

$directories should be only the directory portion of the path on systems
that have the concept of a volume or that have path syntax that differentiates
files from directories. Consider using C<splitpath()> otherwise.

Unlike just splitting the directories on the separator, empty directory names
(C<"">) can be returned. Since C<catdir()> on Mac OS always appends a trailing
colon to distinguish a directory path from a file path, a single trailing colon
will be ignored, i.e. there's no empty directory name after it.

Hence, on Mac OS, both

    File::Spec->splitdir( ":a:b::c:" );    and
    File::Spec->splitdir( ":a:b::c" );

yield:

    ( "a", "b", "::", "c")

while

    File::Spec->splitdir( ":a:b::c::" );

yields:

    ( "a", "b", "::", "c", "::")


=cut

sub splitdir {
	my ($self, $path) = @_;
	my @result = ();
	my ($head, $sep, $tail, $volume, $directories);

	return @result if ( (!defined($path)) || ($path eq '') );
	return (':') if ($path eq ':');

	( $volume, $sep, $directories ) = $path =~ m|^((?:[^:]+:)?)(:*)(.*)|s;

	# deprecated, but handle it correctly
	if ($volume) {
		push (@result, $volume);
		$sep .= ':';
	}

	while ($sep || $directories) {
		if (length($sep) > 1) {
			my $updir_count = length($sep) - 1;
			for (my $i=0; $i<$updir_count; $i++) {
				# push '::' updir_count times;
				# simulate Unix '..' updirs
				push (@result, '::');
			}
		}
		$sep = '';
		if ($directories) {
			( $head, $sep, $tail ) = $directories =~ m|^((?:[^:]+)?)(:*)(.*)|s;
			push (@result, $head);
			$directories = $tail;
		}
	}
	return @result;
}


=item catpath

    $path = File::Spec->catpath($volume,$directory,$file);

Takes volume, directory and file portions and returns an entire path. On Mac OS,
$volume, $directory and $file are concatenated.  A ':' is inserted if need be. You
may pass an empty string for each portion. If all portions are empty, the empty
string is returned. If $volume is empty, the result will be a relative path,
beginning with a ':'. If $volume and $directory are empty, a leading ":" (if any)
is removed form $file and the remainder is returned. If $file is empty, the
resulting path will have a trailing ':'.


=cut

sub catpath {
    my ($self,$volume,$directory,$file) = @_;

    if ( (! $volume) && (! $directory) ) {
	$file =~ s/^:// if $file;
	return $file ;
    }

    # We look for a volume in $volume, then in $directory, but not both

    my ($dir_volume, $dir_dirs) = $self->splitpath($directory, 1);

    $volume = $dir_volume unless length $volume;
    my $path = $volume; # may be ''
    $path .= ':' unless (substr($path, -1) eq ':'); # ensure trailing ':'

    if ($directory) {
	$directory = $dir_dirs if $volume;
	$directory =~ s/^://; # remove leading ':' if any
	$path .= $directory;
	$path .= ':' unless (substr($path, -1) eq ':'); # ensure trailing ':'
    }

    if ($file) {
	$file =~ s/^://; # remove leading ':' if any
	$path .= $file;
    }

    return $path;
}

=item abs2rel

Takes a destination path and an optional base path and returns a relative path
from the base path to the destination path:

    $rel_path = File::Spec->abs2rel( $path ) ;
    $rel_path = File::Spec->abs2rel( $path, $base ) ;

Note that both paths are assumed to have a notation that distinguishes a
directory path (with trailing ':') from a file path (without trailing ':').

If $base is not present or '', then the current working directory is used.
If $base is relative, then it is converted to absolute form using C<rel2abs()>.
This means that it is taken to be relative to the current working directory.

If $path and $base appear to be on two different volumes, we will not
attempt to resolve the two paths, and we will instead simply return
$path.  Note that previous versions of this module ignored the volume
of $base, which resulted in garbage results part of the time.

If $base doesn't have a trailing colon, the last element of $base is
assumed to be a filename.  This filename is ignored.  Otherwise all path
components are assumed to be directories.

If $path is relative, it is converted to absolute form using C<rel2abs()>.
This means that it is taken to be relative to the current working directory.

Based on code written by Shigio Yamaguchi.


=cut

# maybe this should be done in canonpath() ?
sub _resolve_updirs {
	my $path = shift @_;
	my $proceed;

	# resolve any updirs, e.g. "HD:tmp::file" -> "HD:file"
	do {
		$proceed = ($path =~ s/^(.*):[^:]+::(.*?)\z/$1:$2/);
	} while ($proceed);

	return $path;
}


sub abs2rel {
    my($self,$path,$base) = @_;

    # Clean up $path
    if ( ! $self->file_name_is_absolute( $path ) ) {
        $path = $self->rel2abs( $path ) ;
    }

    # Figure out the effective $base and clean it up.
    if ( !defined( $base ) || $base eq '' ) {
	$base = Cwd::getcwd();
    }
    elsif ( ! $self->file_name_is_absolute( $base ) ) {
        $base = $self->rel2abs( $base ) ;
	$base = _resolve_updirs( $base ); # resolve updirs in $base
    }
    else {
	$base = _resolve_updirs( $base );
    }

    # Split up paths - ignore $base's file
    my ( $path_vol, $path_dirs, $path_file ) =  $self->splitpath( $path );
    my ( $base_vol, $base_dirs )             =  $self->splitpath( $base );

    return $path unless lc( $path_vol ) eq lc( $base_vol );

    # Now, remove all leading components that are the same
    my @pathchunks = $self->splitdir( $path_dirs );
    my @basechunks = $self->splitdir( $base_dirs );
	
    while ( @pathchunks &&
	    @basechunks &&
	    lc( $pathchunks[0] ) eq lc( $basechunks[0] ) ) {
        shift @pathchunks ;
        shift @basechunks ;
    }

    # @pathchunks now has the directories to descend in to.
    # ensure relative path, even if @pathchunks is empty
    $path_dirs = $self->catdir( ':', @pathchunks );

    # @basechunks now contains the number of directories to climb out of.
    $base_dirs = (':' x @basechunks) . ':' ;

    return $self->catpath( '', $self->catdir( $base_dirs, $path_dirs ), $path_file ) ;
}

=item rel2abs

Converts a relative path to an absolute path:

    $abs_path = File::Spec->rel2abs( $path ) ;
    $abs_path = File::Spec->rel2abs( $path, $base ) ;

Note that both paths are assumed to have a notation that distinguishes a
directory path (with trailing ':') from a file path (without trailing ':').

If $base is not present or '', then $base is set to the current working
directory. If $base is relative, then it is converted to absolute form
using C<rel2abs()>. This means that it is taken to be relative to the
current working directory.

If $base doesn't have a trailing colon, the last element of $base is
assumed to be a filename.  This filename is ignored.  Otherwise all path
components are assumed to be directories.

If $path is already absolute, it is returned and $base is ignored.

Based on code written by Shigio Yamaguchi.

=cut

sub rel2abs {
    my ($self,$path,$base) = @_;

    if ( ! $self->file_name_is_absolute($path) ) {
        # Figure out the effective $base and clean it up.
        if ( !defined( $base ) || $base eq '' ) {
	    $base = Cwd::getcwd();
        }
        elsif ( ! $self->file_name_is_absolute($base) ) {
            $base = $self->rel2abs($base) ;
        }

	# Split up paths

	# ignore $path's volume
        my ( $path_dirs, $path_file ) = ($self->splitpath($path))[1,2] ;

        # ignore $base's file part
	my ( $base_vol, $base_dirs ) = $self->splitpath($base) ;

	# Glom them together
	$path_dirs = ':' if ($path_dirs eq '');
	$base_dirs =~ s/:$//; # remove trailing ':', if any
	$base_dirs = $base_dirs . $path_dirs;

        $path = $self->catpath( $base_vol, $base_dirs, $path_file );
    }
    return $path;
}


=back

=head1 AUTHORS

See the authors list in I<File::Spec>. Mac OS support by Paul Schinder
<schinder@pobox.com> and Thomas Wegner <wegner_thomas@yahoo.com>.

=head1 COPYRIGHT

Copyright (c) 2004 by the Perl 5 Porters.  All rights reserved.

This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

=head1 SEE ALSO

See L<File::Spec> and L<File::Spec::Unix>.  This package overrides the
implementation of these methods, not the semantics.

=cut

1;
PKoc[�L� nnSpec/OS2.pmnu�[���package File::Spec::OS2;

use strict;
use Cwd ();
require File::Spec::Unix;

our $VERSION = '3.74';
$VERSION =~ tr/_//d;

our @ISA = qw(File::Spec::Unix);

sub devnull {
    return "/dev/nul";
}

sub case_tolerant {
    return 1;
}

sub file_name_is_absolute {
    my ($self,$file) = @_;
    return scalar($file =~ m{^([a-z]:)?[\\/]}is);
}

sub path {
    my $path = $ENV{PATH};
    $path =~ s:\\:/:g;
    my @path = split(';',$path);
    foreach (@path) { $_ = '.' if $_ eq '' }
    return @path;
}

sub tmpdir {
    my $cached = $_[0]->_cached_tmpdir(qw 'TMPDIR TEMP TMP');
    return $cached if defined $cached;
    my @d = @ENV{qw(TMPDIR TEMP TMP)};	# function call could autovivivy
    $_[0]->_cache_tmpdir(
	$_[0]->_tmpdir( @d, '/tmp', '/' ), qw 'TMPDIR TEMP TMP'
    );
}

sub catdir {
    my $self = shift;
    my @args = @_;
    foreach (@args) {
	tr[\\][/];
        # append a backslash to each argument unless it has one there
        $_ .= "/" unless m{/$};
    }
    return $self->canonpath(join('', @args));
}

sub canonpath {
    my ($self,$path) = @_;
    return unless defined $path;

    $path =~ s/^([a-z]:)/\l$1/s;
    $path =~ s|\\|/|g;
    $path =~ s|([^/])/+|$1/|g;                  # xx////xx  -> xx/xx
    $path =~ s|(/\.)+/|/|g;                     # xx/././xx -> xx/xx
    $path =~ s|^(\./)+(?=[^/])||s;		# ./xx      -> xx
    $path =~ s|/\Z(?!\n)||
             unless $path =~ m#^([a-z]:)?/\Z(?!\n)#si;# xx/       -> xx
    $path =~ s{^/\.\.$}{/};                     # /..    -> /
    1 while $path =~ s{^/\.\.}{};               # /../xx -> /xx
    return $path;
}


sub splitpath {
    my ($self,$path, $nofile) = @_;
    my ($volume,$directory,$file) = ('','','');
    if ( $nofile ) {
        $path =~ 
            m{^( (?:[a-zA-Z]:|(?:\\\\|//)[^\\/]+[\\/][^\\/]+)? ) 
                 (.*)
             }xs;
        $volume    = $1;
        $directory = $2;
    }
    else {
        $path =~ 
            m{^ ( (?: [a-zA-Z]: |
                      (?:\\\\|//)[^\\/]+[\\/][^\\/]+
                  )?
                )
                ( (?:.*[\\\\/](?:\.\.?\Z(?!\n))?)? )
                (.*)
             }xs;
        $volume    = $1;
        $directory = $2;
        $file      = $3;
    }

    return ($volume,$directory,$file);
}


sub splitdir {
    my ($self,$directories) = @_ ;
    split m|[\\/]|, $directories, -1;
}


sub catpath {
    my ($self,$volume,$directory,$file) = @_;

    # If it's UNC, make sure the glue separator is there, reusing
    # whatever separator is first in the $volume
    $volume .= $1
        if ( $volume =~ m@^([\\/])[\\/][^\\/]+[\\/][^\\/]+\Z(?!\n)@s &&
             $directory =~ m@^[^\\/]@s
           ) ;

    $volume .= $directory ;

    # If the volume is not just A:, make sure the glue separator is 
    # there, reusing whatever separator is first in the $volume if possible.
    if ( $volume !~ m@^[a-zA-Z]:\Z(?!\n)@s &&
         $volume =~ m@[^\\/]\Z(?!\n)@      &&
         $file   =~ m@[^\\/]@
       ) {
        $volume =~ m@([\\/])@ ;
        my $sep = $1 ? $1 : '/' ;
        $volume .= $sep ;
    }

    $volume .= $file ;

    return $volume ;
}


sub abs2rel {
    my($self,$path,$base) = @_;

    # Clean up $path
    if ( ! $self->file_name_is_absolute( $path ) ) {
        $path = $self->rel2abs( $path ) ;
    } else {
        $path = $self->canonpath( $path ) ;
    }

    # Figure out the effective $base and clean it up.
    if ( !defined( $base ) || $base eq '' ) {
	$base = Cwd::getcwd();
    } elsif ( ! $self->file_name_is_absolute( $base ) ) {
        $base = $self->rel2abs( $base ) ;
    } else {
        $base = $self->canonpath( $base ) ;
    }

    # Split up paths
    my ( $path_volume, $path_directories, $path_file ) = $self->splitpath( $path, 1 ) ;
    my ( $base_volume, $base_directories ) = $self->splitpath( $base, 1 ) ;
    return $path unless $path_volume eq $base_volume;

    # Now, remove all leading components that are the same
    my @pathchunks = $self->splitdir( $path_directories );
    my @basechunks = $self->splitdir( $base_directories );

    while ( @pathchunks && 
            @basechunks && 
            lc( $pathchunks[0] ) eq lc( $basechunks[0] ) 
          ) {
        shift @pathchunks ;
        shift @basechunks ;
    }

    # No need to catdir, we know these are well formed.
    $path_directories = CORE::join( '/', @pathchunks );
    $base_directories = CORE::join( '/', @basechunks );

    # $base_directories now contains the directories the resulting relative
    # path must ascend out of before it can descend to $path_directory.  So, 
    # replace all names with $parentDir

    #FA Need to replace between backslashes...
    $base_directories =~ s|[^\\/]+|..|g ;

    # Glue the two together, using a separator if necessary, and preventing an
    # empty result.

    #FA Must check that new directories are not empty.
    if ( $path_directories ne '' && $base_directories ne '' ) {
        $path_directories = "$base_directories/$path_directories" ;
    } else {
        $path_directories = "$base_directories$path_directories" ;
    }

    return $self->canonpath( 
        $self->catpath( "", $path_directories, $path_file ) 
    ) ;
}


sub rel2abs {
    my ($self,$path,$base ) = @_;

    if ( ! $self->file_name_is_absolute( $path ) ) {

        if ( !defined( $base ) || $base eq '' ) {
	    $base = Cwd::getcwd();
        }
        elsif ( ! $self->file_name_is_absolute( $base ) ) {
            $base = $self->rel2abs( $base ) ;
        }
        else {
            $base = $self->canonpath( $base ) ;
        }

        my ( $path_directories, $path_file ) =
            ($self->splitpath( $path, 1 ))[1,2] ;

        my ( $base_volume, $base_directories ) =
            $self->splitpath( $base, 1 ) ;

        $path = $self->catpath( 
            $base_volume, 
            $self->catdir( $base_directories, $path_directories ), 
            $path_file
        ) ;
    }

    return $self->canonpath( $path ) ;
}

1;
__END__

=head1 NAME

File::Spec::OS2 - methods for OS/2 file specs

=head1 SYNOPSIS

 require File::Spec::OS2; # Done internally by File::Spec if needed

=head1 DESCRIPTION

See L<File::Spec> and L<File::Spec::Unix>.  This package overrides the
implementation of these methods, not the semantics.

Amongst the changes made for OS/2 are...

=over 4

=item tmpdir

Modifies the list of places temp directory information is looked for.

    $ENV{TMPDIR}
    $ENV{TEMP}
    $ENV{TMP}
    /tmp
    /

=item splitpath

Volumes can be drive letters or UNC sharenames (\\server\share).

=back

=head1 COPYRIGHT

Copyright (c) 2004 by the Perl 5 Porters.  All rights reserved.

This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

=cut
PKoc[�Hz���Spec/AmigaOS.pmnu�[���package File::Spec::AmigaOS;

use strict;
require File::Spec::Unix;

our $VERSION = '3.74';
$VERSION =~ tr/_//d;

our @ISA = qw(File::Spec::Unix);

=head1 NAME

File::Spec::AmigaOS - File::Spec for AmigaOS

=head1 SYNOPSIS

 require File::Spec::AmigaOS; # Done automatically by File::Spec
                              # if needed

=head1 DESCRIPTION

Methods for manipulating file specifications.

=head1 METHODS

=over 2

=item tmpdir

Returns $ENV{TMPDIR} or if that is unset, "/t".

=cut

my $tmpdir;
sub tmpdir {
  return $tmpdir if defined $tmpdir;
  $tmpdir = $_[0]->_tmpdir( $ENV{TMPDIR}, "/t" );
}

=item file_name_is_absolute

Returns true if there's a colon in the file name,
or if it begins with a slash.

=cut

sub file_name_is_absolute {
  my ($self, $file) = @_;

  # Not 100% robust as a "/" must not preceded a ":"
  # but this cannot happen in a well formed path.
  return $file =~ m{^/|:}s;
}

=back

All the other methods are from L<File::Spec::Unix>.

=cut

1;
PKoc[��
�+�+
Spec/Win32.pmnu�[���package File::Spec::Win32;

use strict;

use Cwd ();
require File::Spec::Unix;

our $VERSION = '3.74';
$VERSION =~ tr/_//d;

our @ISA = qw(File::Spec::Unix);

# Some regexes we use for path splitting
my $DRIVE_RX = '[a-zA-Z]:';
my $UNC_RX = '(?:\\\\\\\\|//)[^\\\\/]+[\\\\/][^\\\\/]+';
my $VOL_RX = "(?:$DRIVE_RX|$UNC_RX)";


=head1 NAME

File::Spec::Win32 - methods for Win32 file specs

=head1 SYNOPSIS

 require File::Spec::Win32; # Done internally by File::Spec if needed

=head1 DESCRIPTION

See File::Spec::Unix for a documentation of the methods provided
there. This package overrides the implementation of these methods, not
the semantics.

=over 4

=item devnull

Returns a string representation of the null device.

=cut

sub devnull {
    return "nul";
}

sub rootdir { '\\' }


=item tmpdir

Returns a string representation of the first existing directory
from the following list:

    $ENV{TMPDIR}
    $ENV{TEMP}
    $ENV{TMP}
    SYS:/temp
    C:\system\temp
    C:/temp
    /tmp
    /

The SYS:/temp is preferred in Novell NetWare and the C:\system\temp
for Symbian (the File::Spec::Win32 is used also for those platforms).

If running under taint mode, and if the environment
variables are tainted, they are not used.

=cut

sub tmpdir {
    my $tmpdir = $_[0]->_cached_tmpdir(qw(TMPDIR TEMP TMP));
    return $tmpdir if defined $tmpdir;
    $tmpdir = $_[0]->_tmpdir( map( $ENV{$_}, qw(TMPDIR TEMP TMP) ),
			      'SYS:/temp',
			      'C:\system\temp',
			      'C:/temp',
			      '/tmp',
			      '/'  );
    $_[0]->_cache_tmpdir($tmpdir, qw(TMPDIR TEMP TMP));
}

=item case_tolerant

MSWin32 case-tolerance depends on GetVolumeInformation() $ouFsFlags == FS_CASE_SENSITIVE,
indicating the case significance when comparing file specifications.
Since XP FS_CASE_SENSITIVE is effectively disabled for the NT subsubsystem.
See http://cygwin.com/ml/cygwin/2007-07/msg00891.html
Default: 1

=cut

sub case_tolerant {
  eval {
    local @INC = @INC;
    pop @INC if $INC[-1] eq '.';
    require Win32API::File;
  } or return 1;
  my $drive = shift || "C:";
  my $osFsType = "\0"x256;
  my $osVolName = "\0"x256;
  my $ouFsFlags = 0;
  Win32API::File::GetVolumeInformation($drive, $osVolName, 256, [], [], $ouFsFlags, $osFsType, 256 );
  if ($ouFsFlags & Win32API::File::FS_CASE_SENSITIVE()) { return 0; }
  else { return 1; }
}

=item file_name_is_absolute

As of right now, this returns 2 if the path is absolute with a
volume, 1 if it's absolute with no volume, 0 otherwise.

=cut

sub file_name_is_absolute {

    my ($self,$file) = @_;

    if ($file =~ m{^($VOL_RX)}o) {
      my $vol = $1;
      return ($vol =~ m{^$UNC_RX}o ? 2
	      : $file =~ m{^$DRIVE_RX[\\/]}o ? 2
	      : 0);
    }
    return $file =~  m{^[\\/]} ? 1 : 0;
}

=item catfile

Concatenate one or more directory names and a filename to form a
complete path ending with a filename

=cut

sub catfile {
    shift;

    # Legacy / compatibility support
    #
    shift, return _canon_cat( "/", @_ )
	if $_[0] eq "";

    # Compatibility with File::Spec <= 3.26:
    #     catfile('A:', 'foo') should return 'A:\foo'.
    return _canon_cat( ($_[0].'\\'), @_[1..$#_] )
        if $_[0] =~ m{^$DRIVE_RX\z}o;

    return _canon_cat( @_ );
}

sub catdir {
    shift;

    # Legacy / compatibility support
    #
    return ""
    	unless @_;
    shift, return _canon_cat( "/", @_ )
	if $_[0] eq "";

    # Compatibility with File::Spec <= 3.26:
    #     catdir('A:', 'foo') should return 'A:\foo'.
    return _canon_cat( ($_[0].'\\'), @_[1..$#_] )
        if $_[0] =~ m{^$DRIVE_RX\z}o;

    return _canon_cat( @_ );
}

sub path {
    my @path = split(';', $ENV{PATH});
    s/"//g for @path;
    @path = grep length, @path;
    unshift(@path, ".");
    return @path;
}

=item canonpath

No physical check on the filesystem, but a logical cleanup of a
path. On UNIX eliminated successive slashes and successive "/.".
On Win32 makes 

	dir1\dir2\dir3\..\..\dir4 -> \dir\dir4 and even
	dir1\dir2\dir3\...\dir4   -> \dir\dir4

=cut

sub canonpath {
    # Legacy / compatibility support
    #
    return $_[1] if !defined($_[1]) or $_[1] eq '';
    return _canon_cat( $_[1] );
}

=item splitpath

   ($volume,$directories,$file) = File::Spec->splitpath( $path );
   ($volume,$directories,$file) = File::Spec->splitpath( $path,
                                                         $no_file );

Splits a path into volume, directory, and filename portions. Assumes that 
the last file is a path unless the path ends in '\\', '\\.', '\\..'
or $no_file is true.  On Win32 this means that $no_file true makes this return 
( $volume, $path, '' ).

Separators accepted are \ and /.

Volumes can be drive letters or UNC sharenames (\\server\share).

The results can be passed to L</catpath> to get back a path equivalent to
(usually identical to) the original path.

=cut

sub splitpath {
    my ($self,$path, $nofile) = @_;
    my ($volume,$directory,$file) = ('','','');
    if ( $nofile ) {
        $path =~ 
            m{^ ( $VOL_RX ? ) (.*) }sox;
        $volume    = $1;
        $directory = $2;
    }
    else {
        $path =~ 
            m{^ ( $VOL_RX ? )
                ( (?:.*[\\/](?:\.\.?\Z(?!\n))?)? )
                (.*)
             }sox;
        $volume    = $1;
        $directory = $2;
        $file      = $3;
    }

    return ($volume,$directory,$file);
}


=item splitdir

The opposite of L<catdir()|File::Spec/catdir>.

    @dirs = File::Spec->splitdir( $directories );

$directories must be only the directory portion of the path on systems 
that have the concept of a volume or that have path syntax that differentiates
files from directories.

Unlike just splitting the directories on the separator, leading empty and 
trailing directory entries can be returned, because these are significant
on some OSs. So,

    File::Spec->splitdir( "/a/b/c" );

Yields:

    ( '', 'a', 'b', '', 'c', '' )

=cut

sub splitdir {
    my ($self,$directories) = @_ ;
    #
    # split() likes to forget about trailing null fields, so here we
    # check to be sure that there will not be any before handling the
    # simple case.
    #
    if ( $directories !~ m|[\\/]\Z(?!\n)| ) {
        return split( m|[\\/]|, $directories );
    }
    else {
        #
        # since there was a trailing separator, add a file name to the end, 
        # then do the split, then replace it with ''.
        #
        my( @directories )= split( m|[\\/]|, "${directories}dummy" ) ;
        $directories[ $#directories ]= '' ;
        return @directories ;
    }
}


=item catpath

Takes volume, directory and file portions and returns an entire path. Under
Unix, $volume is ignored, and this is just like catfile(). On other OSs,
the $volume become significant.

=cut

sub catpath {
    my ($self,$volume,$directory,$file) = @_;

    # If it's UNC, make sure the glue separator is there, reusing
    # whatever separator is first in the $volume
    my $v;
    $volume .= $v
        if ( (($v) = $volume =~ m@^([\\/])[\\/][^\\/]+[\\/][^\\/]+\Z(?!\n)@s) &&
             $directory =~ m@^[^\\/]@s
           ) ;

    $volume .= $directory ;

    # If the volume is not just A:, make sure the glue separator is 
    # there, reusing whatever separator is first in the $volume if possible.
    if ( $volume !~ m@^[a-zA-Z]:\Z(?!\n)@s &&
         $volume =~ m@[^\\/]\Z(?!\n)@      &&
         $file   =~ m@[^\\/]@
       ) {
        $volume =~ m@([\\/])@ ;
        my $sep = $1 ? $1 : '\\' ;
        $volume .= $sep ;
    }

    $volume .= $file ;

    return $volume ;
}

sub _same {
  lc($_[1]) eq lc($_[2]);
}

sub rel2abs {
    my ($self,$path,$base ) = @_;

    my $is_abs = $self->file_name_is_absolute($path);

    # Check for volume (should probably document the '2' thing...)
    return $self->canonpath( $path ) if $is_abs == 2;

    if ($is_abs) {
      # It's missing a volume, add one
      my $vol = ($self->splitpath( Cwd::getcwd() ))[0];
      return $self->canonpath( $vol . $path );
    }

    if ( !defined( $base ) || $base eq '' ) {
      $base = Cwd::getdcwd( ($self->splitpath( $path ))[0] ) if defined &Cwd::getdcwd ;
      $base = Cwd::getcwd() unless defined $base ;
    }
    elsif ( ! $self->file_name_is_absolute( $base ) ) {
      $base = $self->rel2abs( $base ) ;
    }
    else {
      $base = $self->canonpath( $base ) ;
    }

    my ( $path_directories, $path_file ) =
      ($self->splitpath( $path, 1 ))[1,2] ;

    my ( $base_volume, $base_directories ) =
      $self->splitpath( $base, 1 ) ;

    $path = $self->catpath( 
			   $base_volume, 
			   $self->catdir( $base_directories, $path_directories ), 
			   $path_file
			  ) ;

    return $self->canonpath( $path ) ;
}

=back

=head2 Note For File::Spec::Win32 Maintainers

Novell NetWare inherits its File::Spec behaviour from File::Spec::Win32.

=head1 COPYRIGHT

Copyright (c) 2004,2007 by the Perl 5 Porters.  All rights reserved.

This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

=head1 SEE ALSO

See L<File::Spec> and L<File::Spec::Unix>.  This package overrides the
implementation of these methods, not the semantics.

=cut


sub _canon_cat				# @path -> path
{
    my ($first, @rest) = @_;

    my $volume = $first =~ s{ \A ([A-Za-z]:) ([\\/]?) }{}x	# drive letter
    	       ? ucfirst( $1 ).( $2 ? "\\" : "" )
	       : $first =~ s{ \A (?:\\\\|//) ([^\\/]+)
				 (?: [\\/] ([^\\/]+) )?
	       			 [\\/]? }{}xs			# UNC volume
	       ? "\\\\$1".( defined $2 ? "\\$2" : "" )."\\"
	       : $first =~ s{ \A [\\/] }{}x			# root dir
	       ? "\\"
	       : "";
    my $path   = join "\\", $first, @rest;

    $path =~ tr#\\/#\\\\#s;		# xx/yy --> xx\yy & xx\\yy --> xx\yy

    					# xx/././yy --> xx/yy
    $path =~ s{(?:
		(?:\A|\\)		# at begin or after a slash
		\.
		(?:\\\.)*		# and more
		(?:\\|\z) 		# at end or followed by slash
	       )+			# performance boost -- I do not know why
	     }{\\}gx;

    # XXX I do not know whether more dots are supported by the OS supporting
    #     this ... annotation (NetWare or symbian but not MSWin32).
    #     Then .... could easily become ../../.. etc:
    # Replace \.\.\. by (\.\.\.+)  and substitute with
    # { $1 . ".." . "\\.." x (length($2)-2) }gex
	     				# ... --> ../..
    $path =~ s{ (\A|\\)			# at begin or after a slash
    		\.\.\.
		(?=\\|\z) 		# at end or followed by slash
	     }{$1..\\..}gx;
    					# xx\yy\..\zz --> xx\zz
    while ( $path =~ s{(?:
		(?:\A|\\)		# at begin or after a slash
		[^\\]+			# rip this 'yy' off
		\\\.\.
		(?<!\A\.\.\\\.\.)	# do *not* replace ^..\..
		(?<!\\\.\.\\\.\.)	# do *not* replace \..\..
		(?:\\|\z) 		# at end or followed by slash
	       )+			# performance boost -- I do not know why
	     }{\\}sx ) {}

    $path =~ s#\A\\##;			# \xx --> xx  NOTE: this is *not* root
    $path =~ s#\\\z##;			# xx\ --> xx

    if ( $volume =~ m#\\\z# )
    {					# <vol>\.. --> <vol>\
	$path =~ s{ \A			# at begin
		    \.\.
		    (?:\\\.\.)*		# and more
		    (?:\\|\z) 		# at end or followed by slash
		 }{}x;

	return $1			# \\HOST\SHARE\ --> \\HOST\SHARE
	    if    $path eq ""
	      and $volume =~ m#\A(\\\\.*)\\\z#s;
    }
    return $path ne "" || $volume ? $volume.$path : ".";
}

1;
PKoc[�4+8,	,	Spec/Functions.pmnu�[���package File::Spec::Functions;

use File::Spec;
use strict;

our $VERSION = '3.74';
$VERSION =~ tr/_//d;

require Exporter;

our @ISA = qw(Exporter);

our @EXPORT = qw(
	canonpath
	catdir
	catfile
	curdir
	rootdir
	updir
	no_upwards
	file_name_is_absolute
	path
);

our @EXPORT_OK = qw(
	devnull
	tmpdir
	splitpath
	splitdir
	catpath
	abs2rel
	rel2abs
	case_tolerant
);

our %EXPORT_TAGS = ( ALL => [ @EXPORT_OK, @EXPORT ] );

require File::Spec::Unix;
my %udeps = (
    canonpath => [],
    catdir => [qw(canonpath)],
    catfile => [qw(canonpath catdir)],
    case_tolerant => [],
    curdir => [],
    devnull => [],
    rootdir => [],
    updir => [],
);

foreach my $meth (@EXPORT, @EXPORT_OK) {
    my $sub = File::Spec->can($meth);
    no strict 'refs';
    if (exists($udeps{$meth}) && $sub == File::Spec::Unix->can($meth) &&
	    !(grep {
		File::Spec->can($_) != File::Spec::Unix->can($_)
	    } @{$udeps{$meth}}) &&
	    defined(&{"File::Spec::Unix::_fn_$meth"})) {
	*{$meth} = \&{"File::Spec::Unix::_fn_$meth"};
    } else {
	*{$meth} = sub {&$sub('File::Spec', @_)};
    }
}


1;
__END__

=head1 NAME

File::Spec::Functions - portably perform operations on file names

=head1 SYNOPSIS

	use File::Spec::Functions;
	$x = catfile('a','b');

=head1 DESCRIPTION

This module exports convenience functions for all of the class methods
provided by File::Spec.

For a reference of available functions, please consult L<File::Spec::Unix>,
which contains the entire set, and which is inherited by the modules for
other platforms. For further information, please see L<File::Spec::Mac>,
L<File::Spec::OS2>, L<File::Spec::Win32>, or L<File::Spec::VMS>.

=head2 Exports

The following functions are exported by default.

	canonpath
	catdir
	catfile
	curdir
	rootdir
	updir
	no_upwards
	file_name_is_absolute
	path


The following functions are exported only by request.

	devnull
	tmpdir
	splitpath
	splitdir
	catpath
	abs2rel
	rel2abs
	case_tolerant

All the functions may be imported using the C<:ALL> tag.

=head1 COPYRIGHT

Copyright (c) 2004 by the Perl 5 Porters.  All rights reserved.

This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

=head1 SEE ALSO

File::Spec, File::Spec::Unix, File::Spec::Mac, File::Spec::OS2,
File::Spec::Win32, File::Spec::VMS, ExtUtils::MakeMaker

=cut

PKoc[�LhlK)K)Spec.pmnu�[���package File::Spec;

use strict;

our $VERSION = '3.74';
$VERSION =~ tr/_//d;

my %module = (
	      MSWin32 => 'Win32',
	      os2     => 'OS2',
	      VMS     => 'VMS',
	      NetWare => 'Win32', # Yes, File::Spec::Win32 works on NetWare.
	      symbian => 'Win32', # Yes, File::Spec::Win32 works on symbian.
	      dos     => 'OS2',   # Yes, File::Spec::OS2 works on DJGPP.
	      cygwin  => 'Cygwin',
	      amigaos => 'AmigaOS');


my $module = $module{$^O} || 'Unix';

require "File/Spec/$module.pm";
our @ISA = ("File::Spec::$module");

1;

__END__

=head1 NAME

File::Spec - portably perform operations on file names

=head1 SYNOPSIS

	use File::Spec;

	$x=File::Spec->catfile('a', 'b', 'c');

which returns 'a/b/c' under Unix. Or:

	use File::Spec::Functions;

	$x = catfile('a', 'b', 'c');

=head1 DESCRIPTION

This module is designed to support operations commonly performed on file
specifications (usually called "file names", but not to be confused with the
contents of a file, or Perl's file handles), such as concatenating several
directory and file names into a single path, or determining whether a path
is rooted. It is based on code directly taken from MakeMaker 5.17, code
written by Andreas KE<ouml>nig, Andy Dougherty, Charles Bailey, Ilya
Zakharevich, Paul Schinder, and others.

Since these functions are different for most operating systems, each set of
OS specific routines is available in a separate module, including:

	File::Spec::Unix
	File::Spec::Mac
	File::Spec::OS2
	File::Spec::Win32
	File::Spec::VMS

The module appropriate for the current OS is automatically loaded by
File::Spec. Since some modules (like VMS) make use of facilities available
only under that OS, it may not be possible to load all modules under all
operating systems.

Since File::Spec is object oriented, subroutines should not be called directly,
as in:

	File::Spec::catfile('a','b');

but rather as class methods:

	File::Spec->catfile('a','b');

For simple uses, L<File::Spec::Functions> provides convenient functional
forms of these methods.

=head1 METHODS

=over 2

=item canonpath
X<canonpath>

No physical check on the filesystem, but a logical cleanup of a
path.

    $cpath = File::Spec->canonpath( $path ) ;

Note that this does *not* collapse F<x/../y> sections into F<y>.  This
is by design.  If F</foo> on your system is a symlink to F</bar/baz>,
then F</foo/../quux> is actually F</bar/quux>, not F</quux> as a naive
F<../>-removal would give you.  If you want to do this kind of
processing, you probably want C<Cwd>'s C<realpath()> function to
actually traverse the filesystem cleaning up paths like this.

=item catdir
X<catdir>

Concatenate two or more directory names to form a complete path ending
with a directory. But remove the trailing slash from the resulting
string, because it doesn't look good, isn't necessary and confuses
OS/2. Of course, if this is the root directory, don't cut off the
trailing slash :-)

    $path = File::Spec->catdir( @directories );

=item catfile
X<catfile>

Concatenate one or more directory names and a filename to form a
complete path ending with a filename

    $path = File::Spec->catfile( @directories, $filename );

=item curdir
X<curdir>

Returns a string representation of the current directory.

    $curdir = File::Spec->curdir();

=item devnull
X<devnull>

Returns a string representation of the null device.

    $devnull = File::Spec->devnull();

=item rootdir
X<rootdir>

Returns a string representation of the root directory.

    $rootdir = File::Spec->rootdir();

=item tmpdir
X<tmpdir>

Returns a string representation of the first writable directory from a
list of possible temporary directories.  Returns the current directory
if no writable temporary directories are found.  The list of directories
checked depends on the platform; e.g. File::Spec::Unix checks C<$ENV{TMPDIR}>
(unless taint is on) and F</tmp>.

    $tmpdir = File::Spec->tmpdir();

=item updir
X<updir>

Returns a string representation of the parent directory.

    $updir = File::Spec->updir();

=item no_upwards

Given a list of files in a directory (such as from C<readdir()>),
strip out C<'.'> and C<'..'>.

B<SECURITY NOTE:> This does NOT filter paths containing C<'..'>, like
C<'../../../../etc/passwd'>, only literal matches to C<'.'> and C<'..'>.

    @paths = File::Spec->no_upwards( readdir $dirhandle );

=item case_tolerant

Returns a true or false value indicating, respectively, that alphabetic
case is not or is significant when comparing file specifications.
Cygwin and Win32 accept an optional drive argument.

    $is_case_tolerant = File::Spec->case_tolerant();

=item file_name_is_absolute

Takes as its argument a path, and returns true if it is an absolute path.

    $is_absolute = File::Spec->file_name_is_absolute( $path );

This does not consult the local filesystem on Unix, Win32, OS/2, or
Mac OS (Classic).  It does consult the working environment for VMS
(see L<File::Spec::VMS/file_name_is_absolute>).

=item path
X<path>

Takes no argument.  Returns the environment variable C<PATH> (or the local
platform's equivalent) as a list.

    @PATH = File::Spec->path();

=item join
X<join, path>

join is the same as catfile.

=item splitpath
X<splitpath> X<split, path>

Splits a path in to volume, directory, and filename portions. On systems
with no concept of volume, returns '' for volume. 

    ($volume,$directories,$file) =
                       File::Spec->splitpath( $path );
    ($volume,$directories,$file) =
                       File::Spec->splitpath( $path, $no_file );

For systems with no syntax differentiating filenames from directories, 
assumes that the last file is a path unless C<$no_file> is true or a
trailing separator or F</.> or F</..> is present. On Unix, this means that C<$no_file>
true makes this return ( '', $path, '' ).

The directory portion may or may not be returned with a trailing '/'.

The results can be passed to L</catpath()> to get back a path equivalent to
(usually identical to) the original path.

=item splitdir
X<splitdir> X<split, dir>

The opposite of L</catdir>.

    @dirs = File::Spec->splitdir( $directories );

C<$directories> must be only the directory portion of the path on systems 
that have the concept of a volume or that have path syntax that differentiates
files from directories.

Unlike just splitting the directories on the separator, empty
directory names (C<''>) can be returned, because these are significant
on some OSes.

=item catpath()

Takes volume, directory and file portions and returns an entire path. Under
Unix, C<$volume> is ignored, and directory and file are concatenated.  A '/' is
inserted if need be.  On other OSes, C<$volume> is significant.

    $full_path = File::Spec->catpath( $volume, $directory, $file );

=item abs2rel
X<abs2rel> X<absolute, path> X<relative, path>

Takes a destination path and an optional base path returns a relative path
from the base path to the destination path:

    $rel_path = File::Spec->abs2rel( $path ) ;
    $rel_path = File::Spec->abs2rel( $path, $base ) ;

If C<$base> is not present or '', then L<Cwd::cwd()|Cwd> is used. If C<$base> is
relative, then it is converted to absolute form using
L</rel2abs()>. This means that it is taken to be relative to
L<Cwd::cwd()|Cwd>.

On systems with the concept of volume, if C<$path> and C<$base> appear to be
on two different volumes, we will not attempt to resolve the two
paths, and we will instead simply return C<$path>.  Note that previous
versions of this module ignored the volume of C<$base>, which resulted in
garbage results part of the time.

On systems that have a grammar that indicates filenames, this ignores the 
C<$base> filename as well. Otherwise all path components are assumed to be
directories.

If C<$path> is relative, it is converted to absolute form using L</rel2abs()>.
This means that it is taken to be relative to L<Cwd::cwd()|Cwd>.

No checks against the filesystem are made.  On VMS, there is
interaction with the working environment, as logicals and
macros are expanded.

Based on code written by Shigio Yamaguchi.

=item rel2abs()
X<rel2abs> X<absolute, path> X<relative, path>

Converts a relative path to an absolute path. 

    $abs_path = File::Spec->rel2abs( $path ) ;
    $abs_path = File::Spec->rel2abs( $path, $base ) ;

If C<$base> is not present or '', then L<Cwd::cwd()|Cwd> is used. If C<$base> is relative,
then it is converted to absolute form using L</rel2abs()>. This means that it
is taken to be relative to L<Cwd::cwd()|Cwd>.

On systems with the concept of volume, if C<$path> and C<$base> appear to be
on two different volumes, we will not attempt to resolve the two
paths, and we will instead simply return C<$path>.  Note that previous
versions of this module ignored the volume of C<$base>, which resulted in
garbage results part of the time.

On systems that have a grammar that indicates filenames, this ignores the 
C<$base> filename as well. Otherwise all path components are assumed to be
directories.

If C<$path> is absolute, it is cleaned up and returned using L</canonpath>.

No checks against the filesystem are made.  On VMS, there is
interaction with the working environment, as logicals and
macros are expanded.

Based on code written by Shigio Yamaguchi.

=back

For further information, please see L<File::Spec::Unix>,
L<File::Spec::Mac>, L<File::Spec::OS2>, L<File::Spec::Win32>, or
L<File::Spec::VMS>.

=head1 SEE ALSO

L<File::Spec::Unix>, L<File::Spec::Mac>, L<File::Spec::OS2>,
L<File::Spec::Win32>, L<File::Spec::VMS>, L<File::Spec::Functions>,
L<ExtUtils::MakeMaker>

=head1 AUTHOR

Currently maintained by Ken Williams C<< <KWILLIAMS@cpan.org> >>.

The vast majority of the code was written by
Kenneth Albanowski C<< <kjahds@kjahds.com> >>,
Andy Dougherty C<< <doughera@lafayette.edu> >>,
Andreas KE<ouml>nig C<< <A.Koenig@franz.ww.TU-Berlin.DE> >>,
Tim Bunce C<< <Tim.Bunce@ig.co.uk> >>.
VMS support by Charles Bailey C<< <bailey@newman.upenn.edu> >>.
OS/2 support by Ilya Zakharevich C<< <ilya@math.ohio-state.edu> >>.
Mac support by Paul Schinder C<< <schinder@pobox.com> >>, and
Thomas Wegner C<< <wegner_thomas@yahoo.com> >>.
abs2rel() and rel2abs() written by Shigio Yamaguchi C<< <shigio@tamacom.com> >>,
modified by Barrie Slaymaker C<< <barries@slaysys.com> >>.
splitpath(), splitdir(), catpath() and catdir() by Barrie Slaymaker.

=head1 COPYRIGHT

Copyright (c) 2004-2013 by the Perl 5 Porters.  All rights reserved.

This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

=cut
PK�2[�/f��MARCBASE.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */

/**
 * Parser for MARC records
 *
 * This package is based on the PHP MARC package, originally called "php-marc",
 * that is part of the Emilda Project (http://www.emilda.org). Christoffer
 * Landtman generously agreed to make the "php-marc" code available under the
 * GNU LGPL so it could be used as the basis of this PEAR package.
 * 
 * PHP version 5
 *
 * LICENSE: This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category  File_Formats
 * @package   File_MARC
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2007-2010 Dan Scott
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version   CVS: $Id: MARCXML.php 301727 2010-07-30 17:30:51Z dbs $
 * @link      http://pear.php.net/package/File_MARC
 * @example   read.php Retrieve specific fields and subfields from a record
 * @example   subfields.php Create new subfields and add them in specific order
 * @example   marc_yaz.php Pretty print a MARC record retrieved via yaz extension
 */

require_once 'File/MARC/Record.php';

// {{{ class File_MARCBASE
/**
 * The main File_MARCBASE class provides common methods for File_MARC and
 * File_MARCXML - primarily for generating MARCXML output.
 *
 * @category File_Formats
 * @package  File_MARC
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link     http://pear.php.net/package/File_MARC
 */
class File_MARCBASE
{

    /**
     * XMLWriter for writing collections
     * 
     * @var XMLWriter
     */
    protected $xmlwriter;

    /**
     * Record class
     *
     * @var string
     */
    protected $record_class;
    // }}}

    // {{{ Constructor: function __construct()
    /**
     * Read in MARCXML records
     *
     * This function reads in files or strings that
     * contain one or more MARCXML records.
     *
     * <code>
     * <?php
     * // Retrieve MARC records from a file
     * $journals = new File_MARC('journals.mrc', SOURCE_FILE);
     *
     * // Retrieve MARC records from a string (e.g. Z39 query results)
     * $monographs = new File_MARC($raw_marc, SOURCE_STRING);
     * ?>
     * </code>
     *
     * @param string $source       Name of the file, or a raw MARC string
     * @param int    $type         Source of the input: SOURCE_FILE or SOURCE_STRING
     * @param string $record_class Record class, defaults to File_MARC_Record
     */
    function __construct($source, $type, $record_class)
    {
        $this->xmlwriter = new XMLWriter();
        $this->xmlwriter->openMemory();
        $this->xmlwriter->startDocument('1.0', 'UTF-8');

        $this->record_class = $record_class ?: File_MARC_Record::class;
    }
    // }}}

    // {{{ toXMLHeader()
    /**
     * Initializes the MARCXML output of a record or collection of records 
     *
     * This method produces an XML representation of a MARC record that
     * attempts to adhere to the MARCXML standard documented at
     * http://www.loc.gov/standards/marcxml/
     *
     * @return bool true if successful
     */
    function toXMLHeader()
    {
        $this->xmlwriter->startElement("collection");
        $this->xmlwriter->writeAttribute("xmlns", "http://www.loc.gov/MARC21/slim");
        return true;
    }
    // }}}

    // {{{ getXMLWriter()
    /**
     * Returns the XMLWriter object
     *
     * This method produces an XML representation of a MARC record that
     * attempts to adhere to the MARCXML standard documented at
     * http://www.loc.gov/standards/marcxml/
     *
     * @return XMLWriter XMLWriter instance
     */
    function getXMLWriter()
    {
        return $this->xmlwriter;
    }
    // }}}

    // {{{ toXMLFooter()
    /**
     * Returns the MARCXML collection footer
     *
     * This method produces an XML representation of a MARC record that
     * attempts to adhere to the MARCXML standard documented at
     * http://www.loc.gov/standards/marcxml/
     *
     * @return string           representation of MARC record in MARCXML format
     */
    function toXMLFooter()
    {
        $this->xmlwriter->endElement(); // end collection
        $this->xmlwriter->endDocument();
        return $this->xmlwriter->outputMemory();
    }
    // }}}

}
// }}}
PK�2[5F	'�"�"MARCXML.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */

/**
 * Parser for MARC records
 *
 * This package is based on the PHP MARC package, originally called "php-marc",
 * that is part of the Emilda Project (http://www.emilda.org). Christoffer
 * Landtman generously agreed to make the "php-marc" code available under the
 * GNU LGPL so it could be used as the basis of this PEAR package.
 * 
 * PHP version 5
 *
 * LICENSE: This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category  File_Formats
 * @package   File_MARC
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2007-2010 Dan Scott
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/File_MARC
 * @example   read.php Retrieve specific fields and subfields from a record
 * @example   subfields.php Create new subfields and add them in specific order
 * @example   marc_yaz.php Pretty print a MARC record retrieved through the PECL yaz extension
 */

require_once 'PEAR/Exception.php';
require_once 'File/MARCBASE.php';
require_once 'File/MARC.php';
require_once 'File/MARC/Record.php';
require_once 'File/MARC/Field.php';
require_once 'File/MARC/Control_Field.php';
require_once 'File/MARC/Data_Field.php';
require_once 'File/MARC/Subfield.php';
require_once 'File/MARC/Exception.php';
require_once 'File/MARC/List.php';

// {{{ class File_MARCXML
/**
 * The main File_MARCXML class enables you to return File_MARC_Record
 * objects from an XML stream or string.
 *
 * @category File_Formats
 * @package  File_MARC
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link     http://pear.php.net/package/File_MARC
 */
class File_MARCXML extends File_MARCBASE
{

    // {{{ constants

    /**
     * MARC records retrieved from a file
     */
    const SOURCE_FILE = 1;

    /**
     * MARC records retrieved from a binary string 
     */
    const SOURCE_STRING = 2;
    // }}}

    /**
     * MARC records retrieved from a SimpleXMLElement object
     */
    const SOURCE_SIMPLEXMLELEMENT = 3;
    // }}}

    // {{{ properties
    /**
     * Source containing raw records
     * 
     * @var resource
     */
    protected $source;

    /**
     * Source type (SOURCE_FILE or SOURCE_STRING)
     * 
     * @var int
     */
    protected $type;

    /**
     * Counter for MARCXML records in a collection
     *
     * @var int
     */
    protected $counter;

    /**
     * XMLWriter for writing collections
     * 
     * @var XMLWriter
     */
    protected $xmlwriter;
    // }}}

    // {{{ Constructor: function __construct()
    /**
     * Read in MARCXML records
     *
     * This function reads in files, strings or SimpleXMLElement objects that
     * contain one or more MARCXML records.
     *
     * <code>
     * <?php
     * // Retrieve MARC records from a file
     * $journals = new File_MARC('journals.mrc', SOURCE_FILE);
     *
     * // Retrieve MARC records from a string (e.g. Z39 query results)
     * $monographs = new File_MARC($raw_marc, SOURCE_STRING);
     *
     * // Retrieve MARCXML records from a string with a namespace URL
     * $records = new File_MARCXML($xml_data, File_MARC::SOURCE_STRING,"http://www.loc.gov/MARC21/slim");
     *
     * // Retrieve MARCXML records from a file with a namespace prefix
     * $records = new File_MARCXML($xml_data, File_MARC::SOURCE_FILE,"marc",true);
     * ?>
     * </code>
     *
     * @param string|SimpleXMLElement $source        Filename, raw MARC string or SimpleXMLElement object
     * @param int                     $type          Source of the input, either SOURCE_FILE, SOURCE_STRING or SOURCE_SIMPLEXMLELEMENT
     * @param string                  $ns            URI or prefix of the namespace
     * @param bool                    $is_prefix     TRUE if $ns is a prefix, FALSE if it's a URI; defaults to FALSE
     * @param string                  $record_class  Record class, defaults to File_MARC_Record
     */
    function __construct($source, $type = self::SOURCE_FILE, $ns = "", $is_prefix = false, $record_class = null)
    {
        parent::__construct($source, $type, $record_class);

        $this->counter = 0;

        if ($source instanceof \SimpleXMLElement) {
            $type = self::SOURCE_SIMPLEXMLELEMENT;
        }

        switch ($type) {

        case self::SOURCE_SIMPLEXMLELEMENT:
            $this->type = self::SOURCE_SIMPLEXMLELEMENT;
            $this->source = $source;
            break;

        case self::SOURCE_FILE:
            $this->type = self::SOURCE_FILE;
            $this->source = simplexml_load_file($source, "SimpleXMLElement", 0, $ns, $is_prefix);
            break;

        case self::SOURCE_STRING:
            $this->type = self::SOURCE_STRING;
            $this->source = simplexml_load_string($source, "SimpleXMLElement", 0, $ns, $is_prefix);
            break;

        default:
            throw new File_MARC_Exception(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_SOURCE], File_MARC_Exception::ERROR_INVALID_SOURCE);
        }

        if (!$this->source) {
            $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_FILE], array('filename' => $source));
            throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INVALID_FILE);
        }
    }
    // }}}

    // {{{ next()
    /**
     * Return next {@link File_MARC_Record} object
     *
     * Decodes the next MARCXML record and returns the {@link File_MARC_Record}
     * object.
     * <code>
     * <?php
     * // Retrieve a set of MARCXML records from a file
     * $journals = new File_MARCXML('journals.xml', SOURCE_FILE);
     *
     * // Iterate through the retrieved records
     * while ($record = $journals->next()) {
     *     print $record;
     *     print "\n";
     * }
     *
     * ?>
     * </code>
     *
     * @return File_MARC_Record next record, or false if there are
     * no more records
     */
    function next()
    {
        if (isset($this->source->record[$this->counter])) {
            $record = $this->source->record[$this->counter++];
        } elseif ($this->source->getName() == "record" && $this->counter == 0) {
            $record = $this->source;
            $this->counter++;
        } else {
            return false;
        }

        if ($record) {
            return $this->_decode($record);
        } else {
            return false;
        }
    }
    // }}}

    // {{{ _decode()
    /**
     * Decode a given MARCXML record
     *
     * @param string $text MARCXML record element
     *
     * @return File_MARC_Record Decoded File_MARC_Record object
     */
    private function _decode($text)
    {
        $marc = new $this->record_class($this);

        // Store leader
        $marc->setLeader($text->leader);

        // go through all the control fields
        foreach ($text->controlfield as $controlfield) {
            $controlfieldattributes = $controlfield->attributes();
            $marc->appendField(new File_MARC_Control_Field((string)$controlfieldattributes['tag'], $controlfield));
        }

        // go through all the data fields
        foreach ($text->datafield as $datafield) {
            $datafieldattributes = $datafield->attributes();
            $subfield_data = array();
            foreach ($datafield->subfield as $subfield) {
                $subfieldattributes = $subfield->attributes();
                $subfield_data[] = new File_MARC_Subfield((string)$subfieldattributes['code'], $subfield);
            }
            
            // If the data is invalid, let's just ignore the one field
            try {
                $new_field = new File_MARC_Data_Field((string)$datafieldattributes['tag'], $subfield_data, $datafieldattributes['ind1'], $datafieldattributes['ind2']);
                $marc->appendField($new_field);
            } catch (Exception $e) {
                $marc->addWarning($e->getMessage());
            }
        }

        return $marc;
    }
    // }}}

}
// }}}

PK�2[Sbw�{7{7MARC.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */

/**
 * Parser for MARC records
 *
 * This package is based on the PHP MARC package, originally called "php-marc",
 * that is part of the Emilda Project (http://www.emilda.org). Christoffer
 * Landtman generously agreed to make the "php-marc" code available under the
 * GNU LGPL so it could be used as the basis of this PEAR package.
 * 
 * PHP version 5
 *
 * LICENSE: This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category  File_Formats
 * @package   File_MARC
 * @author    Christoffer Landtman <landtman@realnode.com>
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2003-2010 Oy Realnode Ab, Dan Scott
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/File_MARC
 * @example   read.php Retrieve specific fields and subfields from a record
 * @example   subfields.php Create new subfields and add them in specific order
 * @example   marc_yaz.php Pretty print a MARC record retrieved through the PECL yaz extension
 */

require_once 'PEAR/Exception.php';
require_once 'File/MARCBASE.php';
require_once 'File/MARC/Record.php';
require_once 'File/MARC/Field.php';
require_once 'File/MARC/Control_Field.php';
require_once 'File/MARC/Data_Field.php';
require_once 'File/MARC/Subfield.php';
require_once 'File/MARC/Exception.php';
require_once 'File/MARC/List.php';

// {{{ class File_MARC
/**
 * The main File_MARC class enables you to return File_MARC_Record
 * objects from a stream or string.
 *
 * @category File_Formats
 * @package  File_MARC
 * @author   Christoffer Landtman <landtman@realnode.com>
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link     http://pear.php.net/package/File_MARC
 */
class File_MARC extends File_MARCBASE
{

    // {{{ constants

    /**
     * MARC records retrieved from a file
     */
    const SOURCE_FILE = 1;

    /**
     * MARC records retrieved from a binary string 
     */
    const SOURCE_STRING = 2;

    /**
     * Hexadecimal value for Subfield indicator
     */
    const SUBFIELD_INDICATOR = "\x1F";

    /**
     * Hexadecimal value for End of Field
     */
    const END_OF_FIELD = "\x1E";

    /**
     * Hexadecimal value for End of Record
     */
    const END_OF_RECORD = "\x1D";

    /**
     * Length of the Directory
     */
    const DIRECTORY_ENTRY_LEN = 12;

    /**
     * Length of the Leader
     */
    const LEADER_LEN = 24;

    /**
     * Maximum record length
     */
    const MAX_RECORD_LENGTH = 99999;
    // }}}

    // {{{ properties
    /**
     * Source containing raw records
     * 
     * @var resource
     */
    protected $source;

    /**
     * Source type (SOURCE_FILE or SOURCE_STRING)
     * 
     * @var int
     */
    protected $type;

    /**
     * XMLWriter for writing collections
     * 
     * @var XMLWriter
     */
    protected $xmlwriter;
    // }}}

    // {{{ Constructor: function __construct()
    /**
     * Read in MARC records
     *
     * This function reads in MARC record files or strings that
     * contain one or more MARC records.
     *
     * <code>
     * <?php
     * // Retrieve MARC records from a file
     * $journals = new File_MARC('journals.mrc', SOURCE_FILE);
     *
     * // Retrieve MARC records from a string (e.g. Z39 query results)
     * $monographs = new File_MARC($raw_marc, SOURCE_STRING);
     * ?>
     * </code>
     *
     * @param string $source        Name of the file, or a raw MARC string
     * @param int    $type          Source of the input, either SOURCE_FILE or SOURCE_STRING
     * @param string $record_class  Record class, defaults to File_MARC_Record
     */
    function __construct($source, $type = self::SOURCE_FILE, $record_class = null)
    {

        parent::__construct($source, $type, $record_class);

        switch ($type) {

        case self::SOURCE_FILE:
            $this->type = self::SOURCE_FILE;
            $this->source = fopen($source, 'rb');
            if (!$this->source) {
                 $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_FILE], array('filename' => $source));
                 throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INVALID_FILE);
            }
            break;

        case self::SOURCE_STRING:
            $this->type = self::SOURCE_STRING;
            $this->source = explode(File_MARC::END_OF_RECORD, $source);
            break;

        default:
            throw new File_MARC_Exception(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_SOURCE], File_MARC_Exception::ERROR_INVALID_SOURCE);
        }
    }
    // }}}

    // {{{ nextRaw()
    /**
     * Return the next raw MARC record
     *
     * Returns the next raw MARC record, unless all records already have
     * been read.
     *
     * @return string Either a raw record or false
     */
    function nextRaw()
    {
        if ($this->type == self::SOURCE_FILE) {
            $record = stream_get_line($this->source, File_MARC::MAX_RECORD_LENGTH, File_MARC::END_OF_RECORD);

            // Remove illegal stuff that sometimes occurs between records
            $record = preg_replace('/^[\\x0a\\x0d\\x00]+/', "", $record);

        } elseif ($this->type == self::SOURCE_STRING) {
            $record = array_shift($this->source);
        }

        // Exit if we are at the end of the file
        if (!$record) {
            return false;
        }

        // Append the end of record we lost during stream_get_line() or explode()
        $record .= File_MARC::END_OF_RECORD;
        return $record;
    }
    // }}}

    // {{{ next()
    /**
     * Return next {@link File_MARC_Record} object
     *
     * Decodes the next raw MARC record and returns the {@link File_MARC_Record}
     * object.
     * <code>
     * <?php
     * // Retrieve a set of MARC records from a file
     * $journals = new File_MARC('journals.mrc', SOURCE_FILE);
     *
     * // Iterate through the retrieved records
     * while ($record = $journals->next()) {
     *     print $record;
     *     print "\n";
     * }
     *
     * ?>
     * </code>
     *
     * @return File_MARC_Record next record, or false if there are
     * no more records
     */
    function next()
    {
        $raw = $this->nextRaw();
        if ($raw) {
            return $this->_decode($raw);
        } else {
            return false;
        }
    }
    // }}}

    // {{{ _decode()
    /**
     * Decode a given raw MARC record
     *
     * Port of Andy Lesters MARC::File::USMARC->decode() Perl function into PHP.
     *
     * @param string $text Raw MARC record
     *
     * @return File_MARC_Record Decoded File_MARC_Record object
     */
    private function _decode($text)
    {
        $marc = new $this->record_class($this);

        // fallback on the actual byte length
        $record_length = strlen($text);

        $matches = array();
        if (preg_match("/^(\d{5})/", $text, $matches)) {
            // Store record length
            $record_length = $matches[1];
            if ($record_length != strlen($text)) {
                $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INCORRECT_LENGTH], array("record_length" => $record_length, "actual" => strlen($text))));
                // Real beats declared byte length
                $record_length = strlen($text);
            }
        } else {
            $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_NONNUMERIC_LENGTH], array("record_length" => substr($text, 0, 5))));
        }

        if (substr($text, -1, 1) != File_MARC::END_OF_RECORD)
             throw new File_MARC_Exception(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_TERMINATOR], File_MARC_Exception::ERROR_INVALID_TERMINATOR);

        // Store leader
        $marc->setLeader(substr($text, 0, File_MARC::LEADER_LEN));

        // bytes 12 - 16 of leader give offset to the body of the record
        $data_start = 0 + substr($text, 12, 5);

        // immediately after the leader comes the directory (no separator)
        $dir = substr($text, File_MARC::LEADER_LEN, $data_start - File_MARC::LEADER_LEN - 1);  // -1 to allow for \x1e at end of directory

        // character after the directory must be \x1e
        if (substr($text, $data_start-1, 1) != File_MARC::END_OF_FIELD) {
            $marc->addWarning(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_NO_DIRECTORY]);
        }

        // All directory entries 12 bytes long, so length % 12 must be 0
        if (strlen($dir) % File_MARC::DIRECTORY_ENTRY_LEN != 0) {
            $marc->addWarning(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_DIRECTORY_LENGTH]);
        }

        // go through all the fields
        $nfields = strlen($dir) / File_MARC::DIRECTORY_ENTRY_LEN;
        for ($n=0; $n<$nfields; $n++) {
            // As pack returns to key 1, leave place 0 in list empty
            list(, $tag) = unpack("A3", substr($dir, $n*File_MARC::DIRECTORY_ENTRY_LEN, File_MARC::DIRECTORY_ENTRY_LEN));
            list(, $len) = unpack("A3/A4", substr($dir, $n*File_MARC::DIRECTORY_ENTRY_LEN, File_MARC::DIRECTORY_ENTRY_LEN));
            list(, $offset) = unpack("A3/A4/A5", substr($dir, $n*File_MARC::DIRECTORY_ENTRY_LEN, File_MARC::DIRECTORY_ENTRY_LEN));

            // Check directory validity
            if (!preg_match("/^[0-9A-Za-z]{3}$/", $tag)) {
                $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_DIRECTORY_TAG], array("tag" => $tag)));
            }
            if (!preg_match("/^\d{4}$/", $len)) {
                $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_DIRECTORY_TAG_LENGTH], array("tag" => $tag, "len" => $len)));
            }
            if (!preg_match("/^\d{5}$/", $offset)) {
                $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_DIRECTORY_OFFSET], array("tag" => $tag, "offset" => $offset)));
            }
            if ($offset + $len > $record_length) {
                $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_DIRECTORY], array("tag" => $tag)));
            }

            $tag_data = substr($text, $data_start + $offset, $len);

            if (substr($tag_data, -1, 1) == File_MARC::END_OF_FIELD) {
                /* get rid of the end-of-tag character */
                $tag_data = substr($tag_data, 0, -1);
                $len--;
            } else {
                $marc->addWarning(File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_FIELD_EOF], array("tag" => $tag)));
            }

            if (preg_match("/^\d+$/", $tag) and ($tag < 10)) {
                $marc->appendField(new File_MARC_Control_Field($tag, $tag_data));
            } else {
                $subfields = explode(File_MARC::SUBFIELD_INDICATOR, $tag_data);
                $indicators = array_shift($subfields);

                if (strlen($indicators) != 2) {
                    $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_INDICATORS], array("tag" => $tag, "indicators" => $indicators));
                    $marc->addWarning($errorMessage);
                    // Do the best with the indicators we've got
                    if (strlen($indicators) == 1) {
                        $ind1 = $indicators;
                        $ind2 = " ";
                    } else {
                        list($ind1,$ind2) = array(" ", " ");
                    }
                } else {
                    $ind1 = substr($indicators, 0, 1);
                    $ind2 = substr($indicators, 1, 1);
                }

                // Split the subfield data into subfield name and data pairs
                $subfield_data = array();
                foreach ($subfields as $subfield) {
                    if (strlen($subfield) > 0) {
                        $subfield_data[] = new File_MARC_Subfield(substr($subfield, 0, 1), substr($subfield, 1));
                    } else {
                         $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_EMPTY_SUBFIELD], array("tag" => $tag));
                         $marc->addWarning($errorMessage);
                    }
                }

                if (!isset($subfield_data)) {
                     $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_EMPTY_SUBFIELD], array("tag" => $tag));
                     $marc->addWarning($errorMessage);
                }


                // If the data is invalid, let's just ignore the one field
                try {
                    $new_field = new File_MARC_Data_Field($tag, $subfield_data, $ind1, $ind2);
                    $marc->appendField($new_field);
                } catch (Exception $e) {
                    $marc->addWarning($e->getMessage());
                }
            }
        }

        return $marc;
    }
    // }}}

}
// }}}

PK�2[�9g4xUxUMARC/Record.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */

/**
 * Parser for MARC records
 *
 * This package is based on the PHP MARC package, originally called "php-marc",
 * that is part of the Emilda Project (http://www.emilda.org). Christoffer
 * Landtman generously agreed to make the "php-marc" code available under the
 * GNU LGPL so it could be used as the basis of this PEAR package.
 * 
 * PHP version 5
 *
 * LICENSE: This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category  File_Formats
 * @package   File_MARC
 * @author    Christoffer Landtman <landtman@realnode.com>
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2003-2008 Oy Realnode Ab, Dan Scott
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/File_MARC
 */

// {{{ class File_MARC_Record
/**
 * Represents a single MARC record
 * 
 * A MARC record contains a leader and zero or more fields held within a
 * linked list structure. Fields are represented by {@link File_MARC_Data_Field}
 * objects.
 *
 * @category File_Formats
 * @package  File_MARC
 * @author   Christoffer Landtman <landtman@realnode.com>
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link     http://pear.php.net/package/File_MARC
 */
class File_MARC_Record
{

    // {{{ properties
    /**
     * Contains a linked list of {@link File_MARC_Data_Field} objects for
     * this record
     * @var File_MARC_List
     */
    protected $fields;

    /**
     * Record leader
     * @var string
     */
    protected $leader;

    /**
     * Non-fatal warnings generated during parsing
     * @var array
     */
    protected $warnings;

    /**
     * XMLWriter for writing collections
     * 
     * @var XMLWriter
     */
    protected $marcxml;

    /**
     * MARC instance for access to the XML header/footer methods
     * We need this so that we can properly wrap a collection of MARC records.
     * 
     * @var File_MARC
     */
    protected $marc;

    // }}}

    // {{{ Constructor: function __construct()
    /**
     * Start function
     *
     * Set all variables to defaults to create new File_MARC_Record object
     *
     * @param File_MARC $marc MARC record from File_MARC or File_MARCXML
     *
     * @return true 
     */
    function __construct($marc = null)
    {
        $this->fields = new File_MARC_List();
        $this->setLeader(str_repeat(' ', 24));
        if (!$marc) {
            $marc = new File_MARC(null, File_MARC::SOURCE_STRING); // oh the hack
        }
        $this->marc = $marc;
        $this->marcxml = $marc->getXMLWriter();
    }
    // }}}

    // {{{ Destructor: function __destruct()
    /**
     * Destroys the data field
     */
    function __destruct()
    {
        $this->fields = null;
        $this->warnings = null;
    }
    // }}}

    // {{{ getLeader()
    /**
     * Get MARC leader
     *
     * Returns the leader for the MARC record. No validation
     * on the specified leader is performed.
     *
     * @return string returns the leader
     */
    function getLeader()
    {
        return (string)$this->leader;
    }
    // }}}

    // {{{ setLeader()
    /**
     * Set MARC record leader
     *
     * Sets the leader for the MARC record. No validation
     * on the specified leader is performed.
     *
     * @param string $leader Leader
     *
     * @return string returns the leader
     */
    function setLeader($leader)
    {
        $this->leader = $leader;
        return $this->leader;
    }
    // }}}

    // {{{ appendField()
    /**
     * Appends field to MARC record
     *
     * Adds a {@link File_MARC_Control_Field} or {@link File_MARC_Data_Field}
     * object to the end of the existing list of fields.
     *
     * @param File_MARC_Field $new_field The field to add
     *
     * @return File_MARC_Field The field that was added
     */
    function appendField(File_MARC_Field $new_field)
    {
        /* Append as the last field in the record */
        $this->fields->appendNode($new_field);
        return $new_field;
    }
    // }}}

    // {{{ prependField()
    /**
     * Prepends field to MARC record
     *
     * Adds a {@link File_MARC_Control_Field} or {@link File_MARC_Data_Field}
     * object to the start of to the existing list of fields.
     *
     * @param File_MARC_Field $new_field The field to add
     *
     * @return File_MARC_Field The field that was added
     */
    function prependField(File_MARC_Field $new_field)
    {
        $this->fields->prependNode($new_field);
        return $new_field;
    }
    // }}}

    // {{{ insertField()
    /**
     * Inserts a field in the MARC record relative to an existing field
     *
     * Inserts a {@link File_MARC_Control_Field} or {@link File_MARC_Data_Field}
     * object before or after a specified existing field.
     *
     * <code>
     * // Example: Insert a new field before the first 650 field
     *
     * // Create the new field
     * $subfields[] = new File_MARC_Subfield('a', 'Scott, Daniel.');
     * $new_field = new File_MARC_Data_Field('100', $subfields, 0, null);
     *
     * // Retrieve the target field for our insertion point
     * $subject = $record->getFields('650');
     *
     * // Insert the new field
     * if (is_array($subject)) {
     *     $record->insertField($new_field, $subject[0], true);
     * }
     * elseif ($subject) {
     *     $record->insertField($new_field, $subject, true);
     * }
     * </code>
     *
     * @param File_MARC_Field $new_field      The field to add
     * @param File_MARC_Field $existing_field The target field
     * @param bool            $before         Insert the new field before the existing field if true, after the existing field if false
     *
     * @return File_MARC_Field                The field that was added
     */
    function insertField(File_MARC_Field $new_field, File_MARC_Field $existing_field, $before = false)
    {
        $this->fields->insertNode($new_field, $existing_field, $before);
        return $new_field;
    }
    // }}}

    // {{{ _buildDirectory()
    /**
     * Build record directory
     *
     * Generate the directory of the record according to the current contents
     * of the record.
     *
     * @return array Array ($fields, $directory, $total, $base_address)
     */
    private function _buildDirectory()
    {
        // Vars
        $fields = array();
        $directory = array();
        $data_end = 0;

        foreach ($this->fields as $field) {
            // No empty fields allowed
            if (!$field->isEmpty()) {
                // Get data in raw format
                $str = $field->toRaw();
                $fields[] = $str;

                // Create directory entry
                $len = strlen($str);
                $direntry = sprintf("%03s%04d%05d", $field->getTag(), $len, $data_end);
                $directory[] = $direntry;
                $data_end += $len;
            }
        }

        /**
         * Rules from MARC::Record::USMARC
         */
        $base_address
            = File_MARC::LEADER_LEN +    // better be 24
                (count($directory) * File_MARC::DIRECTORY_ENTRY_LEN) +
                                // all the directory entries
                1;              // end-of-field marker


        $total
            = $base_address +  // stuff before first field
                $data_end +      // Length of the fields
                1;              // End-of-record marker


        return array($fields, $directory, $total, $base_address);
    }
    // }}}

    // {{{ setLeaderLengths()
    /**
     * Set MARC record leader lengths
     *
     * Set the Leader lengths of the record according to defaults specified in
     * {@link http://www.loc.gov/marc/bibliographic/ecbdldrd.html}
     *
     * @param int $record_length Record length
     * @param int $base_address  Base address of data
     *
     * @return bool              Success or failure
     */
    function setLeaderLengths($record_length, $base_address)
    {
        if (!is_int($record_length)) {
            return false;
        }
        if (!is_int($base_address)) {
            return false;
        }

        // Set record length
        $this->setLeader(substr_replace($this->getLeader(), sprintf("%05d", $record_length), 0, 5));
        $this->setLeader(substr_replace($this->getLeader(), sprintf("%05d", $base_address), File_MARC::DIRECTORY_ENTRY_LEN, 5));
        $this->setLeader(substr_replace($this->getLeader(), '22', 10, 2));
        $this->setLeader(substr_replace($this->getLeader(), '4500', 20, 4));

        if (strlen($this->getLeader()) > File_MARC::LEADER_LEN) {
            // Avoid incoming leaders that are mangled to be overly long
            $this->setLeader(substr($this->getLeader(), 0, File_MARC::LEADER_LEN));
            $this->addWarning("Input leader was too long; truncated to " . File_MARC::LEADER_LEN . " characters");
        }
        return true;
    }
    // }}}

    // {{{ getField()
    /**
     * Return the first {@link File_MARC_Data_Field} or
     * {@link File_MARC_Control_Field} object that matches the specified tag
     * name. Returns false if no match is found.
     *
     * @param string $spec tag name
     * @param bool   $pcre if true, then match as a regular expression
     *
     * @return {@link File_MARC_Data_Field}|{@link File_MARC_Control_Field} first field that matches the requested tag name
     */
    function getField($spec = null, $pcre = null)
    {
        foreach ($this->fields as $field) {
            if (($pcre
                && preg_match("/$spec/", $field->getTag()))
                || (!$pcre
                && $spec == $field->getTag())
            ) {
                return $field;
            }
        }
        return false;
    }
    // }}}

    // {{{ getFields()
    /**
     * Return an array or {@link File_MARC_List} containing all
     * {@link File_MARC_Data_Field} or  {@link File_MARC_Control_Field} objects
     * that match the specified tag name. If the tag name is omitted all
     * fields are returned.
     *
     * @param string $spec tag name
     * @param bool   $pcre if true, then match as a regular expression
     *
     * @return File_MARC_List|array {@link File_MARC_Data_Field} or
     * {@link File_MARC_Control_Field} objects that match the requested tag name
     */
    function getFields($spec = null, $pcre = null)
    {
        if (!$spec) {
            return $this->fields;
        }

        // Okay, we're actually looking for something specific
        $matches = array();
        foreach ($this->fields as $field) {
            if (($pcre && preg_match("/$spec/", $field->getTag()))
                || (!$pcre && $spec == $field->getTag())
            ) {
                $matches[] = $field;
            }
        }
        return $matches;
    }
    // }}}

    // {{{ deleteFields()
    /**
     * Delete all occurrences of a field matching a tag name from the record.
     *
     * @param string $tag  tag for the fields to be deleted
     * @param bool   $pcre if true, then match as a regular expression
     *
     * @return int         number of fields that were deleted
     */
    function deleteFields($tag, $pcre = null)
    {
        $cnt = 0;
        foreach ($this->getFields() as $field) {
            if (($pcre
                && preg_match("/$tag/", $field->getTag()))
                || (!$pcre
                && $tag == $field->getTag())
            ) {
                $field->delete();
                $cnt++;
            }
        }
        return $cnt;
    }
    // }}}

    // {{{ addWarning()
    /**
     * Add a warning to the MARC record that something non-fatal occurred during
     * parsing.
     *
     * @param string $warning warning message
     *
     * @return true
     */
    public function addWarning($warning)
    {
        $this->warnings[] = $warning;
    }
    // }}}

    // {{{ getWarnings()
    /**
     * Return the array of warnings from the MARC record.
     *
     * @return array warning messages
     */
    public function getWarnings()
    {
        return $this->warnings;
    }
    // }}}

    // {{{ output methods
    /**
     * ========== OUTPUT METHODS ==========
     */

    // {{{ toRaw()
    /**
     * Return the record in raw MARC format.
     *
     * If you have modified an existing MARC record or created a new MARC
     * record, use this method to save the record for use in other programs
     * that accept the MARC format -- for example, your integrated library
     * system.
     *
     * <code>
     * // Example: Modify a record and save the output to a file
     * $record->deleteFields('650');
     *
     * // Now that the record has no subject fields, save it to disk
     * fopen($file, '/home/dan/no_subject.mrc', 'w');
     * fwrite($file, $record->toRaw());
     * fclose($file);
     * </code>
     *
     * @return string Raw MARC data
     */
    function toRaw()
    {
        list($fields, $directory, $record_length, $base_address) = $this->_buildDirectory();
        $this->setLeaderLengths($record_length, $base_address);

        /**
         * Glue together all parts
         */
        return $this->getLeader().implode("", $directory).File_MARC::END_OF_FIELD.implode("", $fields).File_MARC::END_OF_RECORD;
    }
    // }}}

    // {{{ __toString()
    /**
     * Return the MARC record in a pretty printed string
     *
     * This method produces an easy-to-read textual display of a MARC record.
     *
     * The structure is roughly:
     * <tag> <ind1> <ind2> _<code><data>
     *                     _<code><data>
     *
     * @return string Formatted representation of MARC record
     */
    function __toString()
    {
        // Begin output
        $formatted = "LDR " . $this->getLeader() . "\n";
        foreach ($this->fields as $field) {
            if (!$field->isEmpty()) {
                $formatted .= $field->__toString() . "\n";
            }
        }
        return $formatted;
    }
    // }}}

    // {{{ toJSON()
    /**
     * Return the MARC record in JSON format
     *
     * This method produces a JSON representation of a MARC record. The input
     * encoding must be UTF8, otherwise the returned values will be corrupted.
     *
     * @return string          representation of MARC record in JSON format
     *
     * @todo Fix encoding input / output issues (PHP 6.0 required?)
     */
    function toJSON()
    {
        $json = new StdClass();
        $json->leader = utf8_encode($this->getLeader());

        /* Start fields */
        $fields = array();
        foreach ($this->fields as $field) {
            if (!$field->isEmpty()) {
                switch(get_class($field)) {
                case "File_MARC_Control_Field":
                    $fields[] = array(utf8_encode($field->getTag()) => utf8_encode($field->getData()));
                    break;

                case "File_MARC_Data_Field":
                    $subs = array();
                    foreach ($field->getSubfields() as $sf) {
                        $subs[] = array(utf8_encode($sf->getCode()) => utf8_encode($sf->getData()));
                    }
                    $contents = new StdClass();
                    $contents->ind1 = utf8_encode($field->getIndicator(1));
                    $contents->ind2 = utf8_encode($field->getIndicator(2));
                    $contents->subfields = $subs;
                    $fields[] = array(utf8_encode($field->getTag()) => $contents);
                    break;
                }
            }
        }
        /* End fields and record */

        $json->fields = $fields;
        $json_rec = json_encode($json);
        // Required because json_encode() does not let us stringify integer keys
        return preg_replace('/("subfields":)(.*?)\["([^\"]+?)"\]/', '\1\2{"0":"\3"}', $json_rec);
    }

    // }}}

    // {{{ toJSONHash()
    /**
     * Return the MARC record in Bill Dueber's MARC-HASH JSON format
     *
     * This method produces a JSON representation of a MARC record as defined
     * at http://robotlibrarian.billdueber.com/new-interest-in-marc-hash-json/
     * The input * encoding must be UTF8, otherwise the returned values will
     * be corrupted.
     *
     * @return string          representation of MARC record in JSON format
     *
     * @todo Fix encoding input / output issues (PHP 6.0 required?)
     */
    function toJSONHash()
    {
        $json = new StdClass();
        $json->type = "marc-hash";
        $json->version = array(1, 0);
        $json->leader = utf8_encode($this->getLeader());

        /* Start fields */
        $fields = array();
        foreach ($this->fields as $field) {
            if (!$field->isEmpty()) {
                switch(get_class($field)) {
                case "File_MARC_Control_Field":
                    $fields[] = array(utf8_encode($field->getTag()), utf8_encode($field->getData()));
                    break;

                case "File_MARC_Data_Field":
                    $subs = array();
                    foreach ($field->getSubfields() as $sf) {
                        $subs[] = array(utf8_encode($sf->getCode()), utf8_encode($sf->getData()));
                    }
                    $contents = array(
                        utf8_encode($field->getTag()),
                        utf8_encode($field->getIndicator(1)),
                        utf8_encode($field->getIndicator(2)),
                        $subs
                    );
                    $fields[] = $contents;
                    break;
                }
            }
        }
        /* End fields and record */

        $json->fields = $fields;
        return json_encode($json);
    }

    // }}}


    // {{{ toXML()
    /**
     * Return the MARC record in MARCXML format
     *
     * This method produces an XML representation of a MARC record that
     * attempts to adhere to the MARCXML standard documented at
     * http://www.loc.gov/standards/marcxml/
     *
     * @param string $encoding output encoding for the MARCXML record
     * @param bool   $indent   pretty-print the MARCXML record
     * @param bool   $single   wrap the <record> element in a <collection> element
     *
     * @return string          representation of MARC record in MARCXML format
     *
     * @todo Fix encoding input / output issues (PHP 6.0 required?)
     */
    function toXML($encoding = "UTF-8", $indent = true, $single = true)
    {
        $this->marcxml->setIndent($indent);
        if ($single) {
            $this->marcxml->startElement("collection");
            $this->marcxml->writeAttribute("xmlns", "http://www.loc.gov/MARC21/slim");
            $this->marcxml->startElement("record");
        } else {
            $this->marcxml->startElement("record");
            $this->marcxml->writeAttribute("xmlns", "http://www.loc.gov/MARC21/slim");
        }
        

        // MARCXML schema has some strict requirements
        // We'll set reasonable defaults to avoid invalid MARCXML
        $xmlLeader = $this->getLeader();

        // Record status
        if ($xmlLeader[5] == " ") {
            // Default to "n" (new record)
            $xmlLeader[5] = "n";
        }

        // Type of record
        if ($xmlLeader[6] == " ") {
            // Default to "a" (language material)
            $xmlLeader[6] = "a";
        }

        $this->marcxml->writeElement("leader", $xmlLeader);

        foreach ($this->fields as $field) {
            if (!$field->isEmpty()) {
                switch(get_class($field)) {
                case "File_MARC_Control_Field":
                    $this->marcxml->startElement("controlfield");
                    $this->marcxml->writeAttribute("tag", $field->getTag());
                    $this->marcxml->text($field->getData());
                    $this->marcxml->endElement(); // end control field
                    break;

                case "File_MARC_Data_Field":
                    $this->marcxml->startElement("datafield");
                    $this->marcxml->writeAttribute("tag", $field->getTag());
                    $this->marcxml->writeAttribute("ind1", $field->getIndicator(1));
                    $this->marcxml->writeAttribute("ind2", $field->getIndicator(2));
                    foreach ($field->getSubfields() as $subfield) {
                        $this->marcxml->startElement("subfield");
                        $this->marcxml->writeAttribute("code", $subfield->getCode());
                        $this->marcxml->text($subfield->getData());
                        $this->marcxml->endElement(); // end subfield
                    }
                    $this->marcxml->endElement(); // end data field
                    break;
                }
            }
        }

        $this->marcxml->endElement(); // end record
        if ($single) {
            $this->marcxml->endElement(); // end collection
            $this->marcxml->endDocument();
        }
        return $this->marcxml->outputMemory();
    }
    // }}}

}
// }}}

PK�2[(#�~��MARC/Exception.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */

/**
 * Parser for MARC records
 *
 * This package is based on the PHP MARC package, originally called "php-marc",
 * that is part of the Emilda Project (http://www.emilda.org). Christoffer
 * Landtman generously agreed to make the "php-marc" code available under the
 * GNU LGPL so it could be used as the basis of this PEAR package.
 * 
 * PHP version 5
 *
 * LICENSE: This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category  File_Formats
 * @package   File_MARC
 * @author    Christoffer Landtman <landtman@realnode.com>
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2003-2008 Oy Realnode Ab, Dan Scott
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/File_MARC
 */

// {{{ class File_MARC_Exception extends PEAR_Exception
/**
 * The File_MARC_Exception class enables error-handling
 * for the File_MARC package.
 *
 * @category File_Formats
 * @package  File_MARC
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link     http://pear.php.net/package/File_MARC
 */
class File_MARC_Exception extends PEAR_Exception
{
    // {{{ Error codes
    /**
     * File could not be opened
     */
    const ERROR_INVALID_FILE = -1;

    /**
     * User passed an unknown SOURCE_ constant
     */
    const ERROR_INVALID_SOURCE = -2;

    /**
     * MARC record ended with an invalid terminator
     */
    const ERROR_INVALID_TERMINATOR = -3;

    /**
     * No directory was found for the MARC record
     */
    const ERROR_NO_DIRECTORY = -4;

    /**
     * An entry in the MARC directory was not 12 bytes
     */
    const ERROR_INVALID_DIRECTORY_LENGTH = -5;

    /**
     * An entry in the MARC directory specified an invalid tag
     */
    const ERROR_INVALID_DIRECTORY_TAG = -6;

    /**
     * An entry in the MARC directory specified an invalid tag length
     */
    const ERROR_INVALID_DIRECTORY_TAG_LENGTH = -7;

    /**
     * An entry in the MARC directory specified an invalid field offset
     */
    const ERROR_INVALID_DIRECTORY_OFFSET = -8;

    /**
     * An entry in the MARC directory runs past the end of the record
     */
    const ERROR_INVALID_DIRECTORY = -9;

    /**
     * A field does not end with the expected end-of-field character
     */
    const ERROR_FIELD_EOF = -10;

    /**
     * A field has invalid indicators
     */
    const ERROR_INVALID_INDICATORS = -11;

    /**
     * A subfield is defined, but has no data
     */
    const ERROR_EMPTY_SUBFIELD = -12;

    /**
     * An indicator other than 1 or 2 was requested
     */
    const ERROR_INVALID_INDICATOR_REQUEST = -13;

    /**
     * An invalid mode for adding a field was specified
     */
    const ERROR_INSERTFIELD_MODE = -14;

    /**
     * An invalid object was passed instead of a File_MARC_Field object
     */
    const ERROR_INVALID_FIELD = -15;

    /**
     * An invalid object was passed instead of a File_MARC_Subfield object
     */
    const ERROR_INVALID_SUBFIELD = -16;

    /**
     * An invalid mode for adding a subfield was specified
     */
    const ERROR_INSERTSUBFIELD_MODE = -17;

    /**
     * The length in the MARC leader does not match the actual record length
     */
    const ERROR_INCORRECT_LENGTH = -18;

    /**
     * The length field in the leader was less than five characters long
     */
    const ERROR_MISSING_LENGTH = -19;

    /**
     * A five-digit length could not be found in the MARC leader
     */
    const ERROR_NONNUMERIC_LENGTH = -20;

    /**
     * Tag does not adhere to MARC standards
     */
    const ERROR_INVALID_TAG = -21;

    /**
     * A field has invalid indicators
     */
    const ERROR_INVALID_INDICATOR = -22;
    // }}}

    // {{{ error messages
    public static $messages = array(
        self::ERROR_EMPTY_SUBFIELD => 'No subfield data found in tag "%tag%"', 
        self::ERROR_FIELD_EOF => 'Field for tag "%tag%" does not end with an end of field character', 
        self::ERROR_INCORRECT_LENGTH => 'Invalid record length: Leader says "%record_length%" bytes; actual record length is "%actual%"', 
        self::ERROR_INSERTFIELD_MODE => 'insertField() mode "%mode%" was not recognized', 
        self::ERROR_INSERTSUBFIELD_MODE => 'insertSubfield() mode "%mode%" was not recognized', 
        self::ERROR_INVALID_DIRECTORY => 'Directory entry for tag "%tag%" runs past the end of the record', 
        self::ERROR_INVALID_DIRECTORY_LENGTH => 'Invalid directory length', 
        self::ERROR_INVALID_DIRECTORY_OFFSET => 'Invalid offset "%offset%" for tag "%tag%" in directory', 
        self::ERROR_INVALID_DIRECTORY_TAG => 'Invalid tag "%tag%" in directory', 
        self::ERROR_INVALID_DIRECTORY_TAG_LENGTH => 'Invalid length "%len%" in directory for tag "%tag%"', 
        self::ERROR_INVALID_FIELD => 'Specified field must be a File_MARC_Data_Field or File_MARC_Control_Field object, but was "%field%"', 
        self::ERROR_INVALID_FILE => 'Invalid input file "%filename%"', 
        self::ERROR_INVALID_INDICATOR_REQUEST => 'Attempt to access indicator "%indicator%" failed; 1 and 2 are the only valid indicators', 
        self::ERROR_INVALID_INDICATORS => 'Invalid indicators "%indicators%" forced to blanks for tag "%tag%"', 
        self::ERROR_INVALID_SOURCE => "Invalid source for MARC records", 
        self::ERROR_INVALID_SUBFIELD => 'Specified field must be a File_MARC_Subfield object, but was "%class%"', 
        self::ERROR_INVALID_TAG => 'Tag "%tag%" is not a valid tag.', 
        self::ERROR_INVALID_TERMINATOR => 'Invalid record terminator', 
        self::ERROR_MISSING_LENGTH => "Couldn't find record length", 
        self::ERROR_NO_DIRECTORY => 'No directory found', 
        self::ERROR_NONNUMERIC_LENGTH => 'Record length "%record_length%" is not numeric',
        self::ERROR_INVALID_INDICATOR => 'Illegal indicator "%indicator%" in field "%tag%" forced to blank', 
    );
    // }}}

    // {{{ formatError()
    /**
     * Replaces placeholder tokens in an error message with actual values.
     *
     * This method enables you to internationalize the messages for the
     * File_MARC class by simply replacing the File_MARC_Exception::$messages
     * array with translated values for the messages.
     *
     * @param string $message     Error message containing placeholders
     * @param array  $errorValues Actual values to substitute for placeholders
     *
     * @return string             Formatted message
     */
    public static function formatError($message, $errorValues)
    {
        foreach ($errorValues as $token => $value) {
            $message = preg_replace("/\%$token\%/", $value, $message);
        }
        return $message;
    }
    // }}}
}
// }}}

PK�2[�S��hh
MARC/List.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */

/**
 * Parser for MARC records
 *
 * This package is based on the PHP MARC package, originally called "php-marc",
 * that is part of the Emilda Project (http://www.emilda.org). Christoffer
 * Landtman generously agreed to make the "php-marc" code available under the
 * GNU LGPL so it could be used as the basis of this PEAR package.
 *
 * PHP version 5
 *
 * LICENSE: This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category  File_Formats
 * @package   File_MARC
 * @author    Christoffer Landtman <landtman@realnode.com>
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2003-2008 Oy Realnode Ab, Dan Scott
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/File_MARC
 */

// {{{ class File_MARC_List extends SplDoublyLinkedList
/**
 * The File_MARC_List class extends the SplDoublyLinkedList class
 * to override the key() method in a meaningful way for foreach() iterators.
 *
 * For the list of {@link File_MARC_Field} objects in a {@link File_MARC_Record}
 * object, the key() method returns the tag name of the field.
 *
 * For the list of {@link File_MARC_Subfield} objects in a {@link
 * File_MARC_Data_Field} object, the key() method returns the code of
 * the subfield.
 *
 * <code>
 * // Iterate through the fields in a record with key=>value iteration
 * foreach ($record->getFields() as $tag=>$value) {
 *     print "$tag: ";
 *     if ($value instanceof File_MARC_Control_Field) {
 *         print $value->getData();
 *     }
 *     else {
 *         // Iterate through the subfields in this data field
 *         foreach ($value->getSubfields() as $code=>$subdata) {
 *             print "_$code";
 *         }
 *     }
 *     print "\n";
 * }
 * </code>
 *
 * @category File_Formats
 * @package  File_MARC
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link     http://pear.php.net/package/File_MARC
 */
class File_MARC_List extends SplDoublyLinkedList
{

    // {{{ properties
    /**
     * Position of the subfield
     * @var int
     */
    protected $position;

    // }}}

    // {{{ key()
    /**
     * Returns the tag for a {@link File_MARC_Field} object, or the code
     * for a {@link File_MARC_Subfield} object.
     *
     * This method enables you to use a foreach iterator to retrieve
     * the tag or code as the key for the iterator.
     *
     * @return string returns the tag or code
     */
    function key()
    {
        if ($this->current() instanceof File_MARC_Field) {
            return $this->current()->getTag();
        } elseif ($this->current() instanceof File_MARC_Subfield) {
            return $this->current()->getCode();
        }
        return false;
    }
    // }}}

    // {{{ function insertNode()
    /**
     * Inserts a node into the linked list, based on a reference node that
     * already exists in the list.
     *
     * @param mixed $new_node      New node to add to the list
     * @param mixed $existing_node Reference position node
     * @param bool  $before        Insert new node before or after the existing node
     *
     * @return bool Success or failure
     **/
    public function insertNode($new_node, $existing_node, $before = false)
    {
        $pos = 0;
        $exist_pos = $existing_node->getPosition();
        $this->rewind();

        // Now add the node according to the requested mode
        switch ($before) {

        case true:
            $this->add($exist_pos, $new_node);
            break;

        // after
        case false:
            if ($this->offsetExists($exist_pos + 1)) {
                $this->add($exist_pos + 1, $new_node);
            } else {
                $this->appendNode($new_node);
                return true;
            }
            break;
        }

        // Fix positions
        $this->rewind();
        while ($n = $this->current()) {
            $n->setPosition($pos);
            $this->next();
            $pos++;
        }

        return true;
    }
    // }}}

    // {{{ function appendNode()
    /**
     * Adds a node onto the linked list.
     *
     * @param mixed $new_node New node to add to the list
     *
     * @return void
     **/
    public function appendNode($new_node)
    {
        $pos = $this->count();
        $new_node->setPosition($pos);
        $this->push($new_node);
    }
    // }}}

    // {{{ function prependNode()
    /**
     * Adds a node to the start of the linked list.
     *
     * @param mixed $new_node New node to add to the list
     *
     * @return void
     **/
    public function prependNode($new_node)
    {
        $this->insertNode($new_node, $this->bottom(), true);
    }
    // }}}

    // {{{ function deleteNode()
    /**
     * Deletes a node from the linked list.
     *
     * @param mixed $node Node to delete from the list
     *
     * @return void
     **/
    public function deleteNode($node)
    {
        $target_pos = $node->getPosition();
        $this->rewind();
        $pos = 0;

        // Omit target node and adjust pos of remainder
        $done = false;
        try {
            while ($n = $this->current()) {
                if ($pos == $target_pos && !$done) {
                    $done = true;
                    $this->next();
                    $this->offsetUnset($pos);
                } elseif ($pos >= $target_pos) {
                    $n->setPosition($pos);
                    $pos++;
                    $this->next();
                } else {
                    $pos++;
                    $this->next();
                }
            }
        }
        catch (Exception $e) {
            // no-op - shift() throws an exception, sigh
        }

    }
    // }}}

    // {{{ setPosition()
    /**
     * Sets position of the subfield
     *
     * @param string $pos new position of the subfield
     *
     * @return void
     */
    function setPosition($pos)
    {
        $this->position = $pos;
    }
    // }}}

    // {{{ getPosition()
    /**
     * Return position of the subfield
     *
     * @return int data
     */
    function getPosition()
    {
        return $this->position;
    }
    // }}}

}
// }}}

PK�2[�+����MARC/Field.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */

/**
 * Parser for MARC records
 *
 * This package is based on the PHP MARC package, originally called "php-marc",
 * that is part of the Emilda Project (http://www.emilda.org). Christoffer
 * Landtman generously agreed to make the "php-marc" code available under the
 * GNU LGPL so it could be used as the basis of this PEAR package.
 * 
 * PHP version 5
 *
 * LICENSE: This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category  File_Formats
 * @package   File_MARC
 * @author    Christoffer Landtman <landtman@realnode.com>
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2003-2008 Oy Realnode Ab, Dan Scott
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/File_MARC
 */

require_once 'File/MARC/List.php';

// {{{ class File_MARC_Field extends File_MARC_List
/**
 * The File_MARC_Field class is expected to be extended to reflect the
 * requirements of control and data fields.
 *
 * Every MARC field contains a tag name.
 *
 * @category File_Formats
 * @package  File_MARC
 * @author   Christoffer Landtman <landtman@realnode.com>
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link     http://pear.php.net/package/File_MARC
 */
class File_MARC_Field extends File_MARC_List
{

    // {{{ properties
    /**
     * The tag name of the Field
     * @var string
     */
    protected $tag;
    // }}}

    // {{{ Constructor: function __construct()
    /**
     * File_MARC_Field constructor
     *
     * Create a new {@link File_MARC_Field} object from passed arguments. We
     * define placeholders for the arguments required by child classes.
     *
     * @param string $tag       tag
     * @param string $subfields placeholder for subfields or control data
     * @param string $ind1      placeholder for first indicator
     * @param string $ind2      placeholder for second indicator
     */
    function __construct($tag, $subfields = null, $ind1 = null, $ind2 = null) 
    {
        $this->tag = $tag;

        // Check if valid tag
        if (!preg_match("/^[0-9A-Za-z]{3}$/", $tag)) {
             $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_TAG], array("tag" => $tag));
             throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INVALID_TAG);
        }

    }
    // }}}

    // {{{ Destructor: function __destruct()
    /**
     * Destroys the data field
     */
    function __destruct()
    {
        $this->tag = null;
    }
    // }}}

    // {{{ getTag()
    /**
     * Returns the tag for this {@link File_MARC_Field} object
     *
     * @return string returns the tag number of the field
     */
    function getTag()
    {
        return (string)$this->tag;
    }
    // }}}

    // {{{ setTag()
    /**
     * Sets the tag for this {@link File_MARC_Field} object
     *
     * @param string $tag new value for the tag
     *
     * @return string returns the tag number of the field
     */
    function setTag($tag)
    {
        $this->tag = $tag;
        return $this->getTag();
    }
    // }}}

    // {{{ isEmpty()
    /**
     * Is empty
     *
     * Checks if the field is empty.
     *
     * @return bool Returns true if the field is empty, otherwise false
     */
    function isEmpty()
    {
        if ($this->getTag()) {
            return false;
        }
        // It is empty
        return true;
    }
    // }}}

    // {{{ isControlField()
    /**
     * Is control field
     *
     * Checks if the field is a control field.
     *
     * @return bool Returns true if the field is a control field, otherwise false
     */
    function isControlField()
    {
        if (get_class($this) == 'File_MARC_Control_Field') {
            return true;
        }
        return false;
    }
    // }}}

    // {{{ isDataField()
    /**
     * Is data field
     *
     * Checks if the field is a data field.
     *
     * @return bool Returns true if the field is a data field, otherwise false
     */
    function isDataField()
    {
        if (get_class($this) == 'File_MARC_Data_Field') {
            return true;
        }
        return false;
    }
    // }}}


    /**
     * ========== OUTPUT METHODS ==========
     */

    // {{{ __toString()
    /**
     * Return Field formatted
     *
     * Return Field as a formatted string.
     *
     * @return string Formatted output of Field
     */
    function __toString()
    {
        return (string)$this->getTag();
    }
    // }}}

    // {{{ toRaw()
    /**
     * Return field in raw MARC format (stub)
     *
     * Return the field formatted in raw MARC for saving into MARC files. This
     * stub method is extended by the child classes.
     *
     * @return bool Raw MARC
     */
    function toRaw()
    {
        return false;
    }
    // }}}

    // {{{ formatField()
    /**
     * Pretty print a MARC_Field object without tags, indicators, etc.
     *
     * @param array $exclude Subfields to exclude from formatted output
     * 
     * @return string Returns the formatted field data
     */

    function formatField($exclude = array('2'))
    {
        if ($this->isControlField()) {
            return $this->getData();
        } else {
            $out = '';
            foreach ($this->getSubfields() as $subfield) {
                if (substr($this->getTag(), 0, 1) == '6' and (in_array($subfield->getCode(), array('v','x','y','z')))) {
                    $out .= ' -- ' . $subfield->getData();
                } elseif (!in_array($subfield->getCode(), $exclude)) {
                    $out .= ' ' . $subfield->getData();
                }
            }
            return trim($out);
        }
    }
    // }}}
}
// }}}

PK�2[�IC�(A(AMARC/Lint/CodeData.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */

/**
 * Code Data to support Lint for MARC records
 *
 * This module is adapted from the MARC::Lint::CodeData CPAN module for Perl,
 * maintained by Bryan Baldus <eijabb@cpan.org> and available for download at
 * http://search.cpan.org/~eijabb/
 *
 * Current MARC::Lint::CodeData version used as basis for this module: 1.37
 *
 * PHP version 5
 *
 * LICENSE: This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category  File_Formats
 * @package   File_MARC
 * @author    Demian Katz <demian.katz@villanova.edu>
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2003-2019 Oy Realnode Ab, Dan Scott
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version   CVS: $Id: Record.php 308146 2011-02-08 20:36:20Z dbs $
 * @link      http://pear.php.net/package/File_MARC
 */

// {{{ class File_MARC_Lint
/**
 * Contains codes from the MARC code lists for Geographic Areas, Languages, and
 * Countries.
 *
 * Code data is used for validating fields 008, 040, 041, and 043.
 *
 * Also, sources for subfield 2 in 600-651 and 655.
 *
 * Note: According to the official MARC documentation, Sears is not a valid 655
 * term. The code data below treats it as valid, in anticipation of a change in
 * the official documentation.
 *
 * @category File_Formats
 * @package  File_MARC
 * @author   Demian Katz <demian.katz@villanova.edu>
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link     http://pear.php.net/package/File_MARC
 */
class File_MARC_Lint_CodeData
{

    // {{{ properties
    /**
     * Valid Geographic Area Codes
     * @var array
     */
    public $geogAreaCodes;

    /**
     * Obsolete Geographic Area Codes
     * @var array
     */
    public $obsoleteGeogAreaCodes;

    /**
     * Valid Language Codes
     * @var array
     */
    public $languageCodes;

    /**
     * Obsolete Language Codes
     * @var array
     */
    public $obsoleteLanguageCodes;

    /**
     * Valid Country Codes
     * @var array
     */
    public $countryCodes;

    /**
     * Obsolete Country Codes
     * @var array
     */
    public $obsoleteCountryCodes;

    /**
     * Valid sources for fields 600-651
     * @var array
     */
    public $sources600_651;

    /**
     * Obsolete sources for fields 600-651
     * @var array
     */
    public $obsoleteSources600_651;

    /**
     * Valid sources for field 655
     * @var array
     */
    public $sources655;

    /**
     * Obsolete sources for field 655
     * @var array
     */
    public $obsoleteSources655;

    // }}}

    // {{{ Constructor: function __construct()
    /**
     * Start function
     *
     * Initialize code arrays.
     *
     * @return true 
     */
    public function __construct()
    {
        // @codingStandardsIgnoreStart
        // fill the valid Geographic Area Codes array
        $this->geogAreaCodes = explode("\t", "a------	a-af---	a-ai---	a-aj---	a-ba---	a-bg---	a-bn---	a-br---	a-bt---	a-bx---	a-cb---	a-cc---	a-cc-an	a-cc-ch	a-cc-cq	a-cc-fu	a-cc-ha	a-cc-he	a-cc-hh	a-cc-hk	a-cc-ho	a-cc-hp	a-cc-hu	a-cc-im	a-cc-ka	a-cc-kc	a-cc-ki	a-cc-kn	a-cc-kr	a-cc-ku	a-cc-kw	a-cc-lp	a-cc-mh	a-cc-nn	a-cc-pe	a-cc-sh	a-cc-sm	a-cc-sp	a-cc-ss	a-cc-su	a-cc-sz	a-cc-ti	a-cc-tn	a-cc-ts	a-cc-yu	a-ccg--	a-cck--	a-ccp--	a-ccs--	a-ccy--	a-ce---	a-ch---	a-cy---	a-em---	a-gs---	a-ii---	a-io---	a-iq---	a-ir---	a-is---	a-ja---	a-jo---	a-kg---	a-kn---	a-ko---	a-kr---	a-ku---	a-kz---	a-le---	a-ls---	a-mk---	a-mp---	a-my---	a-np---	a-nw---	a-ph---	a-pk---	a-pp---	a-qa---	a-si---	a-su---	a-sy---	a-ta---	a-th---	a-tk---	a-ts---	a-tu---	a-uz---	a-vt---	a-ye---	aa-----	ab-----	ac-----	ae-----	af-----	ag-----	ah-----	ai-----	ak-----	am-----	an-----	ao-----	aopf---	aoxp---	ap-----	ar-----	as-----	at-----	au-----	aw-----	awba---	awgz---	ay-----	az-----	b------	c------	cc-----	cl-----	d------	dd-----	e------	e-aa---	e-an---	e-au---	e-be---	e-bn---	e-bu---	e-bw---	e-ci---	e-cs---	e-dk---	e-er---	e-fi---	e-fr---	e-ge---	e-gi---	e-gr---	e-gw---	e-gx---	e-hu---	e-ic---	e-ie---	e-it---	e-kv---	e-lh---	e-li---	e-lu---	e-lv---	e-mc---	e-mm---	e-mo---	e-mv---	e-ne---	e-no---	e-pl---	e-po---	e-rb---	e-rm---	e-ru---	e-sm---	e-sp---	e-sw---	e-sz---	e-uk---	e-uk-en	e-uk-ni	e-uk-st	e-uk-ui	e-uk-wl	e-un---	e-ur---	e-urc--	e-ure--	e-urf--	e-urk--	e-urn--	e-urp--	e-urr--	e-urs--	e-uru--	e-urw--	e-vc---	e-xn---	e-xo---	e-xr---	e-xv---	e-yu---	ea-----	eb-----	ec-----	ed-----	ee-----	el-----	en-----	eo-----	ep-----	er-----	es-----	ev-----	ew-----	f------	f-ae---	f-ao---	f-bd---	f-bs---	f-cd---	f-cf---	f-cg---	f-cm---	f-cx---	f-dm---	f-ea---	f-eg---	f-et---	f-ft---	f-gh---	f-gm---	f-go---	f-gv---	f-iv---	f-ke---	f-lb---	f-lo---	f-ly---	f-mg---	f-ml---	f-mr---	f-mu---	f-mw---	f-mz---	f-ng---	f-nr---	f-pg---	f-rh---	f-rw---	f-sa---	f-sd---	f-sf---	f-sg---	f-sh---	f-sj---	f-sl---	f-so---	f-sq---	f-ss---	f-sx---	f-tg---	f-ti---	f-tz---	f-ua---	f-ug---	f-uv---	f-za---	fa-----	fb-----	fc-----	fd-----	fe-----	ff-----	fg-----	fh-----	fi-----	fl-----	fn-----	fq-----	fr-----	fs-----	fu-----	fv-----	fw-----	fz-----	h------	i------	i-bi---	i-cq---	i-fs---	i-hm---	i-mf---	i-my---	i-re---	i-se---	i-xa---	i-xb---	i-xc---	i-xo---	l------	ln-----	lnaz---	lnbm---	lnca---	lncv---	lnfa---	lnjn---	lnma---	lnsb---	ls-----	lsai---	lsbv---	lsfk---	lstd---	lsxj---	lsxs---	m------	ma-----	mb-----	me-----	mm-----	mr-----	n------	n-cn---	n-cn-ab	n-cn-bc	n-cn-mb	n-cn-nf	n-cn-nk	n-cn-ns	n-cn-nt	n-cn-nu	n-cn-on	n-cn-pi	n-cn-qu	n-cn-sn	n-cn-yk	n-cnh--	n-cnm--	n-cnp--	n-gl---	n-mx---	n-us---	n-us-ak	n-us-al	n-us-ar	n-us-az	n-us-ca	n-us-co	n-us-ct	n-us-dc	n-us-de	n-us-fl	n-us-ga	n-us-hi	n-us-ia	n-us-id	n-us-il	n-us-in	n-us-ks	n-us-ky	n-us-la	n-us-ma	n-us-md	n-us-me	n-us-mi	n-us-mn	n-us-mo	n-us-ms	n-us-mt	n-us-nb	n-us-nc	n-us-nd	n-us-nh	n-us-nj	n-us-nm	n-us-nv	n-us-ny	n-us-oh	n-us-ok	n-us-or	n-us-pa	n-us-ri	n-us-sc	n-us-sd	n-us-tn	n-us-tx	n-us-ut	n-us-va	n-us-vt	n-us-wa	n-us-wi	n-us-wv	n-us-wy	n-usa--	n-usc--	n-use--	n-usl--	n-usm--	n-usn--	n-uso--	n-usp--	n-usr--	n-uss--	n-ust--	n-usu--	n-xl---	nc-----	ncbh---	nccr---	nccz---	nces---	ncgt---	ncho---	ncnq---	ncpn---	nl-----	nm-----	np-----	nr-----	nw-----	nwaq---	nwaw---	nwbb---	nwbf---	nwbn---	nwcj---	nwco---	nwcu---	nwdq---	nwdr---	nweu---	nwgd---	nwgp---	nwhi---	nwht---	nwjm---	nwla---	nwli---	nwmj---	nwmq---	nwna---	nwpr---	nwsc---	nwsd---	nwsn---	nwst---	nwsv---	nwtc---	nwtr---	nwuc---	nwvb---	nwvi---	nwwi---	nwxa---	nwxi---	nwxk---	nwxm---	p------	pn-----	po-----	poas---	pobp---	poci---	pocw---	poea---	pofj---	pofp---	pogg---	pogu---	poji---	pokb---	poki---	poln---	pome---	pomi---	ponl---	ponn---	ponu---	popc---	popl---	pops---	posh---	potl---	poto---	pott---	potv---	poup---	powf---	powk---	pows---	poxd---	poxe---	poxf---	poxh---	ps-----	q------	r------	s------	s-ag---	s-bl---	s-bo---	s-ck---	s-cl---	s-ec---	s-fg---	s-gy---	s-pe---	s-py---	s-sr---	s-uy---	s-ve---	sa-----	sn-----	sp-----	t------	u------	u-ac---	u-at---	u-at-ac	u-at-ne	u-at-no	u-at-qn	u-at-sa	u-at-tm	u-at-vi	u-at-we	u-atc--	u-ate--	u-atn--	u-cs---	u-nz---	w------	x------	xa-----	xb-----	xc-----	xd-----	zd-----	zju----	zma----	zme----	zmo----	zne----	zo-----	zpl----	zs-----	zsa----	zsu----	zur----	zve----");
        
        // fill the obsolete Geographic Area Codes array
        $this->obsoleteGeogAreaCodes = explode("\t", "t-ay---	e-ur-ai	e-ur-aj	nwbc---	e-ur-bw	f-by---	pocp---	e-url--	cr-----	v------	e-ur-er	et-----	e-ur-gs	pogn---	nwga---	nwgs---	a-hk---	ei-----	f-if---	awiy---	awiw---	awiu---	e-ur-kz	e-ur-kg	e-ur-lv	e-ur-li	a-mh---	cm-----	e-ur-mv	n-usw--	a-ok---	a-pt---	e-ur-ru	pory---	nwsb---	posc---	a-sk---	posn---	e-uro--	e-ur-ta	e-ur-tk	e-ur-un	e-ur-uz	a-vn---	a-vs---	nwvr---	e-urv--	a-ys---");
        
        // fill the valid Language Codes array
        $this->languageCodes = explode("\t", "   	aar	abk	ace	ach	ada	ady	afa	afh	afr	ain	aka	akk	alb	ale	alg	alt	amh	ang	anp	apa	ara	arc	arg	arm	arn	arp	art	arw	asm	ast	ath	aus	ava	ave	awa	aym	aze	bad	bai	bak	bal	bam	ban	baq	bas	bat	bej	bel	bem	ben	ber	bho	bih	bik	bin	bis	bla	bnt	bos	bra	bre	btk	bua	bug	bul	bur	byn	cad	cai	car	cat	cau	ceb	cel	cha	chb	che	chg	chi	chk	chm	chn	cho	chp	chr	chu	chv	chy	cmc	cop	cor	cos	cpe	cpf	cpp	cre	crh	crp	csb	cus	cze	dak	dan	dar	day	del	den	dgr	din	div	doi	dra	dsb	dua	dum	dut	dyu	dzo	efi	egy	eka	elx	eng	enm	epo	est	ewe	ewo	fan	fao	fat	fij	fil	fin	fiu	fon	fre	frm	fro	frr	frs	fry	ful	fur	gaa	gay	gba	gem	geo	ger	gez	gil	gla	gle	glg	glv	gmh	goh	gon	gor	got	grb	grc	gre	grn	gsw	guj	gwi	hai	hat	hau	haw	heb	her	hil	him	hin	hit	hmn	hmo	hrv	hsb	hun	hup	iba	ibo	ice	ido	iii	ijo	iku	ile	ilo	ina	inc	ind	ine	inh	ipk	ira	iro	ita	jav	jbo	jpn	jpr	jrb	kaa	kab	kac	kal	kam	kan	kar	kas	kau	kaw	kaz	kbd	kha	khi	khm	kho	kik	kin	kir	kmb	kok	kom	kon	kor	kos	kpe	krc	krl	kro	kru	kua	kum	kur	kut	lad	lah	lam	lao	lat	lav	lez	lim	lin	lit	lol	loz	ltz	lua	lub	lug	lui	lun	luo	lus	mac	mad	mag	mah	mai	mak	mal	man	mao	map	mar	mas	may	mdf	mdr	men	mga	mic	min	mis	mkh	mlg	mlt	mnc	mni	mno	moh	mon	mos	mul	mun	mus	mwl	mwr	myn	myv	nah	nai	nap	nau	nav	nbl	nde	ndo	nds	nep	new	nia	nic	niu	nno	nob	nog	non	nor	nqo	nso	nub	nwc	nya	nym	nyn	nyo	nzi	oci	oji	ori	orm	osa	oss	ota	oto	paa	pag	pal	pam	pan	pap	pau	peo	per	phi	phn	pli	pol	pon	por	pra	pro	pus	que	raj	rap	rar	roa	roh	rom	rum	run	rup	rus	sad	sag	sah	sai	sal	sam	san	sas	sat	scn	sco	sel	sem	sga	sgn	shn	sid	sin	sio	sit	sla	slo	slv	sma	sme	smi	smj	smn	smo	sms	sna	snd	snk	sog	som	son	sot	spa	srd	srn	srp	srr	ssa	ssw	suk	sun	sus	sux	swa	swe	syc	syr	tah	tai	tam	tat	tel	tem	ter	tet	tgk	tgl	tha	tib	tig	tir	tiv	tkl	tlh	tli	tmh	tog	ton	tpi	tsi	tsn	tso	tuk	tum	tup	tur	tut	tvl	twi	tyv	udm	uga	uig	ukr	umb	und	urd	uzb	vai	ven	vie	vol	vot	wak	wal	war	was	wel	wen	wln	wol	xal	xho	yao	yap	yid	yor	ypk	zap	zbl	zen	zha	znd	zul	zun	zxx	zza");
        
        // fill the obsolete Language Codes array
        $this->obsoleteLanguageCodes = explode("\t", "ajm	esk	esp	eth	far	fri	gag	gua	int	iri	cam	kus	mla	max	mol	lan	gal	lap	sao	gae	scc	scr	sho	snh	sso	swz	tag	taj	tar	tru	tsw");
        
        // fill the valid Country Codes array
        $this->countryCodes = explode("\t", "aa 	abc	aca	ae 	af 	ag 	ai 	aj 	aku	alu	am 	an 	ao 	aq 	aru	as 	at 	au 	aw 	ay 	azu	ba 	bb 	bcc	bd 	be 	bf 	bg 	bh 	bi 	bl 	bm 	bn 	bo 	bp 	br 	bs 	bt 	bu 	bv 	bw 	bx 	ca 	cau	cb 	cc 	cd 	ce 	cf 	cg 	ch 	ci 	cj 	ck 	cl 	cm 	co 	cou	cq 	cr 	ctu	cu 	cv 	cw 	cx 	cy 	dcu	deu	dk 	dm 	dq 	dr 	ea 	ec 	eg 	em 	enk	er 	es 	et 	fa 	fg 	fi 	fj 	fk 	flu	fm 	fp 	fr 	fs 	ft 	gau	gb 	gd 	gh 	gi 	gl 	gm 	go 	gp 	gr 	gs 	gt 	gu 	gv 	gw 	gy 	gz 	hiu	hm 	ho 	ht 	hu 	iau	ic 	idu	ie 	ii 	ilu	inu	io 	iq 	ir 	is 	it 	iv 	iy 	ja 	ji 	jm 	jo 	ke 	kg 	kn 	ko 	ksu	ku 	kv 	kyu	kz 	lau	lb 	le 	lh 	li 	lo 	ls 	lu 	lv 	ly 	mau	mbc	mc 	mdu	meu	mf 	mg 	miu	mj 	mk 	ml 	mm 	mnu	mo 	mou	mp 	mq 	mr 	msu	mtu	mu 	mv 	mw 	mx 	my 	mz 	na 	nbu	ncu	ndu	ne 	nfc	ng 	nhu	nik	nju	nkc	nl 	nmu	nn 	no 	np 	nq 	nr 	nsc	ntc	nu 	nuc	nvu	nw 	nx 	nyu	nz 	ohu	oku	onc	oru	ot 	pau	pc 	pe 	pf 	pg 	ph 	pic	pk 	pl 	pn 	po 	pp 	pr 	pw 	py 	qa 	qea	quc	rb 	re 	rh 	riu	rm 	ru 	rw 	sa 	sc 	scu	sd 	sdu	se 	sf 	sg 	sh 	si 	sj 	sl 	sm 	sn 	snc	so 	sp 	sq 	sr 	ss 	st 	stk	su 	sw 	sx 	sy 	sz 	ta 	tc 	tg 	th 	ti 	tk 	tl 	tma	tnu	to 	tr 	ts 	tu 	tv 	txu	tz 	ua 	uc 	ug 	uik	un 	up 	utu	uv 	uy 	uz 	vau	vb 	vc 	ve 	vi 	vm 	vp 	vra	vtu	wau	wea	wf 	wiu	wj 	wk 	wlk	ws 	wvu	wyu	xa 	xb 	xc 	xd 	xe 	xf 	xga	xh 	xj 	xk 	xl 	xm 	xn 	xna	xo 	xoa	xp 	xr 	xra	xs 	xv 	xx 	xxc	xxk	xxu	ye 	ykc	za ");
        
        // fill the obsolete Country Codes array
        $this->obsoleteCountryCodes = explode("\t", "ai 	air	ac 	ajr	bwr	cn 	cz 	cp 	ln 	cs 	err	gsr	ge 	gn 	hk 	iw 	iu 	jn 	kzr	kgr	lvr	lir	mh 	mvr	nm 	pt 	rur	ry 	xi 	sk 	xxr	sb 	sv 	tar	tt 	tkr	unr	uk 	ui 	us 	uzr	vn 	vs 	wb 	ys 	yu ");
        
        // the codes cash, lcsh, lcshac, mesh, nal, and rvm are covered by 2nd
        // indicators in 600-655
        // they are only used when indicators are not available
        $this->sources600_651 = explode("\t", "aass	aat	abne	aedoml	afo	afset	agrifors	agrovoc	agrovocf	agrovocs	aiatsisl	aiatsisp	aiatsiss	aktp	albt	allars	apaist	armac	asft	ashlnl	asrcrfcd	asrcseo	asrctoa	asth	ated	atg	atla	aucsh	bare	barn	bhb	bella	bet	bhammf	bhashe	bib1814	bibalex	biccbmc	bicssc	bidex	bisacsh	bisacmt	bisacrt	bjornson	blcpss	blmlsh	blnpn	bokbas	bt	btr	cabt	cash	cbk	cck	ccsa	cct	ccte	cctf	cdcng	ceeus	chirosh	cht	ciesiniv	cilla	collett	conorsi	csahssa	csalsct	csapa	csh	csht	cstud	czenas	czmesh	dacs	dbn	dcs	ddcri	ddcrit	ddcut	dissao	dit	dltlt	dltt	drama	dtict	ebfem	eclas	eet	eflch	eks	embiaecid	embne	emnmus	ept	erfemn	ericd	est	eum	eurovocen	eurovocfr	eurovocsl	fast	fes	finmesh	fire	fmesh	fnhl	francis	fssh	galestne	gccst	gcipmedia	gcipplatform	gem	gemet	georeft	gnd	gnis	gst	gtt	hamsun	hapi	hkcan	helecon	henn	hlasstg	hoidokki	hrvmesh	huc	humord	iaat	ibsen	ica	icpsr	idas	idsbb	idszbz	idszbzes	idszbzna	idszbzzg	idszbzzh	idszbzzk	iescs	iest	ilot	ilpt	inist	inspect	ipat	ipsp	isis	itglit	itoamc	itrt	jhpb	jhpk	jlabsh	juho	jupo	jurivoc	kaa	kaba	kao	kassu	kauno	kaunokki	kdm	khib	kito	kitu	kkts	koko	kssbar	kta	kto	ktpt	ktta	kubikat	kula	kulo	kupu	lacnaf	lapponica	larpcal	lcac	lcdgt	lcmpt	lcsh	lcshac	lcstt	lctgm	lemac	lemb	liito	liv	lnmmbr	local	ltcsh	lua	maaq	maotao	mar	masa	mech	mero	mesh	mipfesd	mmm	mpirdes	msc	msh	mtirdes	musa	muso	muzeukc	muzeukn	muzvukci	naf	nal	nalnaf	nasat	nbdbt	nbiemnfag	ncjt	ndlsh	netc	ndllsh	nicem	nimacsc	nlgaf	nlgkk	nlgsh	nlmnaf	no-ubo-mr	noraf	noram	norbok	normesh	noubomn	noubojur	nsbncf	nskps	ntcpsc	ntcsd	ntids	ntissc	nzggn	nznb	odlt	ogst	onet	opms	ordnok	pascal	pepp	peri	pha	pkk	pleiades	pmbok	pmcsg	pmont	pmt	poliscit	popinte	precis	prvt	psychit	puho	quiding	qlsp	qrma	qrmak	qtglit	raam	ram	rasuqam	renib	reo	rero	rerovoc	rma	rpe	rswk	rswkaf	rugeo	rurkp	rvm	rvmgd	samisk	sanb	sao	sbiao	sbt	scbi	scgdst	scisshl	scot	sears	sfit	sgc	sgce	shbe	she	shsples	sigle	sipri	sk	skon	slem	smda	snt	socio	solstad	sosa	spines	ssg	sthus	stw	swd	swemesh	taika	tasmas	taxhs	tbit	tbjvp	tekord	tero	tesa	tesbhaecid	test	tgn	tha	thema	thesoz	thia	tho	thub	tips	tisa	tlka	tlsh	toit	trfarn	trfbmb	trfgr	trfoba	trfzb	trt	trtsa	tsht	tsr	ttka	ttll	tucua	udc	ukslc	ulan	umitrist	unbisn	unbist	unescot	usaidt	valo	vcaadu	vffyl	vmj	waqaf	watrest	wgst	wot	wpicsh	ysa	yso");
        $this->obsoleteSources600_651 = explode("\t", "cash	lcsh	lcshac	mesh	nal	nobomn	noubojor	reroa	rvm");
        $this->sources655 = explode("\t", "aat	afset	aiatsisl	aiatsisp	aiatsiss	aktp	alett	amg	asrcrfcd	asrcseo	asrctoa	asth	aucsh	barn	barngf	bib1814	bibalex	biccbmc	bidex	bgtchm	bisacsh	bisacmt	bisacrt	bjornson	bt	cash	chirosh	cct	cdcng	cjh	collett	conorsi	csht	czenas	dacs	dcs	dct	ddcut	eet	eflch	embne	emnmus	ept	erfemn	ericd	estc	eurovocen	eurovocsl	fast	fbg	fgtpcm	finmesh	fire	ftamc	galestne	gatbeg	gem	gmd	gmgpc	gnd	gsafd	gst	gtlm	hamsun	hapi	hkcan	hoidokki	ica	ilot	isbdcontent	isbdmedia	itglit	itrt	jhpb	jhpk	kkts	lacnaf	lcgft	lcmpt	lcsh	lcshac	lcstt	lctgm	lemac	lobt	local	maaq	mar	marccategory	marcform	marcgt	marcsmd	mech	mesh	migfg	mim	msh	muzeukc	muzeukn	muzeukv	muzvukci	nal	nalnaf	nbdbgf	nbiemnfag	ndlsh	netc	ngl	nimafc	nlgaf	nlgkk	nlgsh	nlmnaf	nmc	no-ubo-mr	noraf	noram	nsbncf	ntids	nzcoh	nzggn	nznb	onet	opms	ordnok	pkk	pmcsg	pmt	proysen	quiding	qlsp	qrmak	qtglit	raam	radfg	rasuqam	rbbin	rbgenr	rbmscv	rbpap	rbpri	rbprov	rbpub	rbtyp	rdabf	rdabs	rdacarrier	rdaco	rdacontent	rdacpc	rdact	rdafnm	rdafs	rdaft	rdagen	rdagrp	rdagw	rdalay	rdamat	rdamedia	rdamt	rdapf	rdapm	rdapo	rdarm	rdarr	rdaspc	rdatc	rdatr	rdavf	reo	rerovoc	reveal	rma	rswk	rswkaf	rugeo	rvm	rvmgf	sao	saogf	scbi	sears	sgc	sgce	sgp	sipri	skon	snt	socio	spines	ssg	stw	swd	swemesh	tbit	thema	tesa	tgfbne	thesoz	tho	thub	toit	tsht	tucua	ukslc	ulan	vgmsgg	vgmsng	vmj	waqaf");
        $this->obsoleteSources655 = explode("\t", "cash	ftamc	lcsh	lcshac	marccarrier	marccontent	marcmedia	mesh	nal	reroa	rvm");
        // @codingStandardsIgnoreEnd
    }
    // }}}
}
// }}}
PK�2[R��A;A;MARC/Data_Field.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */

/**
 * Parser for MARC records
 *
 * This package is based on the PHP MARC package, originally called "php-marc",
 * that is part of the Emilda Project (http://www.emilda.org). Christoffer
 * Landtman generously agreed to make the "php-marc" code available under the
 * GNU LGPL so it could be used as the basis of this PEAR package.
 *
 * PHP version 5
 *
 * LICENSE: This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category  File_Formats
 * @package   File_MARC
 * @author    Christoffer Landtman <landtman@realnode.com>
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2003-2008 Oy Realnode Ab, Dan Scott
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/File_MARC
 */

// {{{ class File_MARC_Data_Field extends File_MARC_Field
/**
 * The File_MARC_Data_Field class represents a single field in a MARC record.
 *
 * A MARC data field consists of a tag name, two indicators which may be null,
 * and zero or more subfields represented by {@link File_MARC_Subfield} objects.
 * Subfields are held within a linked list structure.
 *
 * @category File_Formats
 * @package  File_MARC
 * @author   Christoffer Landtman <landtman@realnode.com>
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link     http://pear.php.net/package/File_MARC
 */
class File_MARC_Data_Field extends File_MARC_Field
{

    // {{{ properties
    /**
     * Value of the first indicator
     * @var string
     */
    protected $ind1;

    /**
     * Value of the second indicator
     * @var string
     */
    protected $ind2;

    /**
     * Linked list of subfields
     * @var File_MARC_List
     */
    protected $subfields;

    // }}}

    // {{{ Constructor: function __construct()
    /**
     * {@link File_MARC_Data_Field} constructor
     *
     * Create a new {@link File_MARC_Data_Field} object. The only required
     * parameter is a tag. This enables programs to build up new fields
     * programmatically.
     *
     * <code>
     * // Example: Create a new data field
     *
     * // We can optionally create an array of subfields first
     * $subfields[] = new File_MARC_Subfield('a', 'Scott, Daniel.');
     *
     * // Create the new 100 field complete with a _a subfield and an indicator
     * $new_field = new File_MARC_Data_Field('100', $subfields, 0, null);
     * </code>
     *
     * @param string $tag       tag
     * @param array  $subfields array of {@link File_MARC_Subfield} objects
     * @param string $ind1      first indicator
     * @param string $ind2      second indicator
     */
    function __construct($tag, array $subfields = null, $ind1 = null, $ind2 = null)
    {
        $this->subfields = new File_MARC_List();

        parent::__construct($tag);

        $this->ind1 = $this->_validateIndicator($ind1);
        $this->ind2 = $this->_validateIndicator($ind2);

        // we'll let users add subfields after if they so desire
        if ($subfields) {
            $this->addSubfields($subfields);
        }
    }
    // }}}

    // {{{ Destructor: function __destruct()
    /**
     * Destroys the data field
     */
    function __destruct()
    {
        $this->subfields = null;
        $this->ind1 = null;
        $this->ind2 = null;
        parent::__destruct();
    }
    // }}}

    // {{{ Explicit destructor: function delete()
    /**
     * Destroys the data field
     *
     * @return true
     */
    function delete()
    {
        $this->__destruct();
    }
    // }}}

    // {{{ protected function _validateIndicator()
    /**
     * Validates an indicator field
     *
     * Validates the value passed in for an indicator. This routine ensures
     * that an indicator is a single character. If the indicator value is null,
     * then this method returns a single character.
     *
     * If the indicator value contains more than a single character, this
     * throws an exception.
     *
     * @param string $indicator Value of the indicator to be validated
     *
     * @return string Returns the indicator, or space if the indicator was null
     */
    private function _validateIndicator($indicator)
    {
        if ($indicator == null) {
            $indicator = ' ';
        } elseif (strlen($indicator) > 1) {
            $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_INDICATOR], array("tag" => $this->getTag(), "indicator" => $indicator));
            throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INVALID_INDICATOR);
        }
        return $indicator;
    }
    // }}}

    // {{{ appendSubfield()
    /**
     * Appends subfield to subfield list
     *
     * Adds a File_MARC_Subfield object to the end of the existing list
     * of subfields.
     *
     * @param File_MARC_Subfield $new_subfield The subfield to add
     *
     * @return File_MARC_Subfield the new File_MARC_Subfield object
     */
    function appendSubfield(File_MARC_Subfield $new_subfield)
    {
        /* Append as the last subfield in the field */
        $this->subfields->appendNode($new_subfield);
    }
    // }}}

    // {{{ prependSubfield()
    /**
     * Prepends subfield to subfield list
     *
     * Adds a File_MARC_Subfield object to the  start of the existing list
     * of subfields.
     *
     * @param File_MARC_Subfield $new_subfield The subfield to add
     *
     * @return File_MARC_Subfield the new File_MARC_Subfield object
     */
    function prependSubfield(File_MARC_Subfield $new_subfield)
    {
        $this->subfields->unshift($new_subfield);
        return $new_subfield;
    }
    // }}}

    // {{{ insertSubfield()
    /**
     * Inserts a field in the MARC record relative to an existing field
     *
     * Inserts a {@link File_MARC_Subfield} object before or after an existing
     * subfield.
     *
     * @param File_MARC_Subfield $new_field      The subfield to add
     * @param File_MARC_Subfield $existing_field The target subfield
     * @param bool               $before         Insert the subfield before the existing subfield if true; after the existing subfield if false
     *
     * @return File_MARC_Subfield                The new subfield
     */
    function insertSubfield(File_MARC_Subfield $new_field, File_MARC_Subfield $existing_field, $before = false)
    {
        $this->subfields->insertNode($new_field, $existing_field, $before);
        return $new_field;
    }
    // }}}

    // {{{ addSubfields()
    /**
     * Adds an array of subfields to a {@link File_MARC_Data_Field} object
     *
     * Appends subfields to existing subfields in the order in which
     * they appear in the array. For finer grained control of the subfield
     * order, use {@link appendSubfield()}, {@link prependSubfield()},
     * or {@link insertSubfield()} to add each subfield individually.
     *
     * @param array $subfields array of {@link File_MARC_Subfield} objects
     *
     * @return int returns the number of subfields that were added
     */
    function addSubfields(array $subfields)
    {
        /*
         * Just in case someone passes in a single File_MARC_Subfield
         * instead of an array
         */
        if ($subfields instanceof File_MARC_Subfield) {
            $this->appendSubfield($subfields);
            return 1;
        }

        // Add subfields
        $cnt = 0;
        foreach ($subfields as $subfield) {
            $this->appendSubfield($subfield);
            $cnt++;
        }

        return $cnt;
    }
    // }}}

    // {{{ deleteSubfield()
    /**
     * Delete a subfield from the field.
     *
     * @param File_MARC_Subfield $subfield The subfield to delete
     *
     * @return void
     */
    function deleteSubfield(File_MARC_Subfield $subfield)
    {
        $this->subfields->deleteNode($subfield);
    }
    // }}}

    // {{{ getIndicator()
    /**
     * Get the value of an indicator
     *
     * @param int $ind number of the indicator (1 or 2)
     *
     * @return string returns indicator value if it exists, otherwise false
     */
    function getIndicator($ind)
    {
        if ($ind == 1) {
            return (string)$this->ind1;
        } elseif ($ind == 2) {
            return (string)$this->ind2;
        } else {
             $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_INDICATOR_REQUEST], array("indicator" => $indicator));
             throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INVALID_INDICATOR_REQUEST);
        }
        return false;
    }
    // }}}

    // {{{ setIndicator()
    /**
     * Set the value of an indicator
     *
     * @param int    $ind   number of the indicator (1 or 2)
     * @param string $value value of the indicator
     *
     * @return string       returns indicator value if it exists, otherwise false
     */
    function setIndicator($ind, $value)
    {
        switch ($ind) {

        case 1:
            $this->ind1 = $this->_validateIndicator($value);
            break;

        case 2:
            $this->ind2 = $this->_validateIndicator($value);
            break;

        default:
            $errorMessage = File_MARC_Exception::formatError(File_MARC_Exception::$messages[File_MARC_Exception::ERROR_INVALID_INDICATOR_REQUEST], array("indicator" => $ind));
            throw new File_MARC_Exception($errorMessage, File_MARC_Exception::ERROR_INVALID_INDICATOR_REQUEST);
            return false;
        }

        return $this->getIndicator($ind);
    }
    // }}}

    // {{{ getSubfield()
    /**
     * Returns the first subfield that matches a requested code.
     *
     * @param string $code subfield code for which the
     * {@link File_MARC_Subfield} is retrieved
     * @param bool   $pcre if true, then match as a regular expression
     *
     * @return File_MARC_Subfield returns the first subfield that matches
     * $code, or false if no codes match $code
     */
    function getSubfield($code = null, $pcre = null)
    {
        // iterate merrily through the subfields looking for the requested code
        foreach ($this->subfields as $sf) {
            if (($pcre
                && preg_match("/$code/", $sf->getCode()))
                || (!$pcre
                && $code == $sf->getCode())
            ) {
                return $sf;
            }
        }

        // No matches were found
        return false;
    }
    // }}}

    // {{{ getSubfields()
    /**
     * Returns an array of subfields that match a requested code,
     * or a {@link File_MARC_List} that contains all of the subfields
     * if the requested code is null.
     *
     * @param string $code subfield code for which the
     * {@link File_MARC_Subfield} is retrieved
     * @param bool   $pcre if true, then match as a regular expression
     *
     * @return File_MARC_List|array returns a linked list of all subfields
     * if $code is null, an array of {@link File_MARC_Subfield} objects if
     * one or more subfields match, or an empty array if no codes match $code
     */
    function getSubfields($code = null, $pcre = null)
    {
        $results = array();

        // return all subfields if no specific subfields were requested
        if ($code === null) {
            $results = $this->subfields;
            return $results;
        }

        // iterate merrily through the subfields looking for the requested code
        foreach ($this->subfields as $sf) {
            if (($pcre
                && preg_match("/$code/", $sf->getCode()))
                || (!$pcre
                && $code == $sf->getCode())
            ) {
                $results[] = $sf;
            }
        }
        return $results;
    }
    // }}}

    // {{{ isEmpty()
    /**
     * Checks if the field is empty.
     *
     * Checks if the field is empty. If the field has at least one subfield
     * with data, it is not empty.
     *
     * @return bool Returns true if the field is empty, otherwise false
     */
    function isEmpty()
    {
        // If $this->subfields is null, we must have deleted it
        if (!$this->subfields) {
            return true;
        }

        // Iterate through the subfields looking for some data
        foreach ($this->subfields as $subfield) {
            // Check if subfield has data
            if (!$subfield->isEmpty()) {
                return false;
            }
        }
        // It is empty
        return true;
    }
    // }}}

    /**
     * ========== OUTPUT METHODS ==========
     */

    // {{{ __toString()
    /**
     * Return Field formatted
     *
     * Return Field as a formatted string.
     *
     * @return string Formatted output of Field
     */
    function __toString()
    {
        // Variables
        $lines = array();
        // Process tag and indicators
        $pre = sprintf("%3s %1s%1s", $this->tag, $this->ind1, $this->ind2);

        // Process subfields
        foreach ($this->subfields as $subfield) {
            $lines[] = sprintf("%6s _%1s%s", $pre, $subfield->getCode(), $subfield->getData());
            $pre = "";
        }

        return join("\n", $lines);
    }
    // }}}

    // {{{ toRaw()
    /**
     * Return Field in Raw MARC
     *
     * Return the Field formatted in Raw MARC for saving into MARC files
     *
     * @return string Raw MARC
     */
    function toRaw()
    {
        $subfields = array();
        foreach ($this->subfields as $subfield) {
            if (!$subfield->isEmpty()) {
                $subfields[] = $subfield->toRaw();
            }
        }
        return (string)$this->ind1.$this->ind2.implode("", $subfields).File_MARC::END_OF_FIELD;
    }
    // }}}

    // {{{ getContents()
    /**
     * Return fields data content as joined string
     *
     * Return all the fields data content as a joined string
     *
     * @param  string $joinChar A string used to join the data conntent.
     * Default is an empty string
     *
     * @return string Joined string
     */
    function getContents($joinChar = '')
    {
        $contents = array();
        foreach($this->subfields as $subfield) {
            $contents[] = $subfield->getData();
        }
        return implode($joinChar, $contents);
    }
    // }}}
}
// }}}

PK�2[lz�`MARC/Control_Field.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */

/**
 * Parser for MARC records
 *
 * This package is based on the PHP MARC package, originally called "php-marc",
 * that is part of the Emilda Project (http://www.emilda.org). Christoffer
 * Landtman generously agreed to make the "php-marc" code available under the
 * GNU LGPL so it could be used as the basis of this PEAR package.
 * 
 * PHP version 5
 *
 * LICENSE: This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category  File_Formats
 * @package   File_MARC
 * @author    Christoffer Landtman <landtman@realnode.com>
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2003-2008 Oy Realnode Ab, Dan Scott
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/File_MARC
 */

// {{{ class File_MARC_Control_Field extends File_MARC_Field
/**
 * The File_MARC_Control_Field class represents a single control field
 * in a MARC record.
 *
 * A MARC control field consists of a tag name and control data.
 *
 * @category File_Formats
 * @package  File_MARC
 * @author   Christoffer Landtman <landtman@realnode.com>
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link     http://pear.php.net/package/File_MARC
 */
class File_MARC_Control_Field extends File_MARC_Field
{

    // {{{ Properties
    /**
     * Value of field, if field is a Control field
     * @var string
     */
    protected $data;
    // }}}

    // {{{ Constructor: function __construct()
    /**
     * Field init function
     *
     * Create a new {@link File_MARC_Control_Field} object from passed arguments
     *
     * @param string $tag  tag
     * @param string $data control field data
     * @param string $ind1 placeholder for class strictness
     * @param string $ind2 placeholder for class strictness
     */
    function __construct($tag, $data, $ind1 = null, $ind2 = null) 
    {
        $this->data = $data;
        parent::__construct($tag);

    }
    // }}}

    // {{{ Destructor: function __destruct()
    /**
     * Destroys the control field
     */
    function __destruct()
    {
        $this->data = null;
        parent::__destruct();
    }
    // }}}

    // {{{ Explicit destructor: function delete()
    /**
     * Destroys the control field
     *
     * @return true
     */
    function delete()
    {
        $this->__destruct();
    }
    // }}}

    // {{{ getData()
    /**
     * Get control field data
     *
     * @return string returns data in control field
     */
    function getData()
    {
        return (string)$this->data;
    }
    // }}}

    // {{{ isEmpty()
    /**
     * Is empty
     *
     * Checks if the field contains data
     *
     * @return bool Returns true if the field is empty, otherwise false
     */
    function isEmpty()
    {
        return ($this->data) ? false : true;
    }
    // }}}

    // {{{ setData()
    /**
     * Set control field data
     *
     * @param string $data data for the control field
     *
     * @return bool returns the new data in the control field
     */
    function setData($data)
    {
        $this->data = $data;
        return $this->getData();
    }
    // }}}

    // {{{ __toString()
    /**
     * Return as a formatted string
     *
     * Return the control field as a formatted string for pretty printing
     *
     * @return string Formatted output of control Field
     */
    function __toString()
    {
        return sprintf("%3s     %s", $this->tag, $this->data);
    }
    // }}}

    // {{{ toRaw()
    /**
     * Return as raw MARC
     *
     * Return the control field formatted in Raw MARC for saving into MARC files
     *
     * @return string Raw MARC
     */
    function toRaw()
    {
        return (string)$this->data.File_MARC::END_OF_FIELD;
    }
    // }}}

}
// }}}

PK�2[Ɍ5��9�9
MARC/Lint.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */

/**
 * Lint for MARC records
 *
 * This module is adapted from the MARC::Lint CPAN module for Perl, maintained by
 * Bryan Baldus <eijabb@cpan.org> and available at http://search.cpan.org/~eijabb/
 *
 * Current MARC::Lint version used as basis for this module: 1.52
 *
 * PHP version 5
 *
 * LICENSE: This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category  File_Formats
 * @package   File_MARC
 * @author    Demian Katz <demian.katz@villanova.edu>
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2003-2019 Oy Realnode Ab, Dan Scott
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version   CVS: $Id: Record.php 308146 2011-02-08 20:36:20Z dbs $
 * @link      http://pear.php.net/package/File_MARC
 */
require_once 'File/MARC/Lint/CodeData.php';
require_once 'Validate/ISPN.php';

// {{{ class File_MARC_Lint
/**
 * Class for testing validity of MARC records against MARC21 standard.
 *
 * @category File_Formats
 * @package  File_MARC
 * @author   Demian Katz <demian.katz@villanova.edu>
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link     http://pear.php.net/package/File_MARC
 */
class File_MARC_Lint
{

    // {{{ properties
    /**
     * Rules used for testing records
     * @var array
     */
    protected $rules;

    /**
     * A File_MARC_Lint_CodeData object for validating codes
     * @var File_MARC_Lint_CodeData
     */
    protected $data;

    /**
     * A Validate_ISPN object for validating ISBN numbers
     * @var Validate_ISPN
     */
    protected $validateIspn;

    /**
     * Warnings generated during analysis
     * @var array
     */
    protected $warnings = array();

    // }}}

    // {{{ Constructor: function __construct()
    /**
     * Start function
     *
     * Set up rules for testing MARC records.
     *
     * @return true
     */
    public function __construct()
    {
        $this->parseRules();
        $this->data = new File_MARC_Lint_CodeData();
        $this->validateIspn = new Validate_ISPN();
    }
    // }}}

    // {{{ getWarnings()
    /**
     * Check the provided MARC record and return an array of warning messages.
     *
     * @param File_MARC_Record $marc Record to check
     *
     * @return array
     */
    public function checkRecord($marc)
    {
        // Reset warnings:
        $this->warnings = array();

        // Fail if we didn't get a valid object:
        if (!is_a($marc, 'File_MARC_Record')) {
            $this->warn('Must pass a File_MARC_Record object to checkRecord');
        } else {
            $this->checkDuplicate1xx($marc);
            $this->checkMissing245($marc);
            $this->standardFieldChecks($marc);
        }

        return $this->warnings;
    }
    // }}}

    // {{{ warn()
    /**
     * Add a warning.
     *
     * @param string $warning Warning to add
     *
     * @return void
     */
    protected function warn($warning)
    {
        $this->warnings[] = $warning;
    }
    // }}}

    // {{{ checkDuplicate1xx()
    /**
     * Check for multiple 1xx fields.
     *
     * @param File_MARC_Record $marc Record to check
     *
     * @return void
     */
    protected function checkDuplicate1xx($marc)
    {
        $result = $marc->getFields('1[0-9][0-9]', true);
        $count = count($result);
        if ($count > 1) {
            $this->warn(
                "1XX: Only one 1XX tag is allowed, but I found $count of them."
            );
        }
    }
    // }}}

    // {{{ checkMissing245()
    /**
     * Check for missing 245 field.
     *
     * @param File_MARC_Record $marc Record to check
     *
     * @return void
     */
    protected function checkMissing245($marc)
    {
        $result = $marc->getFields('245');
        if (count($result) == 0) {
            $this->warn('245: No 245 tag.');
        }
    }
    // }}}

    // {{{ standardFieldChecks()
    /**
     * Check all fields against the standard rules encoded in the class.
     *
     * @param File_MARC_Record $marc Record to check
     *
     * @return void
     */
    protected function standardFieldChecks($marc)
    {
        $fieldsSeen = array();
        foreach ($marc->getFields() as $current) {
            $tagNo = $current->getTag();
            // if 880 field, inherit rules from tagno in subfield _6
            if ($tagNo == 880) {
                if ($sub6 = $current->getSubfield(6)) {
                    $tagNo = substr($sub6->getData(), 0, 3);
                    $tagrules = isset($this->rules[$tagNo])
                        ? $this->rules[$tagNo] : null;
                    // 880 is repeatable, but its linked field may not be
                    if (isset($tagrules['repeatable'])
                        && $tagrules['repeatable'] == 'NR'
                        && isset($fieldsSeen['880.'.$tagNo])
                    ) {
                        $this->warn("$tagNo: Field is not repeatable.");
                    }
                    $fieldsSeen['880.'.$tagNo] = isset($fieldsSeen['880.'.$tagNo])
                        ? $fieldsSeen['880.'.$tagNo] + 1 : 1;
                } else {
                    $this->warn("880: No subfield 6.");
                    $tagRules = null;
                }
            } else {
                // Default case -- not an 880 field:
                $tagrules = isset($this->rules[$tagNo])
                    ? $this->rules[$tagNo] : null;
                if (isset($tagrules['repeatable']) && $tagrules['repeatable'] == 'NR'
                    && isset($fieldsSeen[$tagNo])
                ) {
                    $this->warn("$tagNo: Field is not repeatable.");
                }
                $fieldsSeen[$tagNo] = isset($fieldsSeen[$tagNo])
                    ? $fieldsSeen[$tagNo] + 1 : 1;
            }

            // Treat data fields differently from control fields:
            if (intval(ltrim($tagNo, '0')) >= 10) {
                if (!empty($tagrules)) {
                    $this->checkIndicators($tagNo, $current, $tagrules);
                    $this->checkSubfields($tagNo, $current, $tagrules);
                }
            } else {
                // Control field:
                if (strstr($current->toRaw(), chr(hexdec('1F')))) {
                    $this->warn(
                        "$tagNo: Subfields are not allowed in fields lower than 010"
                    );
                }
            }

            // Check to see if a checkxxx() function exists, and call it on the
            // field if it does
            $method = 'check' . $tagNo;
            if (method_exists($this, $method)) {
                $this->$method($current);
            }
        }
    }
    // }}}

    // {{{ checkIndicators()
    /**
     * Check the indicators for the provided field.
     *
     * @param string          $tagNo Tag number being checked
     * @param File_MARC_Field $field Field to check
     * @param array           $rules Rules to use for checking
     *
     * @return void
     */
    protected function checkIndicators($tagNo, $field, $rules)
    {
        for ($i = 1; $i <= 2; $i++) {
            $ind = $field->getIndicator($i);
            if ($ind === false || $ind == ' ') {
                $ind = 'b';
            }
            if (!strstr($rules['ind' . $i]['values'], $ind)) {
                // Make indicator blank value human-readable for message:
                if ($ind == 'b') {
                    $ind = 'blank';
                }
                $this->warn(
                    "$tagNo: Indicator $i must be "
                    . $rules['ind' . $i]['hr_values']
                    . " but it's \"$ind\""
                );
            }
        }
    }
    // }}}

    // {{{ checkSubfields()
    /**
     * Check the subfields for the provided field.
     *
     * @param string          $tagNo Tag number being checked
     * @param File_MARC_Field $field Field to check
     * @param array           $rules Rules to use for checking
     *
     * @return void
     */
    protected function checkSubfields($tagNo, $field, $rules)
    {
        $subSeen = array();

        foreach ($field->getSubfields() as $current) {
            $code = $current->getCode();
            $data = $current->getData();

            $subrules = isset($rules['sub' . $code])
                ? $rules['sub' . $code] : null;

            if (empty($subrules)) {
                $this->warn("$tagNo: Subfield _$code is not allowed.");
            } elseif ($subrules['repeatable'] == 'NR' && isset($subSeen[$code])) {
                $this->warn("$tagNo: Subfield _$code is not repeatable.");
            }

            if (preg_match('/\r|\t|\n/', $data)) {
                $this->warn(
                    "$tagNo: Subfield _$code has an invalid control character"
                );
            }

            $subSeen[$code] = isset($subSeen[$code]) ? $subSeen[$code]++ : 1;
        }
    }
    // }}}

    // {{{ check020()
    /**
     * Looks at 020$a and reports errors if the check digit is wrong.
     * Looks at 020$z and validates number if hyphens are present.
     *
     * @param File_MARC_Field $field Field to check
     *
     * @return void
     */
    protected function check020($field)
    {
        foreach ($field->getSubfields() as $current) {
            $data = $current->getData();
            // remove any hyphens
            $isbn = str_replace('-', '', $data);
            // remove nondigits
            $isbn = preg_replace('/^\D*(\d{9,12}[X\d])\b.*$/', '$1', $isbn);

            if ($current->getCode() == 'a') {
                if ((substr($data, 0, strlen($isbn)) != $isbn)) {
                    $this->warn("020: Subfield a may have invalid characters.");
                }

                // report error if no space precedes a qualifier in subfield a
                if (preg_match('/\(/', $data) && !preg_match('/[X0-9] \(/', $data)) {
                    $this->warn(
                        "020: Subfield a qualifier must be preceded by space, $data."
                    );
                }

                // report error if unable to find 10-13 digit string of digits in
                // subfield 'a'
                if (!preg_match('/(?:^\d{10}$)|(?:^\d{13}$)|(?:^\d{9}X$)/', $isbn)) {
                    $this->warn(
                        "020: Subfield a has the wrong number of digits, $data."
                    );
                } else {
                    if (strlen($isbn) == 10) {
                        if (!$this->validateIspn->isbn10($isbn)) {
                            $this->warn("020: Subfield a has bad checksum, $data.");
                        }
                    } else if (strlen($isbn) == 13) {
                        if (!$this->validateIspn->isbn13($isbn)) {
                            $this->warn(
                                "020: Subfield a has bad checksum (13 digit), $data."
                            );
                        }
                    }
                }
            } else if ($current->getCode() == 'z') {
                // look for valid isbn in 020$z
                if (preg_match('/^ISBN/', $data)
                    || preg_match('/^\d*\-\d+/', $data)
                ) {
                    // ##################################################
                    // ## Turned on for now--Comment to unimplement  ####
                    // ##################################################
                    if ((strlen($isbn) == 10)
                        && ($this->validateIspn->isbn10($isbn) == 1)
                    ) {
                        $this->warn("020:  Subfield z is numerically valid.");
                    }
                }
            }
        }
    }
    // }}}

    // {{{ check041()
    /**
     * Warns if subfields are not evenly divisible by 3 unless second indicator is 7
     * (future implementation would ensure that each subfield is exactly 3 characters
     * unless ind2 is 7--since subfields are now repeatable. This is not implemented
     * here due to the large number of records needing to be corrected.). Validates
     * against the MARC Code List for Languages (<http://www.loc.gov/marc/>).
     *
     * @param File_MARC_Field $field Field to check
     *
     * @return void
     */
    protected function check041($field)
    {
        // warn if length of each subfield is not divisible by 3 unless ind2 is 7
        if ($field->getIndicator(2) != '7') {
            foreach ($field->getSubfields() as $sub) {
                $code = $sub->getCode();
                $data = $sub->getData();
                if (strlen($data) % 3 != 0) {
                    $this->warn(
                        "041: Subfield _$code must be evenly divisible by 3 or "
                        . "exactly three characters if ind2 is not 7, ($data)."
                    );
                } else {
                    for ($i = 0; $i < strlen($data); $i += 3) {
                        $chk = substr($data, $i, 3);
                        if (!in_array($chk, $this->data->languageCodes)) {
                            $obs = $this->data->obsoleteLanguageCodes;
                            if (in_array($chk, $obs)) {
                                $this->warn(
                                    "041: Subfield _$code, $data, may be obsolete."
                                );
                            } else {
                                $this->warn(
                                    "041: Subfield _$code, $data ($chk),"
                                    . " is not valid."
                                );
                            }
                        }
                    }
                }
            }
        }
    }
    // }}}

    // {{{ check043()
    /**
     * Warns if each subfield a is not exactly 7 characters. Validates each code
     * against the MARC code list for Geographic Areas (<http://www.loc.gov/marc/>).
     *
     * @param File_MARC_Field $field Field to check
     *
     * @return void
     */
    protected function check043($field)
    {
        foreach ($field->getSubfields('a') as $suba) {
            // warn if length of subfield a is not exactly 7
            $data = $suba->getData();
            if (strlen($data) != 7) {
                $this->warn("043: Subfield _a must be exactly 7 characters, $data");
            } else if (!in_array($data, $this->data->geogAreaCodes)) {
                if (in_array($data, $this->data->obsoleteGeogAreaCodes)) {
                    $this->warn("043: Subfield _a, $data, may be obsolete.");
                } else {
                    $this->warn("043: Subfield _a, $data, is not valid.");
                }
            }
        }
    }
    // }}}

    // {{{ check245()
    /**
     * -Makes sure $a exists (and is first subfield).
     * -Warns if last character of field is not a period
     * --Follows LCRI 1.0C, Nov. 2003 rather than MARC21 rule
     * -Verifies that $c is preceded by / (space-/)
     * -Verifies that initials in $c are not spaced
     * -Verifies that $b is preceded by :;= (space-colon, space-semicolon,
     *  space-equals)
     * -Verifies that $h is not preceded by space unless it is dash-space
     * -Verifies that data of $h is enclosed in square brackets
     * -Verifies that $n is preceded by . (period)
     * --As part of that, looks for no-space period, or dash-space-period
     *  (for replaced elipses)
     * -Verifies that $p is preceded by , (no-space-comma) when following $n and
     *  . (period) when following other subfields.
     * -Performs rudimentary article check of 245 2nd indicator vs. 1st word of
     *  245$a (for manual verification).
     *
     * Article checking is done by internal checkArticle method, which should work
     * for 130, 240, 245, 440, 630, 730, and 830.
     *
     * @param File_MARC_Field $field Field to check
     *
     * @return void
     */
    protected function check245($field)
    {
        if (count($field->getSubfields('a')) == 0) {
            $this->warn("245: Must have a subfield _a.");
        }

        // Convert subfields to array and set flags indicating which subfields are
        // present while we're at it.
        $tmp = $field->getSubfields();
        $hasSubfields = $subfields = array();
        foreach ($tmp as $current) {
            $subfields[] = $current;
            $hasSubfields[$current->getCode()] = true;
        }

        // 245 must end in period (may want to make this less restrictive by allowing
        // trailing spaces)
        // do 2 checks--for final punctuation (MARC21 rule), and for period
        // (LCRI 1.0C, Nov. 2003)
        $lastChar = substr($subfields[count($subfields)-1]->getData(), -1);
        if (!in_array($lastChar, array('.', '?', '!'))) {
            $this->warn("245: Must end with . (period).");
        } else if ($lastChar != '.') {
            $this->warn(
                "245: MARC21 allows ? or ! as final punctuation but LCRI 1.0C, Nov."
                . " 2003 (LCPS 1.7.1 for RDA records), requires period."
            );
        }

        // Check for first subfield
        // subfield a should be first subfield (or 2nd if subfield '6' is present)
        if (isset($hasSubfields['6'])) {
            // make sure there are at least 2 subfields
            if (count($subfields) < 2) {
                $this->warn("245: May have too few subfields.");
            } else {
                $first = $subfields[0]->getCode();
                $second = $subfields[1]->getCode();
                if ($first != '6') {
                    $this->warn("245: First subfield must be _6, but it is $first");
                }
                if ($second != 'a') {
                    $this->warn(
                        "245: First subfield after subfield _6 must be _a, but it "
                        . "is _$second"
                    );
                }
            }
        } else {
            // 1st subfield must be 'a'
            $first = $subfields[0]->getCode();
            if ($first != 'a') {
                $this->warn("245: First subfield must be _a, but it is _$first");
            }
        }
        // End check for first subfield

        // subfield c, if present, must be preceded by /
        // also look for space between initials
        if (isset($hasSubfields['c'])) {
            foreach ($subfields as $i => $current) {
                // 245 subfield c must be preceded by / (space-/)
                if ($current->getCode() == 'c') {
                    if ($i > 0
                        && !preg_match('/\s\/$/', $subfields[$i-1]->getData())
                    ) {
                        $this->warn("245: Subfield _c must be preceded by /");
                    }
                    // 245 subfield c initials should not have space
                    if (preg_match('/\b\w\. \b\w\./', $current->getData())) {
                        $this->warn(
                            "245: Subfield _c initials should not have a space."
                        );
                    }
                    break;
                }
            }
        }

        // each subfield b, if present, should be preceded by :;= (colon, semicolon,
        // or equals sign)
        if (isset($hasSubfields['b'])) {
            // 245 subfield b should be preceded by space-:;= (colon, semicolon, or
            // equals sign)
            foreach ($subfields as $i => $current) {
                if ($current->getCode() == 'b' && $i > 0
                    && !preg_match('/ [:;=]$/', $subfields[$i-1]->getData())
                ) {
                    $this->warn(
                        "245: Subfield _b should be preceded by space-colon, "
                        . "space-semicolon, or space-equals sign."
                    );
                }
            }
        }

        // each subfield h, if present, should be preceded by non-space
        if (isset($hasSubfields['h'])) {
            // 245 subfield h should not be preceded by space
            foreach ($subfields as $i => $current) {
                // report error if subfield 'h' is preceded by space (unless
                // dash-space)
                if ($current->getCode() == 'h') {
                    $prev = $subfields[$i-1]->getData();
                    if ($i > 0 && !preg_match('/(\S$)|(\-\- $)/', $prev)) {
                        $this->warn(
                            "245: Subfield _h should not be preceded by space."
                        );
                    }
                    // report error if subfield 'h' does not start with open square
                    // bracket with a matching close bracket; could have check
                    // against list of valid values here
                    $data = $current->getData();
                    if (!preg_match('/^\[\w*\s*\w*\]/', $data)) {
                        $this->warn(
                            "245: Subfield _h must have matching square brackets,"
                            . " $data."
                        );
                    }
                }
            }
        }

        // each subfield n, if present, must be preceded by . (period)
        if (isset($hasSubfields['n'])) {
            // 245 subfield n must be preceded by . (period)
            foreach ($subfields as $i => $current) {
                // report error if subfield 'n' is not preceded by non-space-period
                // or dash-space-period
                if ($current->getCode() == 'n' && $i > 0) {
                    $prev = $subfields[$i-1]->getData();
                    if (!preg_match('/(\S\.$)|(\-\- \.$)/', $prev)) {
                        $this->warn(
                            "245: Subfield _n must be preceded by . (period)."
                        );
                    }
                }
            }
        }

        // each subfield p, if present, must be preceded by a , (no-space-comma)
        // if it follows subfield n, or by . (no-space-period or
        // dash-space-period) following other subfields
        if (isset($hasSubfields['p'])) {
            // 245 subfield p must be preceded by . (period) or , (comma)
            foreach ($subfields as $i => $current) {
                if ($current->getCode() == 'p' && $i > 0) {
                    $prev = $subfields[$i-1];
                    // case for subfield 'n' being field before this one (allows
                    // dash-space-comma)
                    if ($prev->getCode() == 'n'
                        && !preg_match('/(\S,$)|(\-\- ,$)/', $prev->getData())
                    ) {
                        $this->warn(
                            "245: Subfield _p must be preceded by , (comma) "
                            . "when it follows subfield _n."
                        );
                    } else if ($prev->getCode() != 'n'
                        && !preg_match('/(\S\.$)|(\-\- \.$)/', $prev->getData())
                    ) {
                        $this->warn(
                            "245: Subfield _p must be preceded by . (period)"
                            . " when it follows a subfield other than _n."
                        );
                    }
                }
            }
        }

        // check for invalid 2nd indicator
        $this->checkArticle($field);
    }
    // }}}

    // {{{ checkArticle()
    /**
     * Check of articles is based on code from Ian Hamilton. This version is more
     * limited in that it focuses on English, Spanish, French, Italian and German
     * articles. Certain possible articles have been removed if they are valid
     * English non-articles. This version also disregards 008_language/041 codes
     * and just uses the list of articles to provide warnings/suggestions.
     *
     * source for articles = <http://www.loc.gov/marc/bibliographic/bdapp-e.html>
     *
     * Should work with fields 130, 240, 245, 440, 630, 730, and 830. Reports error
     * if another field is passed in.
     *
     * @param File_MARC_Field $field Field to check
     *
     * @return void
     */
    protected function checkArticle($field)
    {
        // add articles here as needed
        // Some omitted due to similarity with valid words (e.g. the German 'die').
        static $article = array(
            'a' => 'eng glg hun por',
            'an' => 'eng',
            'das' => 'ger',
            'dem' => 'ger',
            'der' => 'ger',
            'ein' => 'ger',
            'eine' => 'ger',
            'einem' => 'ger',
            'einen' => 'ger',
            'einer' => 'ger',
            'eines' => 'ger',
            'el' => 'spa',
            'en' => 'cat dan nor swe',
            'gl' => 'ita',
            'gli' => 'ita',
            'il' => 'ita mlt',
            'l' => 'cat fre ita mlt',
            'la' => 'cat fre ita spa',
            'las' => 'spa',
            'le' => 'fre ita',
            'les' => 'cat fre',
            'lo' => 'ita spa',
            'los' => 'spa',
            'os' => 'por',
            'the' => 'eng',
            'um' => 'por',
            'uma' => 'por',
            'un' => 'cat spa fre ita',
            'una' => 'cat spa ita',
            'une' => 'fre',
            'uno' => 'ita',
        );

        // add exceptions here as needed
        // may want to make keys lowercase
        static $exceptions = array(
            'A & E',
            'A & ',
            'A-',
            'A+',
            'A is ',
            'A isn\'t ',
            'A l\'',
            'A la ',
            'A posteriori',
            'A priori',
            'A to ',
            'El Nino',
            'El Salvador',
            'L is ',
            'L-',
            'La Salle',
            'Las Vegas',
            'Lo cual',
            'Lo mein',
            'Lo que',
            'Los Alamos',
            'Los Angeles',
        );

        // get tagno to determine which indicator to check and for reporting
        $tagNo = $field->getTag();
        // retrieve tagno from subfield 6 if 880 field
        if ($tagNo == '880' && ($sub6 = $field->getSubfield('6'))) {
            $tagNo = substr($sub6->getData(), 0, 3);
        }

        // $ind holds nonfiling character indicator value
        $ind = '';
        // $first_or_second holds which indicator is for nonfiling char value
        $first_or_second = '';
        if (in_array($tagNo, array(130, 630, 730))) {
            $ind = $field->getIndicator(1);
            $first_or_second = '1st';
        } else if (in_array($tagNo, array(240, 245, 440, 830))) {
            $ind = $field->getIndicator(2);
            $first_or_second = '2nd';
        } else {
            $this->warn(
                'Internal error: ' . $tagNo
                . " is not a valid field for article checking\n"
            );
            return;
        }

        if (!is_numeric($ind)) {
            $this->warn($tagNo . ": Non-filing indicator is non-numeric");
            return;
        }

        // get subfield 'a' of the title field
        $titleField = $field->getSubfield('a');
        $title = $titleField ? $titleField->getData() : '';

        // warn about out-of-range skip indicators (note: this feature is an
        // addition to the PHP code; it is not ported directly from MARC::Lint).
        if ($ind > strlen($title)) {
            $this->warn($tagNo . ": Non-filing indicator is out of range");
            return;
        }

        $char1_notalphanum = 0;
        // check for apostrophe, quote, bracket,  or parenthesis, before first word
        // remove if found and add to non-word counter
        while (preg_match('/^["\'\[\(*]/', $title)) {
            $char1_notalphanum++;
            $title = preg_replace('/^["\'\[\(*]/', '', $title);
        }
        // split title into first word + rest on space, parens, bracket, apostrophe,
        // quote, or hyphen
        preg_match('/^([^ \(\)\[\]\'"\-]+)([ \(\)\[\]\'"\-])?(.*)/i', $title, $hits);
        $firstword = isset($hits[1]) ? $hits[1] : '';
        $separator = isset($hits[2]) ? $hits[2] : '';
        $etc = isset($hits[3]) ? $hits[3] : '';

        // get length of first word plus the number of chars removed above plus one
        // for the separator
        $nonfilingchars = strlen($firstword) + $char1_notalphanum + 1;

        // check to see if first word is an exception
        $isan_exception = false;
        foreach ($exceptions as $current) {
            if (substr($title, 0, strlen($current)) == $current) {
                $isan_exception = true;
                break;
            }
        }

        // lowercase chars of $firstword for comparison with article list
        $firstword = strtolower($firstword);

        // see if first word is in the list of articles and not an exception
        $isan_article = !$isan_exception && isset($article[$firstword]);

        // if article then $nonfilingchars should match $ind
        if ($isan_article) {
            // account for quotes, apostrophes, parens, or brackets before 2nd word
            if (strlen($separator) && preg_match('/^[ \(\)\[\]\'"\-]+/', $etc)) {
                while (preg_match('/^[ "\'\[\]\(\)*]/', $etc)) {
                    $nonfilingchars++;
                    $etc = preg_replace('/^[ "\'\[\]\(\)*]/', '', $etc);
                }
            }
            if ($nonfilingchars != $ind) {
                $this->warn(
                    $tagNo . ": First word, $firstword, may be an article, check "
                    . "$first_or_second indicator ($ind)."
                );
            }
        } else {
            // not an article so warn if $ind is not 0
            if ($ind != '0') {
                $this->warn(
                    $tagNo . ": First word, $firstword, does not appear to be an "
                    . "article, check $first_or_second indicator ($ind)."
                );
            }
        }
    }
    // }}}

    // {{{ parseRules()
    /**
     * Support method for constructor to load MARC rules.
     *
     * @return void
     */
    protected function parseRules()
    {
        // Break apart the rule data on line breaks:
        $lines = explode("\n", $this->getRawRules());

        // Each group of data is split by a blank line -- process one group
        // at a time:
        $currentGroup = array();
        foreach ($lines as $currentLine) {
            if (empty($currentLine) && !empty($currentGroup)) {
                $this->processRuleGroup($currentGroup);
                $currentGroup = array();
            } else {
                $currentGroup[] = preg_replace("/\s+/", " ", $currentLine);
            }
        }

        // Still have unprocessed data after the loop?  Handle it now:
        if (!empty($currentGroup)) {
            $this->processRuleGroup($currentGroup);
        }
    }
    // }}}

    // {{{ processRuleGroup()
    /**
     * Support method for parseRules() -- process one group of lines representing
     * a single tag.
     *
     * @param array $rules Rule lines to process
     *
     * @return void
     */
    protected function processRuleGroup($rules)
    {
        // The first line is guaranteed to exist and gives us some basic info:
        list($tag, $repeatable, $description) = explode(' ', $rules[0]);
        $this->rules[$tag] = array(
            'repeatable' => $repeatable,
            'desc' => $description
        );

        // We may or may not have additional details:
        for ($i = 1; $i < count($rules); $i++) {
            list($key, $value, $lineDesc) = explode(' ', $rules[$i] . ' ');
            if (substr($key, 0, 3) == 'ind') {
                // Expand ranges:
                $value = str_replace('0-9', '0123456789', $value);
                $this->rules[$tag][$key] = array(
                    'values' => $value,
                    'hr_values' => $this->getHumanReadableIndicatorValues($value),
                    'desc'=> $lineDesc
                );
            } else {
                if (strlen($key) <= 1) {
                    $this->rules[$tag]['sub' . $key] = array(
                        'repeatable' => $value,
                        'desc' => $lineDesc
                    );
                } elseif (strstr($key, '-')) {
                    list($startKey, $endKey) = explode('-', $key);
                    for ($key = $startKey; $key <= $endKey; $key++) {
                        $this->rules[$tag]['sub' . $key] = array(
                            'repeatable' => $value,
                            'desc' => $lineDesc
                        );
                    }
                }
            }
        }
    }
    // }}}

    // {{{ getHumanReadableIndicatorValues()
    /**
     * Turn a set of indicator rules into a human-readable list.
     *
     * @param string $rules Indicator rules
     *
     * @return string
     */
    protected function getHumanReadableIndicatorValues($rules)
    {
        // No processing needed for blank rule:
        if ($rules == 'blank') {
            return $rules;
        }

        // Create string:
        $string = '';
        $length = strlen($rules);
        for ($i = 0; $i < $length; $i++) {
            $current = substr($rules, $i, 1);
            if ($current == 'b') {
                $current = 'blank';
            }
            $string .= $current;
            if ($length - $i == 2) {
                $string .= ' or ';
            } else if ($length - $i > 2) {
                $string .= ', ';
            }
        }

        return $string;
    }
    // }}}

    // {{{ getRawRules()
    /**
     * Support method for parseRules() -- get the raw rules from MARC::Lint.
     *
     * @return string
     */
    protected function getRawRules()
    {
        // When updating rules, don't forget to escape the dollar signs in the text!
        // It would be simpler to change from HEREDOC to NOWDOC syntax, but that
        // would raise the requirements to PHP 5.3.
        // @codingStandardsIgnoreStart
        return <<<RULES
001     NR      CONTROL NUMBER
ind1    blank   Undefined
ind2    blank   Undefined
        NR      Undefined

002     NR      LOCALLY DEFINED (UNOFFICIAL)
ind1    blank   Undefined
ind2    blank   Undefined
        NR      Undefined

003     NR      CONTROL NUMBER IDENTIFIER
ind1    blank   Undefined
ind2    blank   Undefined
        NR      Undefined

005     NR      DATE AND TIME OF LATEST TRANSACTION
ind1    blank   Undefined
ind2    blank   Undefined
        NR      Undefined

006     R       FIXED-LENGTH DATA ELEMENTS--ADDITIONAL MATERIAL CHARACTERISTICS--GENERAL INFORMATION
ind1    blank   Undefined
ind2    blank   Undefined
        R       Undefined

007     R       PHYSICAL DESCRIPTION FIXED FIELD--GENERAL INFORMATION
ind1    blank   Undefined
ind2    blank   Undefined
        R       Undefined

008     NR      FIXED-LENGTH DATA ELEMENTS--GENERAL INFORMATION
ind1    blank   Undefined
ind2    blank   Undefined
        NR      Undefined

010     NR      LIBRARY OF CONGRESS CONTROL NUMBER
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      LC control number
b       R       NUCMC control number
z       R       Canceled/invalid LC control number
8       R       Field link and sequence number

013     R       PATENT CONTROL INFORMATION
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Number
b       NR      Country
c       NR      Type of number
d       R       Date
e       R       Status
f       R       Party to document
6       NR      Linkage
8       R       Field link and sequence number

015     R       NATIONAL BIBLIOGRAPHY NUMBER
ind1    blank   Undefined
ind2    blank   Undefined
a       R       National bibliography number
q       R       Qualifying information
z       R       Canceled/Invalid national bibliography number
2       NR      Source
6       NR      Linkage
8       R       Field link and sequence number

016     R       NATIONAL BIBLIOGRAPHIC AGENCY CONTROL NUMBER
ind1    b7      National bibliographic agency
ind2    blank   Undefined
a       NR      Record control number
z       R       Canceled or invalid record control number
2       NR      Source
8       R       Field link and sequence number

017     R       COPYRIGHT OR LEGAL DEPOSIT NUMBER
ind1    blank   Undefined
ind2    b8      Undefined
a       R       Copyright or legal deposit number
b       NR      Assigning agency
d       NR      Date
i       NR      Display text
z       R       Canceled/invalid copyright or legal deposit number
2       NR      Source
6       NR      Linkage
8       R       Field link and sequence number

018     NR      COPYRIGHT ARTICLE-FEE CODE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Copyright article-fee code
6       NR      Linkage
8       R       Field link and sequence number

020     R       INTERNATIONAL STANDARD BOOK NUMBER
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      International Standard Book Number
c       NR      Terms of availability
q       R       Qualifying information
z       R       Canceled/invalid ISBN
6       NR      Linkage
8       R       Field link and sequence number

022     R       INTERNATIONAL STANDARD SERIAL NUMBER
ind1    b01     Level of international interest
ind2    blank   Undefined
a       NR      International Standard Serial Number
l       NR      ISSN-L
m       R       Canceled ISSN-L
y       R       Incorrect ISSN
z       R       Canceled ISSN
2       NR      Source
6       NR      Linkage
8       R       Field link and sequence number

024     R       OTHER STANDARD IDENTIFIER
ind1    0123478    Type of standard number or code
ind2    b01     Difference indicator
a       NR      Standard number or code
c       NR      Terms of availability
d       NR      Additional codes following the standard number or code
q       R       Qualifying information
z       R       Canceled/invalid standard number or code
2       NR      Source of number or code
6       NR      Linkage
8       R       Field link and sequence number

025     R       OVERSEAS ACQUISITION NUMBER
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Overseas acquisition number
8       R       Field link and sequence number

026     R       FINGERPRINT IDENTIFIER
ind1    blank   Undefined
ind2    blank   Undefined
a       R       First and second groups of characters
b       R       Third and fourth groups of characters
c       NR      Date
d       R       Number of volume or part
e       NR      Unparsed fingerprint
2       NR      Source
5       R       Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

027     R       STANDARD TECHNICAL REPORT NUMBER
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Standard technical report number
q       R       Qualifying information
z       R       Canceled/invalid number
6       NR      Linkage
8       R       Field link and sequence number

028     R       PUBLISHER NUMBER OR DISTRIBUTOR NUMBER
ind1    0123456   Type of publisher number
ind2    0123    Note/added entry controller
a       NR      Publisher or distributor number
b       NR      Source
q       R       Qualifying information
6       NR      Linkage
8       R       Field link and sequence number

030     R       CODEN DESIGNATION
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      CODEN
z       R       Canceled/invalid CODEN
6       NR      Linkage
8       R       Field link and sequence number

031     R       MUSICAL INCIPITS INFORMATION
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Number of work
b       NR      Number of movement
c       NR      Number of excerpt
d       R       Caption or heading
e       NR      Role
g       NR      Clef
m       NR      Voice/instrument
n       NR      Key signature
o       NR      Time signature
p       NR      Musical notation
q       R       General note
r       NR      Key or mode
s       R       Coded validity note
t       R       Text incipit
u       R       Uniform Resource Identifier
y       R       Link text
z       R       Public note
2       NR      System code
6       NR      Linkage
8       R       Field link and sequence number

032     R       POSTAL REGISTRATION NUMBER
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Postal registration number
b       NR      Source (agency assigning number)
6       NR      Linkage
8       R       Field link and sequence number

033     R       DATE/TIME AND PLACE OF AN EVENT
ind1    b012    Type of date in subfield \$a
ind2    b012    Type of event
a       R       Formatted date/time
b       R       Geographic classification area code
c       R       Geographic classification subarea code
p       R       Place of event
0       R       Record control number
2       R       Source of term
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

034     R       CODED CARTOGRAPHIC MATHEMATICAL DATA
ind1    013     Type of scale
ind2    b01     Type of ring
a       NR      Category of scale
b       R       Constant ratio linear horizontal scale
c       R       Constant ratio linear vertical scale
d       NR      Coordinates--westernmost longitude
e       NR      Coordinates--easternmost longitude
f       NR      Coordinates--northernmost latitude
g       NR      Coordinates--southernmost latitude
h       R       Angular scale
j       NR      Declination--northern limit
k       NR      Declination--southern limit
m       NR      Right ascension--eastern limit
n       NR      Right ascension--western limit
p       NR      Equinox
r       NR      Distance from earth
s       R       G-ring latitude
t       R       G-ring longitude
x       NR      Beginning date
y       NR      Ending date
z       NR      Name of extraterrestrial body
0       R       Authority record control number or standard number
2       NR      Source
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

035     R       SYSTEM CONTROL NUMBER
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      System control number
z       R       Canceled/invalid control number
6       NR      Linkage
8       R       Field link and sequence number

036     NR      ORIGINAL STUDY NUMBER FOR COMPUTER DATA FILES
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Original study number
b       NR      Source (agency assigning number)
6       NR      Linkage
8       R       Field link and sequence number

037     R       SOURCE OF ACQUISITION
ind1    b23     Source of acquisition sequence
ind2    blank   Undefined
a       NR      Stock number
b       NR      Source of stock number/acquisition
c       R       Terms of availability
f       R       Form of issue
g       R       Additional format characteristics
n       R       Note
3       NR      Materials specified
5       R       Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

038     NR      RECORD CONTENT LICENSOR
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Record content licensor
6       NR      Linkage
8       R       Field link and sequence number

040     NR      CATALOGING SOURCE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Original cataloging agency
b       NR      Language of cataloging
c       NR      Transcribing agency
d       R       Modifying agency
e       R       Description conventions
6       NR      Linkage
8       R       Field link and sequence number

041     R       LANGUAGE CODE
ind1    b01      Translation indication
ind2    b7      Source of code
a       R       Language code of text/sound track or separate title
b       R       Language code of summary or abstract
d       R       Language code of sung or spoken text
e       R       Language code of librettos
f       R       Language code of table of contents
g       R       Language code of accompanying material other than librettos
h       R       Language code of original
j       R       Language code of subtitles or captions
k       R       Language code of intermediate translations
m       R       Language code of original accompanying materials other than librettos
n       R       Language code of original libretto
2       NR      Source of code
6       NR      Linkage
8       R       Field link and sequence number

042     NR      AUTHENTICATION CODE
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Authentication code

043     NR      GEOGRAPHIC AREA CODE
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Geographic area code
b       R       Local GAC code
c       R       ISO code
0       R       Authority record control number or standard number
2       R       Source of local code
6       NR      Linkage
8       R       Field link and sequence number

044     NR      COUNTRY OF PUBLISHING/PRODUCING ENTITY CODE
ind1    blank   Undefined
ind2    blank   Undefined
a       R       MARC country code
b       R       Local subentity code
c       R       ISO country code
2       R       Source of local subentity code
6       NR      Linkage
8       R       Field link and sequence number

045     NR      TIME PERIOD OF CONTENT
ind1    b012    Type of time period in subfield \$b or \$c
ind2    blank   Undefined
a       R       Time period code
b       R       Formatted 9999 B.C. through C.E. time period
c       R       Formatted pre-9999 B.C. time period
6       NR      Linkage
8       R       Field link and sequence number

046     R       SPECIAL CODED DATES
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Type of date code
b       NR      Date 1 (B.C.E. date)
c       NR      Date 1 (C.E. date)
d       NR      Date 2 (B.C.E. date)
e       NR      Date 2 (C.E. date)
j       NR      Date resource modified
k       NR      Beginning or single date created
l       NR      Ending date created
m       NR      Beginning of date valid
n       NR      End of date valid
o       NR      Single or starting date for aggregated content
p       NR      Ending date for aggregated content
2       NR      Source of date
6       NR      Linkage
8       R       Field link and sequence number

047     R       FORM OF MUSICAL COMPOSITION CODE
ind1    blank   Undefined
ind2    b7      Source of code
a       R       Form of musical composition code
2       NR      Source of code
8       R       Field link and sequence number

048     R       NUMBER OF MUSICAL INSTRUMENTS OR VOICES CODE
ind1    blank   Undefined
ind2    b7      Source specified in subfield \$2
a       R       Performer or ensemble
b       R       Soloist
2       NR      Source of code
8       R       Field link and sequence number

050     R       LIBRARY OF CONGRESS CALL NUMBER
ind1    b01     Existence in LC collection
ind2    04      Source of call number
a       R       Classification number
b       NR      Item number
0       R       Authority record control number or standard number
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

051     R       LIBRARY OF CONGRESS COPY, ISSUE, OFFPRINT STATEMENT
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Classification number
b       NR      Item number
c       NR      Copy information
8       R       Field link and sequence number

052     R       GEOGRAPHIC CLASSIFICATION
ind1    b17     Code source
ind2    blank   Undefined
a       NR      Geographic classification area code
b       R       Geographic classification subarea code
d       R       Populated place name
0       R       Authority record control number or standard number
2       NR      Code source
6       NR      Linkage
8       R       Field link and sequence number

055     R       CLASSIFICATION NUMBERS ASSIGNED IN CANADA
ind1    b01     Existence in LAC collection
ind2    0123456789   Type, completeness, source of class/call number
a       NR      Classification number
b       NR      Item number
0       R       Authority record control number or standard number
2       NR      Source of call/class number
8       R       Field link and sequence number

060     R       NATIONAL LIBRARY OF MEDICINE CALL NUMBER
ind1    b01     Existence in NLM collection
ind2    04      Source of call number
a       R       Classification number
b       NR      Item number
0       R       Authority record control number or standard number
8       R       Field link and sequence number

061     R       NATIONAL LIBRARY OF MEDICINE COPY STATEMENT
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Classification number
b       NR      Item number
c       NR      Copy information
8       R       Field link and sequence number

066     NR      CHARACTER SETS PRESENT
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Primary G0 character set
b       NR      Primary G1 character set
c       R       Alternate G0 or G1 character set

070     R       NATIONAL AGRICULTURAL LIBRARY CALL NUMBER
ind1    b01     Existence in NAL collection
ind2    blank   Undefined
a       R       Classification number
b       NR      Item number
0       R       Authority record control number or standard number
8       R       Field link and sequence number

071     R       NATIONAL AGRICULTURAL LIBRARY COPY STATEMENT
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Classification number
b       NR      Item number
c       NR      Copy information
8       R       Field link and sequence number

072     R       SUBJECT CATEGORY CODE
ind1    blank   Undefined
ind2    07      Source specified in subfield \$2
a       NR      Subject category code
x       R       Subject category code subdivision
2       NR      Source
6       NR      Linkage
8       R       Field link and sequence number

074     R       GPO ITEM NUMBER
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      GPO item number
z       R       Canceled/invalid GPO item number
8       R       Field link and sequence number

080     R       UNIVERSAL DECIMAL CLASSIFICATION NUMBER
ind1    01      Type of edition
ind2    blank   Undefined
a       NR      Universal Decimal Classification number
b       NR      Item number
x       R       Common auxiliary subdivision
0       R       Authority record control number or standard number
2       NR      Edition identifier
6       NR      Linkage
8       R       Field link and sequence number

082     R       DEWEY DECIMAL CLASSIFICATION NUMBER
ind1    017     Type of edition
ind2    b04     Source of classification number
a       R       Classification number
b       NR      Item number
m       NR      Standard or optional designation
q       NR      Assigning agency
2       NR      Edition number
6       NR      Linkage
8       R       Field link and sequence number

083     R       ADDITIONAL DEWEY DECIMAL CLASSIFICATION NUMBER
ind1    017     Type of edition
ind2    blank   Undefined
a       R       Classification number
c       R       Classification number--Ending number of span
m       NR      Standard or optional designation
q       NR      Assigning agency
y       R       Table sequence number for internal subarrangement or add table
z       R       Table identification
2       NR      Edition number
6       NR      Linkage
8       R       Field link and sequence number

084     R       OTHER CLASSIFICATION NUMBER
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Classification number
b       NR      Item number
q       NR      Assigning agency
0       R       Authority record control number or standard number
2       NR      Source of number
6       NR      Linkage
8       R       Field link and sequence number

085     R       SYNTHESIZED CLASSIFICATION NUMBER COMPONENTS
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Number where instructions are found-single number or beginning number of span
b       R       Base number
c       R       Classification number-ending number of span
f       R       Facet designator
r       R       Root number
s       R       Digits added from classification number in schedule or external table
t       R       Digits added from internal subarrangement or add table
u       R       Number being analyzed
v       R       Number in internal subarrangement or add table where instructions are found
w       R       Table identification-Internal subarrangement or add table
y       R       Table sequence number for internal subarrangement or add table
z       R       Table identification
0       R       Authority record control number or standard number
6       NR      Linkage
8       R       Field link and sequence number

086     R       GOVERNMENT DOCUMENT CLASSIFICATION NUMBER
ind1    b01     Number source
ind2    blank   Undefined
a       NR      Classification number
z       R       Canceled/invalid classification number
0       R       Authority record control number or standard number
2       NR      Number source
6       NR      Linkage
8       R       Field link and sequence number

088     R       REPORT NUMBER
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Report number
z       R       Canceled/invalid report number
6       NR      Linkage
8       R       Field link and sequence number

100     NR      MAIN ENTRY--PERSONAL NAME
ind1    013     Type of personal name entry element
ind2    blank   Undefined
a       NR      Personal name
b       NR      Numeration
c       R       Titles and other words associated with a name
d       NR      Dates associated with a name
e       R       Relator term
f       NR      Date of a work
g       R       Miscellaneous information
j       R       Attribution qualifier
k       R       Form subheading
l       NR      Language of a work
n       R       Number of part/section of a work
p       R       Name of part/section of a work
q       NR      Fuller form of name
t       NR      Title of a work
u       NR      Affiliation
0       R       Authority record control number
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

110     NR      MAIN ENTRY--CORPORATE NAME
ind1    012     Type of corporate name entry element
ind2    blank   Undefined
a       NR      Corporate name or jurisdiction name as entry element
b       R       Subordinate unit
c       R       Location of meeting
d       R       Date of meeting or treaty signing
e       R       Relator term
f       NR      Date of a work
g       R       Miscellaneous information
k       R       Form subheading
l       NR      Language of a work
n       R       Number of part/section/meeting
p       R       Name of part/section of a work
t       NR      Title of a work
u       NR      Affiliation
0       R       Authority record control number
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

111     NR      MAIN ENTRY--MEETING NAME
ind1    012     Type of meeting name entry element
ind2    blank   Undefined
a       NR      Meeting name or jurisdiction name as entry element
c       R       Location of meeting
d       NR      Date of meeting
e       R       Subordinate unit
f       NR      Date of a work
g       R       Miscellaneous information
j       R       Relator term
k       R       Form subheading
l       NR      Language of a work
n       R       Number of part/section/meeting
p       R       Name of part/section of a work
q       NR      Name of meeting following jurisdiction name entry element
t       NR      Title of a work
u       NR      Affiliation
0       R       Authority record control number
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

130     NR      MAIN ENTRY--UNIFORM TITLE
ind1    0-9     Nonfiling characters
ind2    blank   Undefined
a       NR      Uniform title
d       R       Date of treaty signing
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
k       R       Form subheading
l       NR      Language of a work
m       R       Medium of performance for music
n       R       Number of part/section of a work
o       NR      Arranged statement for music
p       R       Name of part/section of a work
r       NR      Key for music
s       NR      Version
t       NR      Title of a work
0       R       Authority record control number
6       NR      Linkage
8       R       Field link and sequence number

210     R       ABBREVIATED TITLE
ind1    01      Title added entry
ind2    b0      Type
a       NR      Abbreviated title
b       NR      Qualifying information
2       R       Source
6       NR      Linkage
8       R       Field link and sequence number

222     R       KEY TITLE
ind1    blank   Specifies whether variant title and/or added entry is required
ind2    0-9     Nonfiling characters
a       NR      Key title
b       NR      Qualifying information
6       NR      Linkage
8       R       Field link and sequence number

240     NR      UNIFORM TITLE
ind1    01    Uniform title printed or displayed
ind2    0-9    Nonfiling characters
a       NR      Uniform title
d       R       Date of treaty signing
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
k       R       Form subheading
l       NR      Language of a work
m       R       Medium of performance for music
n       R       Number of part/section of a work
o       NR      Arranged statement for music
p       R       Name of part/section of a work
r       NR      Key for music
s       NR      Version
0       R       Authority record control number
6       NR      Linkage
8       R       Field link and sequence number

242     R       TRANSLATION OF TITLE BY CATALOGING AGENCY
ind1    01    Title added entry
ind2    0-9    Nonfiling characters
a       NR      Title
b       NR      Remainder of title
c       NR      Statement of responsibility, etc.
h       NR      Medium
n       R       Number of part/section of a work
p       R       Name of part/section of a work
y       NR      Language code of translated title
6       NR      Linkage
8       R       Field link and sequence number

243     NR      COLLECTIVE UNIFORM TITLE
ind1    01    Uniform title printed or displayed
ind2    0-9    Nonfiling characters
a       NR      Uniform title
d       R       Date of treaty signing
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
k       R       Form subheading
l       NR      Language of a work
m       R       Medium of performance for music
n       R       Number of part/section of a work
o       NR      Arranged statement for music
p       R       Name of part/section of a work
r       NR      Key for music
s       NR      Version
6       NR      Linkage
8       R       Field link and sequence number

245     NR      TITLE STATEMENT
ind1    01    Title added entry
ind2    0-9    Nonfiling characters
a       NR      Title
b       NR      Remainder of title
c       NR      Statement of responsibility, etc.
f       NR      Inclusive dates
g       NR      Bulk dates
h       NR      Medium
k       R       Form
n       R       Number of part/section of a work
p       R       Name of part/section of a work
s       NR      Version
6       NR      Linkage
8       R       Field link and sequence number

246     R       VARYING FORM OF TITLE
ind1    0123    Note/added entry controller
ind2    b012345678    Type of title
a       NR      Title proper/short title
b       NR      Remainder of title
f       NR      Date or sequential designation
g       R       Miscellaneous information
h       NR      Medium
i       NR      Display text
n       R       Number of part/section of a work
p       R       Name of part/section of a work
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

247     R       FORMER TITLE
ind1    01      Title added entry
ind2    01      Note controller
a       NR      Title
b       NR      Remainder of title
f       NR      Date or sequential designation
g       R       Miscellaneous information
h       NR      Medium
n       R       Number of part/section of a work
p       R       Name of part/section of a work
x       NR      International Standard Serial Number
6       NR      Linkage
8       R       Field link and sequence number

250     R       EDITION STATEMENT
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Edition statement
b       NR      Remainder of edition statement
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

254     NR      MUSICAL PRESENTATION STATEMENT
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Musical presentation statement
6       NR      Linkage
8       R       Field link and sequence number

255     R       CARTOGRAPHIC MATHEMATICAL DATA
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Statement of scale
b       NR      Statement of projection
c       NR      Statement of coordinates
d       NR      Statement of zone
e       NR      Statement of equinox
f       NR      Outer G-ring coordinate pairs
g       NR      Exclusion G-ring coordinate pairs
6       NR      Linkage
8       R       Field link and sequence number

256     NR      COMPUTER FILE CHARACTERISTICS
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Computer file characteristics
6       NR      Linkage
8       R       Field link and sequence number

257     R       COUNTRY OF PRODUCING ENTITY
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Country of producing entity
0       R       Authority record control number or standard number
2       NR      Source
6       NR      Linkage
8       R       Field link and sequence number

258     R       PHILATELIC ISSUE DATE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Issuing jurisdiction
b       NR      Denomination
6       NR      Linkage
8       R       Field link and sequence number

260     R       PUBLICATION, DISTRIBUTION, ETC. (IMPRINT)
ind1    b23     Sequence of publishing statements
ind2    blank   Undefined
a       R       Place of publication, distribution, etc.
b       R       Name of publisher, distributor, etc.
c       R       Date of publication, distribution, etc.
d       NR      Plate or publisher's number for music (Pre-AACR 2)
e       R       Place of manufacture
f       R       Manufacturer
g       R       Date of manufacture
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

261     NR      IMPRINT STATEMENT FOR FILMS (Pre-AACR 1 Revised)
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Producing company
b       R       Releasing company (primary distributor)
d       R       Date of production, release, etc.
e       R       Contractual producer
f       R       Place of production, release, etc.
6       NR      Linkage
8       R       Field link and sequence number

262     NR      IMPRINT STATEMENT FOR SOUND RECORDINGS (Pre-AACR 2)
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Place of production, release, etc.
b       NR      Publisher or trade name
c       NR      Date of production, release, etc.
k       NR      Serial identification
l       NR      Matrix and/or take number
6       NR      Linkage
8       R       Field link and sequence number

263     NR      PROJECTED PUBLICATION DATE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Projected publication date
6       NR      Linkage
8       R       Field link and sequence number

264     R       PRODUCTION, PUBLICATION, DISTRIBUTION, MANUFACTURE, AND COPYRIGHT NOTICE
ind1    b23     Sequence of statements
ind2    01234   Function of entity
a       R       Place of production, publication, distribution, manufacture
b       R       Name of producer, publisher, distributor, manufacturer
c       R       Date of production, publication, distribution, manufacture, or copyright notice
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number (R)

270     R       ADDRESS
ind1    b12     Level
ind2    b07     Type of address
a       R       Address
b       NR      City
c       NR      State or province
d       NR      Country
e       NR      Postal code
f       NR      Terms preceding attention name
g       NR      Attention name
h       NR      Attention position
i       NR      Type of address
j       R       Specialized telephone number
k       R       Telephone number
l       R       Fax number
m       R       Electronic mail address
n       R       TDD or TTY number
p       R       Contact person
q       R       Title of contact person
r       R       Hours
z       R       Public note
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

300     R       PHYSICAL DESCRIPTION
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Extent
b       NR      Other physical details
c       R       Dimensions
e       NR      Accompanying material
f       R       Type of unit
g       R       Size of unit
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

306     NR      PLAYING TIME
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Playing time
6       NR      Linkage
8       R       Field link and sequence number

307     R       HOURS, ETC.
ind1    b8      Display constant controller
ind2    blank   Undefined
a       NR      Hours
b       NR      Additional information
6       NR      Linkage
8       R       Field link and sequence number

310     NR      CURRENT PUBLICATION FREQUENCY
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Current publication frequency
b       NR      Date of current publication frequency
6       NR      Linkage
8       R       Field link and sequence number

321     R       FORMER PUBLICATION FREQUENCY
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Former publication frequency
b       NR      Dates of former publication frequency
6       NR      Linkage
8       R       Field link and sequence number

336     R       CONTENT TYPE
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Content type term
b       R       Content type code
0       R       Authority record control number or standard number
2       NR      Source
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

337     R       MEDIA TYPE
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Media type term
b       R       Media type code
0       R       Authority record control number or standard number
2       NR      Source
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

338     R       CARRIER TYPE
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Carrier type term
b       R       Carrier type code
0       R       Authority record control number or standard number
2       NR      Source
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

340     R       PHYSICAL MEDIUM
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Material base and configuration
b       R       Dimensions
c       R       Materials applied to surface
d       R       Information recording technique
e       R       Support
f       R       Production rate/ratio
g       R       Color content
h       R       Location within medium
i       R       Technical specifications of medium
j       R       Generation
k       R       Layout
m       R       Book format
n       R       Font size
o       R       Polarity
0       R       Authority record control number or standard number
2       NR      Source
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

342     R       GEOSPATIAL REFERENCE DATA
ind1    01      Geospatial reference dimension
ind2    012345678    Geospatial reference method
a       NR      Name
b       NR      Coordinate or distance units
c       NR      Latitude resolution
d       NR      Longitude resolution
e       R       Standard parallel or oblique line latitude
f       R       Oblique line longitude
g       NR      Longitude of central meridian or projection center
h       NR      Latitude of projection origin or projection center
i       NR      False easting
j       NR      False northing
k       NR      Scale factor
l       NR      Height of perspective point above surface
m       NR      Azimuthal angle
o       NR      Landsat number and path number
p       NR      Zone identifier
q       NR      Ellipsoid name
r       NR      Semi-major axis
s       NR      Denominator of flattening ratio
t       NR      Vertical resolution
u       NR      Vertical encoding method
v       NR      Local planar, local, or other projection or grid description
w       NR      Local planar or local georeference information
2       NR      Reference method used
6       NR      Linkage
8       R       Field link and sequence number

343     R       PLANAR COORDINATE DATA
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Planar coordinate encoding method
b       NR      Planar distance units
c       NR      Abscissa resolution
d       NR      Ordinate resolution
e       NR      Distance resolution
f       NR      Bearing resolution
g       NR      Bearing units
h       NR      Bearing reference direction
i       NR      Bearing reference meridian
6       NR      Linkage
8       R       Field link and sequence number

344     R       SOUND CHARACTERISTICS
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Type of recording
b       R       Recording medium
c       R       Playing speed
d       R       Groove characteristic
e       R       Track configuration
f       R       Tape configuration
g       R       Configuration of playback channels
h       R       Special playback characteristics
0       R       Authority record control number or standard number
2       NR      Source
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

345     R       PROJECTION CHARACTERISTICS OF MOVING IMAGE
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Presentation format
b       R       Projection speed
0       R       Authority record control number or standard number
2       NR      Source
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

346     R       VIDEO CHARACTERISTICS
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Video format
b       R       Broadcast standard
0       R       Authority record control number or standard number
2       NR      Source
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

347     R       DIGITAL FILE CHARACTERISTICS
ind1    blank   Undefined
ind2    blank   Undefined
a       R       File type
b       R       Encoding format
c       R       File size
d       R       Resolution
e       R       Regional encoding
f       R       Encoded bitrate
0       R       Authority record control number or standard number
2       NR      Source
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

348     R       FORMAT OF NOTATED MUSIC
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Format of notated music term
b       R       Format of notated music code
0       R       Authority record control number or standard number
2       NR      Source of term
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

351     R       ORGANIZATION AND ARRANGEMENT OF MATERIALS
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Organization
b       R       Arrangement
c       NR      Hierarchical level
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

352     R       DIGITAL GRAPHIC REPRESENTATION
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Direct reference method
b       R       Object type
c       R       Object count
d       NR      Row count
e       NR      Column count
f       NR      Vertical count
g       NR      VPF topology level
i       NR      Indirect reference description
q       R       Format of the digital image
6       NR      Linkage
8       R       Field link and sequence number

355     R       SECURITY CLASSIFICATION CONTROL
ind1    0123458    Controlled element
ind2    blank   Undefined
a       NR      Security classification
b       R       Handling instructions
c       R       External dissemination information
d       NR      Downgrading or declassification event
e       NR      Classification system
f       NR      Country of origin code
g       NR      Downgrading date
h       NR      Declassification date
j       R       Authorization
6       NR      Linkage
8       R       Field link and sequence number

357     NR      ORIGINATOR DISSEMINATION CONTROL
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Originator control term
b       R       Originating agency
c       R       Authorized recipients of material
g       R       Other restrictions
6       NR      Linkage
8       R       Field link and sequence number

362     R       DATES OF PUBLICATION AND/OR SEQUENTIAL DESIGNATION
ind1    01      Format of date
ind2    blank   Undefined
a       NR      Dates of publication and/or sequential designation
z       NR      Source of information
6       NR      Linkage
8       R       Field link and sequence number

363     R       NORMALIZED DATE AND SEQUENTIAL DESIGNATION
ind1    b01      Start/End designator
ind2    b01      State of issuanceUndefined
a       NR      First level of enumeration
b       NR      Second level of enumeration
c       NR      Third level of enumeration
d       NR      Fourth level of enumeration
e       NR      Fifth level of enumeration
f       NR      Sixth level of enumeration
g       NR      Alternative numbering scheme, first level of enumeration
h       NR      Alternative numbering scheme, second level of enumeration
i       NR      First level of chronology
j       NR      Second level of chronology
k       NR      Third level of chronology
l       NR      Fourth level of chronology
m       NR      Alternative numbering scheme, chronology
u       NR      First level textual designation
v       NR      First level of chronology, issuance
x       R       Nonpublic note
z       R       Public note
6       NR      Linkage
8       NR      Field link and sequence number

365     R       TRADE PRICE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Price type code
b       NR      Price amount
c       NR      Currency code
d       NR      Unit of pricing
e       NR      Price note
f       NR      Price effective from
g       NR      Price effective until
h       NR      Tax rate 1
i       NR      Tax rate 2
j       NR      ISO country code
k       NR      MARC country code
m       NR      Identification of pricing entity
2       NR      Source of price type code
6       NR      Linkage
8       R       Field link and sequence number

366     R       TRADE AVAILABILITY INFORMATION
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Publishers' compressed title identification
b       NR      Detailed date of publication
c       NR      Availability status code
d       NR      Expected next availability date
e       NR      Note
f       NR      Publishers' discount category
g       NR      Date made out of print
j       NR      ISO country code
k       NR      MARC country code
m       NR      Identification of agency
2       NR      Source of availability status code
6       NR      Linkage
8       R       Field link and sequence number

370     R       ASSOCIATED PLACE
ind1    blank   Undefined
ind2    blank   Undefined
c       R       Associated country
f       R       Other associated place
g       R       Place of origin of work or expression
i       R       Relationship information
s       NR      Start period
t       NR      End period
u       R       Uniform Resource Identifier
v       R       Source of information
0       R       Authority record control number or standard number
2       NR      Source of term
3       NR      Materials specified
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

377     R       ASSOCIATED LANGUAGE
ind1    blank   Undefined
ind2    b7      Undefined
a       R       Language code
0       R       Authority record control number or standard number
l       R       Language term
2       NR      Source
6       NR      Linkage
8       R       Field link and sequence number

380     R       FORM OF WORK
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Form of work
0       R       Record control number
2       NR      Source of term
6       NR      Linkage
8       R       Field link and sequence number

381     R       OTHER DISTINGUISHING CHARACTERISTICS OF WORK OR EXPRESSION
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Other distinguishing characteristic
u       R       Uniform Resource Identifier
v       R       Source of information
0       R       Record control number
2       NR      Source of term
6       NR      Linkage
8       R       Field link and sequence number

382     R       MEDIUM OF PERFORMANCE
ind1    b01     Undefined
ind2    b01     Undefined
a       R       Medium of performance
b       R       Soloist
d       R       Doubling instrument
e       R       Number of ensembles of the same type
n       R       Number of performers of the same medium
p       R       Alternative medium of performance
r       NR      Total number of individuals performing alongside ensembles
s       NR      Total number of performers
t       NR      Total number of ensembles
v       R       Note
0       R       Record control number
2       NR      Source of term
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

383     R       NUMERIC DESIGNATION OF MUSICAL WORK
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Serial number
b       R       Opus number
c       R       Thematic index number
d       NR      Thematic index code
e       NR      Publisher associated with opus number
2       NR      Source
6       NR      Linkage
8       R       Field link and sequence number

384     NR      KEY
ind1    b01     Key type
ind2    blank   Undefined
a       NR      Key
6       NR      Linkage
8       R       Field link and sequence number

385     R       AUDIENCE CHARACTERISTICS
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Audience term
b       R       Audience code
m       NR      Demographic group term
n       NR      Demographic group code
0       R       Authority record control number or standard number
2       NR      Source
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

386     R       CREATOR/CONTRIBUTOR CHARACTERISTICS
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Creator/contributor term
b       R       Creator/contributor code
i       R       Relationship information
m       NR      Demographic group term
n       NR      Demographic group code
0       R       Authority record control number or standard number
2       NR      Source
3       NR      Materials specified
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

388     R       TIME PERIOD OF CREATION
ind1    b12     Type of time period
ind2    blank   Undefined
a       R       Time period of creation term (R)
0       R       Authority record control number or standard number (R)
2       NR      Source of term (NR)
3       NR      Materials specified (NR)
6       NR      Linkage (NR)
8       R       Field link and sequence number (R)

400     R       SERIES STATEMENT/ADDED ENTRY--PERSONAL NAME
ind1    013     Type of personal name entry element
ind2    01      Pronoun represents main entry
a       NR      Personal name
b       NR      Numeration
c       R       Titles and other words associated with a name
d       NR      Dates associated with a name
e       R       Relator term
f       NR      Date of a work
g       NR      Miscellaneous information
k       R       Form subheading
l       NR      Language of a work
n       R       Number of part/section of a work
p       R       Name of part/section of a work
t       NR      Title of a work
u       NR      Affiliation
v       NR      Volume number/sequential designation
x       NR      International Standard Serial Number
4       R       Relator code
6       NR      Linkage
8       R       Field link and sequence number

410     R       SERIES STATEMENT/ADDED ENTRY--CORPORATE NAME
ind1    012     Type of corporate name entry element
ind2    01      Pronoun represents main entry
a       NR      Corporate name or jurisdiction name as entry element
b       R       Subordinate unit
c       NR      Location of meeting
d       R       Date of meeting or treaty signing
e       R       Relator term
f       NR      Date of a work
g       NR      Miscellaneous information
k       R       Form subheading
l       NR      Language of a work
n       R       Number of part/section/meeting
p       R       Name of part/section of a work
t       NR      Title of a work
u       NR      Affiliation
v       NR      Volume number/sequential designation
x       NR      International Standard Serial Number
4       R       Relator code
6       NR      Linkage
8       R       Field link and sequence number

411     R       SERIES STATEMENT/ADDED ENTRY--MEETING NAME
ind1    012     Type of meeting name entry element
ind2    01      Pronoun represents main entry
a       NR      Meeting name or jurisdiction name as entry element
c       NR      Location of meeting
d       NR      Date of meeting
e       R       Subordinate unit
f       NR      Date of a work
g       NR      Miscellaneous information
k       R       Form subheading
l       NR      Language of a work
n       R       Number of part/section/meeting
p       R       Name of part/section of a work
q       NR      Name of meeting following jurisdiction name entry element
t       NR      Title of a work
u       NR      Affiliation
v       NR      Volume number/sequential designation
x       NR      International Standard Serial Number
4       R       Relator code
6       NR      Linkage
8       R       Field link and sequence number

440     R       SERIES STATEMENT/ADDED ENTRY--TITLE [OBSOLETE]
ind1    blank   Undefined
ind2    0-9     Nonfiling characters
a       NR      Title
n       R       Number of part/section of a work
p       R       Name of part/section of a work
v       NR      Volume number/sequential designation
x       NR      International Standard Serial Number
w       R       Bibliographic record control number
0       R       Authority record control number
6       NR      Linkage
8       R       Field link and sequence number

490     R       SERIES STATEMENT
ind1    01      Specifies whether series is traced
ind2    blank   Undefined
a       R       Series statement
l       NR      Library of Congress call number
v       R       Volume number/sequential designation
x       R       International Standard Serial Number
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

500     R       GENERAL NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      General note
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

501     R       WITH NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      With note
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

502     R       DISSERTATION NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Dissertation note
b       NR      Degree type
c       NR      Name of granting institution
d       NR      Year of degree granted
g       R       Miscellaneous information
o       R       Dissertation identifier
6       NR      Linkage
8       R       Field link and sequence number

504     R       BIBLIOGRAPHY, ETC. NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Bibliography, etc. note
b       NR      Number of references
6       NR      Linkage
8       R       Field link and sequence number

505     R       FORMATTED CONTENTS NOTE
ind1    0128    Display constant controller
ind2    b0      Level of content designation
a       NR      Formatted contents note
g       R       Miscellaneous information
r       R       Statement of responsibility
t       R       Title
u       R       Uniform Resource Identifier
6       NR      Linkage
8       R       Field link and sequence number

506     R       RESTRICTIONS ON ACCESS NOTE
ind1    b01     Restriction
ind2    blank   Undefined
a       NR      Terms governing access
b       R       Jurisdiction
c       R       Physical access provisions
d       R       Authorized users
e       R       Authorization
f       R       Standard terminology for access restiction
u       R       Uniform Resource Identifier
2       NR      Source of term
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

507     NR      SCALE NOTE FOR GRAPHIC MATERIAL
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Representative fraction of scale note
b       NR      Remainder of scale note
6       NR      Linkage
8       R       Field link and sequence number

508     R       CREATION/PRODUCTION CREDITS NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Creation/production credits note
6       NR      Linkage
8       R       Field link and sequence number

510     R       CITATION/REFERENCES NOTE
ind1    01234   Coverage/location in source
ind2    blank   Undefined
a       NR      Name of source
b       NR      Coverage of source
c       NR      Location within source
u       R       Uniform Resource Identifier
x       NR      International Standard Serial Number
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

511     R       PARTICIPANT OR PERFORMER NOTE
ind1    01      Display constant controller
ind2    blank   Undefined
a       NR      Participant or performer note
6       NR      Linkage
8       R       Field link and sequence number

513     R       TYPE OF REPORT AND PERIOD COVERED NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Type of report
b       NR      Period covered
6       NR      Linkage
8       R       Field link and sequence number

514     NR      DATA QUALITY NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Attribute accuracy report
b       R       Attribute accuracy value
c       R       Attribute accuracy explanation
d       NR      Logical consistency report
e       NR      Completeness report
f       NR      Horizontal position accuracy report
g       R       Horizontal position accuracy value
h       R       Horizontal position accuracy explanation
i       NR      Vertical positional accuracy report
j       R       Vertical positional accuracy value
k       R       Vertical positional accuracy explanation
m       NR      Cloud cover
u       R       Uniform Resource Identifier
z       R       Display note
6       NR      Linkage
8       R       Field link and sequence number

515     R       NUMBERING PECULIARITIES NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Numbering peculiarities note
6       NR      Linkage
8       R       Field link and sequence number

516     R       TYPE OF COMPUTER FILE OR DATA NOTE
ind1    b8      Display constant controller
ind2    blank   Undefined
a       NR      Type of computer file or data note
6       NR      Linkage
8       R       Field link and sequence number

518     R       DATE/TIME AND PLACE OF AN EVENT NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Date/time and place of an event note
d       R       Date of event
o       R       Other event information
p       R       Place of event
0       R       Record control number
2       R       Source of term
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

520     R       SUMMARY, ETC.
ind1    b012348    Display constant controller
ind2    blank   Undefined
a       NR      Summary, etc. note
b       NR      Expansion of summary note
c       NR      Assigning agency
u       R       Uniform Resource Identifier
2       NR      Source
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

521     R       TARGET AUDIENCE NOTE
ind1    b012348    Display constant controller
ind2    blank   Undefined
a       R       Target audience note
b       NR      Source
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

522     R       GEOGRAPHIC COVERAGE NOTE
ind1    b8      Display constant controller
ind2    blank   Undefined
a       NR      Geographic coverage note
6       NR      Linkage
8       R       Field link and sequence number

524     R       PREFERRED CITATION OF DESCRIBED MATERIALS NOTE
ind1    b8      Display constant controller
ind2    blank   Undefined
a       NR      Preferred citation of described materials note
2       NR      Source of schema used
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

525     R       SUPPLEMENT NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Supplement note
6       NR      Linkage
8       R       Field link and sequence number

526     R       STUDY PROGRAM INFORMATION NOTE
ind1    08      Display constant controller
ind2    blank   Undefined
a       NR      Program name
b       NR      Interest level
c       NR      Reading level
d       NR      Title point value
i       NR      Display text
x       R       Nonpublic note
z       R       Public note
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

530     R       ADDITIONAL PHYSICAL FORM AVAILABLE NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Additional physical form available note
b       NR      Availability source
c       NR      Availability conditions
d       NR      Order number
u       R       Uniform Resource Identifier
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

533     R       REPRODUCTION NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Type of reproduction
b       R       Place of reproduction
c       R       Agency responsible for reproduction
d       NR      Date of reproduction
e       NR      Physical description of reproduction
f       R       Series statement of reproduction
m       R       Dates and/or sequential designation of issues reproduced
n       R       Note about reproduction
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
7       NR      Fixed-length data elements of reproduction
8       R       Field link and sequence number

534     R       ORIGINAL VERSION NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Main entry of original
b       NR      Edition statement of original
c       NR      Publication, distribution, etc. of original
e       NR      Physical description, etc. of original
f       R       Series statement of original
k       R       Key title of original
l       NR      Location of original
m       NR      Material specific details
n       R       Note about original
o       R       Other resource identifier
p       NR      Introductory phrase
t       NR      Title statement of original
x       R       International Standard Serial Number
z       R       International Standard Book Number
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

535     R       LOCATION OF ORIGINALS/DUPLICATES NOTE
ind1    12      Additional information about custodian
ind2    blank   Undefined
a       NR      Custodian
b       R       Postal address
c       R       Country
d       R       Telecommunications address
g       NR      Repository location code
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

536     R       FUNDING INFORMATION NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Text of note
b       R       Contract number
c       R       Grant number
d       R       Undifferentiated number
e       R       Program element number
f       R       Project number
g       R       Task number
h       R       Work unit number
6       NR      Linkage
8       R       Field link and sequence number

538     R       SYSTEM DETAILS NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      System details note
i       NR      Display text
u       R       Uniform Resource Identifier
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

540     R       TERMS GOVERNING USE AND REPRODUCTION NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Terms governing use and reproduction
b       NR      Jurisdiction
c       NR      Authorization
d       NR      Authorized users
u       R       Uniform Resource Identifier
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

541     R       IMMEDIATE SOURCE OF ACQUISITION NOTE
ind1    b01     Undefined
ind2    blank   Undefined
a       NR      Source of acquisition
b       NR      Address
c       NR      Method of acquisition
d       NR      Date of acquisition
e       NR      Accession number
f       NR      Owner
h       NR      Purchase price
n       R       Extent
o       R       Type of unit
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

542     R       INFORMATION RELATING TO COPYRIGHT STATUS
ind1    b01     Relationship
ind2    blank   Undefined
a       NR      Personal creator
b       NR      Personal creator death date
c       NR      Corporate creator
d       R       Copyright holder
e       R       Copyright holder contact information
f       R       Copyright statement
g       NR      Copyright date
h       R       Copyright renewal date
i       NR      Publication date
j       NR      Creation date
k       R       Publisher
l       NR      Copyright status
m       NR      Publication status
n       R       Note
o       NR      Research date
q       NR      Assigning agency
r       NR      Jurisdiction of copyright assessment
s       NR      Source of information
u       R       Uniform Resource Identifier
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

544     R       LOCATION OF OTHER ARCHIVAL MATERIALS NOTE
ind1    b01     Relationship
ind2    blank   Undefined
a       R       Custodian
b       R       Address
c       R       Country
d       R       Title
e       R       Provenance
n       R       Note
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

545     R       BIOGRAPHICAL OR HISTORICAL DATA
ind1    b01     Type of data
ind2    blank   Undefined
a       NR      Biographical or historical note
b       NR      Expansion
u       R       Uniform Resource Identifier
6       NR      Linkage
8       R       Field link and sequence number

546     R       LANGUAGE NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Language note
b       R       Information code or alphabet
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

547     R       FORMER TITLE COMPLEXITY NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Former title complexity note
6       NR      Linkage
8       R       Field link and sequence number

550     R       ISSUING BODY NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Issuing body note
6       NR      Linkage
8       R       Field link and sequence number

552     R       ENTITY AND ATTRIBUTE INFORMATION NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Entity type label
b       NR      Entity type definition and source
c       NR      Attribute label
d       NR      Attribute definition and source
e       R       Enumerated domain value
f       R       Enumerated domain value definition and source
g       NR      Range domain minimum and maximum
h       NR      Codeset name and source
i       NR      Unrepresentable domain
j       NR      Attribute units of measurement and resolution
k       NR      Beginning date and ending date of attribute values
l       NR      Attribute value accuracy
m       NR      Attribute value accuracy explanation
n       NR      Attribute measurement frequency
o       R       Entity and attribute overview
p       R       Entity and attribute detail citation
u       R       Uniform Resource Identifier
z       R       Display note
6       NR      Linkage
8       R       Field link and sequence number

555     R       CUMULATIVE INDEX/FINDING AIDS NOTE
ind1    b08     Display constant controller
ind2    blank   Undefined
a       NR      Cumulative index/finding aids note
b       R       Availability source
c       NR      Degree of control
d       NR      Bibliographic reference
u       R       Uniform Resource Identifier
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

556     R       INFORMATION ABOUT DOCUMENTATION NOTE
ind1    b8      Display constant controller
ind2    blank   Undefined
a       NR      Information about documentation note
z       R       International Standard Book Number
6       NR      Linkage
8       R       Field link and sequence number

561     R       OWNERSHIP AND CUSTODIAL HISTORY
ind1    b01     Undefined
ind2    blank   Undefined
a       NR      History
u       R       Uniform Resource Identifier
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

562     R       COPY AND VERSION IDENTIFICATION NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Identifying markings
b       R       Copy identification
c       R       Version identification
d       R       Presentation format
e       R       Number of copies
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

563     R       BINDING INFORMATION
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Binding note
u       R       Uniform Resource Identifier
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

565     R       CASE FILE CHARACTERISTICS NOTE
ind1    b08     Display constant controller
ind2    blank   Undefined
a       NR      Number of cases/variables
b       R       Name of variable
c       R       Unit of analysis
d       R       Universe of data
e       R       Filing scheme or code
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

567     R       METHODOLOGY NOTE
ind1    b8      Display constant controller
ind2    blank   Undefined
a       NR      Methodology note
b       R       Controlled term
0       R       Authority record control number or standard number
2       NR      Source of term
6       NR      Linkage
8       R       Field link and sequence number

580     R       LINKING ENTRY COMPLEXITY NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Linking entry complexity note
6       NR      Linkage
8       R       Field link and sequence number

581     R       PUBLICATIONS ABOUT DESCRIBED MATERIALS NOTE
ind1    b8      Display constant controller
ind2    blank   Undefined
a       NR      Publications about described materials note
z       R       International Standard Book Number
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

583     R       ACTION NOTE
ind1    b01     Undefined
ind2    blank   Undefined
a       NR      Action
b       R       Action identification
c       R       Time/date of action
d       R       Action interval
e       R       Contingency for action
f       R       Authorization
h       R       Jurisdiction
i       R       Method of action
j       R       Site of action
k       R       Action agent
l       R       Status
n       R       Extent
o       R       Type of unit
u       R       Uniform Resource Identifier
x       R       Nonpublic note
z       R       Public note
2       NR      Source of term
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

584     R       ACCUMULATION AND FREQUENCY OF USE NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Accumulation
b       R       Frequency of use
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

585     R       EXHIBITIONS NOTE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Exhibitions note
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

586     R       AWARDS NOTE
ind1    b8      Display constant controller
ind2    blank   Undefined
a       NR      Awards note
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

588     R       SOURCE OF DESCRIPTION NOTE
ind1    b01     Display constant controller
ind2    blank   Undefined
a       NR      Source of description note
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

600     R       SUBJECT ADDED ENTRY--PERSONAL NAME
ind1    013     Type of personal name entry element
ind2    01234567    Thesaurus
a       NR      Personal name
b       NR      Numeration
c       R       Titles and other words associated with a name
d       NR      Dates associated with a name
e       R       Relator term
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
j       R       Attribution qualifier
k       R       Form subheading
l       NR      Language of a work
m       R       Medium of performance for music
n       R       Number of part/section of a work
o       NR      Arranged statement for music
p       R       Name of part/section of a work
q       NR      Fuller form of name
r       NR      Key for music
s       NR      Version
t       NR      Title of a work
u       NR      Affiliation
v       R       Form subdivision
x       R       General subdivision
y       R       Chronological subdivision
z       R       Geographic subdivision
0       R       Authority record control number
2       NR      Source of heading or term
3       NR      Materials specified
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

610     R       SUBJECT ADDED ENTRY--CORPORATE NAME
ind1    012     Type of corporate name entry element
ind2    01234567    Thesaurus
a       NR      Corporate name or jurisdiction name as entry element
b       R       Subordinate unit
c       R       Location of meeting
d       R       Date of meeting or treaty signing
e       R       Relator term
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
k       R       Form subheading
l       NR      Language of a work
m       R       Medium of performance for music
n       R       Number of part/section/meeting
o       NR      Arranged statement for music
p       R       Name of part/section of a work
r       NR      Key for music
s       NR      Version
t       NR      Title of a work
u       NR      Affiliation
v       R       Form subdivision
x       R       General subdivision
y       R       Chronological subdivision
z       R       Geographic subdivision
0       R       Authority record control number
2       NR      Source of heading or term
3       NR      Materials specified
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

611     R       SUBJECT ADDED ENTRY--MEETING NAME
ind1    012     Type of meeting name entry element
ind2    01234567    Thesaurus
a       NR      Meeting name or jurisdiction name as entry element
c       R       Location of meeting
d       NR      Date of meeting
e       R       Subordinate unit
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
j       R       Relator term
k       R       Form subheading
l       NR      Language of a work
n       R       Number of part/section/meeting
p       R       Name of part/section of a work
q       NR      Name of meeting following jurisdiction name entry element
s       NR      Version
t       NR      Title of a work
u       NR      Affiliation
v       R       Form subdivision
x       R       General subdivision
y       R       Chronological subdivision
z       R       Geographic subdivision
0       R       Authority record control number
2       NR      Source of heading or term
3       NR      Materials specified
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

630     R       SUBJECT ADDED ENTRY--UNIFORM TITLE
ind1    0-9     Nonfiling characters
ind2    01234567    Thesaurus
a       NR      Uniform title
d       R       Date of treaty signing
e       R       Relator term
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
k       R       Form subheading
l       NR      Language of a work
m       R       Medium of performance for music
n       R       Number of part/section of a work
o       NR      Arranged statement for music
p       R       Name of part/section of a work
r       NR      Key for music
s       NR      Version
t       NR      Title of a work
v       R       Form subdivision
x       R       General subdivision
y       R       Chronological subdivision
z       R       Geographic subdivision
0       R       Authority record control number
2       NR      Source of heading or term
3       NR      Materials specified
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

647     R       SUBJECT ADDED ENTRY--NAMED EVENT
ind1    blank   Undefined
ind2    01234567    Thesaurus
a       NR      Named event
c       R       Location of named event
d       NR      Date of named event
g       R       Miscellaneous information
v       R       Form subdivision
x       R       General subdivision
y       R       Chronological subdivision
z       R       Geographic subdivision
0       R       Authority record control number or standard number
2       NR      Source of heading or term
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

648     R       SUBJECT ADDED ENTRY--CHRONOLOGICAL TERM
ind1    blank   Undefined
ind2    01234567    Thesaurus
a       NR      Chronological term
v       R       Form subdivision
x       R       General subdivision
y       R       Chronological subdivision
z       R       Geographic subdivision
0       R       Authority record control number
2       NR      Source of heading or term
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

650     R       SUBJECT ADDED ENTRY--TOPICAL TERM
ind1    b012    Level of subject
ind2    01234567    Thesaurus
a       NR      Topical term or geographic name as entry element
b       NR      Topical term following geographic name as entry element
c       NR      Location of event
d       NR      Active dates
e       NR      Relator term
v       R       Form subdivision
x       R       General subdivision
y       R       Chronological subdivision
z       R       Geographic subdivision
0       R       Authority record control number
2       NR      Source of heading or term
3       NR      Materials specified
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

651     R       SUBJECT ADDED ENTRY--GEOGRAPHIC NAME
ind1    blank   Undefined
ind2    01234567    Thesaurus
a       NR      Geographic name
e       R       Relator term
v       R       Form subdivision
x       R       General subdivision
y       R       Chronological subdivision
z       R       Geographic subdivision
0       R       Authority record control number
2       NR      Source of heading or term
3       NR      Materials specified
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

653     R       INDEX TERM--UNCONTROLLED
ind1    b012    Level of index term
ind2    b0123456   Type of term or name
a       R       Uncontrolled term
6       NR      Linkage
8       R       Field link and sequence number

654     R       SUBJECT ADDED ENTRY--FACETED TOPICAL TERMS
ind1    b012    Level of subject
ind2    blank   Undefined
a       R       Focus term
b       R       Non-focus term
c       R       Facet/hierarchy designation
e       R       Relator term
v       R       Form subdivision
y       R       Chronological subdivision
z       R       Geographic subdivision
0       R       Authority record control number
2       NR      Source of heading or term
3       NR      Materials specified
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

655     R       INDEX TERM--GENRE/FORM
ind1    b0      Type of heading
ind2    01234567    Thesaurus
a       NR      Genre/form data or focus term
b       R       Non-focus term
c       R       Facet/hierarchy designation
v       R       Form subdivision
x       R       General subdivision
y       R       Chronological subdivision
z       R       Geographic subdivision
0       R       Authority record control number
2       NR      Source of term
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

656     R       INDEX TERM--OCCUPATION
ind1    blank   Undefined
ind2    7       Source of term
a       NR      Occupation
k       NR      Form
v       R       Form subdivision
x       R       General subdivision
y       R       Chronological subdivision
z       R       Geographic subdivision
0       R       Authority record control number
2       NR      Source of term
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

657     R       INDEX TERM--FUNCTION
ind1    blank   Undefined
ind2    7       Source of term
a       NR      Function
v       R       Form subdivision
x       R       General subdivision
y       R       Chronological subdivision
z       R       Geographic subdivision
0       R       Authority record control number
2       NR      Source of term
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

658     R       INDEX TERM--CURRICULUM OBJECTIVE
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Main curriculum objective
b       R       Subordinate curriculum objective
c       NR      Curriculum code
d       NR      Correlation factor
2       NR      Source of term or code
6       NR      Linkage
8       R       Field link and sequence number

662     R       SUBJECT ADDED ENTRY--HIERARCHICAL PLACE NAME
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Country or larger entity
b       NR      First-order political jurisdiction
c       R       Intermediate political jurisdiction
d       NR      City
e       R       Relator term
f       R       City subsection
g       R       Other nonjurisdictional geographic region and feature
h       R       Extraterrestrial area
0       R       Authority record control number
2       NR      Source of heading or term
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

700     R       ADDED ENTRY--PERSONAL NAME
ind1    013     Type of personal name entry element
ind2    b2      Type of added entry
a       NR      Personal name
b       NR      Numeration
c       R       Titles and other words associated with a name
d       NR      Dates associated with a name
e       R       Relator term
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
i       R       Relationship information
j       R       Attribution qualifier
k       R       Form subheading
l       NR      Language of a work
m       R       Medium of performance for music
n       R       Number of part/section of a work
o       NR      Arranged statement for music
p       R       Name of part/section of a work
q       NR      Fuller form of name
r       NR      Key for music
s       NR      Version
t       NR      Title of a work
u       NR      Affiliation
x       NR      International Standard Serial Number
0       R       Authority record control number
3       NR      Materials specified
4       R       Relationship
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

710     R       ADDED ENTRY--CORPORATE NAME
ind1    012     Type of corporate name entry element
ind2    b2      Type of added entry
a       NR      Corporate name or jurisdiction name as entry element
b       R       Subordinate unit
c       R       Location of meeting
d       R       Date of meeting or treaty signing
e       R       Relator term
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
i       R       Relationship information
k       R       Form subheading
l       NR      Language of a work
m       R       Medium of performance for music
n       R       Number of part/section/meeting
o       NR      Arranged statement for music
p       R       Name of part/section of a work
r       NR      Key for music
s       NR      Version
t       NR      Title of a work
u       NR      Affiliation
x       NR      International Standard Serial Number
0       R       Authority record control number
3       NR      Materials specified
4       R       Relationship
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

711     R       ADDED ENTRY--MEETING NAME
ind1    012     Type of meeting name entry element
ind2    b2      Type of added entry
a       NR      Meeting name or jurisdiction name as entry element
c       R       Location of meeting
d       NR      Date of meeting
e       R       Subordinate unit
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
i       R       Relationship information
j       R       Relator term
k       R       Form subheading
l       NR      Language of a work
n       R       Number of part/section/meeting
p       R       Name of part/section of a work
q       NR      Name of meeting following jurisdiction name entry element
s       NR      Version
t       NR      Title of a work
u       NR      Affiliation
x       NR      International Standard Serial Number
0       R       Authority record control number
3       NR      Materials specified
4       R       Relationship
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

720     R       ADDED ENTRY--UNCONTROLLED NAME
ind1    b12     Type of name
ind2    blank   Undefined
a       NR      Name
e       R       Relator term
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

730     R       ADDED ENTRY--UNIFORM TITLE
ind1    0-9     Nonfiling characters
ind2    b2      Type of added entry
a       NR      Uniform title
d       R       Date of treaty signing
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
i       R       Relationship information
k       R       Form subheading
l       NR      Language of a work
m       R       Medium of performance for music
n       R       Number of part/section of a work
o       NR      Arranged statement for music
p       R       Name of part/section of a work
r       NR      Key for music
s       NR      Version
t       NR      Title of a work
x       NR      International Standard Serial Number
0       R       Authority record control number
3       NR      Materials specified
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

740     R       ADDED ENTRY--UNCONTROLLED RELATED/ANALYTICAL TITLE
ind1    0-9     Nonfiling characters
ind2    b2      Type of added entry
a       NR      Uncontrolled related/analytical title
h       NR      Medium
n       R       Number of part/section of a work
p       R       Name of part/section of a work
5       NR      Institution to which field applies
6       NR      Linkage
8       R       Field link and sequence number

751     R       ADDED ENTRY--GEOGRAPHIC NAME
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Geographic name
e       R       Relator term
0       R       Authority record control number
2       NR      Source of heading or term
3       NR      Materials specified
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

752     R       ADDED ENTRY--HIERARCHICAL PLACE NAME
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Country or larger entity
b       NR      First-order political jurisdiction
c       NR      Intermediate political jurisdiction
d       NR      City
e       R       Relator term
f       R       City subsection
g       R       Other nonjurisdictional geographic region and feature
h       R       Extraterrestrial area
0       R       Authority record control number
2       NR      Source of heading or term
4       R       Relationship
6       NR      Linkage
8       R       Field link and sequence number

753     R       SYSTEM DETAILS ACCESS TO COMPUTER FILES
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Make and model of machine
b       NR      Programming language
c       NR      Operating system
0       R       Authority record control number or standard number
2       NR      Source of term
6       NR      Linkage
8       R       Field link and sequence number

754     R       ADDED ENTRY--TAXONOMIC IDENTIFICATION
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Taxonomic name
c       R       Taxonomic category
d       R       Common or alternative name
x       R       Non-public note
z       R       Public note
0       R       Authority record control number
2       NR      Source of taxonomic identification
6       NR      Linkage
8       R       Field link and sequence number

760     R       MAIN SERIES ENTRY
ind1    01      Note controller
ind2    b8      Display constant controller
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
s       NR      Uniform title
t       NR      Title
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

762     R       SUBSERIES ENTRY
ind1    01      Note controller
ind2    b8      Display constant controller
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
s       NR      Uniform title
t       NR      Title
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

765     R       ORIGINAL LANGUAGE ENTRY
ind1    01      Note controller
ind2    b8      Display constant controller
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
r       R       Report number
s       NR      Uniform title
t       NR      Title
u       NR      Standard Technical Report Number
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
z       R       International Standard Book Number
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

767     R       TRANSLATION ENTRY
ind1    01      Note controller
ind2    b8      Display constant controller
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
r       R       Report number
s       NR      Uniform title
t       NR      Title
u       NR      Standard Technical Report Number
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
z       R       International Standard Book Number
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

770     R       SUPPLEMENT/SPECIAL ISSUE ENTRY
ind1    01      Note controller
ind2    b8      Display constant controller
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
r       R       Report number
s       NR      Uniform title
t       NR      Title
u       NR      Standard Technical Report Number
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
z       R       International Standard Book Number
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

772     R       SUPPLEMENT PARENT ENTRY
ind1    01      Note controller
ind2    b08     Display constant controller
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
r       R       Report number
s       NR      Uniform title
t       NR      Title
u       NR      Standard Technical Report Number
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
z       R       International Stan dard Book Number
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

773     R       HOST ITEM ENTRY
ind1    01      Note controller
ind2    b8      Display constant controller
a       NR      Main entry heading
b       NR      Edition
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
p       NR      Abbreviated title
q       NR      Enumeration and first page
r       R       Report number
s       NR      Uniform title
t       NR      Title
u       NR      Standard Technical Report Number
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
z       R       International Standard Book Number
3       NR      Materials specified
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

774     R       CONSTITUENT UNIT ENTRY
ind1    01      Note controller
ind2    b8      Display constant controller
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
r       R       Report number
s       NR      Uniform title
t       NR      Title
u       NR      Standard Technical Report Number
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
z       R       International Standard Book Number
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

775     R       OTHER EDITION ENTRY
ind1    01      Note controller
ind2    b8      Display constant controller
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
e       NR      Language code
f       NR      Country code
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
r       R       Report number
s       NR      Uniform title
t       NR      Title
u       NR      Standard Technical Report Number
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
z       R       International Standard Book Number
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

776     R       ADDITIONAL PHYSICAL FORM ENTRY
ind1    01      Note controller
ind2    b8      Display constant controller
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
r       R       Report number
s       NR      Uniform title
t       NR      Title
u       NR      Standard Technical Report Number
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
z       R       International Standard Book Number
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

777     R       ISSUED WITH ENTRY
ind1    01      Note controller
ind2    b8      Display constant controller
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
s       NR      Uniform title
t       NR      Title
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

780     R       PRECEDING ENTRY
ind1    01      Note controller
ind2    01234567    Type of relationship
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
r       R       Report number
s       NR      Uniform title
t       NR      Title
u       NR      Standard Technical Report Number
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
z       R       International Standard Book Number
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

785     R       SUCCEEDING ENTRY
ind1    01      Note controller
ind2    012345678    Type of relationship
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
r       R       Report number
s       NR      Uniform title
t       NR      Title
u       NR      Standa rd Technical Report Number
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
z       R       International Standard Book Number
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

786     R       DATA SOURCE ENTRY
ind1    01      Note controller
ind2    b8      Display constant controller
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
j       NR      Period of content
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
p       NR      Abbreviated title
r       R       Report number
s       NR      Uniform title
t       NR      Title
u       NR      Standard Technical Report Number
v       NR      Source Contribution
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
z       R       International Standard Book Number
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

787     R       OTHER RELATIONSHIP ENTRY
ind1    01      Note controller
ind2    b8      Display constant controller
a       NR      Main entry heading
b       NR      Edition
c       NR      Qualifying information
d       NR      Place, publisher, and date of publication
g       R       Related parts
h       NR      Physical description
i       R       Relationship information
k       R       Series data for related item
m       NR      Material-specific details
n       R       Note
o       R       Other item identifier
r       R       Report number
s       NR      Uniform title
t       NR      Title
u       NR      Standard Technical Report Number
w       R       Record control number
x       NR      International Standard Serial Number
y       NR      CODEN designation
z       R       International Standard Book Number
4       R       Relationship
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

800     R       SERIES ADDED ENTRY--PERSONAL NAME
ind1    013     Type of personal name entry element
ind2    blank   Undefined
a       NR      Personal name
b       NR      Numeration
c       R       Titles and other words associated with a name
d       NR      Dates associated with a name
e       R       Relator term
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
j       R       Attribution qualifier
k       R       Form subheading
l       NR      Language of a work
m       R       Medium of performance for music
n       R       Number of part/section of a work
o       NR      Arranged statement for music
p       R       Name of part/section of a work
q       NR      Fuller form of name
r       NR      Key for music
s       NR      Version
t       NR      Title of a work
u       NR      Affiliation
v       NR      Volume/sequential designation
w       R       Bibliographic record control number
x       NR      International Standard Serial Number
0       R       Authority record control number
3       NR      Materials specified
4       R       Relationship
5       R       Institution to which field applies
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

810     R       SERIES ADDED ENTRY--CORPORATE NAME
ind1    012     Type of corporate name entry element
ind2    blank   Undefined
a       NR      Corporate name or jurisdiction name as entry element
b       R       Subordinate unit
c       R       Location of meeting
d       R       Date of meeting or treaty signing
e       R       Relator term
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
k       R       Form subheading
l       NR      Language of a work
m       R       Medium of performance for music
n       R       Number of part/section/meeting
o       NR      Arranged statement for music
p       R       Name of part/section of a work
r       NR      Key for music
s       NR      Version
t       NR      Title of a work
u       NR      Affiliation
v       NR      Volume/sequential designation
w       R       Bibliographic record control number
x       NR      International Standard Serial Number
0       R       Authority record control number
3       NR      Materials specified
4       R       Relationship
5       R       Institution to which field applies
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

811     R       SERIES ADDED ENTRY--MEETING NAME
ind1    012     Type of meeting name entry element
ind2    blank   Undefined
a       NR      Meeting name or jurisdiction name as entry element
c       R       Location of meeting
d       NR      Date of meeting
e       R       Subordinate unit
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
j       R       Relator term
k       R       Form subheading
l       NR      Language of a work
n       R       Number of part/section/meeting
p       R       Name of part/section of a work
q       NR      Name of meeting following jurisdiction name entry element
s       NR      Version
t       NR      Title of a work
u       NR      Affiliation
v       NR      Volume/sequential designation
w       R       Bibliographic record control number
x       NR      International Standard Serial Number
0       R       Authority record control number
3       NR      Materials specified
4       R       Relationship
5       R       Institution to which field applies
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

830     R       SERIES ADDED ENTRY--UNIFORM TITLE
ind1    blank   Undefined
ind2    0-9     Nonfiling characters
a       NR      Uniform title
d       R       Date of treaty signing
f       NR      Date of a work
g       R       Miscellaneous information
h       NR      Medium
k       R       Form subheading
l       NR      Language of a work
m       R       Medium of performance for music
n       R       Number of part/section of a work
o       NR      Arranged statement for music
p       R       Name of part/section of a work
r       NR      Key for music
s       NR      Version
t       NR      Title of a work
v       NR      Volume/sequential designation
w       R       Bibliographic record control number
x       NR      International Standard Serial Number
0       R       Authority record control number
3       NR      Materials specified
5       R       Institution to which field applies
6       NR      Linkage
7       NR      Control subfield
8       R       Field link and sequence number

841     NR      HOLDINGS CODED DATA VALUES

842     NR      TEXTUAL PHYSICAL FORM DESIGNATOR

843     R       REPRODUCTION NOTE

844     NR      NAME OF UNIT

845     R       TERMS GOVERNING USE AND REPRODUCTION NOTE

850     R       HOLDING INSTITUTION
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Holding institution
8       R       Field link and sequence number

852     R       LOCATION
ind1    b012345678    Shelving scheme
ind2    b012    Shelving order
a       NR      Location
b       R       Sublocation or collection
c       R       Shelving location
d       R       Former shelving location
e       R       Address
f       R       Coded location qualifier
g       R       Non-coded location qualifier
h       NR      Classification part
i       R       Item part
j       NR      Shelving control number
k       R       Call number prefix
l       NR      Shelving form of title
m       R       Call number suffix
n       NR      Country code
p       NR      Piece designation
q       NR      Piece physical condition
s       R       Copyright article-fee code
t       NR      Copy number
u       R       Uniform Resource Identifier
x       R       Nonpublic note
z       R       Public note
2       NR      Source of classification or shelving scheme
3       NR      Materials specified
6       NR      Linkage
8       NR      Sequence number

853     R       CAPTIONS AND PATTERN--BASIC BIBLIOGRAPHIC UNIT

854     R       CAPTIONS AND PATTERN--SUPPLEMENTARY MATERIAL

855     R       CAPTIONS AND PATTERN--INDEXES

856     R       ELECTRONIC LOCATION AND ACCESS
ind1    b012347    Access method
ind2    b0128   Relationship
a       R       Host name
b       R       Access number
c       R       Compression information
d       R       Path
f       R       Electronic name
h       NR      Processor of request
i       R       Instruction
j       NR      Bits per second
k       NR      Password
l       NR      Logon
m       R       Contact for access assistance
n       NR      Name of location of host
o       NR      Operating system
p       NR      Port
q       NR      Electronic format type
r       NR      Settings
s       R       File size
t       R       Terminal emulation
u       R       Uniform Resource Identifier
v       R       Hours access method available
w       R       Record control number
x       R       Nonpublic note
y       R       Link text
z       R       Public note
2       NR      Access method
3       NR      Materials specified
6       NR      Linkage
8       R       Field link and sequence number

863     R       ENUMERATION AND CHRONOLOGY--BASIC BIBLIOGRAPHIC UNIT

864     R       ENUMERATION AND CHRONOLOGY--SUPPLEMENTARY MATERIAL

865     R       ENUMERATION AND CHRONOLOGY--INDEXES

866     R       TEXTUAL HOLDINGS--BASIC BIBLIOGRAPHIC UNIT

867     R       TEXTUAL HOLDINGS--SUPPLEMENTARY MATERIAL

868     R       TEXTUAL HOLDINGS--INDEXES

876     R       ITEM INFORMATION--BASIC BIBLIOGRAPHIC UNIT

877     R       ITEM INFORMATION--SUPPLEMENTARY MATERIAL

878     R       ITEM INFORMATION--INDEXES

880     R       ALTERNATE GRAPHIC REPRESENTATION
ind1            Same as associated field
ind2            Same as associated field
6       NR      Linkage

882     NR      REPLACEMENT RECORD INFORMATION
ind1    blank   Undefined
ind2    blank   Undefined
a       R       Replacement title
i       R       Explanatory text
w       R       Replacement bibliographic record control number
6       NR      Linkage
8       R       Field link and sequence number

883     R       MACHINE-GENERATED METADATA PROVENANCE
ind1    b01     Type of field
ind2    blank   Undefined
a       NR      Generation process
c       NR      Confidence value
d       NR      Generation date
q       NR      Generation agency
x       NR      Validity end date
u       NR      Uniform Resource Identifier
w       R       Bibliographic record control number
0       R       Authority record control number or standard number
8       R       Field link and sequence number

884     R       DESCRIPTION CONVERSION INFORMATION
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Conversion process
g       NR      Conversion date
k       NR      Identifier of source metadata
q       NR      Conversion agency
u       R       Uniform Resource Identifier

885     R       MATCHING INFORMATION
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Matching information
b       NR      Status of matching and its checking
c       NR      Confidence value
d       NR      Generation date
w       R       Record control number
x       R       Nonpublic note
z       R       Public note
0       R       Authority record control number or standard number
2       NR      Source
5       R       Institution to which field applies

886     R       FOREIGN MARC INFORMATION FIELD
ind1    012     Type of field
ind2    blank   Undefined
a       NR      Tag of the foreign MARC field
b       NR      Content of the foreign MARC field
c-z     NR      Foreign MARC subfield
0-1     NR      Foreign MARC subfield
2       NR      Source of data
4       NR      Source of data
3-9     NR      Source of data

887     R       NON-MARC INFORMATION FIELD
ind1    blank   Undefined
ind2    blank   Undefined
a       NR      Content of non-MARC field
2       NR      Source of data
RULES;
        // @codingStandardsIgnoreEnd
    }
    // }}}
}
// }}}

PK�2[7�*c��MARC/Subfield.phpnu�[���<?php

/* vim: set expandtab shiftwidth=4 tabstop=4 softtabstop=4 foldmethod=marker: */

/**
 * Parser for MARC records
 *
 * This package is based on the PHP MARC package, originally called "php-marc",
 * that is part of the Emilda Project (http://www.emilda.org). Christoffer
 * Landtman generously agreed to make the "php-marc" code available under the
 * GNU LGPL so it could be used as the basis of this PEAR package.
 * 
 * PHP version 5
 *
 * LICENSE: This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @category  File_Formats
 * @package   File_MARC
 * @author    Christoffer Landtman <landtman@realnode.com>
 * @author    Dan Scott <dscott@laurentian.ca>
 * @copyright 2003-2008 Oy Realnode Ab, Dan Scott
 * @license   http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @version   CVS: $Id$
 * @link      http://pear.php.net/package/File_MARC
 */

// {{{ class File_MARC_Subfield
/**
 * The File_MARC_Subfield class represents a single subfield in a MARC
 * record field.
 *
 * Represents a subfield within a MARC field and implements all management
 * functions related to a single subfield. This class also implements
 * the possibility of duplicate subfields within a single field, for example
 * 650 _z Test1 _z Test2.
 *
 * @category File_Formats
 * @package  File_MARC
 * @author   Christoffer Landtman <landtman@realnode.com>
 * @author   Dan Scott <dscott@laurentian.ca>
 * @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
 * @link     http://pear.php.net/package/File_MARC
 */
class File_MARC_Subfield
{
    // {{{ properties
    /**
     * Subfield code, e.g. _a, _b
     * @var string
     */
    protected $code;

    /**
     * Data contained by the subfield
     * @var string
     */
    protected $data;

    /**
     * Position of the subfield
     * @var int
     */
    protected $position;

    // }}}

    // {{{ Constructor: function __construct()
    /**
     * File_MARC_Subfield constructor
     *
     * Create a new subfield to represent the code and data
     *
     * @param string $code Subfield code
     * @param string $data Subfield data
     */
    function __construct($code, $data)
    {
        $this->code = $code;
        $this->data = $data;
    }
    // }}}

    // {{{ Destructor: function __destruct()
    /**
     * Destroys the subfield
     */
    function __destruct()
    {
        $this->code = null;
        $this->data = null;
        $this->position = null;
    }
    // }}}

    // {{{ Explicit destructor: function delete()
    /**
     * Destroys the subfield
     *
     * @return true
     */
    function delete()
    {
        $this->__destruct();
    }
    // }}}

    // {{{ getCode()
    /**
     * Return code of the subfield
     *
     * @return string Tag name
     */
    function getCode()
    {
        return (string)$this->code;
    }
    // }}}

    // {{{ getData()
    /**
     * Return data of the subfield
     *
     * @return string data
     */
    function getData()
    {
        return (string)$this->data;
    }
    // }}}

    // {{{ getPosition()
    /**
     * Return position of the subfield
     *
     * @return int data
     */
    function getPosition()
    {
        return $this->position;
    }
    // }}}

    // {{{ __toString()
    /**
     * Return string representation of subfield
     *
     * @return string String representation
     */
    public function __toString()
    {
        $pretty = '[' . $this->getCode() . ']: ' . $this->getData();
        return $pretty;
    }
    // }}}

    // {{{ toRaw()
    /**
     * Return the USMARC representation of the subfield
     *
     * @return string USMARC representation
     */
    function toRaw()
    {
        $result = File_MARC::SUBFIELD_INDICATOR.$this->code.$this->data;
        return (string)$result;
    }
    // }}}

    // {{{ setCode()
    /**
     * Sets code of the subfield
     *
     * @param string $code new code for the subfield
     *
     * @return string code 
     */
    function setCode($code)
    {
        if ($code) {
            // could check more stringently; m/[a-Z]/ or the likes
            $this->code = $code;
        } else {
            // code must be _something_; raise error
            return false;
        }
        return true;
    }
    // }}}

    // {{{ setData()
    /**
     * Sets data of the subfield
     *
     * @param string $data new data for the subfield
     *
     * @return string data
     */
    function setData($data)
    {
        $this->data = $data;
        return true;
    }
    // }}}

    // {{{ setPosition()
    /**
     * Sets position of the subfield
     *
     * @param string $pos new position of the subfield
     *
     * @return void
     */
    function setPosition($pos)
    {
        $this->position = $pos;
    }
    // }}}

    // {{{ isEmpty()
    /**
     * Checks whether the subfield is empty or not
     *
     * @return bool True or false
     */
    function isEmpty()
    {
        // There is data
        if (strlen($this->data)) {
            return false;
        }

        // There is no data
        return true;
    }
    // }}}
}
// }}}

PK
W�Z �$?[3[3Glob.pmnu�[���PK
W�Z��W::
�3DosGlob.pmnu�[���PK�6�Z��M�^'^'Sstat.pmnu�[���PK�6�Z��H??�zCopy.pmnu�[���PK�6�Z��CU>=>=
�GlobMapper.pmnu�[���PK�6�Z3�w�+�+i�Basename.pmnu�[���PK�6�Z�J@d�d�^#Find.pmnu�[���PK�6�Z�tڪ��
��Compare.pmnu�[���PKnc[��##�Spec/Epoc.pmnu�[���PKnc[�
5m~�Spec/Cygwin.pmnu�[���PKnc[�F� >>��Spec/Unix.pmnu�[���PKnc[���WW#Spec/Mac.pmnu�[���PKoc[�L� nn`cSpec/OS2.pmnu�[���PKoc[�Hz���	~Spec/AmigaOS.pmnu�[���PKoc[��
�+�+
�Spec/Win32.pmnu�[���PKoc[�4+8,	,	,�Spec/Functions.pmnu�[���PKoc[�LhlK)K)��Spec.pmnu�[���PK�2[�/f���MARCBASE.phpnu�[���PK�2[5F	'�"�"��MARCXML.phpnu�[���PK�2[Sbw�{7{7�MARC.phpnu�[���PK�2[�9g4xUxUhOMARC/Record.phpnu�[���PK�2[(#�~���MARC/Exception.phpnu�[���PK�2[�S��hh
��MARC/List.phpnu�[���PK�2[�+������MARC/Field.phpnu�[���PK�2[�IC�(A(A��MARC/Lint/CodeData.phpnu�[���PK�2[R��A;A;:MARC/Data_Field.phpnu�[���PK�2[lz�`�uMARC/Control_Field.phpnu�[���PK�2[Ɍ5��9�9
�MARC/Lint.phpnu�[���PK�2[7�*c���MARC/Subfield.phpnu�[���PK���