Attached a simple bytecode header reader/writes that writes out the natively correct output, and can read in recognize the output of "any" (for small enough values of any) other platform. Tried on x86 (32LE), sparc (32BE), alpha (64LE), mips (32BE/64BE, compiler-switchable), and unicosmk (64BE, really an alpha, not true Cray CPU).
Compile as 'cc -o pbh -I/perl5/include pbh.h' and use as ./pbh -o pbh.foo (write) or ./pbh -i pbh.bar (read). I confess to cutting down Dan's spec a bit, by changing the major/minor to be bytes, and moving the cookie to the end (for better alignment), now this basic header is only 16 bytes. An interesting detail is that (in case UVSIZE == 4) even if I write the 0x1234567 to the char offset 8, the long might end up beginning at offset 12... this is what happens in the MIPS, as opposed to Sparc where the long lands at offset 8 as expected. Probably some funky alignment issue that I'm much too sleepy to ponder now. In case we want 8-byte magic signature "PARROTRY" would work, just as an idle observation :-) -- $jhi++; # http://www.iki.fi/jhi/ # There is this special biologist word we use for 'stable'. # It is 'dead'. -- Jack Cohen
/* * Copyright 2001 Jarkko Hietaniemi. All rights reserved. * This is free software. It may be used, redistributed * and/or modified under the same terms as Perl itself. */ #include "EXTERN.h" #include "perl.h" #define PARROT_BYTECODE_MAJOR 0 #define PARROT_BYTECODE_MINOR 1 #define PARROT_BYTECODE_IO_SUCCESS 0 #define PARROT_BYTECODE_IO_FAILURE -1 #define PARROT_BYTECODE_MAGIC_FAILURE -2 #define PARROT_BYTECODE_EMPTY_FAILURE -3 typedef struct { U8 wordsize; int major; int minor; U8 cookie[8]; } parrot_bytecode_header; #define PARROT_BYTECODE_HEADER_SIZE (4+1+1+1+1+8) #define PARROT_BYTECODE_HEADER_MAGIC 0 #define PARROT_BYTECODE_HEADER_WORDSIZE 4 #define PARROT_BYTECODE_HEADER_MAJOR 5 #define PARROT_BYTECODE_HEADER_MINOR 6 #define PARROT_BYTECODE_HEADER_EMPTY 7 #define PARROT_BYTECODE_HEADER_COOKIE 8 int parrot_bytecode_header_read(FILE *fp, parrot_bytecode_header *pbh) { U8 buffer[PARROT_BYTECODE_HEADER_SIZE]; if (fread(buffer, PARROT_BYTECODE_HEADER_SIZE, 1, fp) == 1) { if (!(buffer[PARROT_BYTECODE_HEADER_MAGIC ] == 'P' && buffer[PARROT_BYTECODE_HEADER_MAGIC + 1] == 'A' && buffer[PARROT_BYTECODE_HEADER_MAGIC + 2] == 'R' && buffer[PARROT_BYTECODE_HEADER_MAGIC + 3] == 'R')) return PARROT_BYTECODE_MAGIC_FAILURE; pbh->wordsize = buffer[PARROT_BYTECODE_HEADER_WORDSIZE]; pbh->major = buffer[PARROT_BYTECODE_HEADER_MAJOR]; pbh->minor = buffer[PARROT_BYTECODE_HEADER_MINOR]; if (buffer[PARROT_BYTECODE_HEADER_EMPTY]) return PARROT_BYTECODE_EMPTY_FAILURE; memcpy(pbh->cookie, buffer + PARROT_BYTECODE_HEADER_COOKIE, sizeof(pbh->cookie)); return PARROT_BYTECODE_IO_SUCCESS; } else return PARROT_BYTECODE_IO_FAILURE; } int parrot_bytecode_header_write(FILE *fp) { U8 buffer[PARROT_BYTECODE_HEADER_SIZE] = { 0 }; buffer[PARROT_BYTECODE_HEADER_MAGIC ] = 'P'; buffer[PARROT_BYTECODE_HEADER_MAGIC + 1] = 'A'; buffer[PARROT_BYTECODE_HEADER_MAGIC + 2] = 'R'; buffer[PARROT_BYTECODE_HEADER_MAGIC + 3] = 'R'; buffer[PARROT_BYTECODE_HEADER_WORDSIZE] = UVSIZE; buffer[PARROT_BYTECODE_HEADER_MAJOR] = PARROT_BYTECODE_MAJOR; buffer[PARROT_BYTECODE_HEADER_MINOR] = PARROT_BYTECODE_MINOR; #undef COOKIE #if UVSIZE == 8 ((UV*)(buffer + PARROT_BYTECODE_HEADER_COOKIE))[0] = 0x123456789abcdef0; #else # if UVSIZE == 4 ((UV*)(buffer + PARROT_BYTECODE_HEADER_COOKIE))[0] = 0x12345678; # else memset(buffer + PARROT_BYTECODE_HEADER_COOKIE, -1, 8); # endif #endif if (fwrite(buffer, PARROT_BYTECODE_HEADER_SIZE, 1, fp) == 1) { return PARROT_BYTECODE_IO_SUCCESS; } else return PARROT_BYTECODE_IO_FAILURE; } void parrot_bytecode_header_dump(FILE *fp, parrot_bytecode_header *pbh) { fprintf(fp, "wordsize = %d\n", pbh->wordsize); fprintf(fp, "major = %d\n", pbh->major); fprintf(fp, "minor = %d\n", pbh->minor); fprintf(fp, "cookie = %02x%02x%02x%02x%02x%02x%02x%02x\n", pbh->cookie[0], pbh->cookie[1], pbh->cookie[2], pbh->cookie[3], pbh->cookie[4], pbh->cookie[5], pbh->cookie[6], pbh->cookie[7]); } void show_usage_and_die(char *argv[]) { fprintf(stderr, "Usage: %s [-o|-i] file\n", argv[0]); exit(1); } int main(int argc, char *argv[]) { if (argc == 3) { FILE *fp; if (strEQ(argv[1], "-o")) { if ((fp = fopen(argv[2], "wb"))) { parrot_bytecode_header_write(fp); fclose(fp); } else { fprintf(stderr, "fopen(\"%s\", \"w\") failed: %s\n", argv[2], strerror(errno)); exit(2); } } else if (strEQ(argv[1], "-i")) { if ((fp = fopen(argv[2], "rb"))) { parrot_bytecode_header pbh; parrot_bytecode_header_read(fp, &pbh); parrot_bytecode_header_dump(stderr, &pbh); fclose(fp); } else { fprintf(stderr, "fopen(\"%s\", \"r\") failed: %s\n", argv[2], strerror(errno)); exit(2); } } else show_usage_and_die(argv); } else show_usage_and_die(argv); return 0; }