OpenPKG CVS Repository
  http://cvs.openpkg.org/
  ____________________________________________________________________________

  Server: cvs.openpkg.org                  Name:   Ralf S. Engelschall
  Root:   /v/openpkg/cvs                   Email:  [EMAIL PROTECTED]
  Module: openpkg-tools                    Date:   24-Jul-2006 16:51:16
  Branch: HEAD                             Handle: 2006072415511500

  Modified files:
    openpkg-tools/cmd       index.pl

  Log:
    Complete refactoring of 'openpkg index' source code (without any
    semantical changes).

  Summary:
    Revision    Changes     Path
    1.8         +522 -496   openpkg-tools/cmd/index.pl
  ____________________________________________________________________________

  patch -p0 <<'@@ .'
  Index: openpkg-tools/cmd/index.pl
  ============================================================================
  $ cvs diff -u -r1.7 -r1.8 index.pl
  --- openpkg-tools/cmd/index.pl        4 Jul 2006 15:47:57 -0000       1.7
  +++ openpkg-tools/cmd/index.pl        24 Jul 2006 14:51:15 -0000      1.8
  @@ -22,47 +22,147 @@
   ##  SUCH DAMAGE.
   ##
   
  -require 5;
  +#############################################################################
  +##
  +##  MAIN PROCEDURE
  +##
  +#############################################################################
   
  +require 5;
   use strict;
  -
   use Getopt::Std;
  -use OpenPKG::Ctx;
  -getopts('r:p:C:o:ci');
  -use vars qw/$opt_r $opt_p $opt_C $opt_o $opt_c $opt_i/;
  -
   use FileHandle;
   use DirHandle;
   
  -my $ctx = new OpenPKG::Ctx;
  -my $l_prefix = $ctx->prefix();
  +#   determine OpenPKG instance prefix via
  +#   1. the environment of the "openpkg build" framework
  +#   2. the installation path of the script
  +#   3. the installation path of the Perl interpreter
  +#   4. the path of the "openpkg" command in $PATH
  +my $l_prefix = $ENV{'OPENPKG_PREFIX'};
  +if (not $l_prefix) {
  +    ($l_prefix) = ($0 =~ 
m/^(.+)\/lib(exec)?\/openpkg(-tools)?\/build(\.pl)?$/);
  +}
  +if (not $l_prefix) {
  +    ($l_prefix) = ($^X =~ m/^(.+)\/bin\/perl.*$/);
  +}
  +if (not $l_prefix) {
  +    $l_prefix = (`(which openpkg) 2>/dev/null` =~ m/^(.+)\/bin\/openpkg$/);
  +}
  +if (not -x "$l_prefix/bin/openpkg") {
  +    die "openpkg:build:FATAL: cannot determine OpenPKG instance prefix";
  +}
  +
  +#   determine tools
   my $RPM = ((-f "$l_prefix/bin/openpkg" && -f 
"$l_prefix/libexec/openpkg/rpm") ?
             "$l_prefix/bin/openpkg rpm" : "$l_prefix/bin/rpm");
   my $R2C = ((-f "$l_prefix/bin/openpkg" && -f 
"$l_prefix/libexec/openpkg/rpm2cpio") ?
             "$l_prefix/bin/openpkg rpm2cpio" : "$l_prefix/bin/rpm2cpio");
   my $BZ  = "$l_prefix/lib/openpkg/bzip2 -9";
   
  -#########################################################################
  +#   parse command line   
  +use vars qw/$opt_r $opt_p $opt_C $opt_o $opt_c $opt_i/;
  +getopts('r:p:C:o:ci');
  +if ($#ARGV < 0) {
  +    print "openpkg:index:USAGE: openpkg index [-r resource] [-p platform] 
[-C cache.db] [-o index.rdf] [-c] [-i] dir ...\n";
  +    exit(1);
  +}
  +
  +#   optionally open cache file
  +my %cache;
  +if ($opt_C) {
  +    eval {
  +        require DB_File;
  +    };
  +    if ($@) {
  +        die "openpkg:index:FATAL: The -C option requires an installed 
DB_File perl module.";
  +    }
  +    tie %cache, 'DB_File', $opt_C, O_CREAT|O_RDWR, 0666, $DB_File::DB_HASH
  +        or die "openpkg:index:FATAL: cannot tie cache '$opt_C' ($!)";
  +}
  +
  +#   provide default for repository path
  +$opt_r = 'OpenPKG-CURRENT/Source/' if (not defined($opt_r));
  +
  +#   create make_resource function closure
  +my $make_resource = gen_make_resource();
  +
  +#   determine output channel 
  +my $fh;
  +my $tmpo;
  +if (defined($opt_o)) {
  +    $tmpo = $opt_o . '.tmp';
  +    if ($opt_c) {
  +        $fh = new FileHandle "| $BZ -c > '$tmpo'"
  +            or die "openpkg:index:FATAL: cannot write '$tmpo' ($!)";
  +    } else {
  +        $fh = new FileHandle "> $tmpo"
  +            or die "openpkg:index:FATAL: cannot write '$tmpo' ($!)";
  +    }
  +} else {
  +    if ($opt_c) {
  +        $fh = new FileHandle "| $BZ -c"
  +            or die "openpkg:index:FATAL: cannot write to stdout ($!)";
  +    } else {
  +        $fh = new FileHandle ">&=1"
  +            or die "openpkg:index:FATAL: cannot write to stdout ($!)";
  +    }
  +}
  +
  +#   generate XML/RDF output
  +xml_head($fh, $opt_r);
  +foreach my $prefix (@ARGV) {
  +    my $list;
  +    if (-d $prefix) {
  +        if ($opt_i) {
  +            $list = list_rpmdir($prefix);
  +        } else {
  +            $list = list_specdir($prefix);
  +        }
  +    } else {
  +        $list = [ $prefix ];
  +        $prefix = dirname($prefix);
  +    }
  +    write_index($fh, $prefix, $opt_r, $opt_p, $list, $opt_C ? \%cache : 
undef);
  +}
  +xml_foot($fh);
   
  -#
  -# escape XML special characters for output in RDF file
  -#
  -# remove trailing whitespace
  -# remove common leading whitespace
  -#
  +#   close output channel
  +$fh->close()
  +    or die "openpkg:index:FATAL: write error on output ($!)";
  +
  +#   post-process output
  +if (defined($tmpo)) {
  +    rename($tmpo, $opt_o)
  +        or die "openpkg:index:FATAL: cannot rename $tmpo to $opt_o ($!)";
  +}
  +
  +#   die gracefully
  +exit(0);
  +
  +#############################################################################
  +##
  +##  OpenPKG RPM Package Specification Parsing
  +##
  +#############################################################################
  +
  +#   escape XML for output in RDF file
   sub e ($) {
  -    my($s) = @_;
  -    my($i);
  +    my ($s) = @_;
  +    my ($i);
   
  +    #   remove trailing whitespace
       $s =~ s/\n+$//sg;
       $s =~ s/[^\S\n]+$//mg;
   
  +    #   remove common leading whitespace
       $i = undef;
  -    while ($s =~ /^([^\S\n]+)/mg) {
  -        $i = $1 if !defined $i || length($1) < length($i);
  +    while ($s =~ m/^([^\S\n]+)/mg) {
  +        $i = $1 if (!defined($i) || (length($1) < length($i)));
       }
  +    $s =~ s/^\Q$i\E//mg if (defined($i));
   
  -    $s =~ s/^\Q$i\E//mg if defined $i;
  +    #   escape XML special characters
       $s =~ s/&/&amp;/sg;
       $s =~ s/</&lt;/sg;
       $s =~ s/>/&gt;/sg;
  @@ -70,250 +170,240 @@
       return $s;
   }
   
  -my %attrname = (
  -    '=='  => 'equ',
  -    '='   => 'equ',
  -    '>='  => 'geq',
  -    '=>'  => 'geq',
  -    '<='  => 'leq',
  -    '=<'  => 'leq',
  -    '>'   => 'gt',
  -    '<'   => 'lt'
  -);
  -my($opreg) = join '|',
  -    map {
  -        "\Q$_\E"
  -    } sort {
  -        length($b) <=> length($a) ||
  -        $b cmp $a
  -    } keys %attrname;
  -
  -sub make_resource ($) {
  -    my($s) = @_;
  -
  -    if ($s =~ /(\S+)\s*($opreg)\s*(.*?)\s*$/o) {
  -        return {
  -            resource  => $1,
  -            attrname  => $attrname{$2},
  -            attrval   => $3
  +#   make_resource closure
  +sub gen_make_resource {
  +    #   generate operator regular expression
  +    #   (used in make_resource below)
  +    my %attrname = (
  +        '=='  => 'equ',
  +        '='   => 'equ',
  +        '>='  => 'geq',
  +        '=>'  => 'geq',
  +        '<='  => 'leq',
  +        '=<'  => 'leq',
  +        '>'   => 'gt',
  +        '<'   => 'lt'
  +    );
  +    my ($opreg) =
  +        join '|',
  +        map {
  +            "\Q$_\E"
  +        } sort {
  +               length($b) <=> length($a)
  +            || $b cmp $a
  +        } keys(%attrname);
  +
  +    #   return function which makes resource object
  +    return sub ($) {
  +        my ($s) = @_;
  +
  +        if ($s =~ m/(\S+)\s*($opreg)\s*(.*?)\s*$/o) {
  +            return {
  +                resource  => $1,
  +                attrname  => $attrname{$2},
  +                attrval   => $3
  +            }
           }
  -    }
  -
  -    return {
  -        resource => $s
  -    }
  -}
  +        else {
  +            return {
  +                resource => $s
  +            }
  +        }
  +    };
  +};
   
  +#   split string into array at comma seperator
  +#   (optioanlly map resource operators into resource objects)
   sub commasep ($$) {
  -    my($k,$v) = @_;
  +    my ($k, $v) = @_;
   
  -    if ($k =~ /^(NoSource)$/) {
  +    if ($k =~ m/^(NoSource)$/) {
           return split(/\s*,\s*/, $v);
       } elsif ($k =~ /^(PreReq|BuildPreReq|Provides|Conflicts)$/) {
  -        return map { make_resource($_) }
  +        return map { &$make_resource($_) }
                  split(/\s*,\s*/, $v);
       }
  -
       return $v;
   }
   
  +#   escape option string
   sub optesc ($) {
  -    my($s) = @_;
  -
  -    $s =~ s/([\x00-\x1f\x80-\xbf\s\%])/sprintf("%%%02x",ord($1))/eg;
  +    my ($s) = @_;
   
  +    $s =~ s/([\x00-\x1f\x80-\xbf\s\%])/sprintf("%%%02x", ord($1))/eg;
       return $s;
   }
   
  +#   variable substitution
   sub vsub ($$) {
  -    my($var,$v) = @_;
  +    my ($var, $v) = @_;
   
       $v =~ s/\%\{([^}]+)\}/
           exists $var->{$1} ? $var->{$1} : '%{'.$1.'}'/emg;
  -
       return $v;
   }
   
  +#   Umgekehrte Polnische Notation (UPN)
  +#   Reverse Polish Notation (RPN)
  +#   << ( %{foo} == "yes" ) && ( ! %{bar} == "no" ) || ( %{baz} == "yes" )
  +#   >> %{foo} %{bar} ! && %{baz} ||
   sub upn ($) {
  -    my($t) = @_;
  -    my(@tok) = $t =~ /(\(|\)|\&\&|\|\||\!|\S+)/g;
  -    my(@out,$op,$o);
  -    my(@save);
  +    my ($t) = @_;
  +    my (@tok);
  +    my (@out, $op, $o);
  +    my (@save);
  +
  +    #   split string into tokens
  +    @tok = ($t =~ m/(\(|\)|\&\&|\|\||\!|\S+)/g);
   
  +    #   iterate over all tokens
       $op = [];
       foreach (@tok) {
           if ($_ eq '(') {
  -            push @save, $op;
  +            push(@save, $op);
               $op = [];
           } elsif ($_ eq ')') {
  -            die "FATAL: unresolved operators in: @tok\n" if @$op;
  -            $op = pop @save
  -                or die "FATAL: parenthesis stack underflow in: @tok\n";
  -            while ($o = pop @$op) {
  -                push @out, $o->[0];
  -                last if $o->[1];
  +            die "openpkg:index:FATAL: unresolved operators in: @tok\n" if 
(@$op);
  +            $op = pop(@save)
  +                or die "openpkg:index:FATAL: unmatched closing parenthesis 
in: @tok\n";
  +            while ($o = pop(@$op)) {
  +                push(@out, $o->[0]);
  +                last if ($o->[1]);
               }
           } elsif ($_ eq '&&') {
  -            push @$op, [ '+', 1 ] ;
  +            push(@$op, [ '+', 1 ]);
           } elsif ($_ eq '||') {
  -            push @$op, [ '|', 1 ] ;
  +            push(@$op, [ '|', 1 ]);
           } elsif ($_ eq '!') {
  -            push @$op, [ '!', 0 ];
  -        } elsif (/^\%\{(\S*?)\}$/) {
  -            push @out, $1;
  -            while ($o = pop @$op) {
  -                push @out, $o->[0];
  -                last if $o->[1]; # binop
  +            push(@$op, [ '!', 0 ]);
  +        } elsif (m/^\%\{(\S*?)\}$/) {
  +            push(@out, $1);
  +            while ($o = pop(@$op)) {
  +                push(@out, $o->[0]);
  +                last if ($o->[1]); # binary operator
               }
           }
       }
  -
  -    return join (' ',@out);
  +    return join (' ', @out);
   }
   
  -#
  -# deduce external variables from description
  -#
  -# before openpkg-20021230
  -#
  +#   deduce external variables from description
  +#   (backward compatibility for times before openpkg-20021230)
   sub find_options ($) {
  -    my($descr) = @_;
  +    my ($descr) = @_;
       my $evar = {};
       $descr =~ s/--define\s*'(\S+)\s*\%\{\1\}'/$evar->{$1} = '%{'.$1.'}', 
''/sge;
       return $evar;
   }
   
  -#
  -# translate default section from spec-file
  -# into a hash
  -# %if/%ifdef/%define... are translated to #if/#ifdef/#define
  -#
  -# #defines are interpolated (correct ?)
  -#
  -# #if/#ifdef/... sections are stripped
  -# result is the same as if all conditions evaluate false (!)
  -#
  -# all attributes are of the form key: value
  -# repeated attributes are coalesced into a list
  -#
  +#   translate default section from spec-file into a hash
  +#   - %if/%ifdef/%define... are translated to #/#ifdef/#define
  +#   - #defines are interpolated (correct ?)
  +#   - #if/#ifdef/... sections are stripped
  +#     result is the same as if all conditions evaluate false (!)
  +#   - all attributes are of the form key: value
  +#   - repeated attributes are coalesced into a list
  +#   hint: evar = expansion variables, ovar = option variables
   sub package2data ($$) {
  -    my($s,$ovar) = @_;
  -    my(%evar,%var);
  -    my(@term, $term);
  -    my(%attr,%avar);
  -    my($l, $v, $cond, $d, $p);
  -    my($re,@defs);
  +    my ($s, $ovar) = @_;
  +    my (%evar, %var);
  +    my (@term, $term);
  +    my (%attr, %avar);
  +    my ($l, $v, $cond, $d, $p);
  +    my ($re, @defs);
   
  -    # combine multilines
  +    #   combine multilines (line continuation!)
       $s =~ s/\\\n/ /sg;
   
  -    #
  -    # map conditional variable macros
  -    #
  +    #   map syntax of conditional variable macros
       $s =~ s/^#\{\!\?([^:]*):\s*%(.*?)\s*\}\s*$/#ifndef $1\n#$2\n#endif/mg;
       $s =~ s/^#\{\!\?([^:]*):\s*(.*?)\s*\}\s*$/#ifndef $1\n$2\n#endif/mg;
   
  -    #
  -    # map option macro
  -    #
  +    #   map syntax of option macro
       $s =~ s/^#option\s+(\S+)\s*(.*?)\s*$/#ifndef $1\n#define $1 
$2\n#endif\n#provides $1 $2/mg;
   
  -    #
  -    # use option variables for interpolation
  -    #
  +    #   use option variables for expansion
       %evar = %$ovar;
   
  -    #
  -    # guess more external parameters by scanning for "default" sections.
  -    #
  +    #   guess more external parameters by scanning for (and removing) "set 
option default" sections
       $re = '^\#ifndef\s+[\w\_]+\s*\n((?:\#define\s+[\w\_]+\s.*\n)+)\#endif\n';
  -    @defs = $s =~ /$re/gm;
  +    @defs = ($s =~ m/$re/gm);
       foreach (@defs) {
  -        while (/^\#define\s+([\w\_]+)\s(.*?)\s*$/mg) {
  +        while (m/^\#define\s+([\w\_]+)\s(.*?)\s*$/mg) {
               $ovar->{$1} = $2;
               $evar{$1} = '%{'.$1.'}';
           }
       }
       $s =~ s/$re//gm;
   
  -    #
  -    # add everything looking like a with_ variable
  -    #
  +    #   add everything looking like a "with_xxx" variable
       $re = '%{(with\_[\w\_]+)}';
  -    @defs = $s =~ /$re/gm;
  +    @defs = ($s =~ /$re/gm);
       foreach (@defs) {
  -        next if exists $ovar->{$1};
  -        $ovar->{$1} = '%{'.$1.'}';
  +        next if (exists($ovar->{$1}));
  +        $ovar->{$1} = '%{'.$1.'}'; # unexpanded
           $evar{$1} = '%{'.$1.'}';
       }
   
  -    #
  -    # extract all conditional sections
  -    #
  +    #   extract all conditional sections (#if/#else/#endif)
       @term = ();
       %var  = ();
       $cond = '';
       foreach $l (split(/\n/, $s)) {
  +        #   expand variables
           $v = vsub(\%avar, vsub(\%var, $l));
   
           if (($p) = $v =~ /^\#if\s+(.*?)\s*$/) {
  -            #
  -            # normalize #if expressions
  -            # "%{variable}" == "yes"
  -            # "%{variable}" == "no"
  -            # operators ! && ||
  -            #
  +            #   normalize #if expressions
  +            #   - "%{variable}" == "yes"
  +            #   - "%{variable}" == "no"
  +            #   - operators ! && ||
  +            #   warn on:
  +            #   - operator !=
  +            #   - any other word
               $term = '';
  -            while ($p =~ 
/(!=)|(\!|\|\||\&\&|\(|\))|"\%\{([^}]+)\}"\s*==\s*"(yes|no)"|(\S+)/g) {
  -                if (defined $1) {
  -                    warn "WARNING: unknown token '$1':\n< $l\n> $v\n";
  -                } elsif (defined $5) {
  -                    warn "WARNING: unknown token '$5':\n< $l\n> $v\n";
  -                } elsif (defined $2) {
  +            while ($p =~ 
m/(!=)|(\!|\|\||\&\&|\(|\))|"\%\{([^}]+)\}"\s*==\s*"(yes|no)"|(\S+)/g) {
  +                if (defined($1)) {
  +                    warn "openpkg:index:WARNING: unknown token '$1':\n< 
$l\n> $v"; # FIXME
  +                } elsif (defined($5)) {
  +                    warn "openpkg:index:WARNING: unknown token '$5':\n< 
$l\n> $v";
  +                } elsif (defined($2)) {
                       $term .= " $2 ";
  -                } elsif (exists $evar{$3}) {
  -                    $term .= ($4 eq 'no' ? '! ' : 
'').vsub(\%evar,'%{'.$3.'}');
  +                } elsif (exists($evar{$3})) {
  +                    $term .= ($4 eq 'no' ? '! ' : '').vsub(\%evar, 
'%{'.$3.'}');
                   } else {
  -                    warn "WARNING: unknown conditional '$3':\n< $l\n> $v\n";
  +                    warn "openpkg:index:WARNING: unknown condition variable 
'$3':\n< $l\n> $v";
                   }
               }
   
  -            #
  -            # join with previous conditions for this #if/#endif block
  -            #
  +            #   join with previous conditions for this #if/#endif block
               if ($term ne '') {
  -                push @term, "( $term )";
  -                $cond = join(' && ', grep { $_ ne '' } @term).'';
  +                push(@term, "( $term )");
  +                $cond = join(' && ', grep { $_ ne '' } @term) . '';
               } else {
  -                push @term, '';
  +                push(@term, '');
               }
  -        } elsif ($v =~ /^\#else\s*$/) {
  -            #
  -            # reverse last condition
  -            #
  +        }
  +        elsif ($v =~ /^\#else\s*$/) {
  +            #   reverse last condition
               if (@term) {
  -                $term[-1] = ' ! '.$term[-1];
  -                $cond = join(' && ', grep { $_ ne '' } @term).'';
  +                $term[-1] = ' ! '. $term[-1];
  +                $cond = join(' && ', grep { $_ ne '' } @term) . '';
               } else {
  -                die "FATAL: else without if\n";
  +                die "openpkg:index:FATAL: \"else\" without \"if\"";
               }
  -        } elsif ($v =~ /^\#endif\s*$/) {
  -            #
  -            # unwind last #if expression
  -            #
  -            pop @term;
  -            $cond = join(' && ', grep { $_ ne '' } @term).'';
  -
  -        } elsif ($v =~ /^\#(?:define)\s*(\S+)\s*(.*?)\s*$/) {
  -
  -            #
  -            # define conditional variables
  -            # truth-value becomes current condition
  -            #
  -            # define internal variables
  -            # -> store for subsequent substitution
  -            #
  -            if (exists $evar{$1}) {
  +        }
  +        elsif ($v =~ /^\#endif\s*$/) {
  +            #   unwind last #if expression
  +            pop(@term);
  +            $cond = join(' && ', grep { $_ ne '' } @term) . '';
  +        } 
  +        elsif ($v =~ /^\#(?:define)\s*(\S+)\s*(.*?)\s*$/) {
  +            #   define conditional variables
  +            #   - truth-value becomes current condition
  +            #   define internal variables
  +            #   - store for subsequent substitution
  +            if (exists($evar{$1})) {
                   if ($2 eq 'yes') {
                       if ($cond eq '') {
                           $evar{$1} = "( \%\{$1\} )";
  @@ -327,98 +417,98 @@
                           $evar{$1} = "( %\{$1\} && ! ( $cond ) )";
                       }
                   } else {
  -                    warn "WARNING: logic too complex for '$1':\n< $l\n> 
$v\n";
  +                    warn "openpkg:index:WARNING: logic too complex for '$1' 
(boolean expressions allowed only):\n< $l\n> $v";
                   }
               } else {
                   $var{$1} = $2;
               }
  -        } elsif ($v =~ /^\#(?:undefine)\s*(\S+)\s*$/) {
  -            if (exists $evar{$1}) {
  +        } 
  +        elsif ($v =~ /^\#(?:undefine)\s*(\S+)\s*$/) {
  +            #   undefine conditional variables
  +            #   undefine internal variables
  +            if (exists($evar{$1})) {
                   $evar{$1} = "\%\{$1\}";
               } else {
  -                delete $var{$1};
  +                delete($var{$1});
               }
  -        } elsif ($v =~ /^\#(?:provides)\s*(\S+)\s*(.*?)\s*$/) {
  -            #
  -            # store option for current condition
  -            #
  -            if (exists $attr{'Name'}->{''}) {
  -                push @{$attr{'Provides'}->{$cond}}, {
  -                    resource => $attr{'Name'}->{''}->[0].'::'.$1,
  +        } 
  +        elsif ($v =~ /^\#(?:provides)\s*(\S+)\s*(.*?)\s*$/) {
  +            #   store option for current condition
  +            if (exists($attr{'Name'}->{''})) {
  +                push(@{$attr{'Provides'}->{$cond}}, {
  +                    resource => $attr{'Name'}->{''}->[0] . '::' . $1,
                       attrname => 'equ',
                       attrval  => optesc($2)
  -                }
  +                });
               } else {
  -                warn "ERROR: no package name set for option $1 = $2\n";
  +                warn "openpkg:index:ERROR: no package name set for option 
\"$1 = $2\"";
               }
  -
  -        } elsif ($v =~ /^\#NoSource\s*(.*?)\s*$/) {
  -        #
  -        # store conditional NoSource attribute
  -        #
  -            push @{$attr{'NoSource'}->{$cond}}, commasep('NoSource',$1);
  -
  -        } elsif ($v =~ /^\s*([^\#]\S*)\s*:\s*(.*?)\s*$/) {
  -            #
  -            # store attribute=value for current condition
  -            #
  -            push @{$attr{$1}->{$cond}}, commasep($1,$2);
  -            $avar{lc($1)} = $2 if $cond eq '';
  +        }
  +        elsif ($v =~ /^\#NoSource\s*(.*?)\s*$/) {
  +            #   store conditional NoSource attribute
  +            push(@{$attr{'NoSource'}->{$cond}}, commasep('NoSource', $1));
  +
  +        } 
  +        elsif ($v =~ /^\s*([^\#]\S*)\s*:\s*(.*?)\s*$/) {
  +            #   store "attribute: value" headers for current condition
  +            push(@{$attr{$1}->{$cond}}, commasep($1,$2));
  +            $avar{lc($1)} = $2 if ($cond eq '');
           }
       }
   
  +    #   return all header "attributes"
       return \%attr;
   }
   
  -#
  -# split spec file into sections starting with a %word
  -#
  -# concatenate extended lines
  -# strip comment lines
  -# map %command to #command
  -# split sections
  -#
  -# return package2data from default section.
  -#
  +#   split spec file into sections starting with a %word
  +#   - concatenate extended lines
  +#   - strip comment lines
  +#   - map %command to #command
  +#   - split sections
  +#   - return package2data() from default section (before first %xxx section)
   sub spec2data ($) {
  -    my($s) = @_;
  -    my(%map);
  -    my($a,$o);
  +    my ($s) = @_;
  +    my (%map);
  +    my ($a, $o);
       my $spec = $s;
   
  -    # remove comments
  +    #   remove comments
       $s =~ s/^\s*#.*?\n//mg;
   
  -    # map commands
  +    #   map commands
       $s =~ 
s/^%(ifdef|ifndef|if|NoSource|option|undefine|define|else|endif|\{)/#$1/mg;
   
  -    # split sections
  -    foreach (split(/^(?=%\w+\s*\n)/m, $s)) {
  -        if (/^%(\w+)\s*\n/) {
  +    #   split sections
  +    foreach (split(m/^(?=%\w+\s*\n)/m, $s)) {
  +        if (m/^%(\w+)\s*\n/) {
               $map{$1} .= $';
           } else {
               $map{'*'} .= $_;
           }
       }
   
  -    if (exists $map{'description'}) {
  +    #   translate package information into "data"
  +    if (exists($map{'description'})) {
  +        #   backward compatibility (options are in description)
           $o = find_options($map{'description'});
           $a = package2data($map{'*'}, $o );
           $a->{'Description'} = { '' => [ $map{'description'} ] };
       } else {
  +        #   standard case
           $a = package2data($map{'*'}, {});
       }
  -
       return $a;
   }
   
  -##########################################################################
  +#############################################################################
  +##
  +##  XML/RDF Generation
  +##
  +#############################################################################
   
  -#
  -# start of XML file
  -#
  +#   start of XML file
   sub xml_head ($$) {
  -    my($fh,$res) = @_;
  +    my ($fh, $res) = @_;
       print $fh <<EOFEOF;
   <?xml version="1.0" encoding="iso-8859-1"?>
   <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
  @@ -427,9 +517,7 @@
   EOFEOF
   }
   
  -#
  -# end of XML file, corresponds with start tags
  -#
  +#   end of XML file, corresponds with start tags
   sub xml_foot ($) {
       my($fh) = @_;
       print $fh <<EOFEOF;
  @@ -438,80 +526,67 @@
   EOFEOF
   }
   
  +#   FIXME: ??
   sub n($$) {
  -    my($a,$k) = @_;
  -    return unless $a->{$k};
  -    return unless $a->{$k}->{''};
  -    return $a->{$k}->{''}->[0];
  +    my ($a, $k) = @_;
  +    return if (not $a->{$k});
  +    return if (not $a->{$k}->{''});
  +    return ($a->{$k}->{''}->[0]);
   }
   
  -#
  -# send out $a->{$k} as text-style tag
  -#
  +#   send out $a->{$k} as text-style tag
   sub xml_text ($$$;$) {
  -    my($i,$a,$k,$tag) = @_;
  -    my($out);
  -    return "" unless exists $a->{$k};
  -    $tag = $k unless defined $tag;
  +    my ($i, $a, $k, $tag) = @_;
  +    my ($out);
  +    return "" if (not exists($a->{$k}));
  +    $tag = $k if (not defined($tag));
       $i = ' ' x $i;
  -
       $out = e(n($a,$k));
  -
       return if $out eq '';
  -
       return "$i<$tag>\n$out\n$i</$tag>\n";
   }
   
  -#
  -# send out @{$a->{$k}} as body of an XML tag
  -# $k is the name of the tag unless overridden by $tag
  -# $i denotes the depth of indentation to form nicely
  -# looking files.
  -#
  -# all data from the list is flattened into a single
  -# body, separated by LF and escaped for XML metachars.
  -#
  +#   send out @{$a->{$k}} as body of an XML tag
  +#   $k is the name of the tag unless overridden by $tag
  +#   $i denotes the depth of indentation to form nicely
  +#   looking files.
  +#   all data from the list is flattened into a single
  +#   body, separated by LF and escaped for XML metachars.
   sub xml_tag ($$$;$) {
  -    my($i,$a,$k,$tag) = @_;
  -    my($out,$cond,$upn);
  -    return "" unless exists $a->{$k};
  -    $tag = $k unless defined $tag;
  +    my ($i, $a, $k, $tag) = @_;
  +    my ($out, $cond, $upn);
  +    return "" if (not exists($a->{$k}));
  +    $tag = $k if (not defined($tag));
       $out = '';
       $i = ' ' x $i;
  -
  -    foreach $cond (sort keys %{$a->{$k}}) {
  +    foreach $cond (sort keys(%{$a->{$k}})) {
           $upn = e(upn($cond));
  -        $out .= $i.
  -            ($cond ne '' ?  "<$tag cond=\"$upn\">" : "<$tag>").
  -            join("\n", map { e($_) } @{$a->{$k}->{$cond}}).
  +        $out .= $i .
  +            ($cond ne '' ? "<$tag cond=\"$upn\">" : "<$tag>") .
  +            join("\n", map { e($_) } @{$a->{$k}->{$cond}}) .
               "</$tag>\n";
       }
  -
       return $out;
   }
   
  -#
  -# send out @{$a->{$k}} as a rdf:bag
  -# $k is the name of the outer tag unless overriden by $tag
  -# $i denotes the depth of indentation, inner tags are indented
  -# 2 or 4 more character positions.
  -#
  -# each element of the bag is listed
  -#
  +#   send out @{$a->{$k}} as a rdf:bag
  +#   $k is the name of the outer tag unless overriden by $tag
  +#   $i denotes the depth of indentation, inner tags are indented
  +#   2 or 4 more character positions.
  +#   each element of the bag is listed
   sub xml_bag ($$$;$) {
  -    my($i,$a,$k,$tag) = @_;
  -    my($out,$cond,$upn);
  -    return "" unless exists $a->{$k};
  -    $tag = $k unless defined $tag;
  +    my ($i, $a, $k, $tag) = @_;
  +    my ($out, $cond, $upn);
  +    return "" if (not exists($a->{$k}));
  +    $tag = $k if (not defined($tag));
       $out = '';
       $i = ' ' x $i;
  -
       foreach $cond (sort keys %{$a->{$k}}) {
  -        next unless @{$a->{$k}->{$cond}};
  +        next if (not @{$a->{$k}->{$cond}});
           $upn = e(upn($cond));
  -        $out .= $i.
  -                ($cond ne '' ? "<$tag cond=\"$upn\">\n" : "<$tag>\n").
  -                "$i  <rdf:bag>\n".
  +        $out .= $i .
  +                ($cond ne '' ? "<$tag cond=\"$upn\">\n" : "<$tag>\n") .
  +                "$i  <rdf:bag>\n" .
                   join("",
                        map {
                            ref $_
  @@ -519,133 +594,121 @@
                              ( exists $_->{attrname}
                                ? " $_->{attrname}=\"".e($_->{attrval})."\""
                                : ""
  -                           ).
  +                           ) .
                              ">".e($_->{resource})."</resource>\n"
                            : "$i    <rdf:li>".e($_)."</rdf:li>\n"
                        }
  -                     @{$a->{$k}->{$cond}}).
  -                "$i  </rdf:bag>\n".
  +                     @{$a->{$k}->{$cond}}) .
  +                "$i  </rdf:bag>\n" .
                   "$i</$tag>\n";
       }
  -
       return $out;
   }
   
  -#
  -# send out reference to another RDF
  -#
  +#   send out reference to another RDF
   sub xml_reference ($$$) {
       my($fh, $res, $href) = @_;
  -
       print $fh <<EOFEOF;
       <Repository rdf:resource="$res" href="$href"/>
   EOFEOF
   }
   
  -#
  -# translate attributes from %$a as generated by package2data
  -# into XML and write to file $fh
  -#
  +#   translate attributes from %$a as generated by package2data
  +#   into XML and write to file $fh
   sub xml_record ($$$) {
  -    my($fh, $a, $href) = @_;
  -    my($maj,$min,$rel,$about);
  +    my ($fh, $a, $href) = @_;
  +    my ($maj, $min, $rel, $about);
   
       $about =
  -        n($a,'Name').'-'.
  -        n($a,'Version').'-'.
  +        n($a,'Name') . '-' .
  +        n($a,'Version') . '-' .
           n($a,'Release');
  -
  -    unless (defined $href) {
  -
  -        # guess location from Information in Specfile
  -
  -        if (exists $a->{'NoSource'}) {
  +    if (not defined($href)) {
  +        #   guess location from Information in Specfile
  +        if (exists($a->{'NoSource'})) {
               $href = "$about.nosrc.rpm";
           } else {
               $href = "$about.src.rpm";
           }
  -        ($maj,$min,$rel) = n($a,'Release') =~ /^(\d+)\.(\d+)\.(\d+)/;
  -
  -        if (defined $min) {
  +        ($maj, $min, $rel) = (n($a, 'Release') =~ m/^(\d+)\.(\d+)\.(\d+)/);
  +        if (defined($min)) {
               if ($maj > 1 || ($maj == 1 && $min > 0)) {
  -                # 1.1 or later
  +                #   OpenPKG-1.1-RELEASE or later
                   if (n($a,'Distribution') =~ /\[PLUS\]/) {
                       $href = 'PLUS/'.$href;
                   }
               }
               if ($maj > 1 || ($maj == 1 && $min >= 0)) {
  -                # 1.0 or later
  +                #   OpenPKG-1.0-RELEASE or later
                   if ($rel > 0) {
                       $href = 'UPD/'.$href;
                   }
               }
           } else {
  -            # current
  +            #   OpenPKG-CURRENT
           }
  -
       }
   
       print $fh <<EOFEOF;
       <rdf:Description about="$about" href="$href">
   EOFEOF
   
  -    # fake Source attribute from Source\d attribtutes
  -    # XXX only default conditional
  +    #   fake Source attribute from Source\d attribtutes
  +    #   XXX only default conditional
       $a->{'Source'} = { '' => [
           map {
  -            s/\Q%{name}\E/n($a,'Name')/esg;
  -            s/\Q%{version}\E/n($a,'Version')/esg;
  -            s/\Q%{release}\E/n($a,'Release')/esg;
  -            #s/.*\///;
  +            s/\Q%{name}\E/n($a, 'Name')/esg;
  +            s/\Q%{version}\E/n($a, 'Version')/esg;
  +            s/\Q%{release}\E/n($a, 'Release')/esg;
               $_;
           }
           map {
               $a->{$_}->{''} ? @{$a->{$_}->{''}} : ()
           }
           sort {
  -            my($x) = $a =~ /^(\d*)$/;
  -            my($y) = $b =~ /^(\d*)$/;
  +            my ($x) = ($a =~ /^(\d*)$/);
  +            my ($y) = ($b =~ /^(\d*)$/);
               return $x <=> $y;
           }
           grep {
               /^Source\d*$/
  -        } keys %$a
  +        } keys(%$a)
       ]};
  -    delete $a->{'Source'} unless @{$a->{'Source'}->{''}};
  +    delete($a->{'Source'}) if (not @{$a->{'Source'}->{''}});
   
       print $fh
  -        xml_tag(6, $a, 'Name'),
  -        xml_tag(6, $a, 'Version'),
  -        xml_tag(6, $a, 'Release'),
  -        xml_tag(6, $a, 'Distribution'),
  -        xml_tag(6, $a, 'Class'),
  -        xml_tag(6, $a, 'Group'),
  -        xml_tag(6, $a, 'License'),
  -        xml_tag(6, $a, 'Packager'),
  -        xml_tag(6, $a, 'Summary'),
  -        xml_tag(6, $a, 'URL'),
  -        xml_tag(6, $a, 'Vendor'),
  -        xml_tag(6, $a, 'SourceRPM'),
  -        xml_tag(6, $a, 'Arch'),
  -        xml_tag(6, $a, 'Os'),
  -        xml_tag(6, $a, 'BuildHost'),
  -        xml_tag(6, $a, 'BuildSystem'),
  -        xml_tag(6, $a, 'BuildTime'),
  -        xml_tag(6, $a, 'Relocations'),
  -        xml_tag(6, $a, 'Size'),
  -        xml_tag(6, $a, 'Prefixes'),
  -        xml_tag(6, $a, 'Platform'),
  -        xml_tag(6, $a, 'SigSize'),
  -        xml_tag(6, $a, 'SigMD5'),
  -        xml_tag(6, $a, 'SigPGP'),
  -        xml_tag(6, $a, 'SigGPG'),
  -        xml_bag(6, $a, 'BuildPreReq'),
  -        xml_bag(6, $a, 'PreReq'),
  -        xml_bag(6, $a, 'Provides'),
  -        xml_bag(6, $a, 'Conflicts'),
  -        xml_bag(6, $a, 'Source'),
  -        xml_bag(6, $a, 'NoSource'),
  -        xml_bag(6, $a, 'Filenames'),
  +        xml_tag(6,  $a, 'Name'),
  +        xml_tag(6,  $a, 'Version'),
  +        xml_tag(6,  $a, 'Release'),
  +        xml_tag(6,  $a, 'Distribution'),
  +        xml_tag(6,  $a, 'Class'),
  +        xml_tag(6,  $a, 'Group'),
  +        xml_tag(6,  $a, 'License'),
  +        xml_tag(6,  $a, 'Packager'),
  +        xml_tag(6,  $a, 'Summary'),
  +        xml_tag(6,  $a, 'URL'),
  +        xml_tag(6,  $a, 'Vendor'),
  +        xml_tag(6,  $a, 'SourceRPM'),
  +        xml_tag(6,  $a, 'Arch'),
  +        xml_tag(6,  $a, 'Os'),
  +        xml_tag(6,  $a, 'BuildHost'),
  +        xml_tag(6,  $a, 'BuildSystem'),
  +        xml_tag(6,  $a, 'BuildTime'),
  +        xml_tag(6,  $a, 'Relocations'),
  +        xml_tag(6,  $a, 'Size'),
  +        xml_tag(6,  $a, 'Prefixes'),
  +        xml_tag(6,  $a, 'Platform'),
  +        xml_tag(6,  $a, 'SigSize'),
  +        xml_tag(6,  $a, 'SigMD5'),
  +        xml_tag(6,  $a, 'SigPGP'),
  +        xml_tag(6,  $a, 'SigGPG'),
  +        xml_bag(6,  $a, 'BuildPreReq'),
  +        xml_bag(6,  $a, 'PreReq'),
  +        xml_bag(6,  $a, 'Provides'),
  +        xml_bag(6,  $a, 'Conflicts'),
  +        xml_bag(6,  $a, 'Source'),
  +        xml_bag(6,  $a, 'NoSource'),
  +        xml_bag(6,  $a, 'Filenames'),
           xml_text(6, $a, 'Description');
   
       print $fh <<EOFEOF;
  @@ -653,28 +716,32 @@
   EOFEOF
   }
   
  -#####################################################################
  +#############################################################################
  +##
  +##  OpenPKG RPM Package Payload Extraction
  +##
  +#############################################################################
   
  +#   extract foo.spec from foo-V-R.src.rpm file
   sub rpm2spec ($) {
  -    my($fn) = @_;
  +    my ($fn) = @_;
       local($SIG{'PIPE'}) = 'IGNORE';
  -    my($pipe) = new FileHandle "$R2C '$fn' |"
  -        or die "FATAL: cannot read '$fn' ($!)\n";
  -    my($buf,@hdr,$n,$m,$name,$step);
  -    my($spec);
  -
  -    while (read($pipe,$buf,110) == 110) {
  -        @hdr = unpack('a6a8a8a8a8a8a8a8a8a8a8a8a8a8',$buf);
  +    my ($pipe) = new FileHandle "$R2C '$fn' |"
  +        or die "openpkg:index:FATAL: cannot read '$fn' ($!)\n";
  +    my ($buf, @hdr, $n, $m, $name, $step);
  +    my ($spec);
  +    while (read($pipe, $buf, 110) == 110) {
  +        @hdr = unpack('a6a8a8a8a8a8a8a8a8a8a8a8a8a8', $buf);
           $n = hex($hdr[12]);      # filename length
           $m = int(($n+5)/4)*4-2;  # filename size (padded)
  -        last unless read($pipe,$buf,$m) == $m;
  -        $name = substr($buf,0,$n-1);
  +        last if (not (read($pipe,$buf,$m) == $m));
  +        $name = substr($buf, 0, $n-1);
           $n = hex($hdr[7]);       # file length
           $m = int(($n+3)/4)*4;    # file size (padded)
  -        if ($name !~ /.spec$/) {
  +        if ($name !~ m/.spec$/) {
               while ($m > 0) {
                   $step = $m > 8192 ? 8192 : $m;
  -                last unless read($pipe,$buf,$step);
  +                last if (not read($pipe,$buf,$step));
                   $m -= length($buf);
               }
           } else {
  @@ -685,19 +752,23 @@
           }
       }
       $pipe->close;
  -
       return $spec;
   }
   
  -#####################################################################
  +#############################################################################
  +##
  +##  OpenPKG RPM Package Header Extraction
  +##
  +#############################################################################
   
  +#   extract header information from foo-V-R.src.rpm
   sub rpm2data ($$) {
  -    my($fn,$platform) = @_;
  -    my($q,$pipe,%a);
  -    my($t,$v);
  +    my ($fn, $platform) = @_;
  +    my ($q, $pipe, %a);
  +    my ($t, $v);
   
  -    unless (defined $platform) {
  -        die "FATAL: indexing binary package '$fn' requires -p option\n";
  +    if (not defined($platform)) {
  +        die "openpkg:index:FATAL: indexing binary package '$fn' requires -p 
option\n";
       }
   
       $q = <<EOFEOF;
  @@ -746,14 +817,13 @@
               $t = $1;
               $v = $2;
           } elsif (/^(\s+.+?)\s*$/) {
  -            next unless defined $t;
  +            next if (not defined($t));
               $v = $1;
           } else {
               $t = undef;
               next;
           }
  -
  -        if (exists $a{$t}) {
  +        if (exists($a{$t})) {
               $a{$t} .= "\n$v";
           } else {
               $a{$t} = $v;
  @@ -763,21 +833,21 @@
   
       %a = map { $_ => $a{$_} }
            grep { $a{$_} ne '(none)' }
  -         keys %a;
  +         keys(%a);
       if ($a{'Relocations'} eq '(non relocatable)') {
  -        delete $a{'Relocations'};
  +        delete($a{'Relocations'});
       }
       if ($a{'SigMD5'} eq '(unknown type)') {
  -        delete $a{'SigMD5'};
  +        delete($a{'SigMD5'});
       }
  -    if (defined $platform) {
  +    if (defined($platform)) {
           $a{'Platform'} = $platform;
       }
       $a{'Description'} = [ $a{'Description'} ];
   
       foreach ('Conflicts', 'PreReq', 'Provides') {
           $a{$_} = [
  -            map { make_resource($_) }
  +            map { &$make_resource($_) }
               grep { !/^rpmlib\(/ }
               split(/\n+/, $a{$_})
           ];
  @@ -785,89 +855,102 @@
   
       return { map {
           $_ => { '' => (ref $a{$_} ? $a{$_} : [ split(/\n+/, $a{$_}) ]) }
  -    } keys %a };
  +    } keys(%a) };
   }
   
  -#####################################################################
  +#############################################################################
  +##
  +##  OpenPKG XML/RDF Index Locating
  +##
  +#############################################################################
   
  +#   detect index files
   sub getindex ($) {
  -    my($dir) = @_;
  -    my(@idx) = sort { -M $a <=> -M $b; }
  -               grep { -f $_ }
  -                ( <$dir/00INDEX.rdf>, <$dir/00INDEX.rdf.*> );
  -
  -    return unless @idx;
  +    my ($dir) = @_;
  +    my (@idx) =
  +        sort { -M $a <=> -M $b; }
  +        grep { -f $_ }
  +        ( <$dir/00INDEX.rdf>, <$dir/00INDEX.rdf.*> );
  +    return if (not @idx);
       return $idx[0];
   }
   
  +#   list RPM directories of unpacked .spec files
   sub list_specdir ($) {
  -    my($dir) = @_;
  -    my($dh,$d,$path);
  -    my(@list);
  +    my ($dir) = @_;
  +    my ($dh, $d, $path);
  +    my (@list);
   
       $dh = new DirHandle($dir);
       while ($d = $dh->read) {
  -        next if $d =~ /^\./;
  +        next if ($d =~ m/^\./);
           $path = "$dir/$d/$d.spec";
  -        push @list, $path if -f $path;
  +        push(@list, $path) if (-f $path);
       }
  -
       return [EMAIL PROTECTED];
   }
   
  +#   list index or RPM file directories
   sub list_rpmdir ($) {
       my($dir) = @_;
  -    my($dh,$d,$path);
  -    my(@list,$idx,$sub);
  +    my($dh, $d, $path);
  +    my(@list, $idx, $sub);
   
       $dh = new DirHandle($dir);
       while ($d = $dh->read) {
  -        next if $d =~ /^\./;
  +        next if ($d =~ m/^\./);
           $path = "$dir/$d";
           if (-d $path) {
               $idx = getindex($path);
  -            if (defined $idx) {
  -                push @list, $idx;
  +            if (defined($idx)) {
  +                push(@list, $idx);
               } else {
                   $sub = list_rpmdir($path);
  -                push @list, @$sub;
  +                push(@list, @$sub);
                   undef $sub;
               }
           } else {
  -            next unless $d =~ /\.rpm$/ && -f $path;
  -            push @list, $path;
  +            next if (not ($d =~ m/\.rpm$/ && -f $path));
  +            push(@list, $path);
           }
       }
  -
       return [EMAIL PROTECTED];
   }
   
  -#####################################################################
  +#############################################################################
  +##
  +##  OpenPKG XML/RDF Index Reading
  +##
  +#############################################################################
   
  +#   fetch a whole file
   sub readfile ($) {
  -    my($fn) = @_;
  -    my($fh) = new FileHandle "< $fn"
  +    my ($fn) = @_;
  +    my ($fh) = new FileHandle "< $fn"
           or die "FATAL: cannot read '$fn' ($!)\n";
  -    my(@l) = <$fh>;
  +    my (@l) = <$fh>; # FIXME: optimize
       $fh->close;
  -    return join('',@l);
  +    return join('', @l);
   }
   
  +#   create relative path by stripping instance prefix
   sub relpath ($$) {
  -    my($prefix,$path) = @_;
  +    my ($prefix, $path) = @_;
       $path =~ s/^\Q$prefix\E\///s;
       return $path;
   }
   
  +#   create directory path with trailing slash
   sub dirname ($) {
  -    my($path) = @_;
  +    my ($path) = @_;
       $path =~ s/\/[^\/]*$//s;
       return $path.'/';
   }
   
  +#   peek at resource identifier of index file
   sub getresource ($) {
  -    my($fn) = @_;
  -    my($fh, $buf);
  +    my ($fn) = @_;
  +    my ($fh, $buf);
   
       if ($fn =~ /\.bz2$/) {
           $fh = new FileHandle "$BZ -dc $fn |"
  @@ -878,127 +961,70 @@
       }
       $fh->read($buf, 1024);
       $fh->close;
  -
       if ($buf =~ /<Repository.*?rdf:resource="([^"]+)"/) {
           return $1;
       }
  -
       return undef;
   }
   
  -#####################################################################
  +#############################################################################
  +##
  +##  OpenPKG XML/RDF Index Output Generation
  +##
  +#############################################################################
   
   sub write_index ($$$$$$) {
  -    my($fh,$prefix,$resource,$platform,$list,$cache) = @_;
  -    my($a,$h,$r,$spec);
  -    my($mtime);
  +    my ($fh, $prefix, $resource, $platform, $list, $cache) = @_;
  +    my ($a, $h, $r, $spec);
  +    my ($mtime);
   
       foreach (@$list) {
           $a = undef;
           $h = undef;
           $r = undef;
  -        if (/\.spec$/) {
  +
  +        #   determine information
  +        if (m/\.spec$/) {
               $spec = readfile($_);
               $a    = spec2data($spec);
  -        } elsif (/([^\/]+\.(?:no)?src\.rpm)$/) {
  -            $h    = relpath($prefix, $_);
  +        } elsif (m/([^\/]+\.(?:no)?src\.rpm)$/) {
  +            $h = relpath($prefix, $_);
               if ($cache) {
  -                $mtime = (stat $_)[9];
  -                if (exists $cache->{"M$_"} &&
  -                    $cache->{"M$_"} == $mtime) {
  +                $mtime = (stat($_))[9];
  +                if (   exists($cache->{"M$_"})
  +                    && $cache->{"M$_"} == $mtime) {
  +                    #   found in cache
                       $spec = $cache->{"S$_"};
                   } else {
  +                    #   not found in cache
                       $spec = rpm2spec($_);
                       $cache->{"S$_"} = $spec;
                       $cache->{"M$_"} = $mtime;
                   }
               } else {
  +                #   no cache at all
                   $spec = rpm2spec($_);
               }
  -            $a    = spec2data($spec);
  -        } elsif (/([^\/]+\.rpm)$/) {
  -            $h    = relpath($prefix, $_);
  -            $a    = rpm2data($_, $platform);
  -        } elsif (/([^\/]+\.rdf[^\/]*)$/) {
  -            $h    = relpath($prefix, $_);
  -            $r    = getresource($_) || $resource.dirname($h);
  +            $a = spec2data($spec);
  +        } elsif (m/([^\/]+\.rpm)$/) {
  +            $h = relpath($prefix, $_);
  +            $a = rpm2data($_, $platform);
  +        } elsif (m/([^\/]+\.rdf[^\/]*)$/) {
  +            $h = relpath($prefix, $_);
  +            $r = getresource($_) || $resource.dirname($h);
           }
   
  +        #   process information
           if ($a) {
               xml_record($fh, $a, $h);
           } elsif ($r) {
               xml_reference($fh, $r, $h);
           } else {
  -            warn "ERROR: cannot process $_\n";
  +            warn "openpkg:index:ERROR: cannot process $_";
           }
       }
   }
   
  -#####################################################################
  -
  -my($prefix,$list,$fh,%cache,$tmpo);
  -
  -if ($#ARGV < 0) {
  -    print "openpkg:index:USAGE: $0 [-r resource] [-p platform] [-C cache.db] 
[-o index.rdf] [-c] [-i] dir ...\n";
  -    exit(1);
  -}
  -
  -if ($opt_C) {
  -    eval {
  -        require DB_File;
  -    };
  -    if ($@) {
  -        die "Sorry. The -C option requires an installed DB_File perl 
module.\n";
  -    }
  -    tie %cache, 'DB_File', $opt_C, O_CREAT|O_RDWR, 0666, $DB_File::DB_HASH
  -        or die "FATAL: cannot tie cache '$opt_C' ($!)\n";
  -}
  -
  -$opt_r = 'OpenPKG-CURRENT/Source/' unless defined $opt_r;
  -
  -if (defined $opt_o) {
  -    $tmpo = $opt_o . '.tmp';
  -    if ($opt_c) {
  -        $fh = new FileHandle "| $BZ -c > '$tmpo'"
  -            or die "FATAL: cannot write '$tmpo' ($!)\n";
  -    } else {
  -        $fh = new FileHandle "> $tmpo"
  -            or die "FATAL: cannot write '$tmpo' ($!)\n";
  -    }
  -} else {
  -    if ($opt_c) {
  -        $fh = new FileHandle "| $BZ -c"
  -            or die "FATAL: cannot write to stdout ($!)\n";
  -    } else {
  -        $fh = new FileHandle ">&=1"
  -            or die "FATAL: cannot write to stdout ($!)\n";
  -    }
  -}
  -
  -xml_head($fh, $opt_r);
  -foreach $prefix (@ARGV) {
  -    if (-d $prefix) {
  -        if ($opt_i) {
  -            $list = list_rpmdir($prefix);
  -        } else {
  -            $list = list_specdir($prefix);
  -        }
  -    } else {
  -        $list = [ $prefix ];
  -        $prefix = dirname($prefix);
  -    }
  -    write_index($fh, $prefix, $opt_r, $opt_p, $list, $opt_C ? \%cache : 
undef);
  -}
  -xml_foot($fh);
  -
  -$fh->close
  -    or die "FATAL: write error on output ($!)\n";
  -
  -if (defined $tmpo) {
  -    rename $tmpo,$opt_o
  -        or die "FATAL: cannot rename $tmpo to $opt_o ($!)\n";
  -}
  -
   __END__
   
   =pod
  @@ .
______________________________________________________________________
The OpenPKG Project                                    www.openpkg.org
CVS Repository Commit List                     [email protected]

Reply via email to