|
@@ -24,20 +24,57 @@
|
|
|
#include <stdlib.h>
|
|
|
#include <memory.h>
|
|
|
|
|
|
+typedef enum {
|
|
|
+ HVOID = 0,
|
|
|
+ HUI8 = 1,
|
|
|
+ HI32 = 2,
|
|
|
+ HF32 = 3,
|
|
|
+ HF64 = 4,
|
|
|
+ HBOOL = 5,
|
|
|
+ HANY = 6,
|
|
|
+ HFUN = 7,
|
|
|
+ // ---------
|
|
|
+ HLAST = 8
|
|
|
+} hl_type_kind;
|
|
|
+
|
|
|
+typedef struct hl_type hl_type;
|
|
|
+
|
|
|
+struct hl_type {
|
|
|
+ hl_type_kind kind;
|
|
|
+ int nargs;
|
|
|
+ hl_type **args;
|
|
|
+ hl_type *ret;
|
|
|
+};
|
|
|
+
|
|
|
+typedef struct {
|
|
|
+ const char *name;
|
|
|
+ int global;
|
|
|
+} hl_native;
|
|
|
+
|
|
|
typedef struct {
|
|
|
int version;
|
|
|
- int nglobals;
|
|
|
+ int nstrings;
|
|
|
int nfloats;
|
|
|
- int nfunctions;
|
|
|
+ int ntypes;
|
|
|
+ int nglobals;
|
|
|
int nnatives;
|
|
|
+ int nfunctions;
|
|
|
int entrypoint;
|
|
|
+ char *strings_data;
|
|
|
+ int *strings_lens;
|
|
|
+ char **strings;
|
|
|
+ double *floats;
|
|
|
+ hl_type *types;
|
|
|
+ hl_type **globals;
|
|
|
+ hl_native *natives;
|
|
|
} hl_code;
|
|
|
|
|
|
typedef struct {
|
|
|
const unsigned char *b;
|
|
|
int size;
|
|
|
int pos;
|
|
|
- int error;
|
|
|
+ const char *error;
|
|
|
+ hl_code *code;
|
|
|
} hl_reader;
|
|
|
|
|
|
#define HL_VERSION 010
|
|
@@ -51,16 +88,51 @@ void hl_global_free() {
|
|
|
#define READ() hl_read_b(r)
|
|
|
#define INDEX() hl_read_index(r)
|
|
|
#define UINDEX() hl_read_uindex(r)
|
|
|
-#define ERROR(msg) { printf("%s\n",msg); hl_code_free(c); return NULL; }
|
|
|
+#define ERROR(msg) r->error = msg;
|
|
|
|
|
|
static unsigned char hl_read_b( hl_reader *r ) {
|
|
|
if( r->pos >= r->size ) {
|
|
|
- r->error = 1;
|
|
|
+ ERROR("No more data");
|
|
|
return 0;
|
|
|
}
|
|
|
return r->b[r->pos++];
|
|
|
}
|
|
|
|
|
|
+static void hl_read_bytes( hl_reader *r, void *data, int size ) {
|
|
|
+ if( size < 0 ) {
|
|
|
+ ERROR("Invalid size");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if( r->pos + size > r->size ) {
|
|
|
+ ERROR("No more data");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ memcpy(data,r->b + r->pos, size);
|
|
|
+ r->pos += size;
|
|
|
+}
|
|
|
+
|
|
|
+static double hl_read_double( hl_reader *r ) {
|
|
|
+ union {
|
|
|
+ double d;
|
|
|
+ char b[8];
|
|
|
+ } s;
|
|
|
+ hl_read_bytes(r, s.b, 8);
|
|
|
+ return s.d;
|
|
|
+}
|
|
|
+
|
|
|
+static int hl_read_i32( hl_reader *r ) {
|
|
|
+ unsigned char a, b, c, d;
|
|
|
+ if( r->pos + 4 > r->size ) {
|
|
|
+ ERROR("No more data");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ a = r->b[r->pos++];
|
|
|
+ b = r->b[r->pos++];
|
|
|
+ c = r->b[r->pos++];
|
|
|
+ d = r->b[r->pos++];
|
|
|
+ return a | (b<<8) | (c<<16) | (d<<24);
|
|
|
+}
|
|
|
+
|
|
|
static int hl_read_index( hl_reader *r ) {
|
|
|
unsigned char b = READ();
|
|
|
if( (b & 0x80) == 0 )
|
|
@@ -80,29 +152,151 @@ static int hl_read_index( hl_reader *r ) {
|
|
|
|
|
|
static int hl_read_uindex( hl_reader *r ) {
|
|
|
int i = hl_read_index(r);
|
|
|
- if( i < 0 ) r->error = 1;
|
|
|
+ if( i < 0 ) {
|
|
|
+ ERROR("Negative index");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
return i;
|
|
|
}
|
|
|
|
|
|
void hl_code_free( hl_code *c ) {
|
|
|
+ int i;
|
|
|
+ if( c == NULL ) return;
|
|
|
+ if( c->strings_data ) free(c->strings_data);
|
|
|
+ if( c->strings_lens ) free(c->strings_lens);
|
|
|
+ if( c->strings ) free(c->strings);
|
|
|
+ if( c->floats ) free(c->floats);
|
|
|
+ if( c->types ) {
|
|
|
+ for(i=0;i<c->ntypes;i++) {
|
|
|
+ hl_type *t = c->types + i;
|
|
|
+ if( t->args ) free(t->args);
|
|
|
+ }
|
|
|
+ free(c->types);
|
|
|
+ }
|
|
|
+ if( c->globals ) free(c->globals);
|
|
|
+ if( c->natives ) free(c->natives);
|
|
|
free(c);
|
|
|
}
|
|
|
|
|
|
+hl_type *hl_get_type( hl_reader *r ) {
|
|
|
+ int i = INDEX();
|
|
|
+ if( i < 0 || i >= r->code->ntypes ) {
|
|
|
+ ERROR("Invalid type index");
|
|
|
+ i = 0;
|
|
|
+ }
|
|
|
+ return r->code->types + i;
|
|
|
+}
|
|
|
+
|
|
|
+const char *hl_get_string( hl_reader *r ) {
|
|
|
+ int i = INDEX();
|
|
|
+ if( i < 0 || i >= r->code->nstrings ) {
|
|
|
+ ERROR("Invalid string index");
|
|
|
+ i = 0;
|
|
|
+ }
|
|
|
+ return r->code->strings[i];
|
|
|
+}
|
|
|
+
|
|
|
+int hl_get_global( hl_reader *r ) {
|
|
|
+ int g = INDEX();
|
|
|
+ if( g < 0 || g >= r->code->nglobals ) {
|
|
|
+ ERROR("Invalid global index");
|
|
|
+ g = 0;
|
|
|
+ }
|
|
|
+ return g;
|
|
|
+}
|
|
|
+
|
|
|
+void hl_read_type( hl_reader *r, hl_type *t ) {
|
|
|
+ int i;
|
|
|
+ t->kind = READ();
|
|
|
+ if( t->kind >= HLAST ) {
|
|
|
+ ERROR("Invalid type");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ switch( t->kind ) {
|
|
|
+ case HFUN:
|
|
|
+ t->nargs = READ();
|
|
|
+ t->args = (hl_type**)malloc(sizeof(hl_type*)*t->nargs);
|
|
|
+ if( t->args == NULL ) {
|
|
|
+ ERROR("Out of memory");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ for(i=0;i<t->nargs;i++)
|
|
|
+ t->args[i] = hl_get_type(r);
|
|
|
+ t->ret = hl_get_type(r);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#define CHK_ERROR() if( r->error ) { hl_code_free(c); printf("%s\n", r->error); return NULL; }
|
|
|
+#define EXIT(msg) { ERROR(msg); CHK_ERROR(); }
|
|
|
+#define ALLOC(v,ptr,count) { v = (ptr *)malloc(count*sizeof(ptr)); if( v == NULL ) EXIT("Out of memory") else memset(v, 0, count*sizeof(ptr)); }
|
|
|
+
|
|
|
hl_code *hl_code_read( const unsigned char *data, int size ) {
|
|
|
- hl_reader _r = { data, size, 0, 0 };
|
|
|
+ hl_reader _r = { data, size, 0, 0, NULL };
|
|
|
hl_reader *r = &_r;
|
|
|
- hl_code *c = (hl_code*)malloc(sizeof(hl_code));
|
|
|
- memset(c,0,sizeof(hl_code));
|
|
|
+ hl_code *c;
|
|
|
+ int i;
|
|
|
+ ALLOC(c, hl_code, 1);
|
|
|
if( READ() != 'H' || READ() != 'L' || READ() != 'B' )
|
|
|
- ERROR("Invalid HL header");
|
|
|
+ EXIT("Invalid header");
|
|
|
+ r->code = c;
|
|
|
c->version = READ();
|
|
|
- c->nglobals = UINDEX();
|
|
|
+ if( c->version <= 0 || c->version > 1 ) {
|
|
|
+ printf("VER=%d\n",c->version);
|
|
|
+ EXIT("Unsupported version");
|
|
|
+ }
|
|
|
+ c->nstrings = UINDEX();
|
|
|
c->nfloats = UINDEX();
|
|
|
+ c->ntypes = UINDEX();
|
|
|
+ c->nglobals = UINDEX();
|
|
|
c->nnatives = UINDEX();
|
|
|
c->nfunctions = UINDEX();
|
|
|
- c->entrypoint = UINDEX();
|
|
|
- if( r->error )
|
|
|
- ERROR("Invalid HL counts");
|
|
|
+ c->entrypoint = UINDEX();
|
|
|
+ {
|
|
|
+ int size = hl_read_i32(r);
|
|
|
+ char *sdata;
|
|
|
+ CHK_ERROR();
|
|
|
+ sdata = (char*)malloc(sizeof(char) * size);
|
|
|
+ if( sdata == NULL )
|
|
|
+ EXIT("Out of memory");
|
|
|
+ hl_read_bytes(r, sdata, size);
|
|
|
+ c->strings_data = sdata;
|
|
|
+ ALLOC(c->strings, char*, c->nstrings);
|
|
|
+ ALLOC(c->strings_lens, int, c->nstrings);
|
|
|
+ for(i=0;i<c->nstrings;i++) {
|
|
|
+ int sz = UINDEX();
|
|
|
+ c->strings[i] = sdata;
|
|
|
+ c->strings_lens[i] = sz;
|
|
|
+ sdata += sz;
|
|
|
+ if( sdata >= c->strings_data + size || *sdata )
|
|
|
+ EXIT("Invalid string");
|
|
|
+ sdata++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ CHK_ERROR();
|
|
|
+ ALLOC(c->floats, double, sizeof(double)*c->nfloats);
|
|
|
+ for(i=0;i<c->nfloats;i++)
|
|
|
+ c->floats[i] = hl_read_double(r);
|
|
|
+ CHK_ERROR();
|
|
|
+ ALLOC(c->types, hl_type, sizeof(hl_type)*c->ntypes);
|
|
|
+ for(i=0;i<c->ntypes;i++) {
|
|
|
+ hl_read_type(r, c->types + i);
|
|
|
+ CHK_ERROR();
|
|
|
+ }
|
|
|
+ ALLOC(c->globals, hl_type*, sizeof(hl_type*)*c->nglobals);
|
|
|
+ for(i=0;i<c->nglobals;i++)
|
|
|
+ c->globals[i] = hl_get_type(r);
|
|
|
+ CHK_ERROR();
|
|
|
+ ALLOC(c->natives, hl_native, sizeof(hl_native)*c->nnatives);
|
|
|
+ for(i=0;i<c->nnatives;i++) {
|
|
|
+ c->natives[i].name = hl_get_string(r);
|
|
|
+ c->natives[i].global = hl_get_global(r);
|
|
|
+ printf("%s,%d\n", c->natives[i].name, c->natives[i].global);
|
|
|
+ }
|
|
|
+ CHK_ERROR();
|
|
|
+ EXIT("TODO");
|
|
|
return NULL;
|
|
|
}
|
|
|
|