cvsuser     01/09/17 14:54:07

  Modified:    .        MANIFEST
  Added:       Parrot   PackFile.pm
               Parrot/PackFile ConstTable.pm Constant.pm FixupTable.pm
  Log:
  Functions for reading, writing and manipulating Parrot Pack Files. NOTE: This
  is a proposed term based on the fact that the file contains more than just byte
  code, and another language (Java) calls its binary files by a broader notion of
  what's in them (Class Files). Since Perl has packages, and since we use pack()
  to write them, we'll call them PackFiles (at least for now).
  
  That does, however, beg the question of file extension. Should we name the
  files "foo.pack" instead of "foo.pbc"?
  
  Revision  Changes    Path
  1.12      +4 -0      parrot/MANIFEST
  
  Index: MANIFEST
  ===================================================================
  RCS file: /home/perlcvs/parrot/MANIFEST,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -w -r1.11 -r1.12
  --- MANIFEST  2001/09/17 14:20:26     1.11
  +++ MANIFEST  2001/09/17 21:54:07     1.12
  @@ -3,6 +3,10 @@
   Makefile.in
   MANIFEST
   Parrot/Opcode.pm
  +Parrot/PackFile.pm
  +Parrot/PackFile/Constant.pm
  +Parrot/PackFile/ConstTable.pm
  +Parrot/PackFile/FixupTable.pm
   Parrot/Test.pm
   README
   TODO
  
  
  
  1.1                  parrot/Parrot/PackFile.pm
  
  Index: PackFile.pm
  ===================================================================
  #!/usr/bin/perl -w
  #
  # PackFile.pm
  #
  # Parrot::PackFile Perl package. Functions for reading, writing and manipulating
  # Parrot Pack Files. NOTE: This is a proposed term based on the fact that the
  # file contains more than just byte code, and another language (Java) calls
  # its binary files by a broader notion of what's in them (Class Files). Since
  # Perl has packages, and since we use pack() to write them, we'll call them
  # PackFiles (at least for now).
  #
  # That does, however, beg the question of file extension. Should we name the
  # files "foo.pack" instead of "foo.pbc"?
  #
  # Copyright (C) 2001 Gregor N. Purdy. All rights reserved.
  # This program is free software. It is subject to the same
  # license as Perl itself.
  #
  # $Id: PackFile.pm,v 1.1 2001/09/17 21:54:07 gregor Exp $
  #
  
  use strict;
  
  package Parrot::PackFile;
  
  use Parrot::PackFile::FixupTable;
  use Parrot::PackFile::ConstTable;
  
  use FileHandle;
  
  my $PARROT_MAGIC = 0x13155a1;
  
  my $template = "l l/a* l/a* l/a*";
  
  
  #
  # new()
  #
  
  sub new
  {
    my $class = shift;
  
    my $self = bless {
      MAGIC => $PARROT_MAGIC,
      FIXUP => Parrot::PackFile::FixupTable->new(),
      CONST => Parrot::PackFile::ConstTable->new(),
      PROG  => '',
    }, $class;
  
    return $self;
  }
  
  #
  # magic()
  #
  
  sub magic
  {
    return $PARROT_MAGIC;
  }
  
  
  #
  # fixup_table()
  #
  
  sub fixup_table
  {
    my $self = shift;
  
    return $self->{FIXUP};
  }
  
  
  #
  # const_table()
  #
  
  sub const_table
  {
    my $self = shift;
  
    return $self->{FIXUP};
  }
  
  
  #
  # byte_code()
  #
  
  sub byte_code
  {
    my $self = shift;
  
    if (@_) { $self->{BCODE} = shift; }
    else    { return $self->{BCODE};  }
  }
  
  
  #
  # unpack()
  #
  # Magic: 4-byte signed integer
  # Fixup: 4-byte length N + N bytes
  # Const: 4-byte length N + N bytes
  # BCode: N bytes
  #
  
  sub unpack
  {
    my ($self, $string) = @_;
  
    printf "Input string is %d bytes long\n", length($string);
  
    my $magic = unpack("l", $string);
    $string = substr($string, 4);
  
    $self->{MAGIC} = $magic;
  
    die "Bad PARROT_MAGIC" unless $magic == $PARROT_MAGIC;
  
    #
    # Read the fixup table:
    #
   
    my $fixup = '';
  
    my $fixup_length = unpack('l', $string);
    $string = substr($string, 4);
  
    if($fixup_length) {
      $fixup = unpack("a$fixup_length", $string);
      $string = substr($string, $fixup_length);
      $self->{FIXUP}->unpack($fixup);
    } else {
      $self->{FIXUP}->clear;
    }
  
    #
    # Read the constant table:
    #
   
    my $const = '';
  
    my $const_length = unpack('l', $string);
    $string = substr($string, 4);
  
    if($const_length) {
      $const = unpack("a$const_length", $string);
      $string = substr($string, $const_length);
      $self->{CONST}->unpack($const);
    } else {
      $self->{CONST}->clear;
    }
  
    #
    # Read the byte code:
    #
    # TODO: This is wrong. It should be a length-payload pair like the
    # rest of the segments, but the assembler and interpreter and
    # disassembler all agree on this implementation despite the docs.
    #
  
    $self->{BCODE} = $string;
  
    #
    # Report on what we found:
    #
  
    printf "  * %6d bytes magic\n", 4;
    printf "  * %6d bytes fixup segment header\n", 4;
    printf "  * %6d bytes fixup\n", length($fixup);
    printf "  * %6d bytes const segment header\n", 4;
    printf "  * %6d bytes const\n", length($const);
    printf "  * %6d bytes bcode\n", length($string);
  
  #  printf "Parsed string with %d bytes of fixup, %d bytes of const and %d bytes of 
prog.\n", length($fixup), length($const), length($prog);
  
  #  my $packed = pack($template, $magic, $fixup, $const, $bcode);
  
  #  printf "Packed is %d bytes long\n", length($packed);
  
    return $self;
  }
  
  
  #
  # read_filehandle()
  #
  
  sub read_filehandle
  {
    my ($self, $fh) = @_;
  
    return unless $fh;
  
    my @lines  = $fh->getlines();
    my $string = join('', @lines);
   
    printf "Read %d lines, %d bytes.\n", scalar(@lines), length($string);
    return $self->unpack($string);
  }
  
  
  #
  # read_file()
  #
  
  sub read_file
  {
    my $self = shift;
  
    my $fh = new FileHandle(shift);
  
    return unless $fh;
  
    return $self->read_filehandle($fh);
  }
  
  
  #
  # pack()
  #
  
  sub pack
  {
    my $self = shift;
  
    my $string = '';
  
    $string .= pack('l', $self->magic);
  
    my $fixup = $self->fixup_table->pack;
    my $const = $self->const_table->pack;
  
    $string .= pack('l', length($fixup));
    $string .= $fixup;
  
    $string .= pack('l', length($const));
    $string .= $const;
  
    #
    # TODO: It is wrong not to write this length, because then we can't have
    # another source-code segment, which the docs say we should be able to
    # have.
    #
  
  #  $string .= pack('l', length($self->byte_code));
    $string .= $self->byte_code;
  
    return $string;
  }
  
  
  #
  # write_filehandle()
  #
  
  sub write_filehandle
  {
    my ($self, $fh) = @_;
  
    print($fh $self->pack);
  }
  
  
  #
  # write_file()
  #
  
  sub write_file
  {
    my $self = shift;
    my $fh = new FileHandle('>' . shift);
  
    return unless $fh;
  
    return $self->write_filehandle($fh);
  }
  
  
  1;
  
  __END__
  
  
  =head1 NAME
  
  Parrot::Bytecode
  
  =head1 SYNOPSIS
  
    use Parrot::Bytecode;
  
  =head1 DESCRIPTION
  
  This package contains all the functions required to process a Parrot bytecode
  file. It is not intended to understand the contents of the bytecode file's
  segments, but merely to dissect and reconstruct data from the various
  segments. See L<parrotbyte> for information about the structure of the frozen
  bycode.
  
  =head1 FORMAT
  
    0
    +----------+----------+----------+----------+
    |         Parrot Magic = 0x 13155a1         |
    +----------+----------+----------+----------+
    
    For each segment:
  
    4, 4 + (4 + S0), 4 + (4 + S0) + (4 + S1)
    +----------+----------+----------+----------+
    |       Segment length in bytes (S)         |
    +----------+----------+----------+----------+
    |                                           |
    :        S bytes of segment content         :
    |                                           |
    +----------+----------+----------+----------+
    
  NOTE: Despite the documentation, current implementations consist
  of two actual segments (fixup and const) followed by a block of
  byte code, which is not in a proper segment.
  
  
  =head2 FIXUP SEGMENT
  
  TODO: Segment format undefined.
  
  =head2 CONSTANTS SEGMENT
  
    0 (relative)
    +----------+----------+----------+----------+
    |            Constant Count (N)             |
    +----------+----------+----------+----------+
  
  For each constant:
  
    4, 4 + (16 + S'0), 4 + (16 + S'0) + (16 + S'1)
    +----------+----------+----------+----------+
    |                   Flags                   |
    +----------+----------+----------+----------+
    |                  Encoding                 |
    +----------+----------+----------+----------+
    |                   Type                    |
    +----------+----------+----------+----------+
    |                   Size S                  |
    +----------+----------+----------+----------+
    |                                           |
    : S' bytes of Data (w/ S % 4 pad \0 bytes)  |
    |                                           |
    +----------+----------+----------+----------+
   
  =head2 BYTE CODE SEGMENT
  
  The pieces that can be found in the byte code segment are as
  follows:
  
    +----------+----------+----------+----------+
    |              Operation Code               |
    +----------+----------+----------+----------+
  
    +----------+----------+----------+----------+
    |             Register Argument             |
    +----------+----------+----------+----------+
  
    +----------+----------+----------+----------+
    |        Integer Constant Argument          |
    +----------+----------+----------+----------+
  
    +----------+----------+----------+----------+
    |         String Constant Argument          |
    +----------+----------+----------+----------+
  
    +----------+----------+----------+----------+
    |         Number Constant Argument          |
    +                                           +
    |                                           |
    +----------+----------+----------+----------+
  
    +----------+----------+----------+----------+
    |              Constant Argument            |
    +----------+----------+----------+----------+
  
  The number and types for each argument can be determined by
  consulting Parrot::Opcode.
  
  =head2 SOURCE CODE SEGMENT
  
  =head1 AUTHOR
  
  Gregor N. Purdy E<lt>[EMAIL PROTECTED]<gt>
  
  =head1 COPYRIGHT
  
  Copyright (C) 2001 Gregor N. Purdy. All rights reserved.
  
  =head1 LICENSE
  
  This program is free software. It is subject to the same
  license as Perl itself.
  
  
  
  
  1.1                  parrot/Parrot/PackFile/ConstTable.pm
  
  Index: ConstTable.pm
  ===================================================================
  #!/usr/bin/perl -w
  #
  # ConstTable.pm
  #
  # Parrot::ConstTable Perl package. Functions for manipulating Parrot
  # bytecode constant tables.
  #
  # Copyright (C) 2001 Gregor N. Purdy. All rights reserved.
  # This program is free software. It is subject to the same
  # license as Perl itself.
  #
  # $Id: ConstTable.pm,v 1.1 2001/09/17 21:54:07 gregor Exp $
  #
  
  use strict;
  
  package Parrot::PackFile::ConstTable;
  
  use Parrot::PackFile::Constant;
  
  my $template = "l/(l l l l/a*)*";
  
  
  #
  # new()
  #
  
  sub new
  {
    my $class = shift;
    my $self = bless { CONST => [ ] }, $class;
  
    if (@_) {
      $self->unpack(shift);
    }
  
    return $self;
  }
  
  
  #
  # clear()
  #
  
  sub clear
  {
    my $self = shift;
  
    $self->{CONST} = [ ];
  
    return;
  }
  
  
  #
  # unpack()
  #
  
  sub unpack
  {
    my ($self, $string) = @_;
  
    my $count = unpack 'l', $string;
    $string = substr($string, 4);
  
    for (1..$count) {
      my $const = new Parrot::PackFile::Constant;
      my $used = $const->unpack($string);
      $string = substr($string, $used);
  
      push @{$self->{CONST}}, $const;
    }
  }
  
  
  #
  # pack()
  #
  
  sub pack
  {
    my $self = shift;
    my $string = '';
  
    $string .= pack('l', scalar(@{$self->{CONST}}));
  
    foreach (@{$self->{CONST}}) {
      $string .= $_->pack;
    }
  
    return $string;
  }
  
  
  1;
  
  __END__
  
  =head1 NAME
  
  Parrot::PackFile::ConstTable
  
  =head1 SYNOPSIS
  
    use Parrot::PackFile::ConstTable
  
  =head1 DESCRIPTION
  
  Constant tables from Parrot pack files.
  
  =head2 clear
  
  =head2 new
  
  =head2 pack
  
  =head2 unpack STRING
  
  =head1 AUTHOR
  
  Gregor N. Purdy E<lt>[EMAIL PROTECTED]<gt>
  
  =head1 COPYRIGHT
  
  Copyright (C) 2001 Gregor N. Purdy. All rights reserved.
  
  =head1 LICENSE
  
  This program is free software. It is subject to the same
  license as Perl itself.
  
  
  
  
  1.1                  parrot/Parrot/PackFile/Constant.pm
  
  Index: Constant.pm
  ===================================================================
  #!/usr/bin/perl -w
  #
  # Constant.pm
  #
  # Parrot Constants.
  #
  # Copyright (C) 2001 Gregor N. Purdy. All rights reserved.
  # This program is free software. It is subject to the same
  # license as Perl itself.
  #
  # $Id: Constant.pm,v 1.1 2001/09/17 21:54:07 gregor Exp $
  #
  
  use strict;
  
  package Parrot::PackFile::Constant;
  
  my $template = "l l l l/a*";
  
  
  #
  # new()
  #
  
  sub new
  {
    my $class = shift;
    my ($flags, $encoding, $type, $size, $data) = @_;
  
    my $self = bless {
      FLAGS    => $flags,
      ENCODING => $encoding,
      TYPE     => $type,
      SIZE     => $size,
      DATA     => $data
    }, $class;
  
    return $self;
  }
  
  
  #
  # flags()
  #
  
  sub flags
  {
    my $self = shift;
    if (@_) { $self->{FLAGS} = shift; }
    else    { return $self->{FLAGS};  }
  }
  
  
  #
  # encoding()
  #
  
  sub encoding
  {
    my $self = shift;
    if (@_) { $self->{ENCODING} = shift; }
    else    { return $self->{ENCODING};  }
  }
  
  
  #
  # type()
  #
  
  sub type
  {
    my $self = shift;
    if (@_) { $self->{TYPE} = shift; }
    else    { return $self->{TYPE};  }
  }
  
  
  #
  # size()
  #
  
  sub size
  {
    my $self = shift;
    if (@_) { $self->{SIZE} = shift; }
    else    { return $self->{SIZE};  }
  }
  
  
  #
  # data()
  #
  
  sub data
  {
    my $self = shift;
    if (@_) { $self->{DATA} = shift; }
    else    { return $self->{DATA};  }
  }
  
  
  #
  # unpack()
  #
  # Unpack from the string and return the number of characters that should
  # be removed from the string.
  #
  
  sub unpack
  {
    my ($self, $string) = @_;
  
    my ($flags, $encoding, $type, $size, $data) = unpack($template, $string);
  
    return $size + ($size % 4);
  }
  
  
  #
  # pack()
  #
  
  sub pack
  {
    my $self = shift;
    
    my $block = $self->data . ("\0" x ($self->size % 4));
  
    return pack($template, $self->flags, $self->encoding, $self->type, $self->size,
      $block);
  }
  
  
  1;
  
  __END__
  
  =head1 NAME
  
  Parrot::PackFile::Constant
  
  =head1 SYNOPSIS
  
    use Parrot::PackFile::Constant;
  
  =head1 DESCRIPTION
  
  =head2 data DATA
  =head2 data
  
  =head2 encoding ENCODING
  =head2 encoding
  
  =head2 flags FLAGS
  =head2 flags 
  
  =head2 new FLAGS ENCODING TYPE SIZE DATA
  
  =head2 pack
  
  =head2 size SIZE
  =head2 size
  
  =head2 type TYPE
  =head2 type
  
  =head2 unpack STRING
  =head2 unpack
  
  =head1 AUTHOR
  
  Gregor N. Purdy E<lt>[EMAIL PROTECTED]<gt>
  
  =head1 COPYRIGHT
  
  Copyright (C) 2001 Gregor N. Purdy. All rights reserved.
  
  =head1 LICENSE
  
  This program is free software. It is subject to the same
  license as Perl itself.
  
  
  
  
  1.1                  parrot/Parrot/PackFile/FixupTable.pm
  
  Index: FixupTable.pm
  ===================================================================
  #!/usr/bin/perl -w
  #
  # FixupTable.pm
  #
  # Parrot::FixupTable Perl package. Functions for manipulating Parrot
  # bytecode fixup tables.
  #
  # Copyright (C) 2001 Gregor N. Purdy. All rights reserved.
  # This program is free software. It is subject to the same
  # license as Perl itself.
  #
  # $Id: FixupTable.pm,v 1.1 2001/09/17 21:54:07 gregor Exp $
  #
  
  use strict;
  
  package Parrot::PackFile::FixupTable;
  
  
  #
  # new()
  #
  
  sub new
  {
    my $class = shift;
    my $self = bless { }, $class;
  
    if (@_) {
      $self->unpack(shift);
    }
  
    return $self;
  }
  
  
  #
  # clear()
  #
  
  sub clear
  {
    my $self = shift;
  
    return;
  }
  
  
  #
  # unpack()
  #
  
  sub unpack
  {
    my $self = shift;
  }
  
  
  #
  # pack()
  #
  
  sub pack
  {
    my $self = shift;
  
    return '';
  }
  
  
  1;
  
  __END__
  
  =head1 NAME
  
  Parrot::PackFile::FixupTable
  
  =head1 SYNOPSIS
  
    use Parrot::PackFile::FixupTable;
  
  =head1 DESCRIPTION
  
  Parrot fixup tables.
  
  =head2 clear
  
  =head2 new
  
  =head2 pack
  
  =head2 unpack
  
  =head1 AUTHOR
  
  Gregor N. Purdy E<lt>[EMAIL PROTECTED]<gt>
  
  =head1 COPYRIGHT
  
  Copyright (C) 2001 Gregor N. Purdy. All rights reserved.
  
  =head1 LICENSE
  
  This program is free software. It is subject to the same
  license as Perl itself.
  
  
  
  

Reply via email to