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

Reply via email to