Dan Sugalski <[EMAIL PROTECTED]> wrote: > To make this actually work we need some standards, and the ability to > embed bytecode segments into an executable (like, say, parrot :) so > they're always at hand.
The attached patch implements one (evil) way to do this. (Even if we don't end up using the pbc2cc utility I've written, the patches to embed.[ch] might be useful; they implement a new embedding interface function for loading a packfile that's already in memory.) -- Brent 'Dax' Royal-Gordon <[EMAIL PROTECTED]> Perl and Parrot hacker There is no cabal.
--- /dev/null Wed Jan 7 17:19:56 2004 +++ pbc2cc.pl Thu Nov 4 19:09:45 2004 @@ -0,0 +1,86 @@ +#!/usr/bin/perl -w + +=head1 TITLE + +pbc2cc.pl - Convert a Parrot bytecode file to a C constant + +=head1 SYNOPSIS + + pbc2cc.pl foo foo.pbc > foo.c + #Generates a foo.c with a Parrot_pbc2cc_read_foo function + # containing foo.pbc's contents. + +=head1 DESCRIPTION + +F<pbc2cc.pl> converts an input file into a C constant, then outputs some code +to load that "file" as a Parrot packfile. The program takes a C identifier and +an input file on the command line (the input file defaults to STDIN if not +specified) and writes its output to STDOUT. It also takes a C identifier to +be used as part of the function name to retrieve the packfile. + +The function generated has the signature: + + Parrot_PackFile Parrot_pbc2cc_read_<name>(Parrot_Interp interpreter); + +Where <name> is the C identifier given on the command line. + +=cut + +use strict; +use File::Temp qw(tempfile); + +my($name, $in)[EMAIL PROTECTED]; +$in ||= '-'; +my $size=0; + +open(IN, "< $in") or die "Can't open input file $in: $!"; +my $temp=tempfile() or die "Can't create temporary file: $!"; + +binmode(IN); +binmode($temp); + +{ + local $/=\1024; + while(<IN>) { + $size += length; + print $temp $_; + } +} + +seek $temp, 0, 0; + +print <<"END"; +/* + * DO NOT EDIT THIS FILE + * This file has been automatically generated by $0 in the Parrot distribution. + */ +#ifndef PARROT_PBC2CC_${name}_GUARD +#define PARROT_PBC2CC_${name}_GUARD + +#include <stdlib.h> +#include <string.h> +#include "parrot/embed.h" + +static const Parrot_Int Parrot_pbc2cc_size_$name=$size; +/* gcc gives a warning about variable-size objects if we try to use that constant here */ +static const unsigned char Parrot_pbc2cc_bits_${name}[$size]={ +END + +{ + local $/=\16; + while(<$temp>) { + print "\t0x", join(", 0x", map { sprintf "%2.2x", $_ } unpack "C*", $_), ",\n"; + } +} + +print <<"END"; +}; + +Parrot_PackFile Parrot_pbc2cc_read_$name(Parrot_Interp interpreter) { +\tunsigned char * rawfile=malloc(Parrot_pbc2cc_size_$name); +\tmemcpy(rawfile, Parrot_pbc2cc_bits_$name, Parrot_pbc2cc_size_$name); +\treturn Parrot_readbc_ptr(interpreter, "$name (embedded)", rawfile, Parrot_pbc2cc_size_$name, 0); +} + +#endif +END Index: include/parrot/embed.h =================================================================== RCS file: /cvs/public/parrot/include/parrot/embed.h,v retrieving revision 1.25 diff -u -r1.25 embed.h --- include/parrot/embed.h 2 May 2004 10:47:51 -0000 1.25 +++ include/parrot/embed.h 5 Nov 2004 03:25:33 -0000 @@ -36,6 +36,8 @@ Parrot_PackFile Parrot_readbc(Parrot_Interp, const char *); +Parrot_PackFile Parrot_readbc_ptr(Parrot_Interp, const char *, unsigned char *, size_t, Parrot_Int); + void Parrot_loadbc(Parrot_Interp, Parrot_PackFile); void Parrot_setup_argv(Parrot_Interp, int argc, char ** argv); Index: src/embed.c =================================================================== RCS file: /cvs/public/parrot/src/embed.c,v retrieving revision 1.119 diff -u -r1.119 embed.c --- src/embed.c 22 Oct 2004 13:29:36 -0000 1.119 +++ src/embed.c 5 Nov 2004 03:25:33 -0000 @@ -201,7 +201,7 @@ Parrot_readbc(Interp *interpreter, const char *filename) { INTVAL program_size, wanted; - char *program_code; + unsigned char *program_code; struct PackFile *pf; FILE * io = NULL; INTVAL is_mapped = 0; @@ -325,14 +325,7 @@ /* Now that we have the bytecode, let's unpack it. */ - pf = PackFile_new(is_mapped); - - if (!PackFile_unpack - (interpreter, pf, (opcode_t *)program_code, program_size)) { - PIO_eprintf(interpreter, "Parrot VM: Can't unpack packfile %s.\n", - filename); - return NULL; - } + pf = Parrot_readbc_ptr(interpreter, filename, program_code, program_size, is_mapped); #ifdef PARROT_HAS_HEADER_SYSMMAN @@ -347,6 +340,20 @@ return pf; } +struct PackFile * +Parrot_readbc_ptr(Interp *interpreter, const char *name, unsigned char *ptr, size_t size, Intval is_mapped) { + struct PackFile *pf = PackFile_new(is_mapped); + + if (!PackFile_unpack + (interpreter, pf, (opcode_t *)ptr, size)) { + PIO_eprintf(interpreter, "Parrot VM: Can't unpack packfile %s.\n", + name); + return NULL; + } + + return pf; +} + /* =item C<void