The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/env perl

use strict;
use warnings;
use feature qw/state say/;
use 5.010;

use Getopt::Long;
use Pod::Usage;
use Finnigan;

my $option_help = 0;
my $option_man = 0;
my $option_dump = 0;
my $option_html = 0;
my $option_wiki = 0;
my $option_size = 0;
my $option_atag = 0;
my $option_relative = 0;

Getopt::Long::Configure ("bundling");
GetOptions(
           'help|?' => \$option_help,
           'man' => \$option_man,
           'dump|d' => \$option_dump,
           'size|s' => \$option_size,
           'html|h' => \$option_html,
           'wiki|w' => \$option_wiki,
           'atag' => \$option_atag,
           'relative|r' => \$option_relative,
          ) or pod2usage(2);
pod2usage(1) if $option_help;
pod2usage(-existstatus => 0, -verbose => 2) if $option_man;

@ARGV == 1 or do{ say STDERR "Expecting a single input file\n"; pod2usage(2) };

my $file = shift @ARGV;

-e $file or die "file '$file' does not exist";
-f $file or die "'$file' is not a plain file";
-s $file or die "'$file' has zero size";

# -----------------------------------------------------------------------------
open INPUT, "<$file" or die "can't open '$file': $!";
binmode INPUT;

my $header = Finnigan::FileHeader->decode(\*INPUT);

if ( $option_size ) {
  if ( $option_atag ) {
    say "size: " . $header->audit_start->size;
  }
  else {
    say "size: " . $header->size;
  }
}

if ( $option_dump ) {
  if ( $option_html ) {
    if ( $option_atag ) {
      $header->audit_start->dump(style => 'html', relative => $option_relative);
    }
    else {
      $header->dump(style => 'html', relative => $option_relative);
    }
  }
  elsif ( $option_wiki ) {
    if ( $option_atag ) {
      $header->audit_start->dump(style => 'wiki', relative => $option_relative);
    }
    else {
      $header->dump(style => 'wiki', relative => $option_relative);
    }
  }
  else {
    if ( $option_atag ) {
      $header->audit_start->dump(relative => $option_relative);
    }
    else {
      $header->dump(relative => $option_relative);
    }
  }
}
else {
  say "$file: version "
    . $header->version . "; "
      . $header->audit_start->time
        . ($header->audit_start->tag1 ? "; " . $header->audit_start->tag1 : "")
          . ($header->tag ? "; " . $header->tag : "")
            ;
}

__END__
=head1 NAME

uf-header - decode the file header in a Finnigan raw file

=head1 SYNOPSIS

uf-header [options] file

 Options:
   --help            brief help message
   --man             full documentation
   --dump            dump all header fields as a table
   --html            request html formatting of the dump
   --wiki            dump as a wiki table
   --size            tell header size
   --atag            dump the content of AuditTags instead of the header itself
   --relative        show relative addresses

=head1 OPTIONS

=over 8

=item B<--help>

Print a brief help message and exit.

=item B<--man>

Print the manual page and exit.

=item B<--dump>

Prints the table listing all header fields with their seek addresses,
sizes, acess keys and values.

=item B<--html>

Dump as html table

=item B<--wiki>

Dump as a wiki table

=item B<--size>

Show header size in bytes.

=item B<--atag>

Dump the contents of the first AuditTag object, rather than the header itself.

=item B<--relative>

Show relative addresses of all itmes. The default is to show the
absolute seek address.

=back

=head1 DESCRIPTION

B<uf-header> will read the given input file and display the contents
of its header or the AuditTag structures embedded into it.

It will return an error message if the file is not a Finnigan raw
file.

By default, it prints a few header items (version number and
parts of its AuditTag) on a single line.

=head1 SEE ALSO

Finnigan::FileHeader

Finnigan::AuditTag

=head1 EXAMPLES

=over 4

=item Prints the file version and creation date:

  uf-header sample.raw

=item Dump all header fields:

  uf-header -d sample.raw

=item Dump the contens of the first AuditTag:

  uf-header -d --atag sample.raw

=back

=cut