# New Ticket Created by  Leopold Toetsch 
# Please include the string:  [perl #17193]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org/rt2/Ticket/Display.html?id=17193 >


Here is a patch, that is selfcontained in packfile.c, so should be 
useful for other potential users of packout.c in the future:

- It's ugly
- It works(tm) [1]

Please apply.

When the masters of KEY find a better solution, I will gladly toss this 
patch, but for now it's necessary to allow imcc to write .pbc files.

I wrote:

> imcc (0.0.9) has an integrated parrot interpreter and tries to write out 
>  a PBC file too. Running code succeeds currently for ~95 % of perl6 
> tests (in half the time ;-).
> 
> But I've problems in writing out the .pbc, especially Const_Table, type 
> PFC_KEY / PARROT_ARG_SC (and _NC if one would use these).
> 
> The problem seems to be, that all other key types can be looked up by 
> key.cache->int_val, but not _SC and _NC as there value is the contents 
> of another string or number constant.
> 
> So packing a packfile seems not to be reversible.
> 
> I see currently 3 possible ways to workaround this problem:
> 
> 1) make another indirection in reading an _SC or _NC key, so that
>   key.cache->int_val is the index into the constant table and not the
>   string_val or the num_val itself.
> 
> 2) don't use ->data as the key->next pointer but some structure
>    data -> { int idx, PMC *next } and store the constant index there.
> 
> 3)
> The easierst solution (for me): provide the possibility to call a 
> callback, that fills the packed structure with the required data. 
> Actually I have also this packed data, because on building the keys I 
> assemble this packed data, which on PackFile_Constant_unpack_key() 
> generates all the PMCs for runtime.
> 
> 1) and 2) would be a general solution but require a major rewrite of key 
> functions / access and have drawback for speed / memory usage.
> 
> 3) is "if you want to packout _SC keys, do it yourself" ;-)
> 


4) and this patch: search in the constant_table :-(


> Comments welcome,

Still,
leo


[1] imcc compiled PBC files of all perl6 tests ran through parrot give 
the same test results as the assembler.pl versions, i.e. succeed except 8_5.


-- attachment  1 ------------------------------------------------------
url: http://rt.perl.org/rt2/attach/37291/30229/6a904c/packout.c.diff

--- packout.c   Wed Aug 21 14:03:56 2002
+++ /home/lt/src/parrot-leo/packout.c   Thu Sep 12 15:22:42 2002
@@ -178,6 +178,7 @@
 NOTE: The memory block had better have at least the amount of memory 
       indicated by PackFile_ConstTable_pack_size()!
 ***************************************/
+static struct PackFile_ConstTable *ct;
 
 void
 PackFile_ConstTable_pack(struct PackFile *packfile,
@@ -192,6 +193,7 @@
     }
 
     cursor = packed;
+    ct = self;
 
     *cursor = self->const_count;
     cursor++;
@@ -206,6 +208,23 @@
     return;
 }
 
+/* this is really ugly, we don't know where our PARROT_ARG_SC
+ * key constant is in constant table,
+ * so we search for it @§$&
+ */
+static int find_in_const(PMC *key, int type)
+{
+    int i;
+    for (i = 0 ; i < ct->const_count; i++)
+        if (type == PFC_STRING && ct->constants[i]->string ==
+                key->cache.string_val)
+            return i;
+        else if (type == PFC_NUMBER && ct->constants[i]->number ==
+                key->cache.num_val)
+            return i;
+    fprintf(stderr, "find_in_const: couldn't find const for key\n");
+    exit(1);
+}
 /***************************************
 Pack a PackFile Constant into a contiguous region of memory. NOTE: The memory
 block had better have at least the amount of memory indicated by
@@ -223,6 +242,7 @@
     size_t i;
     opcode_t padded_size;
     opcode_t packed_size;
+    struct PMC *key;
 
     if (!self) {
         /* TODO: OK to be silent here? */
@@ -260,7 +280,8 @@
         padded_size = self->string->bufused;
 
         if (padded_size % sizeof(opcode_t)) {
-            padded_size += sizeof(opcode_t) - (padded_size % sizeof(opcode_t));
+                padded_size += sizeof(opcode_t) -
+                    (padded_size % sizeof(opcode_t));
         }
 
         /* Include space for flags, encoding, type, and size fields.  */
@@ -298,8 +319,60 @@
          */
         break;
 
+        case PFC_KEY:
+            packed_size = sizeof(opcode_t);
+            for (i = 0, key = self->key; key; key = key->data, i++)
+                packed_size += 2 * sizeof(opcode_t);
+            /* size */
+            *cursor++ = packed_size;
+            /* number of key components */
+            *cursor++ = i;
+            /* and now type / value per component */
+            for (key = self->key; key; key = key->data) {
+                switch (key->flags & KEY_type_FLAGS) {
+                    case KEY_integer_FLAG:
+                        *cursor++ = PARROT_ARG_IC;
+                        *cursor++ = key->cache.int_val;
+                        break;
+                    case KEY_number_FLAG:
+                        *cursor++ = PARROT_ARG_NC;
+                        *cursor++ = find_in_const(key, PFC_NUMBER); /* Argh */
+                        break;
+                    case KEY_string_FLAG:
+                        *cursor++ = PARROT_ARG_SC;
+                        *cursor++ = find_in_const(key, PFC_STRING);/* Argh */
+                        break;
+
+                    case KEY_integer_FLAG | KEY_register_FLAG:
+                        *cursor++ = PARROT_ARG_I;
+                        *cursor++ = key->cache.int_val;
+                        break;
+                    case KEY_number_FLAG | KEY_register_FLAG:
+                        *cursor++ = PARROT_ARG_N;
+                        *cursor++ = key->cache.int_val;
+                        break;
+                    case KEY_string_FLAG | KEY_register_FLAG:
+                        *cursor++ = PARROT_ARG_S;
+                        *cursor++ = key->cache.int_val;
+                        break;
+                    case KEY_pmc_FLAG | KEY_register_FLAG:
+                        *cursor++ = PARROT_ARG_P;
+                        *cursor++ = key->cache.int_val;
+                        break;
+                    default:
+                        fprintf(stderr, "PackFile_Constant_pack: "
+                                "unsupported constant type\n");
+                        exit(1);
+                }
+            }
+
+            break;
+
     default:
         /* TODO: OK to be silent here? */
+            /* ARGH, don't be silent -lt */
+            fprintf(stderr, "PackFile_Constant_pack: unsupported constant\n");
+            exit(1);
         break;
     }
 

Reply via email to