summaryrefslogtreecommitdiff
path: root/systems/texlive/tlnet/tlpkg/TeXLive/TLPSRC.pm
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /systems/texlive/tlnet/tlpkg/TeXLive/TLPSRC.pm
Initial commit
Diffstat (limited to 'systems/texlive/tlnet/tlpkg/TeXLive/TLPSRC.pm')
-rw-r--r--systems/texlive/tlnet/tlpkg/TeXLive/TLPSRC.pm1194
1 files changed, 1194 insertions, 0 deletions
diff --git a/systems/texlive/tlnet/tlpkg/TeXLive/TLPSRC.pm b/systems/texlive/tlnet/tlpkg/TeXLive/TLPSRC.pm
new file mode 100644
index 0000000000..1bd1e73808
--- /dev/null
+++ b/systems/texlive/tlnet/tlpkg/TeXLive/TLPSRC.pm
@@ -0,0 +1,1194 @@
+# $Id: TLPSRC.pm 49434 2018-12-17 18:48:58Z karl $
+# TeXLive::TLPSRC.pm - module for handling tlpsrc files
+# Copyright 2007-2018 Norbert Preining
+# This file is licensed under the GNU General Public License version 2
+# or any later version.
+
+package TeXLive::TLPSRC;
+
+use FileHandle;
+use TeXLive::TLConfig qw($CategoriesRegexp $DefaultCategory);
+use TeXLive::TLUtils;
+use TeXLive::TLPOBJ;
+use TeXLive::TLTREE;
+
+my $svnrev = '$Revision: 49434 $';
+my $_modulerevision = ($svnrev =~ m/: ([0-9]+) /) ? $1 : "unknown";
+sub module_revision { return $_modulerevision; }
+
+my $_tmp; # sorry
+my %autopatterns; # computed once internally
+
+sub new {
+ my $class = shift;
+ my %params = @_;
+ my $self = {
+ name => $params{'name'},
+ category => defined($params{'category'}) ? $params{'category'}
+ : $DefaultCategory,
+ shortdesc => $params{'shortdesc'},
+ longdesc => $params{'longdesc'},
+ catalogue => $params{'catalogue'},
+ runpatterns => $params{'runpatterns'},
+ srcpatterns => $params{'srcpatterns'},
+ docpatterns => $params{'docpatterns'},
+ binpatterns => $params{'binpatterns'},
+ postactions => $params{'postactions'},
+ executes => defined($params{'executes'}) ? $params{'executes'} : [],
+ depends => defined($params{'depends'}) ? $params{'depends'} : [],
+ };
+ bless $self, $class;
+ return $self;
+}
+
+
+sub from_file {
+ my $self = shift;
+ die "need exactly one filename for initialization" if @_ != 1;
+ my $srcfile = $_[0];
+ my $pkgname = TeXLive::TLUtils::basename($srcfile);
+ $pkgname =~ s/\.tlpsrc$//;
+
+ if (! -r "$srcfile") {
+ # if the argument is not readable as is, try looking for it in the
+ # hierarchy where we are. The %INC hash records where packages were
+ # found, so we use that to locate ourselves.
+ (my $trydir = $INC{"TeXLive/TLPSRC.pm"}) =~ s,/[^/]*$,,;
+ chomp ($trydir = `cd $trydir/../tlpsrc && pwd`); # make absolute
+ my $tryfile = "$trydir/$pkgname.tlpsrc";
+ #warn "$trydir\n$tryfile\n";
+ $srcfile = $tryfile if -r $tryfile;
+ }
+
+ open(TMP, "<$srcfile") || die("failed to open tlpsrc '$srcfile': $!");
+ my @lines = <TMP>;
+ close(TMP);
+
+ my $name = $pkgname;
+ my $category = "Package";
+ my $shortdesc = "";
+ my $longdesc= "";
+ my $catalogue = "";
+ my (@executes, @depends);
+ my (@runpatterns, @docpatterns, @binpatterns, @srcpatterns);
+ my (@postactions);
+ my $foundnametag = 0;
+ my $finished = 0;
+ my $savedline = "";
+ my %tlpvars;
+ $tlpvars{"PKGNAME"} = $name;
+
+ my $lineno = 0;
+ for my $line (@lines) {
+ $lineno++;
+
+ # we allow continuation lines in tlpsrc files, i.e., lines ending with \.
+ if ($line =~ /^(.*)\\$/) {
+ $savedline .= $1;
+ next;
+ }
+ if ($savedline ne "") {
+ # we are in a continuation line
+ $line = "$savedline$line";
+ $savedline = "";
+ }
+
+ $line =~ /^\s*#/ && next; # skip comment lines
+ next if $line =~ /^\s*$/; # skip blank lines
+ # (blank lines are significant in tlpobj, but not tlpsrc)
+ #
+ $line =~ /^ /
+ && die "$srcfile:$lineno: non-continuation indentation not allowed: `$line'";
+ #
+ # remove trailing white space.
+ $line =~ s/\s+$//;
+
+ # expand tlpvars while reading in (except in descriptions).
+ # that means we have to respect *order* and define variables
+ # as we read the tlpsrc file.
+ if ($line !~ /^(short|long)desc\s/) {
+ #debug: my $origline = $line;
+ for my $k (keys %tlpvars) {
+ $line =~ s/\$\{\Q$k\E\}/$tlpvars{$k}/g;
+ }
+ # check that no variables remain unexpanded, or rather, for any
+ # remaining $ (which we don't otherwise allow in tlpsrc files, so
+ # should never occur) ... except for ${ARCH} which we specially
+ # expand in TLTREE.pm. (Sigh: we distribute one file dvi$pdf.bat,
+ # but fortunately it is matched by a directory.)
+ #
+ (my $testline = $line) =~ s,\$\{ARCH\},,g;
+ $testline =~ /\$/
+ && die "$srcfile:$lineno: variable undefined or syntax error: $line\n";
+ #debug: warn "new line $line, from $origline\n" if $origline ne $line;
+ } # end variable expansion.
+
+ # names of source packages can either be
+ # - normal names: ^[-\w]+$
+ # - win32 specific packages: ^[-\w]+\.win32$
+ # - normal texlive specific packages: ^texlive.*\..*$
+ # - configuration texlive specific packages: ^00texlive.*\..*$
+ if ($line =~ /^name\s/) {
+ $line =~ /^name\s+([-\w]+(\.win32)?|(00)?texlive\..*)$/;
+ $foundnametag
+ && die "$srcfile:$lineno: second name directive not allowed: $line"
+ . "(have $name)\n";
+ $name = $1;
+ $foundnametag = 1;
+ # let's assume that $PKGNAME doesn't occur before any name
+ # directive (which would result in different expansions); there is
+ # no need for it in practice.
+ $tlpvars{"PKGNAME"} = $name;
+
+ } elsif ($line =~ /^category\s+$CategoriesRegexp$/) {
+ $category = $1;
+
+ } elsif ($line =~ /^shortdesc\s*(.*)$/) {
+ $shortdesc
+ && die "$srcfile:$lineno: second shortdesc not allowed: $line"
+ . "(have $shortdesc)\n";
+ $shortdesc = $1;
+
+ } elsif ($line =~ /^shortdesc$/) {
+ $shortdesc = "";
+
+ } elsif ($line =~ /^longdesc$/) {
+ $longdesc .= "\n";
+
+ } elsif ($line =~ /^longdesc\s+(.*)$/) {
+ $longdesc .= "$1 ";
+
+ } elsif ($line =~ /^catalogue\s+(.*)$/) {
+ $catalogue
+ && die "$srcfile:$lineno: second catalogue not allowed: $line"
+ . "(have $catalogue)\n";
+ $catalogue = $1;
+
+ } elsif ($line =~ /^runpattern\s+(.*)$/) {
+ push (@runpatterns, $1) if ($1 ne "");
+
+ } elsif ($line =~ /^srcpattern\s+(.*)$/) {
+ push (@srcpatterns, $1) if ($1 ne "");
+
+ } elsif ($line =~ /^docpattern\s+(.*)$/) {
+ push (@docpatterns, $1) if ($1 ne "");
+
+ } elsif ($line =~ /^binpattern\s+(.*)$/) {
+ push (@binpatterns, $1) if ($1 ne "");
+
+ } elsif ($line =~ /^execute\s+(.*)$/) {
+ push (@executes, $1) if ($1 ne "");
+
+ } elsif ($line =~ /^depend\s+(.*)$/) {
+ push (@depends, $1) if ($1 ne "");
+
+ } elsif ($line =~ /^postaction\s+(.*)$/) {
+ push (@postactions, $1) if ($1 ne "");
+
+ } elsif ($line =~ /^tlpsetvar\s+([-_a-zA-Z0-9]+)\s+(.*)$/) {
+ $tlpvars{$1} = $2;
+
+ } else {
+ die "$srcfile:$lineno: unknown tlpsrc directive, fix: $line\n";
+ }
+ }
+ $self->_srcfile($srcfile);
+ if ($name =~ m/^[[:space:]]*$/) {
+ die "Cannot deduce name from file argument and name tag not found";
+ }
+ $self->name($name);
+ $self->category($category);
+ $self->catalogue($catalogue) if $catalogue;
+ $self->shortdesc($shortdesc) if $shortdesc;
+ $self->longdesc($longdesc) if $longdesc;
+ $self->srcpatterns(@srcpatterns) if @srcpatterns;
+ $self->runpatterns(@runpatterns) if @runpatterns;
+ $self->binpatterns(@binpatterns) if @binpatterns;
+ $self->docpatterns(@docpatterns) if @docpatterns;
+ $self->executes(@executes) if @executes;
+ $self->depends(@depends) if @depends;
+ $self->postactions(@postactions) if @postactions;
+}
+
+
+sub writeout {
+ my $self = shift;
+ my $fd = (@_ ? $_[0] : STDOUT);
+ format_name $fd "multilineformat"; # format defined in TLPOBJ, and $:
+ $fd->format_lines_per_page (99999); # no pages in this format
+ print $fd "name ", $self->name, "\n";
+ print $fd "category ", $self->category, "\n";
+ defined($self->{'catalogue'}) && print $fd "catalogue $self->{'catalogue'}\n";
+ defined($self->{'shortdesc'}) && print $fd "shortdesc $self->{'shortdesc'}\n";
+ if (defined($self->{'longdesc'})) {
+ $_tmp = "$self->{'longdesc'}";
+ write $fd; # use that multilineformat
+ }
+ if (defined($self->{'depends'})) {
+ foreach (@{$self->{'depends'}}) {
+ print $fd "depend $_\n";
+ }
+ }
+ if (defined($self->{'executes'})) {
+ foreach (@{$self->{'executes'}}) {
+ print $fd "execute $_\n";
+ }
+ }
+ if (defined($self->{'postactions'})) {
+ foreach (@{$self->{'postactions'}}) {
+ print $fd "postaction $_\n";
+ }
+ }
+ if (defined($self->{'srcpatterns'}) && (@{$self->{'srcpatterns'}})) {
+ foreach (sort @{$self->{'srcpatterns'}}) {
+ print $fd "srcpattern $_\n";
+ }
+ }
+ if (defined($self->{'runpatterns'}) && (@{$self->{'runpatterns'}})) {
+ foreach (sort @{$self->{'runpatterns'}}) {
+ print $fd "runpattern $_\n";
+ }
+ }
+ if (defined($self->{'docpatterns'}) && (@{$self->{'docpatterns'}})) {
+ foreach (sort @{$self->{'docpatterns'}}) {
+ print $fd "docpattern $_\n";
+ }
+ }
+ if (defined($self->{'binpatterns'}) && (@{$self->{'binpatterns'}})) {
+ foreach (sort @{$self->{'binpatterns'}}) {
+ print $fd "binpattern $_\n";
+ }
+ }
+}
+
+
+# the hard work, generate the TLPOBJ data.
+#
+sub make_tlpobj {
+ my ($self,$tltree,$autopattern_root) = @_;
+ my %allpatterns = &find_default_patterns($autopattern_root);
+ my $category_patterns = $allpatterns{$self->category};
+
+ my $tlp = TeXLive::TLPOBJ->new;
+ $tlp->name($self->name);
+ $tlp->category($self->category);
+ $tlp->shortdesc($self->{'shortdesc'}) if (defined($self->{'shortdesc'}));
+ $tlp->longdesc($self->{'longdesc'}) if (defined($self->{'longdesc'}));
+ $tlp->catalogue($self->{'catalogue'}) if (defined($self->{'catalogue'}));
+ $tlp->executes(@{$self->{'executes'}}) if (defined($self->{'executes'}));
+ $tlp->postactions(@{$self->{'postactions'}}) if (defined($self->{'postactions'}));
+ $tlp->depends(@{$self->{'depends'}}) if (defined($self->{'depends'}));
+ $tlp->revision(0);
+
+ # convert each fmttrigger to a depend line, if not already present.
+ if (defined($tlp->executes)) { # else no fmttriggers
+ my @deps = (defined($tlp->depends) ? $tlp->depends : ());
+ my $tlpname = $tlp->name;
+ for my $e ($tlp->executes) {
+ # we only check for AddFormat lines
+ if ($e =~ m/^\s*AddFormat\s+(.*)\s*$/) {
+ my %fmtline = TeXLive::TLUtils::parse_AddFormat_line($1);
+ if (defined($fmtline{"error"})) {
+ tlwarn ("error in parsing $e for return hash: $fmtline{error}\n");
+ } else {
+ # make sure that we don't add circular deps
+ TeXLive::TLUtils::push_uniq (\@deps,
+ grep { $_ ne $tlpname } @{$fmtline{'fmttriggers'}});
+ }
+ }
+ }
+ $tlp->depends(@deps);
+ }
+
+ my $filemax;
+ my $usedefault;
+ my @allpospats;
+ my @allnegpats;
+ my $pkgname = $self->name;
+ my @autoaddpat;
+
+ # src/run/doc patterns
+ #
+ # WARNING WARNING WARNING
+ # the "bin" must be last since we drop through for further dealing
+ # with specialities of the bin patterns!!!!
+ for my $pattype (qw/src run doc bin/) {
+ @allpospats = ();
+ @allnegpats = ();
+ @autoaddpat = ();
+ $usedefault = 1;
+ foreach my $p (@{$self->{${pattype} . 'patterns'}}) {
+ if ($p =~ m/^a\s+(.*)\s*$/) {
+ # format
+ # a toplevel1 toplevel2 toplevel3 ...
+ # which add autopatterns as if we are doing single packages
+ # toplevel1 toplevel2 toplevel3
+ push @autoaddpat, split(' ', $1);
+ } elsif ($p =~ m/^!\+(.*)$/) {
+ push @allnegpats, $1;
+ } elsif ($p =~ m/^\+!(.*)$/) {
+ push @allnegpats, $1;
+ } elsif ($p =~ m/^\+(.*)$/) {
+ push @allpospats, $1;
+ } elsif ($p =~ m/^!(.*)$/) {
+ push @allnegpats, $1;
+ $usedefault = 0;
+ } else {
+ push @allpospats, $p;
+ $usedefault = 0;
+ }
+ }
+
+ if ($usedefault) {
+ push @autoaddpat, $pkgname;
+ }
+ if (defined($category_patterns)) {
+ for my $a (@autoaddpat) {
+ my $type_patterns = $category_patterns->{$pattype};
+ for my $p (@{$type_patterns}) {
+ # the occurrence of %[str:]NAME[:str]% and its
+ # expansion is documented in 00texlive.autopatterns.tlpsrc
+ # we have to make a copy of $p otherwise we change it in the
+ # hash once and for all
+ my $pp = $p;
+ while ($pp =~ m/%(([^%]*):)?NAME(:([^%]*))?%/) {
+ my $nn = $a;
+ if (defined($1)) {
+ $nn =~ s/^$2//;
+ }
+ if (defined($3)) {
+ $nn =~ s/$4$//;
+ }
+ $pp =~ s/%(([^%]*):)?NAME(:([^%]*))?%/$nn/;
+ }
+ # replace the string %NAME% with the actual package name
+ #(my $pp = $p) =~ s/%NAME%/$a/g;
+ # sort through the patterns, and make sure that * are added to
+ # tag the default patterns
+ if ($pp =~ m/^!(.*)$/) {
+ push @allnegpats, "*$1";
+ } else {
+ push @allpospats, "*$pp";
+ }
+ }
+ }
+ }
+ # at this point we do NOT do the actual pattern matching for
+ # bin patterns, since we have some specialities to do
+ last if ($pattype eq "bin");
+
+ # for all other patterns we create the list and add the files
+ foreach my $p (@allpospats) {
+ ddebug("pos pattern $p\n");
+ $self->_do_normal_pattern($p,$tlp,$tltree,$pattype);
+ }
+ foreach my $p (@allnegpats) {
+ ddebug("neg pattern $p\n");
+ $self->_do_normal_pattern($p,$tlp,$tltree,$pattype,1);
+ }
+ }
+ #
+ # binpatterns
+ #
+ # mind that @allpospats and @allnegpats have already been set up
+ # in the above loop. We only have to deal with the specialities of
+ # the bin patterns
+ foreach my $p (@allpospats) {
+ my @todoarchs = $tltree->architectures;
+ my $finalp = $p;
+ if ($p =~ m%^(\w+)/(!?[-_a-z0-9,]+)\s+(.*)$%) {
+ my $pt = $1;
+ my $aa = $2;
+ my $pr = $3;
+ if ($aa =~ m/^!(.*)$/) {
+ # negative specification
+ my %negarchs;
+ foreach (split(/,/,$1)) {
+ $negarchs{$_} = 1;
+ }
+ my @foo = ();
+ foreach (@todoarchs) {
+ push @foo, $_ unless defined($negarchs{$_});
+ }
+ @todoarchs = @foo;
+ } else {
+ @todoarchs = split(/,/,$aa);
+ }
+ # set $p to the pattern without arch specification
+ $finalp = "$pt $pr";
+ }
+ # one final trick
+ # if the original pattern string matches bin/win32/ then we *only*
+ # work on the win32 arch
+ if ($finalp =~ m! bin/win32/!) {
+ @todoarchs = qw/win32/;
+ }
+ # now @todoarchs contains only those archs for which we want
+ # to match the pattern
+ foreach my $arch (@todoarchs) {
+ # get only those files matching the pattern
+ my @archfiles = $tltree->get_matching_files('bin',$finalp, $pkgname, $arch);
+ if (!@archfiles) {
+ if (($arch ne "win32") || defined($::tlpsrc_pattern_warn_win)) {
+ tlwarn("$self->{name} ($arch): no hit on binpattern $finalp\n");
+ }
+ }
+ $tlp->add_binfiles($arch,@archfiles);
+ }
+ }
+ foreach my $p (@allnegpats) {
+ my @todoarchs = $tltree->architectures;
+ my $finalp = $p;
+ if ($p =~ m%^(\w+)/(!?[-_a-z0-9,]+)\s+(.*)$%) {
+ my $pt = $1;
+ my $aa = $2;
+ my $pr = $3;
+ if ($aa =~ m/^!(.*)$/) {
+ # negative specification
+ my %negarchs;
+ foreach (split(/,/,$1)) {
+ $negarchs{$_} = 1;
+ }
+ my @foo = ();
+ foreach (@todoarchs) {
+ push @foo, $_ unless defined($negarchs{$_});
+ }
+ @todoarchs = @foo;
+ } else {
+ @todoarchs = split(/,/,$aa);
+ }
+ # set $p to the pattern without arch specification
+ $finalp = "$pt $pr";
+ }
+ # now @todoarchs contains only those archs for which we want
+ # to match the pattern
+ foreach my $arch (@todoarchs) {
+ # get only those files matching the pattern
+ my @archfiles = $tltree->get_matching_files('bin', $finalp, $pkgname, $arch);
+ if (!@archfiles) {
+ if (($arch ne "win32") || defined($::tlpsrc_pattern_warn_win)) {
+ tlwarn("$self->{name} ($arch): no hit on negative binpattern $finalp\n")
+ unless $::tlpsrc_pattern_no_warn_negative;
+ # see comments in libexec/place script.
+ }
+ }
+ $tlp->remove_binfiles($arch,@archfiles);
+ }
+ }
+ # add the revision number of the .tlpsrc file to the compute list:
+ $tlp->recompute_revision($tltree,
+ $tltree->file_svn_lastrevision("tlpkg/tlpsrc/$self->{name}.tlpsrc"));
+ $tlp->recompute_sizes($tltree);
+ return $tlp;
+}
+
+sub _do_normal_pattern {
+ my ($self,$p,$tlp,$tltree,$type,$negative) = @_;
+ my $is_default_pattern = 0;
+ if ($p =~ m/^\*/) {
+ $is_default_pattern = 1;
+ $p =~ s/^\*//;
+ }
+ my @matchfiles = $tltree->get_matching_files($type, $p, $self->{'name'});
+ if (!$is_default_pattern && !@matchfiles
+ && ($p !~ m,^f ignore,) && ($p !~ m,^d tlpkg/backups,)) {
+ tlwarn("$self->{name}: no hit for pattern $p\n")
+ unless $negative && $::tlpsrc_pattern_no_warn_negative;
+ }
+ if (defined($negative) && $negative == 1) {
+ $tlp->remove_files($type,@matchfiles);
+ } else {
+ $tlp->add_files($type,@matchfiles);
+ }
+}
+
+
+# get the default patterns for all categories from an external file,
+# return hash with keys being the categories (Package, Collection, etc.)
+# and values being refs to another hash. The subhash's keys are the
+# file types (run bin doc ...) with values being refs to an array of
+# patterns for that type.
+#
+sub find_default_patterns {
+ my ($tlroot) = @_;
+ # %autopatterns is global.
+ return %autopatterns if keys %autopatterns; # only compute once
+
+ my $apfile = "$tlroot/tlpkg/tlpsrc/00texlive.autopatterns.tlpsrc";
+ die "No autopatterns file found: $apfile" if ! -r $apfile;
+
+ my $tlsrc = new TeXLive::TLPSRC;
+ $tlsrc->from_file ($apfile);
+ if ($tlsrc->binpatterns) {
+ for my $p ($tlsrc->binpatterns) {
+ my ($cat, @rest) = split ' ', $p;
+ push @{$autopatterns{$cat}{"bin"}}, join(' ', @rest);
+ }
+ }
+ if ($tlsrc->srcpatterns) {
+ for my $p ($tlsrc->srcpatterns) {
+ my ($cat, @rest) = split ' ', $p;
+ push @{$autopatterns{$cat}{"src"}}, join(' ', @rest);
+ }
+ }
+ if ($tlsrc->docpatterns) {
+ for my $p ($tlsrc->docpatterns) {
+ my ($cat, @rest) = split ' ', $p;
+ push @{$autopatterns{$cat}{"doc"}}, join(' ', @rest);
+ }
+ }
+ if ($tlsrc->runpatterns) {
+ for my $p ($tlsrc->runpatterns) {
+ my ($cat, @rest) = split ' ', $p;
+ push @{$autopatterns{$cat}{"run"}}, join(' ', @rest);
+ }
+ }
+
+ for my $cat (keys %autopatterns) {
+ ddebug ("Category $cat\n");
+ for my $d (@{$autopatterns{$cat}{"bin"}}) {
+ ddebug ("auto bin pattern $d\n");
+ }
+ for my $d (@{$autopatterns{$cat}{"src"}}) {
+ ddebug ("auto src pattern $d\n");
+ }
+ for my $d (@{$autopatterns{$cat}{"doc"}}) {
+ ddebug ("auto doc pattern $d\n");
+ }
+ for my $d (@{$autopatterns{$cat}{"run"}}) {
+ ddebug ("auto run pattern $d\n");
+ }
+ }
+
+ return %autopatterns;
+}
+
+
+# member access functions
+#
+sub _srcfile {
+ my $self = shift;
+ if (@_) { $self->{'_srcfile'} = shift }
+ return $self->{'_srcfile'};
+}
+sub name {
+ my $self = shift;
+ if (@_) { $self->{'name'} = shift }
+ return $self->{'name'};
+}
+sub category {
+ my $self = shift;
+ if (@_) { $self->{'category'} = shift }
+ return $self->{'category'};
+}
+sub shortdesc {
+ my $self = shift;
+ if (@_) { $self->{'shortdesc'} = shift }
+ return $self->{'shortdesc'};
+}
+sub longdesc {
+ my $self = shift;
+ if (@_) { $self->{'longdesc'} = shift }
+ return $self->{'longdesc'};
+}
+sub catalogue {
+ my $self = shift;
+ if (@_) { $self->{'catalogue'} = shift }
+ return $self->{'catalogue'};
+}
+sub srcpatterns {
+ my $self = shift;
+ if (@_) { @{ $self->{'srcpatterns'} } = @_ }
+ if (defined($self->{'srcpatterns'})) {
+ return @{ $self->{'srcpatterns'} };
+ } else {
+ return;
+ }
+}
+sub docpatterns {
+ my $self = shift;
+ if (@_) { @{ $self->{'docpatterns'} } = @_ }
+ if (defined($self->{'docpatterns'})) {
+ return @{ $self->{'docpatterns'} };
+ } else {
+ return;
+ }
+}
+sub binpatterns {
+ my $self = shift;
+ if (@_) { @{ $self->{'binpatterns'} } = @_ }
+ if (defined($self->{'binpatterns'})) {
+ return @{ $self->{'binpatterns'} };
+ } else {
+ return;
+ }
+}
+sub depends {
+ my $self = shift;
+ if (@_) { @{ $self->{'depends'} } = @_ }
+ return @{ $self->{'depends'} };
+}
+sub runpatterns {
+ my $self = shift;
+ if (@_) { @{ $self->{'runpatterns'} } = @_ }
+ if (defined($self->{'runpatterns'})) {
+ return @{ $self->{'runpatterns'} };
+ } else {
+ return;
+ }
+}
+sub executes {
+ my $self = shift;
+ if (@_) { @{ $self->{'executes'} } = @_ }
+ return @{ $self->{'executes'} };
+}
+sub postactions {
+ my $self = shift;
+ if (@_) { @{ $self->{'postactions'} } = @_ }
+ return @{ $self->{'postactions'} };
+}
+
+1;
+__END__
+
+
+=head1 NAME
+
+C<TeXLive::TLPSRC> -- TeX Live Package Source module
+
+=head1 SYNOPSIS
+
+ use TeXLive::TLPSRC;
+
+ my $tlpsrc = TeXLive::TLPSRC->new(name => "foobar");
+ $tlpsrc->from_file("/some/tlpsrc/package.tlpsrc");
+ $tlpsrc->from_file("package");
+ $tlpsrc->writeout;
+ $tlpsrc->writeout(\*FILEHANDLE);
+
+=head1 DESCRIPTION
+
+The C<TeXLive::TLPSRC> module handles TeX Live Package Source
+(C<.tlpsrc>) files, which contain all (and only) the information which
+cannot be automatically derived from other sources, notably the TeX Live
+directory tree and the TeX Catalogue. In other words, C<.tlpsrc> files
+are hand-maintained.
+
+=head1 FILE SPECIFICATION
+
+A C<tlpsrc> file consists of lines of the form:
+
+I<key> I<value>
+
+where I<key> can be C<name>, C<category>, C<shortdesc>, C<longdesc>,
+C<catalogue>, C<runpattern>, C<srcpattern>, C<docpattern>, C<binpattern>,
+C<execute>, C<postaction>, or C<depend>.
+
+Continuation lines are supported via a trailing backslash. That is, if
+the C<.tlpsrc> file contains two physical lines like this:
+
+ foo\
+ bar
+
+they are concatenated into C<foobar>. The backslash and the newline are
+removed; no other whitespace is added or removed.
+
+Comment lines begin with a # and continue to the end of the line.
+
+Blank lines are ignored.
+
+The meaning of the I<key>s:
+
+=over 4
+
+=item C<name>
+
+identifies the package; C<value> must consist only of C<[-_a-zA-Z0-9]>,
+i.e., with what Perl considers a C<\w>.
+
+There are three exceptions to this rule:
+
+=over 8
+
+=item B<name.ARCH>
+
+where B<ARCH> is a supported architecture-os combination. This has two
+uses. First, packages are split (automatically) into containers for the
+different architectures to make possible installations including only
+the necessary binaries. Second, one can add 'one-arch-only' packages,
+often used to deal with Windows peculiarities.
+
+=item B<00texlive>I<something>
+
+These packages are used for internal operation and storage containers
+for settings. I<00texlive> packages are never be split into separate
+arch-packages, and containers are never generated for these packages.
+
+The full list of currently used packages of this type is:
+
+=over 8
+
+=item B<00texlive.config>
+
+This package contains configuration options for the TeX Live archive.
+If container_split_{doc,src}_files occurs in the depend lines the
+{doc,src} files are split into separate containers (.tar.xz)
+during container build time. Note that this has NO effect on the
+appearance within the texlive.tlpdb. It is only on container level.
+The container_format/XXXXX specifies the format, currently allowed
+is only "xz", which generates .tar.xz files. zip can be supported.
+release/NNNN specifies the release number as used in the installer.
+
+=item B<00texlive.installation>
+
+This package serves a double purpose:
+
+1. at installation time the present values are taken as default for
+the installer
+
+2. on an installed system it serves as configuration file. Since
+we have to remember these settings for additional package
+installation, removal, etc.
+
+=item B<00texlive.image>
+
+This package collects some files which are not caught by any of the
+other TL packages. Its primary purpose is to make the file coverage
+check happy. The files here are not copied by the installer
+and containers are not built; they exist only in the
+TeX Live Master tree.
+
+=item B<00texlive.installer>
+
+This package defines the files to go into the installer
+archives (install-tl-unx.tar.gz, install-tl.zip) built
+by the tl-make-installer script. Most of what's here is also
+included in the texlive.infra package -- ordinarily duplicates
+are not allowed, but in this case, 00texlive.installer is never
+used *except* to build the installer archives, so it's ok.
+
+=back
+
+=item B<texlive>I<some.thing>
+
+(notice the dot in the package name) These packages are central TeX Live
+internal packages and are treated as usual packages in (more or less)
+all respects, but have that extra dot to be sure they will never clash
+with any package that can possibly appear on CTAN. The only such
+package currently is C<texlive.infra>, which contains L<tlmgr> and other
+basic infrastructure functionality.
+
+=back
+
+=item C<category>
+
+identifies the category into which this package belongs. This determines
+the default patterns applied. Possible categories are defined in
+C<TeXLive::TLConfig>, currently C<Collection>, C<Scheme>, C<TLCore>,
+C<Package>, C<ConTeXt>. Most packages will fall into the C<Package>
+category.
+
+=item C<catalogue>
+
+identifies the name under which this package can be found in the TeX
+Catalogue.
+
+=item C<shortdesc>
+
+gives a one line description of the package. Subsequent entries will
+overwrite the former ones. In TeX Live primarily used for collections and
+schemes.
+
+=item C<longdesc>
+
+gives a long description of the package. Susequent entries are
+concatenated into a long text. In TeX Live only used for collections and
+schemes.
+
+=item C<depend>
+
+gives the list of dependencies, which are just other package names.
+All the C<depend> lines contribute to the dependencies of the package.
+Examples:
+
+ depend cm
+ depend plain
+ depend collection-basic
+
+=item C<execute>
+
+gives a free form entry of install time jobs to be executed. Currently
+the following possible values are understood by the installers:
+
+=over 4
+
+=item C<execute addMap> I<font>C<.map>
+
+enables the font map file I<font>C<.map> in the C<updmap.cfg> file.
+
+=item C<execute addMixedMap> I<font>C<.map>
+
+enables the font map file I<font>C<.map> for Mixed mode in the
+C<updmap.cfg> file.
+
+=item C<execute AddHyphen name=I<texlang> file=I<file> [I<var>...]>
+
+activates the hyphenation pattern with name I<texlang> and load the file
+I<file> for that language. The additional variables I<var> are:
+C<lefthyphenmin>, C<righthyphenmin> (both integers), C<synonyms> (a
+comma-separated list of alias names for that hyphenation), C<databases>
+(a comma-separated list of databases the entry should go in; currently
+recognized are: C<dat> (C<language.dat>), C<def> (C<language.def>) and
+C<lua> (C<language.dat.lua>)), C<file_patterns> and C<file_exceptions>
+(files with the patterns (resp. exceptions) in plain txt), and
+C<luaspecial> (string).
+
+The variable C<databases> defaults to C<dat,def>, or C<dat,def,lua> if
+one of the keys C<file_patterns>, C<file_exceptions> or C<luaspecial> is
+used.
+
+=item C<execute AddFormat name=I<fmt> engine=I<eng> [I<var>...]>
+
+activates the format with name I<fmt> based on the engine I<eng>. The
+additional variables I<var> are:
+C<mode> which can only be equal to C<disable> in which case the format
+will only be mentioned but disabled (prefixed with C<#!>;
+C<patterns> which gives the patterns file, if not present C<-> is used;
+C<options> which gives the additional options for the C<fmtutil.cnf> file.
+
+=back
+
+=item C<postaction>
+
+gives a free from entry of post install and removal actions to be
+executed. The difference to the C<execute> statement is that
+C<postaction> is concerned with system integration, i.e., adjusting
+things outside the installation directory, while C<execute> touches
+only things within the installation.
+
+Currently the following C<postaction>s are understood:
+
+=over 4
+
+=item C<postaction shortcut name=I<name> type=menu|desktop icon=I<path> cmd=I<cmd> args=I<args> hide=0|1>
+
+On W32 creates a shortcut either in the main TeX Live menu or on the
+desktop. Please see the documentation of TeXLive::TLWinGoo for details
+on the parameters.
+
+=item C<postaction filetype name=I<name> cmd=I<cmd>>
+
+On W32 associates the file type I<name> with the command I<cmd>.
+
+=item C<postaction fileassoc extension=I<.ext> filetype=I<name>>
+
+On W32 declares files with the extenstion I<.ext> of file type I<name>.
+
+=item C<postaction script file=I<file> [filew32=I<filew32>]>
+
+This postaction executes the given I<file> with two arguments, the first
+being the root of the installation, the second being either the string
+C<install> or C<remove>.
+
+If the C<filew32> argument is given this script is run on Windows systems
+instead of the one given via C<file>.
+
+=back
+
+=item C<tlpsetvar> I<var> I<val>
+
+sets variable I<var> to I<val>, for use within the current C<.tlpsrc>
+only. Order matters. The variable can be expanded with
+C<${>I<var>C<}> (after it is defined). Characters allowed in the I<var>
+name are C<-_a-zA-Z0-9>.
+
+=item C<(src|run|doc|bin)pattern> I<pattern>
+
+adds a pattern (next section) to the respective list of patterns.
+
+=back
+
+=head1 PATTERNS
+
+Patterns specify which files are to be included into a C<tlpobj> at
+expansion time. Patterns are of the form
+
+ [PREFIX]TYPE[/[!]ARCHSPEC] PAT
+
+where
+
+ PREFIX = + | +! | !
+ TYPE = t | f | d | r
+ ARCHSPEC = <list of architectures separated by comma>
+
+Simple patterns without PREFIX and ARCHSPEC specifications are explained
+first.
+
+=over 4
+
+=item C<f> I<path>
+
+includes all files which match C<path> where B<only> the last component
+of C<path> can contain the usual glob characters C<*> and C<?> (but no
+others!).
+
+=item C<d> I<path>
+
+includes all the files in and below the directory specified as C<path>.
+
+=item C<t> I<word1 ... wordN wordL>
+
+includes all the files in and below all directories of the form
+
+ word1/word2/.../wordN/.../any/dirs/.../wordL/
+
+i.e., all the first words but the last form the prefix of the path, then
+there can be an arbitrary number of subdirectories, followed by C<wordL>
+as the final directory. A real life example from C<omega.tlpsrc>:
+
+ runpattern t texmf-dist fonts omega
+
+matches C<texmf-dist/fonts/**/omega>, where C<**> matches any number of
+intervening subdirectories, e.g.:
+
+ texmf-dist/fonts/ofm/public/omega
+ texmf-dist/fonts/tfm/public/omega
+ texmf-dist/fonts/type1/public/omega
+
+=item C<r> I<regexp>
+
+includes all files matching the regexp C</^regexp$/>
+
+=item C<a> I<name1> [<name2> ...]
+
+includes auto generated patterns for each I<nameN> as if the package
+itself would be named I<nameN>. That is useful if a package (like venturisadf)
+contains toplevel directories named after different fonts.
+
+=back
+
+=head2 Special patterns
+
+=over 4
+
+=item PREFIX
+
+If the C<PREFIX> contains the symbol C<!> the meaning of the pattern is
+reversed, i.e., files matching this pattern are removed from the list of
+included files.
+
+The prefix C<+> means to append to the list of automatically synthesized
+patterns, instead of replacing them.
+
+The C<+> and C<!> prefixes can be combined. This is useful to exclude
+directories from the automatic pattern list. For example,
+C<graphics.tlpsrc> contains this line:
+
+ docpattern +!d texmf-dist/doc/latex/tufte-latex/graphics
+
+so that this subdirectory of the C<tufte-latex> package that happens to
+be named `graphics' is not mistakenly included in the C<graphics>
+package.
+
+=item Auto-generated patterns
+
+If a given pattern section is empty or B<all> the provided patterns have
+the prefix C<+> (e.g., C<+f ...>), then the following patterns, listed
+by type are I<automatically> added at expansion time. Note that this list
+is not definitive, but is taken from the patterns of tlpsrc files
+named C<00texlive.autopatterns.>I<Category>C<.tlpsrc>.
+
+=over 4
+
+=item C<runpattern>
+
+For category C<Package>:
+
+ t texmf-dist topdir $name
+
+where C<topdir> is one of: C<bibtex>, C<context>, C<dvips>, C<fonts>,
+C<makeindex>, C<metafont>, C<metapost>, C<mft>, C<omega>, C<scripts>,
+C<tex>, C<vtex>.
+
+For category C<ConTeXt>:
+
+ d texmf-dist/tex/context/third/%context-:NAME%
+ d texmf-dist/metapost/context/third/%context-:NAME%
+ f texmf-dist/tex/context/interface/third/*%context-:NAME%.xml
+
+(where C<%context-:NAME%> is replaced by the package name with an initial
+C<context-> is removed. E.g., if the package is called C<context-foobar>
+the replacement in the above rules will be C<foobar>.)
+
+For other categories B<no> patterns are automatically added to the
+list of C<runpattern>s.
+
+=item C<docpattern>
+
+for category C<Package>:
+
+ t texmf-dist doc $name
+
+for category C<ConTeXt>:
+
+ d texmf-dist/doc/context/third/%context-:NAME%
+
+(see above for the C<NAME> construct)
+
+=item C<srcpattern>
+
+for category C<Package>:
+
+ t texmf-dist source $name
+
+for category C<ConTeXt>:
+
+ d texmf-dist/source/context/third/%context-:NAME%
+
+(see above for the C<NAME> construct)
+
+=item C<binpattern>
+
+No C<binpattern>s are ever automatically added.
+
+=back
+
+=item Special treatment of binpatterns
+
+The binpatterns have to deal with all the different architectures. To
+ease the writing of patterns, we have the following:
+
+=over 4
+
+=item Architecture expansion
+
+Within a binpattern, the string C<${ARCH}> is automatically expanded to
+all available architectures.
+
+=item C<bat/exe/dll/texlua> for Windows
+
+C<binpattern>s that match Windows, e.g., C<f bin/win32/foobar> or C<f
+bin/${ARCH}/foobar>, also match the files C<foobar.bat>, C<foobar.cmd>,
+C<foobar.dll>, C<foobar.exe>, and C<foobar.texlua>.
+
+In addition, C<foobar.exe.manifest> and C<foobar.dll.manifest> are matched.
+
+The above two properties allows to capture the binaries for all
+architectures in one binpattern
+
+ binpattern f bin/${ARCH}/dvips
+
+and would get C<bin/win32/dvips.exe> into the runfiles for C<arch=win32>.
+
+This C<bat>/C<exe>/etc. expansion I<only> works for patterns of the C<f>
+type.
+
+=item ARCHSPEC specification of a pattern
+
+Sometimes files should be included into the list of binfiles of a
+package only for some architectures, or for all but some architectures.
+This can be done by specifying the list of architectures for which this
+pattern should be matched after the pattern specifier using a C</>:
+
+ binpattern f/win32 tlpkg/bin/perl.exe
+
+will include the file C<tlpkg/bin/perl.exe> only in the binfiles for
+the architecture C<win32>. Another example:
+
+ binpattern f/arch1,arch2,arch3 path/$ARCH/foo/bar
+
+This will only try to match this pattern for arch1, arch2, and arch3.
+
+Normally, a binpattern is matched against all possible architectures. If
+you want to exclude some architectures, instead of listing all the ones
+you want to include as above, you can prefix the list of architectures
+with a ! and these architectures will not be tested. Example:
+
+ binpattern f/!arch1,arch2 path/$ARCH/foo/bar
+
+will be matched against all architectures I<except> arch1 and arch2.
+
+=back
+
+=back
+
+
+=head1 MEMBER ACCESS FUNCTIONS
+
+For any of the above I<key>s a function
+
+ $tlpsrc->key
+
+is available, which returns the current value when called without an argument,
+and sets the respective value when called with an argument.
+
+Arguments and return values for C<name>, C<category>, C<shortdesc>,
+C<longdesc>, C<catalogue> are single scalars. Arguments and return values
+for C<depends>, C<executes>, and the various C<patterns> are lists.
+
+In addition, the C<_srcfile> member refers to the filename for this
+C<TLPSRC> object, if set (normally by C<from_file>).
+
+=head1 OTHER FUNCTIONS
+
+The following functions can be called for a C<TLPSRC> object:
+
+=over 4
+
+=item C<new>
+
+The constructor C<new> returns a new C<TLPSRC> object. The arguments
+to the C<new> constructor can be in the usual hash representation for
+the different keys above:
+
+ $tlpsrc = TLPSRC->new (name => "foobar",
+ shortdesc => "The foobar package");
+
+=item C<from_file("filename")>
+
+reads a C<tlpsrc> file from disk. C<filename> can either be a full path
+(if it's readable, it's used), or just a package identifier such as
+C<plain>. In the latter case, the directory searched is the C<tlpsrc>
+sibling of the C<TeXLive> package directory where C<TLPSRC.pm> was found.
+
+ $tlpsrc=new TeXLive::TLPSRC;
+ $tlpsrc->from_file("/path/to/the/tlpsrc/somepkg.tlpsrc");
+ $tlpsrc->from_file("somepkg");
+
+=item C<writeout>
+
+writes the textual representation of a C<TLPSRC> object to stdout, or the
+filehandle if given:
+
+ $tlpsrc->writeout;
+ $tlpsrc->writeout(\*FILEHANDLE);
+
+=item C<make_tlpobj($tltree)>
+
+creates a C<TLPOBJ> object from a C<TLPSRC> object and a C<TLTREE> object.
+This function does the necessary work to expand the manual data and
+enrich it which the actual content from C<$tltree> to a C<TLPOBJ> object.
+
+=back
+
+=head1 SEE ALSO
+
+The modules L<TeXLive::TLConfig>, L<TeXLive::TLUtils>, L<TeXLive::TLPOBJ>,
+L<TeXLive::TLPDB>, L<TeXLive::TLTREE>.
+
+The programs L<tlpsrc2tlpdb> and L<tlpsrc2tlpobj>.
+
+=head1 AUTHORS AND COPYRIGHT
+
+This script and its documentation were written for the TeX Live
+distribution (L<http://tug.org/texlive>) and both are licensed under the
+GNU General Public License Version 2 or later.
+
+=cut
+
+### Local Variables:
+### perl-indent-level: 2
+### tab-width: 2
+### indent-tabs-mode: nil
+### End:
+# vim:set tabstop=2 expandtab: #