Update Files
This commit is contained in:
111
Kha/Backends/Kinc-HL/hl/src/std/array.c
Normal file
111
Kha/Backends/Kinc-HL/hl/src/std/array.c
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C)2005-2016 Haxe Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <hl.h>
|
||||
|
||||
HL_PRIM varray *hl_alloc_array( hl_type *at, int size ) {
|
||||
if( size == 0 && at->kind == HDYN ) {
|
||||
static varray empty_array = { &hlt_array, &hlt_dyn };
|
||||
return &empty_array;
|
||||
}
|
||||
int esize = hl_type_size(at);
|
||||
varray *a;
|
||||
if( size < 0 ) hl_error("Invalid array size");
|
||||
a = (varray*)hl_gc_alloc_gen(&hlt_array, sizeof(varray) + esize*size, (hl_is_ptr(at) ? MEM_KIND_DYNAMIC : MEM_KIND_NOPTR) | MEM_ZERO);
|
||||
a->t = &hlt_array;
|
||||
a->at = at;
|
||||
a->size = size;
|
||||
return a;
|
||||
}
|
||||
|
||||
HL_PRIM void hl_array_blit( varray *dst, int dpos, varray *src, int spos, int len ) {
|
||||
int size = hl_type_size(dst->at);
|
||||
memmove( hl_aptr(dst,vbyte) + dpos * size, hl_aptr(src,vbyte) + spos * size, len * size);
|
||||
}
|
||||
|
||||
HL_PRIM hl_type *hl_array_type( varray *a ) {
|
||||
return a->at;
|
||||
}
|
||||
|
||||
DEFINE_PRIM(_ARR,alloc_array,_TYPE _I32);
|
||||
DEFINE_PRIM(_VOID,array_blit,_ARR _I32 _ARR _I32 _I32);
|
||||
DEFINE_PRIM(_TYPE,array_type,_ARR);
|
||||
|
||||
typedef struct {
|
||||
hl_type *at;
|
||||
int osize;
|
||||
int size;
|
||||
} hl_carray;
|
||||
|
||||
HL_PRIM void *hl_alloc_carray( hl_type *at, int size ) {
|
||||
if( at->kind != HOBJ && at->kind != HSTRUCT )
|
||||
hl_error("Invalid array type");
|
||||
if( size < 0 )
|
||||
hl_error("Invalid array size");
|
||||
|
||||
hl_runtime_obj *rt = at->obj->rt;
|
||||
if( rt == NULL || rt->methods == NULL ) rt = hl_get_obj_proto(at);
|
||||
int osize = rt->size;
|
||||
if( osize & (HL_WSIZE-1) ) osize += HL_WSIZE - (osize & (HL_WSIZE-1));
|
||||
hl_carray *arr;
|
||||
int header = sizeof(hl_carray);
|
||||
if( at->kind == HSTRUCT ) {
|
||||
header += sizeof(vdynamic) * size;
|
||||
arr = (hl_carray*)hl_gc_alloc_gen(at, header + size * osize, (rt->hasPtr ? MEM_KIND_RAW : MEM_KIND_NOPTR) | MEM_ZERO);
|
||||
arr->osize = sizeof(vdynamic);
|
||||
} else {
|
||||
arr = (hl_carray*)hl_gc_alloc_gen(at, header + size * osize, (rt->hasPtr ? MEM_KIND_DYNAMIC : MEM_KIND_NOPTR) | MEM_ZERO);
|
||||
arr->osize = osize;
|
||||
}
|
||||
arr->size = size;
|
||||
arr->at = at;
|
||||
|
||||
int i,k;
|
||||
for(k=0;k<size;k++) {
|
||||
vobj *o = (vobj*)((char*)arr + header + osize * k);
|
||||
if( at->kind == HOBJ )
|
||||
o->t = at;
|
||||
else {
|
||||
vdynamic *d = (vdynamic*)((char*)(arr + 1) + k * sizeof(vdynamic));
|
||||
d->t = at;
|
||||
d->v.ptr = o;
|
||||
}
|
||||
for(i=0;i<rt->nbindings;i++) {
|
||||
hl_runtime_binding *b = rt->bindings + i;
|
||||
*(void**)(((char*)o) + rt->fields_indexes[b->fid]) = b->closure ? hl_alloc_closure_ptr(b->closure,b->ptr,o) : b->ptr;
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_carray_length( hl_carray *arr ) {
|
||||
return arr->size;
|
||||
}
|
||||
|
||||
HL_PRIM vdynamic *hl_carray_get( hl_carray *arr, int pos ) {
|
||||
if( pos < 0 || pos >= arr->size ) return NULL;
|
||||
return (vdynamic*)((char*)(arr + 1) + pos * arr->osize);
|
||||
}
|
||||
|
||||
#define _CARRAY _ABSTRACT(hl_carray)
|
||||
DEFINE_PRIM(_CARRAY,alloc_carray,_TYPE _I32);
|
||||
DEFINE_PRIM(_DYN,carray_get,_CARRAY _I32);
|
||||
DEFINE_PRIM(_I32,carray_length,_CARRAY);
|
396
Kha/Backends/Kinc-HL/hl/src/std/buffer.c
Normal file
396
Kha/Backends/Kinc-HL/hl/src/std/buffer.c
Normal file
@ -0,0 +1,396 @@
|
||||
/*
|
||||
* Copyright (C)2005-2016 Haxe Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <hl.h>
|
||||
|
||||
#ifdef PRId64
|
||||
# define PR_I64 USTR("%" PRId64)
|
||||
#else
|
||||
# define PR_I64 USTR("%lld")
|
||||
#endif
|
||||
|
||||
typedef struct _stringitem {
|
||||
uchar *str;
|
||||
int size;
|
||||
int len;
|
||||
struct _stringitem *next;
|
||||
} * stringitem;
|
||||
|
||||
struct hl_buffer {
|
||||
int totlen;
|
||||
int blen;
|
||||
stringitem data;
|
||||
};
|
||||
|
||||
HL_PRIM hl_buffer *hl_alloc_buffer() {
|
||||
hl_buffer *b = (hl_buffer*)hl_gc_alloc_raw(sizeof(hl_buffer));
|
||||
b->totlen = 0;
|
||||
b->blen = 16;
|
||||
b->data = NULL;
|
||||
return b;
|
||||
}
|
||||
|
||||
static void buffer_append_new( hl_buffer *b, const uchar *s, int len ) {
|
||||
int size;
|
||||
stringitem it;
|
||||
while( b->totlen >= (b->blen << 2) )
|
||||
b->blen <<= 1;
|
||||
size = (len < b->blen)?b->blen:len;
|
||||
it = (stringitem)hl_gc_alloc_raw(sizeof(struct _stringitem));
|
||||
it->str = (uchar*)hl_gc_alloc_noptr(size<<1);
|
||||
memcpy(it->str,s,len<<1);
|
||||
it->size = size;
|
||||
it->len = len;
|
||||
it->next = b->data;
|
||||
b->data = it;
|
||||
}
|
||||
|
||||
HL_PRIM void hl_buffer_str_sub( hl_buffer *b, const uchar *s, int len ) {
|
||||
stringitem it;
|
||||
int offset = 0;
|
||||
if( s == NULL || len <= 0 )
|
||||
return;
|
||||
b->totlen += len;
|
||||
it = b->data;
|
||||
if( it ) {
|
||||
int free = it->size - it->len;
|
||||
if( free >= len ) {
|
||||
memcpy(it->str + it->len,s,len<<1);
|
||||
it->len += len;
|
||||
return;
|
||||
} else {
|
||||
memcpy(it->str + it->len,s,free<<1);
|
||||
it->len += free;
|
||||
offset = free;
|
||||
len -= free;
|
||||
}
|
||||
}
|
||||
buffer_append_new(b,s + offset,len);
|
||||
}
|
||||
|
||||
HL_PRIM void hl_buffer_str( hl_buffer *b, const uchar *s ) {
|
||||
if( s ) hl_buffer_str_sub(b,s,(int)ustrlen(s)); else hl_buffer_str_sub(b,USTR("NULL"),4);
|
||||
}
|
||||
|
||||
HL_PRIM void hl_buffer_cstr( hl_buffer *b, const char *s ) {
|
||||
if( s ) {
|
||||
int len = (int)hl_utf8_length((vbyte*)s,0);
|
||||
uchar *out = (uchar*)malloc(sizeof(uchar)*(len+1));
|
||||
hl_from_utf8(out,len,s);
|
||||
hl_buffer_str_sub(b,out,len);
|
||||
free(out);
|
||||
} else hl_buffer_str_sub(b,USTR("NULL"),4);
|
||||
}
|
||||
|
||||
HL_PRIM void hl_buffer_char( hl_buffer *b, uchar c ) {
|
||||
stringitem it;
|
||||
b->totlen++;
|
||||
it = b->data;
|
||||
if( it && it->len != it->size ) {
|
||||
it->str[it->len++] = c;
|
||||
return;
|
||||
}
|
||||
buffer_append_new(b,(uchar*)&c,1);
|
||||
}
|
||||
|
||||
HL_PRIM uchar *hl_buffer_content( hl_buffer *b, int *len ) {
|
||||
uchar *buf = (uchar*)hl_gc_alloc_noptr((b->totlen+1)<<1);
|
||||
stringitem it = b->data;
|
||||
uchar *s = ((uchar*)buf) + b->totlen;
|
||||
*s = 0;
|
||||
while( it != NULL ) {
|
||||
stringitem tmp;
|
||||
s -= it->len;
|
||||
memcpy(s,it->str,it->len<<1);
|
||||
tmp = it->next;
|
||||
it = tmp;
|
||||
}
|
||||
if( len ) *len = b->totlen;
|
||||
return buf;
|
||||
}
|
||||
|
||||
int hl_buffer_length( hl_buffer *b ) {
|
||||
return b->totlen;
|
||||
}
|
||||
|
||||
typedef struct vlist {
|
||||
vdynamic *v;
|
||||
struct vlist *next;
|
||||
} vlist;
|
||||
|
||||
static void hl_buffer_rec( hl_buffer *b, vdynamic *v, vlist *stack );
|
||||
|
||||
static void hl_buffer_addr( hl_buffer *b, void *data, hl_type *t, vlist *stack ) {
|
||||
uchar buf[32];
|
||||
switch( t->kind ) {
|
||||
case HUI8:
|
||||
hl_buffer_str_sub(b,buf,usprintf(buf,32,USTR("%d"),(int)*(unsigned char*)data));
|
||||
break;
|
||||
case HUI16:
|
||||
hl_buffer_str_sub(b,buf,usprintf(buf,32,USTR("%d"),(int)*(unsigned short*)data));
|
||||
break;
|
||||
case HI32:
|
||||
hl_buffer_str_sub(b,buf,usprintf(buf,32,USTR("%d"),*(int*)data));
|
||||
break;
|
||||
case HI64:
|
||||
hl_buffer_str_sub(b,buf,usprintf(buf,32,PR_I64,*(int64*)data));
|
||||
break;
|
||||
case HF32:
|
||||
hl_buffer_str_sub(b,buf,usprintf(buf,32,USTR("%.9f"),*(float*)data));
|
||||
break;
|
||||
case HF64:
|
||||
hl_buffer_str_sub(b,buf,usprintf(buf,32,USTR("%.17g"),*(double*)data));
|
||||
break;
|
||||
case HBYTES:
|
||||
hl_buffer_str(b,*(uchar**)data);
|
||||
break;
|
||||
case HTYPE:
|
||||
case HREF:
|
||||
case HABSTRACT:
|
||||
{
|
||||
vdynamic tmp;
|
||||
tmp.t = t;
|
||||
tmp.v.ptr = *(void**)data;
|
||||
hl_buffer_rec(b, tmp.v.ptr ? &tmp : NULL, stack);
|
||||
}
|
||||
break;
|
||||
case HBOOL:
|
||||
if( *(unsigned char*)data )
|
||||
hl_buffer_str_sub(b,USTR("true"),4);
|
||||
else
|
||||
hl_buffer_str_sub(b,USTR("false"),5);
|
||||
break;
|
||||
default:
|
||||
hl_buffer_rec(b, *(vdynamic**)data, stack);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void hl_buffer_rec( hl_buffer *b, vdynamic *v, vlist *stack ) {
|
||||
uchar buf[32];
|
||||
if( v == NULL ) {
|
||||
hl_buffer_str_sub(b,USTR("null"),4);
|
||||
return;
|
||||
}
|
||||
switch( v->t->kind ) {
|
||||
case HVOID:
|
||||
hl_buffer_str_sub(b,USTR("void"),4);
|
||||
break;
|
||||
case HUI8:
|
||||
hl_buffer_str_sub(b,buf,usprintf(buf,32,USTR("%d"),v->v.ui8));
|
||||
break;
|
||||
case HUI16:
|
||||
hl_buffer_str_sub(b,buf,usprintf(buf,32,USTR("%d"),v->v.ui16));
|
||||
break;
|
||||
case HI32:
|
||||
hl_buffer_str_sub(b,buf,usprintf(buf,32,USTR("%d"),v->v.i));
|
||||
break;
|
||||
case HI64:
|
||||
hl_buffer_str_sub(b,buf,usprintf(buf,32,PR_I64,v->v.i64));
|
||||
break;
|
||||
case HF32:
|
||||
hl_buffer_str_sub(b,buf,usprintf(buf,32,USTR("%.9f"),v->v.f));
|
||||
break;
|
||||
case HF64:
|
||||
hl_buffer_str_sub(b,buf,usprintf(buf,32,USTR("%.17g"),v->v.d));
|
||||
break;
|
||||
case HBOOL:
|
||||
if( v->v.b )
|
||||
hl_buffer_str_sub(b,USTR("true"),4);
|
||||
else
|
||||
hl_buffer_str_sub(b,USTR("false"),5);
|
||||
break;
|
||||
case HBYTES:
|
||||
hl_buffer_str(b,(uchar*)v->v.bytes);
|
||||
break;
|
||||
case HFUN:
|
||||
hl_buffer_str_sub(b,USTR("function#"),9);
|
||||
hl_buffer_str_sub(b, buf, usprintf(buf, 32, _PTR_FMT,(int_val)v));
|
||||
break;
|
||||
case HMETHOD:
|
||||
hl_buffer_str_sub(b,USTR("method#"),7);
|
||||
hl_buffer_str_sub(b, buf, usprintf(buf, 32, _PTR_FMT,(int_val)v->v.ptr));
|
||||
break;
|
||||
case HOBJ:
|
||||
case HSTRUCT:
|
||||
{
|
||||
hl_type_obj *o = v->t->obj;
|
||||
if( o->rt == NULL || hl_get_obj_proto(v->t)->toStringFun == NULL ) {
|
||||
if( v->t->kind == HSTRUCT ) hl_buffer_char(b,'@');
|
||||
hl_buffer_str(b,o->name);
|
||||
} else
|
||||
hl_buffer_str(b,o->rt->toStringFun(v->t->kind == HSTRUCT ? (vdynamic*)v->v.ptr : v));
|
||||
}
|
||||
break;
|
||||
case HARRAY:
|
||||
{
|
||||
int i;
|
||||
varray *a = (varray*)v;
|
||||
hl_type *at = a->at;
|
||||
int stride = hl_type_size(at);
|
||||
vlist l;
|
||||
vlist *vtmp = stack;
|
||||
while( vtmp != NULL ) {
|
||||
if( vtmp->v == v ) {
|
||||
hl_buffer_str_sub(b,USTR("..."),3);
|
||||
return;
|
||||
}
|
||||
vtmp = vtmp->next;
|
||||
}
|
||||
l.v = v;
|
||||
l.next = stack;
|
||||
hl_buffer_char(b,'[');
|
||||
for(i=0;i<a->size;i++) {
|
||||
if( i )
|
||||
hl_buffer_str_sub(b,USTR(", "),2);
|
||||
hl_buffer_addr(b,hl_aptr(a,char) + i * stride,at,&l);
|
||||
}
|
||||
hl_buffer_char(b,']');
|
||||
}
|
||||
break;
|
||||
case HTYPE:
|
||||
hl_buffer_str(b, hl_type_str((hl_type*)v->v.ptr));
|
||||
break;
|
||||
case HREF:
|
||||
hl_buffer_str_sub(b, USTR("ref"), 3);
|
||||
break;
|
||||
case HVIRTUAL:
|
||||
{
|
||||
vvirtual *vv = (vvirtual*)v;
|
||||
int i;
|
||||
vlist l;
|
||||
vlist *vtmp = stack;
|
||||
if( vv->value ) {
|
||||
hl_buffer_rec(b, vv->value, stack);
|
||||
return;
|
||||
}
|
||||
while( vtmp != NULL ) {
|
||||
if( vtmp->v == v ) {
|
||||
hl_buffer_str_sub(b,USTR("..."),3);
|
||||
return;
|
||||
}
|
||||
vtmp = vtmp->next;
|
||||
}
|
||||
l.v = v;
|
||||
l.next = stack;
|
||||
hl_buffer_char(b, '{');
|
||||
for(i=0;i<vv->t->virt->nfields;i++) {
|
||||
hl_field_lookup *f = vv->t->virt->lookup + i;
|
||||
if( i ) hl_buffer_str_sub(b,USTR(", "),2);
|
||||
hl_buffer_str(b,(uchar*)hl_field_name(f->hashed_name));
|
||||
hl_buffer_str_sub(b,USTR(" : "),3);
|
||||
hl_buffer_addr(b, (char*)v + vv->t->virt->indexes[f->field_index], f->t, &l);
|
||||
}
|
||||
hl_buffer_char(b, '}');
|
||||
}
|
||||
break;
|
||||
case HDYNOBJ:
|
||||
{
|
||||
vdynobj *o = (vdynobj*)v;
|
||||
int i;
|
||||
vlist l;
|
||||
vlist *vtmp = stack;
|
||||
hl_field_lookup *f;
|
||||
while( vtmp != NULL ) {
|
||||
if( vtmp->v == v ) {
|
||||
hl_buffer_str_sub(b,USTR("..."),3);
|
||||
return;
|
||||
}
|
||||
vtmp = vtmp->next;
|
||||
}
|
||||
l.v = v;
|
||||
l.next = stack;
|
||||
f = hl_lookup_find(o->lookup,o->nfields,hl_hash_gen(USTR("__string"),false));
|
||||
if( f && f->t->kind == HFUN && f->t->fun->nargs == 0 && f->t->fun->ret->kind == HBYTES ) {
|
||||
vclosure *v = (vclosure*)o->values[f->field_index];
|
||||
if( v ) {
|
||||
hl_buffer_str(b, v->hasValue ? ((uchar*(*)(void*))v->fun)(v->value) : ((uchar*(*)())v->fun)());
|
||||
break;
|
||||
}
|
||||
}
|
||||
hl_buffer_char(b, '{');
|
||||
for(i=0;i<o->nfields;i++) {
|
||||
hl_field_lookup *f = o->lookup + i;
|
||||
if( i ) hl_buffer_str_sub(b,USTR(", "),2);
|
||||
hl_buffer_str(b,(uchar*)hl_field_name(f->hashed_name));
|
||||
hl_buffer_str_sub(b,USTR(" : "),3);
|
||||
hl_buffer_addr(b, hl_is_ptr(f->t) ? (void*)(o->values + f->field_index) : (void*)(o->raw_data + f->field_index), f->t, &l);
|
||||
}
|
||||
hl_buffer_char(b, '}');
|
||||
}
|
||||
break;
|
||||
case HABSTRACT:
|
||||
hl_buffer_char(b, '~');
|
||||
hl_buffer_str(b, v->t->abs_name);
|
||||
hl_buffer_char(b, ':');
|
||||
hl_buffer_str_sub(b, buf, usprintf(buf, 32, _PTR_FMT,(int_val)v->v.ptr));
|
||||
break;
|
||||
case HENUM:
|
||||
{
|
||||
int i;
|
||||
vlist l;
|
||||
vlist *vtmp = stack;
|
||||
hl_enum_construct *c = v->t->tenum->constructs + ((venum*)v)->index;
|
||||
if( !c->nparams ) {
|
||||
hl_buffer_str(b, c->name);
|
||||
break;
|
||||
}
|
||||
while( vtmp != NULL ) {
|
||||
if( vtmp->v == v ) {
|
||||
hl_buffer_str_sub(b,USTR("..."),3);
|
||||
return;
|
||||
}
|
||||
vtmp = vtmp->next;
|
||||
}
|
||||
l.v = v;
|
||||
l.next = stack;
|
||||
hl_buffer_str(b, c->name);
|
||||
hl_buffer_char(b,'(');
|
||||
for(i=0;i<c->nparams;i++) {
|
||||
if( i ) hl_buffer_char(b,',');
|
||||
hl_buffer_addr(b,(char*)v + c->offsets[i],c->params[i], &l);
|
||||
}
|
||||
hl_buffer_char(b,')');
|
||||
}
|
||||
break;
|
||||
case HNULL:
|
||||
hl_buffer_str_sub(b, USTR("_null_"), 6);
|
||||
break;
|
||||
default:
|
||||
hl_buffer_str_sub(b, buf, usprintf(buf, 32, _PTR_FMT USTR("H"),(int_val)v));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
HL_PRIM void hl_buffer_val( hl_buffer *b, vdynamic *v ) {
|
||||
hl_buffer_rec(b,v,NULL);
|
||||
}
|
||||
|
||||
HL_PRIM uchar *hl_to_string( vdynamic *v ) {
|
||||
if( v == NULL )
|
||||
return USTR("null");
|
||||
if( v->t->kind == HBOOL )
|
||||
return v->v.b ? USTR("true") : USTR("false");
|
||||
hl_buffer *b = hl_alloc_buffer();
|
||||
hl_buffer_val(b,v);
|
||||
hl_buffer_char(b,0);
|
||||
return hl_buffer_content(b,NULL);
|
||||
}
|
280
Kha/Backends/Kinc-HL/hl/src/std/bytes.c
Normal file
280
Kha/Backends/Kinc-HL/hl/src/std/bytes.c
Normal file
@ -0,0 +1,280 @@
|
||||
/*
|
||||
* Copyright (C)2005-2016 Haxe Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <hl.h>
|
||||
|
||||
HL_PRIM vbyte *hl_alloc_bytes( int size ) {
|
||||
return (vbyte*)hl_gc_alloc_noptr(size);
|
||||
}
|
||||
|
||||
HL_PRIM vbyte *hl_copy_bytes( const vbyte *ptr, int size ) {
|
||||
vbyte *b = hl_alloc_bytes(size);
|
||||
memcpy(b,ptr,size);
|
||||
return b;
|
||||
}
|
||||
|
||||
HL_PRIM void hl_bytes_blit( char *dst, int dpos, char *src, int spos, int len ) {
|
||||
memmove(dst + dpos,src+spos,len);
|
||||
}
|
||||
|
||||
HL_PRIM int hl_bytes_compare( vbyte *a, int apos, vbyte *b, int bpos, int len ) {
|
||||
return memcmp(a+apos,b+bpos,len);
|
||||
}
|
||||
|
||||
HL_PRIM int hl_bytes_compare16( vbyte *a, vbyte *b, int len ) {
|
||||
unsigned short *s1 = (unsigned short *)a;
|
||||
unsigned short *s2 = (unsigned short *)b;
|
||||
int i;
|
||||
for(i=0;i<len;i++)
|
||||
if( s1[i] != s2[i] )
|
||||
return ((int)s1[i]) - ((int)s2[i]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef unsigned char byte;
|
||||
static void *
|
||||
memfind_rb (const void *in_block, /* Block containing data */
|
||||
size_t block_size, /* Size of block in bytes */
|
||||
const void *in_pattern, /* Pattern to search for */
|
||||
size_t pattern_size, /* Size of pattern block */
|
||||
size_t *shift, /* Shift table (search buffer) */
|
||||
bool *repeat_find) /* TRUE: search buffer already init */
|
||||
{
|
||||
size_t
|
||||
byte_nbr, /* Distance through block */
|
||||
match_size; /* Size of matched part */
|
||||
const byte
|
||||
*match_base = NULL, /* Base of match of pattern */
|
||||
*match_ptr = NULL, /* Point within current match */
|
||||
*limit = NULL; /* Last potiental match point */
|
||||
const byte
|
||||
*block = (byte *) in_block, /* Concrete pointer to block data */
|
||||
*pattern = (byte *) in_pattern; /* Concrete pointer to search value */
|
||||
|
||||
if (block == NULL || pattern == NULL || shift == NULL)
|
||||
return (NULL);
|
||||
|
||||
/* Pattern must be smaller or equal in size to string */
|
||||
if (block_size < pattern_size)
|
||||
return (NULL); /* Otherwise it's not found */
|
||||
|
||||
if (pattern_size == 0) /* Empty patterns match at start */
|
||||
return ((void *)block);
|
||||
|
||||
/* Build the shift table unless we're continuing a previous search */
|
||||
|
||||
/* The shift table determines how far to shift before trying to match */
|
||||
/* again, if a match at this point fails. If the byte after where the */
|
||||
/* end of our pattern falls is not in our pattern, then we start to */
|
||||
/* match again after that byte; otherwise we line up the last occurence */
|
||||
/* of that byte in our pattern under that byte, and try match again. */
|
||||
|
||||
if (!repeat_find || !*repeat_find)
|
||||
{
|
||||
for (byte_nbr = 0; byte_nbr < 256; byte_nbr++)
|
||||
shift [byte_nbr] = pattern_size + 1;
|
||||
for (byte_nbr = 0; byte_nbr < pattern_size; byte_nbr++)
|
||||
shift [(byte) pattern [byte_nbr]] = pattern_size - byte_nbr;
|
||||
|
||||
if (repeat_find)
|
||||
*repeat_find = true;
|
||||
}
|
||||
|
||||
/* Search for the block, each time jumping up by the amount */
|
||||
/* computed in the shift table */
|
||||
|
||||
limit = block + (block_size - pattern_size + 1);
|
||||
|
||||
for (match_base = block;
|
||||
match_base < limit;
|
||||
match_base += shift [*(match_base + pattern_size)])
|
||||
{
|
||||
match_ptr = match_base;
|
||||
match_size = 0;
|
||||
|
||||
/* Compare pattern until it all matches, or we find a difference */
|
||||
while (*match_ptr++ == pattern [match_size++])
|
||||
{
|
||||
/* If we found a match, return the start address */
|
||||
if (match_size >= pattern_size)
|
||||
return ((void*)(match_base));
|
||||
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_bytes_find( vbyte *where, int pos, int len, vbyte *which, int wpos, int wlen ) {
|
||||
size_t searchbuf [256];
|
||||
bool repeat_find = false;
|
||||
vbyte *found = (vbyte*)memfind_rb(where + pos,len,which+wpos,wlen,searchbuf,&repeat_find);
|
||||
if( found == NULL ) return -1;
|
||||
return (int)(size_t)(found - where);
|
||||
}
|
||||
|
||||
HL_PRIM int hl_bytes_rfind( vbyte *where, int len, vbyte *which, int wlen ) {
|
||||
if( wlen > len ) return -1;
|
||||
if( wlen == 0 ) return len; // at end
|
||||
int pos = len - wlen;
|
||||
while( pos >= 0 ) {
|
||||
if( memcmp(where+pos,which,wlen) == 0 )
|
||||
return pos;
|
||||
pos--;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
HL_PRIM void hl_bytes_fill( vbyte *bytes, int pos, int len, int value ) {
|
||||
memset(bytes+pos,value,len);
|
||||
}
|
||||
|
||||
|
||||
static int ms_gcd( int m, int n ) {
|
||||
while( n != 0 ) {
|
||||
int t = m % n;
|
||||
m=n; n=t;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
#define TSORT int
|
||||
#define TID(t) t##_i32
|
||||
#include "sort.h"
|
||||
#define TSORT double
|
||||
#define TID(t) t##_f64
|
||||
#include "sort.h"
|
||||
|
||||
HL_PRIM void hl_bsort_i32( vbyte *bytes, int pos, int len, vclosure *cmp ) {
|
||||
m_sort_i32 m;
|
||||
m.arr = (int*)(bytes + pos);
|
||||
m.c = cmp;
|
||||
merge_sort_rec_i32(&m,0,len);
|
||||
}
|
||||
|
||||
HL_PRIM void hl_bsort_f64( vbyte *bytes, int pos, int len, vclosure *cmp ) {
|
||||
m_sort_f64 m;
|
||||
m.arr = (double*)(bytes + pos);
|
||||
m.c = cmp;
|
||||
merge_sort_rec_f64(&m,0,len);
|
||||
}
|
||||
|
||||
static inline bool is_space_char(uchar c) {
|
||||
return c == 32 || (c > 8 && c < 14);
|
||||
}
|
||||
|
||||
HL_PRIM double hl_parse_float( vbyte *bytes, int pos, int len ) {
|
||||
const uchar *str = (uchar*)(bytes+pos);
|
||||
uchar *end = NULL;
|
||||
while( is_space_char(*str) ) str++;
|
||||
double d = utod(str,&end);
|
||||
if( end == str )
|
||||
return hl_nan();
|
||||
return d;
|
||||
}
|
||||
|
||||
static inline bool has_hex_prefix( const uchar *c, int len, bool is_signed ) {
|
||||
if (is_signed)
|
||||
return len >= 3 && c[1] == '0' && (c[2] == 'x' || c[2] == 'X');
|
||||
return len >= 2 && c[0] == '0' && (c[1] == 'x' || c[1] == 'X');
|
||||
}
|
||||
|
||||
HL_PRIM vdynamic *hl_parse_int( vbyte *bytes, int pos, int len ) {
|
||||
const uchar *c = (uchar*)(bytes + pos);
|
||||
const uchar *start = c;
|
||||
int h;
|
||||
while( is_space_char(*c) ) c++;
|
||||
uchar sign = c[0];
|
||||
bool is_signed = sign == '-' || sign == '+';
|
||||
if( has_hex_prefix(c,(int)(len+start-c),is_signed) ) {
|
||||
h = 0;
|
||||
c += is_signed ? 3 : 2;
|
||||
while( *c ) {
|
||||
uchar k = *c++;
|
||||
if( k >= '0' && k <= '9' )
|
||||
h = (h << 4) | (k - '0');
|
||||
else if( k >= 'A' && k <= 'F' )
|
||||
h = (h << 4) | ((k - 'A') + 10);
|
||||
else if( k >= 'a' && k <= 'f' )
|
||||
h = (h << 4) | ((k - 'a') + 10);
|
||||
else
|
||||
break;
|
||||
}
|
||||
if( sign == '-' ) h = -h;
|
||||
} else {
|
||||
uchar *end = NULL;
|
||||
h = utoi(c,&end);
|
||||
if( c == end )
|
||||
return NULL;
|
||||
}
|
||||
return hl_make_dyn(&h,&hlt_i32);
|
||||
}
|
||||
|
||||
// pointer manipulation
|
||||
|
||||
HL_PRIM vbyte *hl_bytes_offset( vbyte *src, int offset ) {
|
||||
return src + offset;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_bytes_subtract( vbyte *a, vbyte *b ) {
|
||||
return (int)(a - b);
|
||||
}
|
||||
|
||||
HL_PRIM int hl_bytes_address( vbyte *a, int *high ) {
|
||||
# ifdef HL_64
|
||||
*high = (int)(((uint64)a)>>32);
|
||||
# else
|
||||
*high = 0;
|
||||
# endif
|
||||
return (int)(int_val)a;
|
||||
}
|
||||
|
||||
HL_PRIM vbyte *hl_bytes_from_address( int low, int high ) {
|
||||
# ifdef HL_64
|
||||
// MSVC does overflow on <<32 even on uint64...
|
||||
struct { int low; int high; } i64;
|
||||
i64.low = low;
|
||||
i64.high = high;
|
||||
return *(vbyte**)&i64;
|
||||
# else
|
||||
return (vbyte*)low;
|
||||
# endif
|
||||
}
|
||||
|
||||
HL_PRIM int hl_string_compare( vbyte *a, vbyte *b, int len ) {
|
||||
return memcmp(a,b,len * sizeof(uchar));
|
||||
}
|
||||
|
||||
DEFINE_PRIM(_BYTES,alloc_bytes,_I32);
|
||||
DEFINE_PRIM(_VOID,bytes_blit,_BYTES _I32 _BYTES _I32 _I32);
|
||||
DEFINE_PRIM(_I32,bytes_compare,_BYTES _I32 _BYTES _I32 _I32);
|
||||
DEFINE_PRIM(_I32,bytes_compare16,_BYTES _BYTES _I32);
|
||||
DEFINE_PRIM(_I32,string_compare,_BYTES _BYTES _I32);
|
||||
DEFINE_PRIM(_I32,bytes_find,_BYTES _I32 _I32 _BYTES _I32 _I32);
|
||||
DEFINE_PRIM(_I32,bytes_rfind,_BYTES _I32 _BYTES _I32);
|
||||
DEFINE_PRIM(_VOID,bytes_fill,_BYTES _I32 _I32 _I32);
|
||||
DEFINE_PRIM(_F64, parse_float,_BYTES _I32 _I32);
|
||||
DEFINE_PRIM(_NULL(_I32), parse_int, _BYTES _I32 _I32);
|
||||
DEFINE_PRIM(_VOID,bsort_i32,_BYTES _I32 _I32 _FUN(_I32,_I32 _I32));
|
||||
DEFINE_PRIM(_VOID,bsort_f64,_BYTES _I32 _I32 _FUN(_I32,_F64 _F64));
|
||||
DEFINE_PRIM(_BYTES,bytes_offset, _BYTES _I32);
|
||||
DEFINE_PRIM(_I32,bytes_subtract, _BYTES _BYTES);
|
||||
DEFINE_PRIM(_I32,bytes_address, _BYTES _REF(_I32));
|
||||
DEFINE_PRIM(_BYTES,bytes_from_address, _I32 _I32);
|
574
Kha/Backends/Kinc-HL/hl/src/std/cast.c
Normal file
574
Kha/Backends/Kinc-HL/hl/src/std/cast.c
Normal file
@ -0,0 +1,574 @@
|
||||
/*
|
||||
* Copyright (C)2005-2016 Haxe Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <hl.h>
|
||||
#include <math.h>
|
||||
|
||||
#define TK2(a,b) ((a) | ((b)<<5))
|
||||
|
||||
static void invalid_cast( hl_type *from, hl_type *to ) {
|
||||
hl_error("Can't cast %s to %s",hl_type_str(from),hl_type_str(to));
|
||||
}
|
||||
|
||||
HL_PRIM vdynamic *hl_make_dyn( void *data, hl_type *t ) {
|
||||
vdynamic *v;
|
||||
switch( t->kind ) {
|
||||
case HUI8:
|
||||
v = (vdynamic*)hl_gc_alloc_noptr(sizeof(vdynamic));
|
||||
v->t = t;
|
||||
v->v.i = *(unsigned char*)data;
|
||||
return v;
|
||||
case HUI16:
|
||||
v = (vdynamic*)hl_gc_alloc_noptr(sizeof(vdynamic));
|
||||
v->t = t;
|
||||
v->v.i = *(unsigned short*)data;
|
||||
return v;
|
||||
case HI32:
|
||||
v = (vdynamic*)hl_gc_alloc_noptr(sizeof(vdynamic));
|
||||
v->t = t;
|
||||
v->v.i = *(int*)data;
|
||||
return v;
|
||||
case HI64:
|
||||
v = (vdynamic*)hl_gc_alloc_noptr(sizeof(vdynamic));
|
||||
v->t = t;
|
||||
v->v.i64 = *(int64*)data;
|
||||
return v;
|
||||
case HF32:
|
||||
v = (vdynamic*)hl_gc_alloc_noptr(sizeof(vdynamic));
|
||||
v->t = t;
|
||||
v->v.f = *(float*)data;
|
||||
return v;
|
||||
case HF64:
|
||||
v = (vdynamic*)hl_gc_alloc_noptr(sizeof(vdynamic));
|
||||
v->t = t;
|
||||
v->v.d = *(double*)data;
|
||||
return v;
|
||||
case HBOOL:
|
||||
return hl_alloc_dynbool(*(bool*)data);
|
||||
case HBYTES:
|
||||
case HTYPE:
|
||||
case HREF:
|
||||
case HABSTRACT:
|
||||
{
|
||||
void *p = *(void**)data;
|
||||
if( p == NULL ) return NULL;
|
||||
v = hl_alloc_dynamic(t);
|
||||
v->v.ptr = p;
|
||||
return v;
|
||||
}
|
||||
default:
|
||||
return *(vdynamic**)data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HL_PRIM int hl_dyn_casti( void *data, hl_type *t, hl_type *to ) {
|
||||
hl_track_call(HL_TRACK_CAST, on_cast(t,to));
|
||||
if( t->kind == HDYN ) {
|
||||
vdynamic *v = *((vdynamic**)data);
|
||||
if( v == NULL ) return 0;
|
||||
t = v->t;
|
||||
if( !hl_is_dynamic(t) ) data = &v->v;
|
||||
}
|
||||
switch( t->kind ) {
|
||||
case HUI8:
|
||||
return *(unsigned char*)data;
|
||||
case HUI16:
|
||||
return *(unsigned short*)data;
|
||||
case HI32:
|
||||
return *(int*)data;
|
||||
case HI64:
|
||||
return (int)*(int64*)data;
|
||||
case HF32:
|
||||
return (int)*(float*)data;
|
||||
case HF64:
|
||||
return (int)*(double*)data;
|
||||
case HBOOL:
|
||||
return *(bool*)data;
|
||||
case HNULL:
|
||||
{
|
||||
vdynamic *v = *(vdynamic**)data;
|
||||
if( v == NULL ) return 0;
|
||||
return hl_dyn_casti(&v->v,t->tparam,to);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
invalid_cast(t,to);
|
||||
return 0;
|
||||
}
|
||||
|
||||
HL_PRIM int64 hl_dyn_casti64( void *data, hl_type *t ) {
|
||||
hl_track_call(HL_TRACK_CAST, on_cast(t,&hlt_i64));
|
||||
if( t->kind == HDYN ) {
|
||||
vdynamic *v = *((vdynamic**)data);
|
||||
if( v == NULL ) return 0;
|
||||
t = v->t;
|
||||
if( !hl_is_dynamic(t) ) data = &v->v;
|
||||
}
|
||||
switch( t->kind ) {
|
||||
case HUI8:
|
||||
return *(unsigned char*)data;
|
||||
case HUI16:
|
||||
return *(unsigned short*)data;
|
||||
case HI32:
|
||||
return *(int*)data;
|
||||
case HI64:
|
||||
return *(int64*)data;
|
||||
case HF32:
|
||||
return (int64)*(float*)data;
|
||||
case HF64:
|
||||
return (int64)*(double*)data;
|
||||
case HBOOL:
|
||||
return *(bool*)data;
|
||||
case HNULL:
|
||||
{
|
||||
vdynamic *v = *(vdynamic**)data;
|
||||
if( v == NULL ) return 0;
|
||||
return hl_dyn_casti64(&v->v,t->tparam);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
invalid_cast(t,&hlt_i64);
|
||||
return 0;
|
||||
}
|
||||
|
||||
HL_PRIM void *hl_dyn_castp( void *data, hl_type *t, hl_type *to ) {
|
||||
hl_track_call(HL_TRACK_CAST, on_cast(t,to));
|
||||
if( to->kind == HDYN && hl_is_dynamic(t) )
|
||||
return *(vdynamic**)data;
|
||||
if( t->kind == HDYN || t->kind == HNULL ) {
|
||||
vdynamic *v = *(vdynamic**)data;
|
||||
if( v == NULL )
|
||||
return NULL;
|
||||
if( to->kind == HNULL && v->t == to->tparam && hl_is_gc_ptr(v) )
|
||||
return v; // v might be a vdynamic on the stack
|
||||
t = v->t;
|
||||
if( !hl_is_dynamic(t) ) data = &v->v;
|
||||
} else if( hl_is_dynamic(t) ) {
|
||||
vdynamic *v = *(vdynamic**)data;
|
||||
if( v == NULL ) return NULL;
|
||||
t = v->t;
|
||||
}
|
||||
if( t == to || hl_safe_cast(t,to) )
|
||||
return *(void**)data;
|
||||
switch( TK2(t->kind,to->kind) ) {
|
||||
case TK2(HOBJ,HOBJ):
|
||||
case TK2(HSTRUCT,HSTRUCT):
|
||||
{
|
||||
hl_type_obj *t1 = t->obj;
|
||||
hl_type_obj *t2 = to->obj;
|
||||
while( true ) {
|
||||
if( t1 == t2 )
|
||||
return *(void**)data;
|
||||
if( t1->super == NULL )
|
||||
break;
|
||||
t1 = t1->super->obj;
|
||||
}
|
||||
if( t->obj->rt->castFun ) {
|
||||
vdynamic *v = t->obj->rt->castFun(*(vdynamic**)data,to);
|
||||
if( v ) return v;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TK2(HFUN,HFUN):
|
||||
{
|
||||
vclosure *c = *(vclosure**)data;
|
||||
if( c == NULL ) return NULL;
|
||||
c = hl_make_fun_wrapper(c,to);
|
||||
if( c ) return c;
|
||||
}
|
||||
break;
|
||||
case TK2(HOBJ,HVIRTUAL):
|
||||
case TK2(HDYNOBJ,HVIRTUAL):
|
||||
case TK2(HVIRTUAL,HVIRTUAL):
|
||||
return hl_to_virtual(to,*(vdynamic**)data);
|
||||
case TK2(HVIRTUAL,HOBJ):
|
||||
{
|
||||
vvirtual *v = *(vvirtual**)data;
|
||||
if( v->value == NULL ) break;
|
||||
return hl_dyn_castp( &v->value, v->value->t, to);
|
||||
}
|
||||
case TK2(HOBJ,HDYN):
|
||||
case TK2(HDYNOBJ,HDYN):
|
||||
case TK2(HFUN,HDYN):
|
||||
case TK2(HNULL,HDYN):
|
||||
case TK2(HARRAY,HDYN):
|
||||
// NO(HSTRUCT,HDYN)
|
||||
return *(void**)data;
|
||||
}
|
||||
if( to->kind == HDYN )
|
||||
return hl_make_dyn(data,t);
|
||||
if( to->kind == HNULL ) {
|
||||
if( to->tparam->kind == t->kind )
|
||||
return hl_make_dyn(data,t);
|
||||
switch( to->tparam->kind ) {
|
||||
case HUI8:
|
||||
case HUI16:
|
||||
case HI32:
|
||||
case HBOOL:
|
||||
{
|
||||
int v = hl_dyn_casti(data,t,to->tparam);
|
||||
return hl_make_dyn(&v,to->tparam);
|
||||
}
|
||||
case HI64:
|
||||
{
|
||||
int64 v = hl_dyn_casti64(data,t);
|
||||
return hl_make_dyn(&v,to->tparam);
|
||||
}
|
||||
case HF32:
|
||||
{
|
||||
float f = hl_dyn_castf(data,t);
|
||||
return hl_make_dyn(&f,to->tparam);
|
||||
}
|
||||
case HF64:
|
||||
{
|
||||
double d = hl_dyn_castd(data,t);
|
||||
return hl_make_dyn(&d,to->tparam);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( to->kind == HREF ) {
|
||||
switch( to->tparam->kind ) {
|
||||
case HUI8:
|
||||
case HUI16:
|
||||
case HI32:
|
||||
case HBOOL:
|
||||
{
|
||||
int *v = (int*)hl_gc_alloc_noptr(sizeof(int));
|
||||
*v = hl_dyn_casti(data,t,to->tparam);
|
||||
return v;
|
||||
}
|
||||
case HI64:
|
||||
{
|
||||
int64 *d = (int64*)hl_gc_alloc_noptr(sizeof(int64));
|
||||
*d = hl_dyn_casti64(data,t);
|
||||
return d;
|
||||
}
|
||||
case HF32:
|
||||
{
|
||||
float *f = (float*)hl_gc_alloc_noptr(sizeof(float));
|
||||
*f = hl_dyn_castf(data,t);
|
||||
return f;
|
||||
}
|
||||
case HF64:
|
||||
{
|
||||
double *d = (double*)hl_gc_alloc_noptr(sizeof(double));
|
||||
*d = hl_dyn_castd(data,t);
|
||||
return d;
|
||||
}
|
||||
default:
|
||||
{
|
||||
void **p = (void**)hl_gc_alloc_raw(sizeof(void*));
|
||||
*p = hl_dyn_castp(data,t,to->tparam);
|
||||
return p;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
invalid_cast(t,to);
|
||||
return 0;
|
||||
}
|
||||
|
||||
HL_PRIM double hl_dyn_castd( void *data, hl_type *t ) {
|
||||
hl_track_call(HL_TRACK_CAST, on_cast(t,&hlt_f64));
|
||||
if( t->kind == HDYN ) {
|
||||
vdynamic *v = *((vdynamic**)data);
|
||||
if( v == NULL ) return 0;
|
||||
t = v->t;
|
||||
if( !hl_is_dynamic(t) ) data = &v->v;
|
||||
}
|
||||
switch( t->kind ) {
|
||||
case HF32:
|
||||
return *(float*)data;
|
||||
case HF64:
|
||||
return *(double*)data;
|
||||
case HUI8:
|
||||
return *(unsigned char*)data;
|
||||
case HUI16:
|
||||
return *(unsigned short*)data;
|
||||
case HI32:
|
||||
return *(int*)data;
|
||||
case HI64:
|
||||
return (double)*(int64*)data;
|
||||
case HBOOL:
|
||||
return *(bool*)data;
|
||||
case HNULL:
|
||||
{
|
||||
vdynamic *v = *(vdynamic**)data;
|
||||
if( v == NULL ) return 0;
|
||||
return hl_dyn_castd(&v->v,t->tparam);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
invalid_cast(t,&hlt_f64);
|
||||
return 0.;
|
||||
}
|
||||
|
||||
HL_PRIM float hl_dyn_castf( void *data, hl_type *t ) {
|
||||
hl_track_call(HL_TRACK_CAST, on_cast(t,&hlt_f32));
|
||||
if( t->kind == HDYN ) {
|
||||
vdynamic *v = *((vdynamic**)data);
|
||||
if( v == NULL ) return 0;
|
||||
t = v->t;
|
||||
if( !hl_is_dynamic(t) ) data = &v->v;
|
||||
}
|
||||
switch( t->kind ) {
|
||||
case HF32:
|
||||
return *(float*)data;
|
||||
case HF64:
|
||||
return (float)*(double*)data;
|
||||
case HUI8:
|
||||
return *(unsigned char*)data;
|
||||
case HUI16:
|
||||
return *(unsigned short*)data;
|
||||
case HI32:
|
||||
return (float)*(int*)data;
|
||||
case HI64:
|
||||
return (float)*(int64*)data;
|
||||
case HBOOL:
|
||||
return *(bool*)data;
|
||||
case HNULL:
|
||||
{
|
||||
vdynamic *v = *(vdynamic**)data;
|
||||
if( v == NULL ) return 0;
|
||||
return hl_dyn_castf(&v->v,t->tparam);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
invalid_cast(t,&hlt_f32);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fcompare( float a, float b ) {
|
||||
float d = a - b;
|
||||
if( d != d )
|
||||
return a == b ? 0 : hl_invalid_comparison; // +INF=+INF
|
||||
return d == 0.f ? 0 : (d > 0.f ? 1 : -1);
|
||||
}
|
||||
|
||||
static int dcompare( double a, double b ) {
|
||||
double d = a - b;
|
||||
if( d != d )
|
||||
return a == b ? 0 : hl_invalid_comparison; // +INF=+INF
|
||||
return d == 0. ? 0 : (d > 0. ? 1 : -1);
|
||||
}
|
||||
|
||||
HL_PRIM int hl_ptr_compare( vdynamic *a, vdynamic *b ) {
|
||||
if( a == b )
|
||||
return 0;
|
||||
return a > b ? 1 : -1;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_dyn_compare( vdynamic *a, vdynamic *b ) {
|
||||
hl_track_call(HL_TRACK_CAST, on_cast(a?a->t:&hlt_dyn,b?b->t:&hlt_dyn));
|
||||
if( a == b )
|
||||
return 0;
|
||||
if( a == NULL )
|
||||
return -1;
|
||||
if( b == NULL )
|
||||
return 1;
|
||||
switch( TK2(a->t->kind,b->t->kind) ) {
|
||||
case TK2(HUI8,HUI8):
|
||||
return (int)a->v.ui8 - (int)b->v.ui8;
|
||||
case TK2(HUI16,HUI16):
|
||||
return (int)a->v.ui16 - (int)b->v.ui16;
|
||||
case TK2(HI32,HI32):
|
||||
{
|
||||
int d = a->v.i - b->v.i;
|
||||
return d == hl_invalid_comparison ? -1 : d;
|
||||
}
|
||||
case TK2(HI64,HI64):
|
||||
{
|
||||
int64 d = a->v.i64 - b->v.i64;
|
||||
return d == 0 ? 0 : (d > 0 ? 1 : -1);
|
||||
}
|
||||
case TK2(HF32,HF32):
|
||||
return fcompare(a->v.f,b->v.f);
|
||||
case TK2(HF64,HF64):
|
||||
return dcompare(a->v.d,b->v.d);
|
||||
case TK2(HBOOL,HBOOL):
|
||||
return (int)a->v.b - (int)b->v.b;
|
||||
case TK2(HF64, HI32):
|
||||
return dcompare(a->v.d,(double)b->v.i);
|
||||
case TK2(HI32, HF64):
|
||||
return dcompare((double)a->v.i,b->v.d);
|
||||
case TK2(HF64, HF32):
|
||||
return dcompare(a->v.d,(double)b->v.f);
|
||||
case TK2(HF32, HF64):
|
||||
return dcompare((double)a->v.f,b->v.d);
|
||||
case TK2(HOBJ,HOBJ):
|
||||
case TK2(HSTRUCT,HSTRUCT):
|
||||
if( a->t->obj->rt->compareFun )
|
||||
return a->t->obj->rt->compareFun(a,b);
|
||||
return a > b ? 1 : -1;
|
||||
case TK2(HENUM,HENUM):
|
||||
return a > b ? 1 : -1;
|
||||
case TK2(HTYPE,HTYPE):
|
||||
case TK2(HBYTES,HBYTES):
|
||||
return a->v.ptr != b->v.ptr;
|
||||
case TK2(HOBJ,HVIRTUAL):
|
||||
case TK2(HDYNOBJ,HVIRTUAL):
|
||||
return hl_dyn_compare(a,((vvirtual*)b)->value);
|
||||
case TK2(HVIRTUAL,HOBJ):
|
||||
case TK2(HVIRTUAL,HDYNOBJ):
|
||||
return hl_dyn_compare(((vvirtual*)a)->value,b);
|
||||
case TK2(HFUN,HFUN):
|
||||
if( ((vclosure*)a)->hasValue == 2 )
|
||||
return hl_dyn_compare((vdynamic*)((vclosure_wrapper*)a)->wrappedFun,b);
|
||||
if( ((vclosure*)b)->hasValue == 2 )
|
||||
return hl_dyn_compare(a,(vdynamic*)((vclosure_wrapper*)b)->wrappedFun);
|
||||
if( ((vclosure*)a)->fun != ((vclosure*)b)->fun )
|
||||
return hl_invalid_comparison;
|
||||
return hl_dyn_compare(((vclosure*)a)->value,((vclosure*)b)->value);
|
||||
case TK2(HVIRTUAL,HVIRTUAL):
|
||||
if( ((vvirtual*)a)->value && ((vvirtual*)b)->value )
|
||||
return hl_dyn_compare(((vvirtual*)a)->value,((vvirtual*)b)->value);
|
||||
return hl_invalid_comparison;
|
||||
}
|
||||
return hl_invalid_comparison;
|
||||
}
|
||||
|
||||
HL_PRIM void hl_write_dyn( void *data, hl_type *t, vdynamic *v, bool is_tmp ) {
|
||||
hl_track_call(HL_TRACK_CAST, on_cast(v?v->t:&hlt_dyn,t));
|
||||
switch( t->kind ) {
|
||||
case HUI8:
|
||||
*(unsigned char*)data = (unsigned char)hl_dyn_casti(&v,&hlt_dyn,t);
|
||||
break;
|
||||
case HBOOL:
|
||||
*(bool*)data = hl_dyn_casti(&v,&hlt_dyn,t) != 0;
|
||||
break;
|
||||
case HUI16:
|
||||
*(unsigned short*)data = (unsigned short)hl_dyn_casti(&v,&hlt_dyn,t);
|
||||
break;
|
||||
case HI32:
|
||||
*(int*)data = hl_dyn_casti(&v,&hlt_dyn,t);
|
||||
break;
|
||||
case HI64:
|
||||
*(int64*)data = hl_dyn_casti64(&v,&hlt_dyn);
|
||||
break;
|
||||
case HF32:
|
||||
*(float*)data = hl_dyn_castf(&v,&hlt_dyn);
|
||||
break;
|
||||
case HF64:
|
||||
*(double*)data = hl_dyn_castd(&v,&hlt_dyn);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
void *ret = (v && hl_same_type(t,v->t)) ? v : hl_dyn_castp(&v,&hlt_dyn,t);
|
||||
if( is_tmp && ret == v ) {
|
||||
ret = hl_alloc_dynamic(v->t);
|
||||
((vdynamic*)ret)->v = v->v;
|
||||
}
|
||||
*(void**)data = ret;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
HL_PRIM vdynamic* hl_value_cast( vdynamic *v, hl_type *t ) {
|
||||
hl_track_call(HL_TRACK_CAST, on_cast(v?v->t:&hlt_dyn,t));
|
||||
if( t->kind == HDYN || v == NULL || hl_safe_cast(v->t,t) )
|
||||
return v;
|
||||
invalid_cast(v->t,t);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_type_safe_cast( hl_type *a, hl_type *b ) {
|
||||
return hl_safe_cast(a,b);
|
||||
}
|
||||
|
||||
#define NULL_VAL HLAST
|
||||
#define OP(op,t1,t2) (TK2(t1,t2) | (op << 10))
|
||||
#define OP_ADD 0
|
||||
#define OP_SUB 1
|
||||
#define OP_MUL 2
|
||||
#define OP_MOD 3
|
||||
#define OP_DIV 4
|
||||
#define OP_SHL 5
|
||||
#define OP_SHR 6
|
||||
#define OP_USHR 7
|
||||
#define OP_AND 8
|
||||
#define OP_OR 9
|
||||
#define OP_XOR 10
|
||||
|
||||
static vdynamic *hl_dynf64( double v ) {
|
||||
vdynamic *d = hl_alloc_dynamic(&hlt_f64);
|
||||
d->v.d = v;
|
||||
return d;
|
||||
}
|
||||
|
||||
static vdynamic *hl_dyni32( int v ) {
|
||||
vdynamic *d = hl_alloc_dynamic(&hlt_i32);
|
||||
d->v.i = v;
|
||||
return d;
|
||||
}
|
||||
|
||||
static bool is_number( hl_type *t ) {
|
||||
return t->kind >= HUI8 && t->kind <= HBOOL;
|
||||
}
|
||||
|
||||
#define FOP(op) { double va = hl_dyn_castd(&a,&hlt_dyn); double vb = hl_dyn_castd(&b,&hlt_dyn); return hl_dynf64(va op vb); }
|
||||
#define IOP(op) { int va = hl_dyn_casti(&a,&hlt_dyn,&hlt_i32); int vb = hl_dyn_casti(&b,&hlt_dyn,&hlt_i32); return hl_dyni32(va op vb); }
|
||||
|
||||
HL_PRIM vdynamic *hl_dyn_op( int op, vdynamic *a, vdynamic *b ) {
|
||||
static uchar *op_names[] = { USTR("+"), USTR("-"), USTR("*"), USTR("%"), USTR("/"), USTR("<<"), USTR(">>"), USTR(">>>"), USTR("&"), USTR("|"), USTR("^") };
|
||||
if( op < 0 || op >= OpLast ) hl_error("Invalid op %d",op);
|
||||
hl_track_call(HL_TRACK_CAST, on_cast(a?a->t:&hlt_dyn,b?b->t:&hlt_dyn));
|
||||
if( !a && !b ) return op == OP_DIV || op == OP_MOD ? hl_dynf64(hl_nan()) : NULL;
|
||||
if( (!a || is_number(a->t)) && (!b || is_number(b->t)) ) {
|
||||
switch( op ) {
|
||||
case OP_ADD: FOP(+);
|
||||
case OP_SUB: FOP(-);
|
||||
case OP_MUL: FOP(*);
|
||||
case OP_MOD: {
|
||||
double va = hl_dyn_castd(&a,&hlt_dyn);
|
||||
double vb = hl_dyn_castd(&b,&hlt_dyn);
|
||||
return hl_dynf64(fmod(va,vb));
|
||||
}
|
||||
case OP_DIV: FOP(/);
|
||||
case OP_SHL: IOP(<<);
|
||||
case OP_SHR: IOP(>>);
|
||||
case OP_USHR: {
|
||||
int va = hl_dyn_casti(&a,&hlt_dyn,&hlt_i32);
|
||||
int vb = hl_dyn_casti(&b,&hlt_dyn,&hlt_i32);
|
||||
return hl_dyni32( ((unsigned)va) >> ((unsigned)vb) );
|
||||
}
|
||||
case OP_AND: IOP(&);
|
||||
case OP_OR: IOP(|);
|
||||
case OP_XOR: IOP(^);
|
||||
}
|
||||
}
|
||||
hl_error("Can't perform dyn op %s %s %s",hl_type_str(a->t),op_names[op],hl_type_str(b->t));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DEFINE_PRIM(_I32, dyn_compare, _DYN _DYN);
|
||||
DEFINE_PRIM(_DYN, value_cast, _DYN _TYPE);
|
||||
DEFINE_PRIM(_BOOL, type_safe_cast, _TYPE _TYPE);
|
||||
DEFINE_PRIM(_DYN, dyn_op, _I32 _DYN _DYN);
|
||||
DEFINE_PRIM(_I32, ptr_compare, _DYN _DYN);
|
||||
|
155
Kha/Backends/Kinc-HL/hl/src/std/date.c
Normal file
155
Kha/Backends/Kinc-HL/hl/src/std/date.c
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (C)2005-2016 Haxe Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <hl.h>
|
||||
|
||||
#ifdef HL_CONSOLE
|
||||
# include <posix/posix.h>
|
||||
#else
|
||||
# include <time.h>
|
||||
#endif
|
||||
|
||||
#ifdef HL_WIN
|
||||
|
||||
static struct tm *localtime_r( time_t *t, struct tm *r ) {
|
||||
struct tm *r2 = localtime(t);
|
||||
if( r2 == NULL ) return NULL;
|
||||
*r = *r2;
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct tm *gmtime_r( time_t *t, struct tm *r ) {
|
||||
struct tm *r2 = gmtime(t);
|
||||
if( r2 == NULL ) return NULL;
|
||||
*r = *r2;
|
||||
return r;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
HL_PRIM int hl_date_now() {
|
||||
return (int)time(NULL);
|
||||
}
|
||||
|
||||
HL_PRIM vbyte *hl_date_to_string( int date, int *len ) {
|
||||
char buf[127];
|
||||
struct tm t;
|
||||
time_t d = (time_t)(unsigned)date;
|
||||
int size;
|
||||
uchar *out;
|
||||
if( !localtime_r(&d,&t) )
|
||||
hl_error("Invalid date");
|
||||
size = (int)strftime(buf,127,"%Y-%m-%d %H:%M:%S",&t);
|
||||
out = (uchar*)hl_gc_alloc_noptr((size + 1) << 1);
|
||||
hl_from_utf8(out,size,buf);
|
||||
*len = size;
|
||||
return (vbyte*)out;
|
||||
}
|
||||
|
||||
HL_PRIM double hl_date_get_time( int date ) {
|
||||
return ((unsigned)date) * 1000.;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_date_from_time( double time ) {
|
||||
return (int)(unsigned int)(time / 1000.);
|
||||
}
|
||||
|
||||
HL_PRIM int hl_date_from_string( vbyte *b, int len ) {
|
||||
struct tm t;
|
||||
int o = 0;
|
||||
const char *str = hl_to_utf8((uchar*)b);
|
||||
bool recal = true;
|
||||
memset(&t,0,sizeof(struct tm));
|
||||
switch( strlen(str) ) {
|
||||
case 19:
|
||||
sscanf(str,"%4d-%2d-%2d %2d:%2d:%2d",&t.tm_year,&t.tm_mon,&t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec);
|
||||
t.tm_isdst = -1;
|
||||
break;
|
||||
case 8:
|
||||
sscanf(str,"%2d:%2d:%2d",&t.tm_hour,&t.tm_min,&t.tm_sec);
|
||||
o = t.tm_sec + t.tm_min * 60 + t.tm_hour * 60 * 60;
|
||||
recal = false;
|
||||
break;
|
||||
case 10:
|
||||
sscanf(str,"%4d-%2d-%2d",&t.tm_year,&t.tm_mon,&t.tm_mday);
|
||||
t.tm_isdst = -1;
|
||||
break;
|
||||
default:
|
||||
hl_error("Invalid date format");
|
||||
break;
|
||||
}
|
||||
if( recal ) {
|
||||
t.tm_year -= 1900;
|
||||
t.tm_mon--;
|
||||
o = (int)mktime(&t);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_date_new( int y, int mo, int d, int h, int m, int s ) {
|
||||
struct tm t;
|
||||
memset(&t,0,sizeof(struct tm));
|
||||
t.tm_year = y - 1900;
|
||||
t.tm_mon = mo;
|
||||
t.tm_mday = d;
|
||||
t.tm_hour = h;
|
||||
t.tm_min = m;
|
||||
t.tm_sec = s;
|
||||
t.tm_isdst = -1;
|
||||
return (int)mktime(&t);
|
||||
}
|
||||
|
||||
HL_PRIM void hl_date_get_inf( int date, int *y, int *mo, int *day, int *h, int *m, int *s, int *wday ) {
|
||||
struct tm t;
|
||||
time_t d = (time_t)(unsigned)date;
|
||||
if( !localtime_r(&d,&t) )
|
||||
hl_error("invalid date");
|
||||
if( y ) *y = t.tm_year + 1900;
|
||||
if( mo ) *mo = t.tm_mon;
|
||||
if( day ) *day = t.tm_mday;
|
||||
if( h ) *h = t.tm_hour;
|
||||
if( m ) *m = t.tm_min;
|
||||
if( s ) *s = t.tm_sec;
|
||||
if( wday ) *wday = t.tm_wday;
|
||||
}
|
||||
|
||||
HL_PRIM void hl_date_get_utc_inf( int date, int *y, int *mo, int *day, int *h, int *m, int *s, int *wday ) {
|
||||
struct tm t;
|
||||
time_t d = (time_t)(unsigned)date;
|
||||
if( !gmtime_r(&d,&t) )
|
||||
hl_error("invalid date");
|
||||
if( y ) *y = t.tm_year + 1900;
|
||||
if( mo ) *mo = t.tm_mon;
|
||||
if( day ) *day = t.tm_mday;
|
||||
if( h ) *h = t.tm_hour;
|
||||
if( m ) *m = t.tm_min;
|
||||
if( s ) *s = t.tm_sec;
|
||||
if( wday ) *wday = t.tm_wday;
|
||||
}
|
||||
|
||||
DEFINE_PRIM(_I32, date_now, _NO_ARG);
|
||||
DEFINE_PRIM(_BYTES, date_to_string, _I32 _REF(_I32));
|
||||
DEFINE_PRIM(_F64, date_get_time, _I32);
|
||||
DEFINE_PRIM(_I32, date_from_time, _F64);
|
||||
DEFINE_PRIM(_I32, date_from_string, _BYTES _I32);
|
||||
DEFINE_PRIM(_I32, date_new, _I32 _I32 _I32 _I32 _I32 _I32);
|
||||
DEFINE_PRIM(_VOID, date_get_inf, _I32 _REF(_I32) _REF(_I32) _REF(_I32) _REF(_I32) _REF(_I32) _REF(_I32) _REF(_I32));
|
||||
DEFINE_PRIM(_VOID, date_get_utc_inf, _I32 _REF(_I32) _REF(_I32) _REF(_I32) _REF(_I32) _REF(_I32) _REF(_I32) _REF(_I32));
|
413
Kha/Backends/Kinc-HL/hl/src/std/debug.c
Normal file
413
Kha/Backends/Kinc-HL/hl/src/std/debug.c
Normal file
@ -0,0 +1,413 @@
|
||||
/*
|
||||
* Copyright (C)2005-2016 Haxe Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <hl.h>
|
||||
#if defined(HL_LINUX) && (defined(__i386__) || defined(__x86_64__))
|
||||
# include <sys/ptrace.h>
|
||||
# include <sys/wait.h>
|
||||
# include <sys/user.h>
|
||||
# include <signal.h>
|
||||
# define USE_PTRACE
|
||||
#endif
|
||||
|
||||
#ifdef HL_MAC
|
||||
# include <mdbg/mdbg.h>
|
||||
#endif
|
||||
|
||||
#if defined(HL_WIN)
|
||||
static HANDLE last_process = NULL, last_thread = NULL;
|
||||
static int last_pid = -1;
|
||||
static int last_tid = -1;
|
||||
static HANDLE OpenPID( int pid ) {
|
||||
if( pid == last_pid )
|
||||
return last_process;
|
||||
CloseHandle(last_process);
|
||||
last_pid = pid;
|
||||
last_process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
|
||||
return last_process;
|
||||
}
|
||||
static HANDLE OpenTID( int tid ) {
|
||||
if( tid == last_tid )
|
||||
return last_thread;
|
||||
CloseHandle(last_thread);
|
||||
last_tid = tid;
|
||||
last_thread = OpenThread(THREAD_ALL_ACCESS, FALSE, tid);
|
||||
return last_thread;
|
||||
}
|
||||
static void CleanHandles() {
|
||||
last_pid = -1;
|
||||
last_tid = -1;
|
||||
CloseHandle(last_process);
|
||||
CloseHandle(last_thread);
|
||||
last_process = NULL;
|
||||
last_thread = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
HL_API bool hl_debug_start( int pid ) {
|
||||
# if defined(HL_WIN)
|
||||
last_pid = -1;
|
||||
return (bool)DebugActiveProcess(pid);
|
||||
# elif defined(HL_MAC)
|
||||
return mdbg_session_attach(pid);
|
||||
# elif defined(USE_PTRACE)
|
||||
return ptrace(PTRACE_ATTACH,pid,0,0) >= 0;
|
||||
# else
|
||||
return false;
|
||||
# endif
|
||||
}
|
||||
|
||||
HL_API bool hl_debug_stop( int pid ) {
|
||||
# if defined(HL_WIN)
|
||||
BOOL b = DebugActiveProcessStop(pid);
|
||||
CleanHandles();
|
||||
return (bool)b;
|
||||
# elif defined(HL_MAC)
|
||||
return mdbg_session_detach(pid);
|
||||
# elif defined(USE_PTRACE)
|
||||
return ptrace(PTRACE_DETACH,pid,0,0) >= 0;
|
||||
# else
|
||||
return false;
|
||||
# endif
|
||||
}
|
||||
|
||||
HL_API bool hl_debug_breakpoint( int pid ) {
|
||||
# if defined(HL_WIN)
|
||||
return (bool)DebugBreakProcess(OpenPID(pid));
|
||||
# elif defined(HL_MAC)
|
||||
return mdbg_session_pause(pid);
|
||||
# elif defined(USE_PTRACE)
|
||||
return kill(pid,SIGTRAP) == 0;
|
||||
# else
|
||||
return false;
|
||||
# endif
|
||||
}
|
||||
|
||||
HL_API bool hl_debug_read( int pid, vbyte *addr, vbyte *buffer, int size ) {
|
||||
# if defined(HL_WIN)
|
||||
return (bool)ReadProcessMemory(OpenPID(pid),addr,buffer,size,NULL);
|
||||
# elif defined(HL_MAC)
|
||||
return mdbg_read_memory(pid, addr, buffer, size);
|
||||
# elif defined(USE_PTRACE)
|
||||
while( size ) {
|
||||
long v = ptrace(PTRACE_PEEKDATA,pid,addr,0);
|
||||
if( size >= sizeof(long) )
|
||||
*(long*)buffer = v;
|
||||
else {
|
||||
memcpy(buffer,&v,size);
|
||||
break;
|
||||
}
|
||||
addr += sizeof(long);
|
||||
size -= sizeof(long);
|
||||
buffer += sizeof(long);
|
||||
}
|
||||
return true;
|
||||
# else
|
||||
return false;
|
||||
# endif
|
||||
}
|
||||
|
||||
HL_API bool hl_debug_write( int pid, vbyte *addr, vbyte *buffer, int size ) {
|
||||
# if defined(HL_WIN)
|
||||
return (bool)WriteProcessMemory(OpenPID(pid),addr,buffer,size,NULL);
|
||||
# elif defined(HL_MAC)
|
||||
return mdbg_write_memory(pid, addr, buffer, size);
|
||||
# elif defined(USE_PTRACE)
|
||||
while( size ) {
|
||||
int sz = size >= sizeof(long) ? sizeof(long) : size;
|
||||
long v = *(long*)buffer;
|
||||
if( sz != sizeof(long) ) {
|
||||
long cur = ptrace(PTRACE_PEEKDATA,pid,addr);
|
||||
memcpy((char*)&v+sz,(char*)&cur+sz,sizeof(long)-sz);
|
||||
}
|
||||
if( ptrace(PTRACE_POKEDATA,pid,addr,v) < 0 )
|
||||
return false;
|
||||
addr += sz;
|
||||
size -= sz;
|
||||
buffer += sz;
|
||||
}
|
||||
return true;
|
||||
# else
|
||||
return false;
|
||||
# endif
|
||||
}
|
||||
|
||||
HL_API bool hl_debug_flush( int pid, vbyte *addr, int size ) {
|
||||
# if defined(HL_WIN)
|
||||
return (bool)FlushInstructionCache(OpenPID(pid),addr,size);
|
||||
# elif defined(HL_MAC)
|
||||
return true;
|
||||
# elif defined(USE_PTRACE)
|
||||
return true;
|
||||
# else
|
||||
return false;
|
||||
# endif
|
||||
}
|
||||
|
||||
#ifdef HL_MAC
|
||||
static int get_reg( int r ) {
|
||||
switch( r ) {
|
||||
case 0: return REG_RSP;
|
||||
case 1: return REG_RBP;
|
||||
case 2: return REG_RIP;
|
||||
case 3: return REG_RFLAGS;
|
||||
case 4: return REG_DR0;
|
||||
case 5: return REG_DR1;
|
||||
case 6: return REG_DR2;
|
||||
case 7: return REG_DR3;
|
||||
case 8: return REG_DR6;
|
||||
case 9: return REG_DR7;
|
||||
case 10: return REG_RAX;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_PTRACE
|
||||
static void *get_reg( int r ) {
|
||||
struct user_regs_struct *regs = NULL;
|
||||
struct user *user = NULL;
|
||||
struct user_fpregs_struct *fp = NULL;
|
||||
switch( r ) {
|
||||
case -1: return &user->u_fpstate;
|
||||
# ifdef HL_64
|
||||
case 0: return ®s->rsp;
|
||||
case 1: return ®s->rbp;
|
||||
case 2: return ®s->rip;
|
||||
case 10: return ®s->rax;
|
||||
case 11: return (void*)(-((int_val)&fp->xmm_space[0])-1);
|
||||
# else
|
||||
case 0: return ®s->esp;
|
||||
case 1: return ®s->ebp;
|
||||
case 2: return ®s->eip;
|
||||
case 10: return ®s->eax;
|
||||
case 11: return -1;
|
||||
# endif
|
||||
case 3: return ®s->eflags;
|
||||
default: return &user->u_debugreg[r-4];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
HL_API int hl_debug_wait( int pid, int *thread, int timeout ) {
|
||||
# if defined(HL_WIN)
|
||||
DEBUG_EVENT e;
|
||||
if( !WaitForDebugEvent(&e,timeout) )
|
||||
return -1;
|
||||
*thread = e.dwThreadId;
|
||||
switch( e.dwDebugEventCode ) {
|
||||
case EXCEPTION_DEBUG_EVENT:
|
||||
switch( e.u.Exception.ExceptionRecord.ExceptionCode ) {
|
||||
case EXCEPTION_BREAKPOINT:
|
||||
case 0x4000001F: // STATUS_WX86_BREAKPOINT
|
||||
return 1;
|
||||
case EXCEPTION_SINGLE_STEP:
|
||||
case 0x4000001E: // STATUS_WX86_SINGLE_STEP
|
||||
return 2;
|
||||
case 0x406D1388: // MS_VC_EXCEPTION (see SetThreadName)
|
||||
ContinueDebugEvent(e.dwProcessId, e.dwThreadId, DBG_CONTINUE);
|
||||
break;
|
||||
case 0xE06D7363: // C++ EH EXCEPTION
|
||||
case 0x6BA: // File Dialog EXCEPTION
|
||||
ContinueDebugEvent(e.dwProcessId, e.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
|
||||
break;
|
||||
case EXCEPTION_STACK_OVERFLOW:
|
||||
return 5;
|
||||
default:
|
||||
return 3;
|
||||
}
|
||||
break;
|
||||
case EXIT_PROCESS_DEBUG_EVENT:
|
||||
return 0;
|
||||
default:
|
||||
ContinueDebugEvent(e.dwProcessId, e.dwThreadId, DBG_CONTINUE);
|
||||
break;
|
||||
}
|
||||
return 4;
|
||||
# elif defined(HL_MAC)
|
||||
return mdbg_session_wait(pid, thread, timeout);
|
||||
# elif defined(USE_PTRACE)
|
||||
int status;
|
||||
int ret = waitpid(pid,&status,0);
|
||||
//printf("WAITPID=%X %X\n",ret,status);
|
||||
*thread = ret;
|
||||
if( WIFEXITED(status) )
|
||||
return 0;
|
||||
if( WIFSTOPPED(status) ) {
|
||||
int sig = WSTOPSIG(status);
|
||||
//printf(" STOPSIG=%d\n",sig);
|
||||
if( sig == SIGSTOP || sig == SIGTRAP )
|
||||
return 1;
|
||||
return 3;
|
||||
}
|
||||
return 4;
|
||||
# else
|
||||
return 0;
|
||||
# endif
|
||||
}
|
||||
|
||||
HL_API bool hl_debug_resume( int pid, int thread ) {
|
||||
# if defined(HL_WIN)
|
||||
return (bool)ContinueDebugEvent(pid, thread, DBG_CONTINUE);
|
||||
# elif defined(HL_MAC)
|
||||
return mdbg_session_resume(pid);
|
||||
# elif defined(USE_PTRACE)
|
||||
return ptrace(PTRACE_CONT,pid,0,0) >= 0;
|
||||
# else
|
||||
return false;
|
||||
# endif
|
||||
}
|
||||
|
||||
#ifdef HL_WIN
|
||||
#define DefineGetReg(type,GetFun) \
|
||||
REGDATA *GetFun( type *c, int reg ) { \
|
||||
switch( reg ) { \
|
||||
case 0: return GET_REG(sp); \
|
||||
case 1: return GET_REG(bp); \
|
||||
case 2: return GET_REG(ip); \
|
||||
case 4: return &c->Dr0; \
|
||||
case 5: return &c->Dr1; \
|
||||
case 6: return &c->Dr2; \
|
||||
case 7: return &c->Dr3; \
|
||||
case 8: return &c->Dr6; \
|
||||
case 9: return &c->Dr7; \
|
||||
case 10: return GET_REG(ax); \
|
||||
default: return GET_REG(ax); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define GET_REG(x) &c->E##x
|
||||
#define REGDATA DWORD
|
||||
|
||||
#ifdef HL_64
|
||||
DefineGetReg(WOW64_CONTEXT,GetContextReg32);
|
||||
# undef GET_REG
|
||||
# undef REGDATA
|
||||
# define GET_REG(x) &c->R##x
|
||||
# define REGDATA DWORD64
|
||||
# endif
|
||||
|
||||
DefineGetReg(CONTEXT,GetContextReg);
|
||||
|
||||
#endif
|
||||
|
||||
HL_API void *hl_debug_read_register( int pid, int thread, int reg, bool is64 ) {
|
||||
# if defined(HL_WIN)
|
||||
# ifdef HL_64
|
||||
if( !is64 ) {
|
||||
WOW64_CONTEXT c;
|
||||
c.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
|
||||
if( !Wow64GetThreadContext(OpenTID(thread),&c) )
|
||||
return NULL;
|
||||
if( reg == 3 )
|
||||
return (void*)(int_val)c.EFlags;
|
||||
if( reg == 11 )
|
||||
return NULL; // TODO
|
||||
return (void*)(int_val)*GetContextReg32(&c,reg);
|
||||
}
|
||||
# else
|
||||
if( is64 ) return NULL;
|
||||
# endif
|
||||
CONTEXT c;
|
||||
c.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
|
||||
if( !GetThreadContext(OpenTID(thread),&c) )
|
||||
return NULL;
|
||||
if( reg == 3 )
|
||||
return (void*)(int_val)c.EFlags;
|
||||
if( reg == 11 )
|
||||
#ifdef HL_64
|
||||
return (void*)(int_val)c.FltSave.XmmRegisters[0].Low;
|
||||
#else
|
||||
return (void*)*(int_val*)&c.ExtendedRegisters[10*16];
|
||||
#endif
|
||||
return (void*)*GetContextReg(&c,reg);
|
||||
# elif defined(HL_MAC)
|
||||
return mdbg_read_register(pid, thread, get_reg(reg), is64);
|
||||
# elif defined(USE_PTRACE)
|
||||
void *r = get_reg(reg);
|
||||
if( ((int_val)r) < 0 ) {
|
||||
// peek FP ptr
|
||||
char *addr = (char*)ptrace(PTRACE_PEEKUSER,thread,get_reg(-1),0);
|
||||
void *out = NULL;
|
||||
hl_debug_read(pid, addr + (-((int_val)r)-1), (vbyte*)&out, sizeof(void*));
|
||||
return out;
|
||||
}
|
||||
return (void*)ptrace(PTRACE_PEEKUSER,thread,r,0);
|
||||
# else
|
||||
return NULL;
|
||||
# endif
|
||||
}
|
||||
|
||||
HL_API bool hl_debug_write_register( int pid, int thread, int reg, void *value, bool is64 ) {
|
||||
# if defined(HL_WIN)
|
||||
# ifdef HL_64
|
||||
if( !is64 ) {
|
||||
WOW64_CONTEXT c;
|
||||
c.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
|
||||
if( !Wow64GetThreadContext(OpenTID(thread),&c) )
|
||||
return false;
|
||||
if( reg == 3 )
|
||||
c.EFlags = (int)(int_val)value;
|
||||
else if( reg == 11 )
|
||||
return false; // TODO
|
||||
else
|
||||
*GetContextReg32(&c,reg) = (DWORD)(int_val)value;
|
||||
return (bool)Wow64SetThreadContext(OpenTID(thread),&c);
|
||||
}
|
||||
# else
|
||||
if( is64 ) return false;
|
||||
# endif
|
||||
CONTEXT c;
|
||||
c.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
|
||||
if( !GetThreadContext(OpenTID(thread),&c) )
|
||||
return false;
|
||||
if( reg == 3 )
|
||||
c.EFlags = (int)(int_val)value;
|
||||
else if( reg == 11 )
|
||||
# ifdef HL_64
|
||||
c.FltSave.XmmRegisters[0].Low = (int_val)value;
|
||||
# else
|
||||
*(int_val*)&c.ExtendedRegisters[10*16] = (int_val)value;
|
||||
# endif
|
||||
else
|
||||
*GetContextReg(&c,reg) = (REGDATA)value;
|
||||
return (bool)SetThreadContext(OpenTID(thread),&c);
|
||||
# elif defined(HL_MAC)
|
||||
return mdbg_write_register(pid, thread, get_reg(reg), value, is64);
|
||||
# elif defined(USE_PTRACE)
|
||||
return ptrace(PTRACE_POKEUSER,thread,get_reg(reg),value) >= 0;
|
||||
# else
|
||||
return false;
|
||||
# endif
|
||||
}
|
||||
|
||||
DEFINE_PRIM(_BOOL, debug_start, _I32);
|
||||
DEFINE_PRIM(_VOID, debug_stop, _I32);
|
||||
DEFINE_PRIM(_BOOL, debug_breakpoint, _I32);
|
||||
DEFINE_PRIM(_BOOL, debug_read, _I32 _BYTES _BYTES _I32);
|
||||
DEFINE_PRIM(_BOOL, debug_write, _I32 _BYTES _BYTES _I32);
|
||||
DEFINE_PRIM(_BOOL, debug_flush, _I32 _BYTES _I32);
|
||||
DEFINE_PRIM(_I32, debug_wait, _I32 _REF(_I32) _I32);
|
||||
DEFINE_PRIM(_BOOL, debug_resume, _I32 _I32);
|
||||
DEFINE_PRIM(_BYTES, debug_read_register, _I32 _I32 _I32 _BOOL);
|
||||
DEFINE_PRIM(_BOOL, debug_write_register, _I32 _I32 _I32 _BYTES _BOOL);
|
||||
|
265
Kha/Backends/Kinc-HL/hl/src/std/error.c
Normal file
265
Kha/Backends/Kinc-HL/hl/src/std/error.c
Normal file
@ -0,0 +1,265 @@
|
||||
/*
|
||||
* Copyright (C)2005-2016 Haxe Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <hl.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HL_CONSOLE
|
||||
#include <posix/posix.h>
|
||||
#endif
|
||||
|
||||
HL_PRIM void *hl_fatal_error( const char *msg, const char *file, int line ) {
|
||||
hl_blocking(true);
|
||||
# ifdef HL_WIN_DESKTOP
|
||||
HWND consoleWnd = GetConsoleWindow();
|
||||
DWORD pid;
|
||||
GetWindowThreadProcessId(consoleWnd, &pid);
|
||||
if( consoleWnd == NULL || GetActiveWindow() != NULL || GetCurrentProcessId() == pid ) {
|
||||
char buf[256];
|
||||
sprintf(buf,"%s\n\n%s(%d)",msg,file,line);
|
||||
MessageBoxA(NULL,buf,"Fatal Error", MB_OK | MB_ICONERROR);
|
||||
}
|
||||
# endif
|
||||
printf("%s(%d) : FATAL ERROR : %s\n",file,line,msg);
|
||||
hl_blocking(false);
|
||||
hl_debug_break();
|
||||
exit(1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
typedef uchar *(*resolve_symbol_type)( void *addr, uchar *out, int *outSize );
|
||||
typedef int (*capture_stack_type)( void **stack, int size );
|
||||
|
||||
static resolve_symbol_type resolve_symbol_func = NULL;
|
||||
static capture_stack_type capture_stack_func = NULL;
|
||||
|
||||
int hl_internal_capture_stack( void **stack, int size ) {
|
||||
return capture_stack_func(stack,size);
|
||||
}
|
||||
|
||||
HL_PRIM uchar *hl_resolve_symbol( void *addr, uchar *out, int *outSize ) {
|
||||
return resolve_symbol_func(addr, out, outSize);
|
||||
}
|
||||
|
||||
static void (*throw_jump)( jmp_buf, int ) = NULL;
|
||||
|
||||
HL_PRIM void hl_setup_longjump( void *j ) {
|
||||
throw_jump = j;
|
||||
}
|
||||
|
||||
HL_PRIM void hl_setup_exception( void *resolve_symbol, void *capture_stack ) {
|
||||
resolve_symbol_func = resolve_symbol;
|
||||
capture_stack_func = capture_stack;
|
||||
}
|
||||
|
||||
HL_PRIM void hl_set_error_handler( vclosure *d ) {
|
||||
hl_thread_info *t = hl_get_thread();
|
||||
t->trap_uncaught = t->trap_current;
|
||||
t->exc_handler = d;
|
||||
}
|
||||
|
||||
static bool break_on_trap( hl_thread_info *t, hl_trap_ctx *trap, vdynamic *v ) {
|
||||
while( true ) {
|
||||
if( trap == NULL || trap == t->trap_uncaught || t->trap_current == NULL || trap->prev == NULL ) return true;
|
||||
if( !trap->tcheck || !v ) return false;
|
||||
hl_type *ot = ((hl_type**)trap->tcheck)[1]; // it's an obj with first field is a hl_type
|
||||
if( !ot || hl_safe_cast(v->t,ot) ) return false;
|
||||
trap = trap->prev;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
HL_PRIM void hl_throw( vdynamic *v ) {
|
||||
hl_thread_info *t = hl_get_thread();
|
||||
hl_trap_ctx *trap = t->trap_current;
|
||||
bool call_handler = false;
|
||||
if( !(t->flags & HL_EXC_RETHROW) )
|
||||
t->exc_stack_count = capture_stack_func(t->exc_stack_trace, HL_EXC_MAX_STACK);
|
||||
t->exc_value = v;
|
||||
t->trap_current = trap->prev;
|
||||
call_handler = trap == t->trap_uncaught || t->trap_current == NULL;
|
||||
if( (t->flags&HL_EXC_CATCH_ALL) || break_on_trap(t,trap,v) ) {
|
||||
if( trap == t->trap_uncaught ) t->trap_uncaught = NULL;
|
||||
t->flags |= HL_EXC_IS_THROW;
|
||||
hl_debug_break();
|
||||
t->flags &= ~HL_EXC_IS_THROW;
|
||||
}
|
||||
t->flags &= ~HL_EXC_RETHROW;
|
||||
if( t->exc_handler && call_handler ) hl_dyn_call_safe(t->exc_handler,&v,1,&call_handler);
|
||||
if( throw_jump == NULL ) throw_jump = longjmp;
|
||||
throw_jump(trap->buf,1);
|
||||
HL_UNREACHABLE;
|
||||
}
|
||||
|
||||
HL_PRIM void hl_null_access() {
|
||||
hl_error("Null access");
|
||||
HL_UNREACHABLE;
|
||||
}
|
||||
|
||||
HL_PRIM void hl_throw_buffer( hl_buffer *b ) {
|
||||
vdynamic *d = hl_alloc_dynamic(&hlt_bytes);
|
||||
d->v.ptr = hl_buffer_content(b,NULL);
|
||||
hl_throw(d);
|
||||
}
|
||||
|
||||
HL_PRIM void hl_dump_stack() {
|
||||
void *stack[0x1000];
|
||||
int count = capture_stack_func(stack, 0x1000);
|
||||
int i;
|
||||
for(i=0;i<count;i++) {
|
||||
void *addr = stack[i];
|
||||
uchar sym[512];
|
||||
int size = 512;
|
||||
uchar *str = resolve_symbol_func(addr, sym, &size);
|
||||
if( str == NULL ) {
|
||||
int iaddr = (int)(int_val)addr;
|
||||
usprintf(sym,512,USTR("@0x%X"),iaddr);
|
||||
str = sym;
|
||||
}
|
||||
uprintf(USTR("%s\n"),str);
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
HL_PRIM varray *hl_exception_stack() {
|
||||
hl_thread_info *t = hl_get_thread();
|
||||
varray *a = hl_alloc_array(&hlt_bytes, t->exc_stack_count);
|
||||
int i, pos = 0;
|
||||
for(i=0;i<t->exc_stack_count;i++) {
|
||||
void *addr = t->exc_stack_trace[i];
|
||||
uchar sym[512];
|
||||
int size = 512;
|
||||
uchar *str = resolve_symbol_func(addr, sym, &size);
|
||||
if( str == NULL ) continue;
|
||||
hl_aptr(a,vbyte*)[pos++] = hl_copy_bytes((vbyte*)str,sizeof(uchar)*(size+1));
|
||||
}
|
||||
a->size = pos;
|
||||
return a;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_exception_stack_raw( varray *arr ) {
|
||||
hl_thread_info *t = hl_get_thread();
|
||||
if( arr ) memcpy(hl_aptr(arr,void*), t->exc_stack_trace, t->exc_stack_count*sizeof(void*));
|
||||
return t->exc_stack_count;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_call_stack_raw( varray *arr ) {
|
||||
if( !arr )
|
||||
return capture_stack_func(NULL,0);
|
||||
return capture_stack_func(hl_aptr(arr,void*), arr->size);
|
||||
}
|
||||
|
||||
HL_PRIM void hl_rethrow( vdynamic *v ) {
|
||||
hl_get_thread()->flags |= HL_EXC_RETHROW;
|
||||
hl_throw(v);
|
||||
}
|
||||
|
||||
HL_PRIM vdynamic *hl_alloc_strbytes( const uchar *fmt, ... ) {
|
||||
uchar _buf[256];
|
||||
vdynamic *d;
|
||||
int len;
|
||||
uchar *buf = _buf;
|
||||
int bsize = sizeof(_buf) / sizeof(uchar);
|
||||
va_list args;
|
||||
while( true ) {
|
||||
va_start(args, fmt);
|
||||
len = uvszprintf(buf,bsize,fmt,args);
|
||||
va_end(args);
|
||||
if( (len + 2) << 1 < bsize ) break;
|
||||
if( buf != _buf ) free(buf);
|
||||
bsize <<= 1;
|
||||
buf = (uchar*)malloc(bsize * sizeof(uchar));
|
||||
}
|
||||
d = hl_alloc_dynamic(&hlt_bytes);
|
||||
d->v.ptr = hl_copy_bytes((vbyte*)buf,(len + 1) << 1);
|
||||
if( buf != _buf ) free(buf);
|
||||
return d;
|
||||
}
|
||||
|
||||
HL_PRIM void hl_fatal_fmt( const char *file, int line, const char *fmt, ...) {
|
||||
char buf[256];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsprintf(buf,fmt, args);
|
||||
va_end(args);
|
||||
hl_fatal_error(buf,file,line);
|
||||
}
|
||||
|
||||
#ifdef HL_VCC
|
||||
# pragma optimize( "", off )
|
||||
#endif
|
||||
HL_PRIM HL_NO_OPT void hl_breakpoint() {
|
||||
hl_debug_break();
|
||||
}
|
||||
#ifdef HL_VCC
|
||||
# pragma optimize( "", on )
|
||||
#endif
|
||||
|
||||
#ifdef HL_LINUX__
|
||||
#include <signal.h>
|
||||
static int debugger_present = -1;
|
||||
static void _sigtrap_handler(int signum) {
|
||||
debugger_present = 0;
|
||||
signal(SIGTRAP,SIG_DFL);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HL_MAC
|
||||
extern bool kinc_debugger_attached(void);
|
||||
#endif
|
||||
|
||||
HL_PRIM bool hl_detect_debugger() {
|
||||
# if defined(HL_WIN)
|
||||
return (bool)IsDebuggerPresent();
|
||||
# elif defined(HL_LINUX__)
|
||||
if( debugger_present == -1 ) {
|
||||
debugger_present = 1;
|
||||
signal(SIGTRAP,_sigtrap_handler);
|
||||
raise(SIGTRAP);
|
||||
}
|
||||
return (bool)debugger_present;
|
||||
# elif defined(HL_MAC)
|
||||
return kinc_debugger_attached();
|
||||
# else
|
||||
return false;
|
||||
# endif
|
||||
}
|
||||
|
||||
#ifdef HL_VCC
|
||||
# pragma optimize( "", off )
|
||||
#endif
|
||||
HL_PRIM HL_NO_OPT void hl_assert() {
|
||||
hl_debug_break();
|
||||
hl_error("assert");
|
||||
}
|
||||
#ifdef HL_VCC
|
||||
# pragma optimize( "", on )
|
||||
#endif
|
||||
|
||||
#define _SYMBOL _ABSTRACT(hl_symbol)
|
||||
|
||||
DEFINE_PRIM(_ARR,exception_stack,_NO_ARG);
|
||||
DEFINE_PRIM(_I32,exception_stack_raw,_ARR);
|
||||
DEFINE_PRIM(_I32,call_stack_raw,_ARR);
|
||||
DEFINE_PRIM(_VOID,set_error_handler,_FUN(_VOID,_DYN));
|
||||
DEFINE_PRIM(_VOID,breakpoint,_NO_ARG);
|
||||
DEFINE_PRIM(_BYTES,resolve_symbol, _SYMBOL _BYTES _REF(_I32));
|
276
Kha/Backends/Kinc-HL/hl/src/std/file.c
Normal file
276
Kha/Backends/Kinc-HL/hl/src/std/file.c
Normal file
@ -0,0 +1,276 @@
|
||||
/*
|
||||
* Copyright (C)2005-2016 Haxe Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#if defined(__GNUC__) && !defined(__APPLE__)
|
||||
# define _FILE_OFFSET_BITS 64
|
||||
#endif
|
||||
|
||||
#include <hl.h>
|
||||
#include <stdio.h>
|
||||
#ifdef HL_CONSOLE
|
||||
# include <posix/posix.h>
|
||||
#endif
|
||||
#ifdef HL_WIN
|
||||
#ifdef HL_WIN_DESKTOP
|
||||
# include <windows.h>
|
||||
# include <io.h>
|
||||
# include <fcntl.h>
|
||||
#else
|
||||
# include<xdk.h>
|
||||
#endif
|
||||
# define fopen(name,mode) _wfopen(name,mode)
|
||||
# define HL_UFOPEN
|
||||
#else
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#ifdef HL_WIN_DESKTOP
|
||||
# define SET_IS_STD(f,b) (f)->is_std = b
|
||||
#else
|
||||
# define SET_IS_STD(f,b)
|
||||
#endif
|
||||
|
||||
typedef struct _hl_fdesc hl_fdesc;
|
||||
struct _hl_fdesc {
|
||||
void (*finalize)( hl_fdesc * );
|
||||
FILE *f;
|
||||
# ifdef HL_WIN_DESKTOP
|
||||
bool is_std;
|
||||
# endif
|
||||
};
|
||||
|
||||
static void fdesc_finalize( hl_fdesc *f ) {
|
||||
if( f->f ) fclose(f->f);
|
||||
}
|
||||
|
||||
HL_PRIM hl_fdesc *hl_file_open( vbyte *name, int mode, bool binary ) {
|
||||
# ifdef HL_UFOPEN
|
||||
static const uchar *MODES[] = { USTR("r"), USTR("w"), USTR("a"), USTR("r+"), USTR("rb"), USTR("wb"), USTR("ab"), USTR("rb+") };
|
||||
FILE *f = fopen((uchar*)name,MODES[mode|(binary?4:0)]);
|
||||
# else
|
||||
static const char *MODES[] = { "r", "w", "a", "r+", "rb", "wb", "ab", "rb+" };
|
||||
FILE *f = fopen((char*)name,MODES[mode|(binary?4:0)]);
|
||||
# endif
|
||||
hl_fdesc *fd;
|
||||
if( f == NULL ) return NULL;
|
||||
fd = (hl_fdesc*)hl_gc_alloc_finalizer(sizeof(hl_fdesc));
|
||||
fd->finalize = fdesc_finalize;
|
||||
fd->f = f;
|
||||
SET_IS_STD(fd, false);
|
||||
return fd;
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_file_is_locked( vbyte *name ) {
|
||||
# ifdef HL_WIN
|
||||
HANDLE h = CreateFile((uchar*)name,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
|
||||
if( h == INVALID_HANDLE_VALUE ) return true;
|
||||
CloseHandle(h);
|
||||
return false;
|
||||
# else
|
||||
return false;
|
||||
# endif
|
||||
}
|
||||
|
||||
HL_PRIM void hl_file_close( hl_fdesc *f ) {
|
||||
if( !f ) return;
|
||||
if( f->f ) fclose(f->f);
|
||||
f->f = NULL;
|
||||
f->finalize = NULL;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_file_write( hl_fdesc *f, vbyte *buf, int pos, int len ) {
|
||||
int ret;
|
||||
if( !f ) return -1;
|
||||
hl_blocking(true);
|
||||
# ifdef HL_WIN_DESKTOP
|
||||
if( f->is_std ) {
|
||||
// except utf8, handle the case where it's not \0 terminated
|
||||
uchar *out = (uchar*)malloc((len+1)*2);
|
||||
vbyte prev = buf[pos+len-1];
|
||||
if( buf[pos+len] ) buf[pos+len-1] = 0;
|
||||
int olen = hl_from_utf8(out,len,(const char*)(buf+pos));
|
||||
buf[pos+len-1] = prev;
|
||||
_setmode(fileno(f->f),_O_U8TEXT);
|
||||
ret = _write(fileno(f->f),out,olen<<1);
|
||||
_setmode(fileno(f->f),_O_TEXT);
|
||||
if( ret > 0 ) ret = len;
|
||||
free(out);
|
||||
} else
|
||||
# endif
|
||||
ret = (int)fwrite(buf+pos,1,len,f->f);
|
||||
hl_blocking(false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_file_read( hl_fdesc *f, vbyte *buf, int pos, int len ) {
|
||||
int ret;
|
||||
if( !f ) return -1;
|
||||
hl_blocking(true);
|
||||
ret = (int)fread((char*)buf+pos,1,len,f->f);
|
||||
hl_blocking(false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_file_write_char( hl_fdesc *f, int c ) {
|
||||
size_t ret;
|
||||
unsigned char cc = (unsigned char)c;
|
||||
if( !f ) return false;
|
||||
hl_blocking(true);
|
||||
# ifdef HL_WIN_DESKTOP
|
||||
if( f->is_std ) {
|
||||
uchar wcc = cc;
|
||||
_setmode(fileno(f->f),_O_U8TEXT);
|
||||
ret = _write(fileno(f->f),&wcc,2);
|
||||
_setmode(fileno(f->f),_O_TEXT);
|
||||
if( ret > 0 ) ret = 1;
|
||||
} else
|
||||
# endif
|
||||
ret = fwrite(&cc,1,1,f->f);
|
||||
hl_blocking(false);
|
||||
return ret == 1;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_file_read_char( hl_fdesc *f ) {
|
||||
unsigned char cc;
|
||||
hl_blocking(true);
|
||||
if( !f || fread(&cc,1,1,f->f) != 1 ) {
|
||||
hl_blocking(false);
|
||||
return -2;
|
||||
}
|
||||
hl_blocking(false);
|
||||
return cc;
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_file_seek( hl_fdesc *f, int pos, int kind ) {
|
||||
if( !f ) return false;
|
||||
return fseek(f->f,pos,kind) == 0;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_file_tell( hl_fdesc *f ) {
|
||||
if( !f ) return -1;
|
||||
return (int)ftell(f->f);
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_file_seek2( hl_fdesc *f, double pos, int kind ) {
|
||||
if( !f ) return false;
|
||||
# ifdef HL_WIN
|
||||
return _fseeki64(f->f,(__int64)pos,kind) == 0;
|
||||
# else
|
||||
return fseek(f->f,(int64)pos,kind) == 0;
|
||||
# endif
|
||||
}
|
||||
|
||||
HL_PRIM double hl_file_tell2( hl_fdesc *f ) {
|
||||
if( !f ) return -1;
|
||||
# ifdef HL_WIN
|
||||
return (double)_ftelli64(f->f);
|
||||
# else
|
||||
return (double)ftell(f->f);
|
||||
# endif
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_file_eof( hl_fdesc *f ) {
|
||||
if( !f ) return true;
|
||||
return (bool)feof(f->f);
|
||||
}
|
||||
|
||||
HL_PRIM int hl_file_error_code() {
|
||||
return errno;
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_file_flush( hl_fdesc *f ) {
|
||||
int ret;
|
||||
if( !f ) return false;
|
||||
hl_blocking(true);
|
||||
ret = fflush( f->f );
|
||||
hl_blocking(false);
|
||||
return ret == 0;
|
||||
}
|
||||
|
||||
#define MAKE_STDIO(k) \
|
||||
HL_PRIM hl_fdesc *hl_file_##k() { \
|
||||
hl_fdesc *f; \
|
||||
f = (hl_fdesc*)hl_gc_alloc_noptr(sizeof(hl_fdesc)); \
|
||||
f->f = k; \
|
||||
f->finalize = NULL; \
|
||||
SET_IS_STD(f, true); \
|
||||
return f; \
|
||||
}
|
||||
|
||||
MAKE_STDIO(stdin);
|
||||
MAKE_STDIO(stdout);
|
||||
MAKE_STDIO(stderr);
|
||||
|
||||
HL_PRIM vbyte *hl_file_contents( vbyte *name, int *size ) {
|
||||
int len;
|
||||
int p = 0;
|
||||
vbyte *content;
|
||||
# ifdef HL_UFOPEN
|
||||
FILE *f = fopen((uchar*)name,USTR("rb"));
|
||||
# else
|
||||
FILE *f = fopen((char*)name,"rb");
|
||||
# endif
|
||||
if( f == NULL )
|
||||
return NULL;
|
||||
hl_blocking(true);
|
||||
fseek(f,0,SEEK_END);
|
||||
len = ftell(f);
|
||||
if( size ) *size = len;
|
||||
fseek(f,0,SEEK_SET);
|
||||
hl_blocking(false);
|
||||
content = (vbyte*)hl_gc_alloc_noptr(size ? len : len+1);
|
||||
hl_blocking(true);
|
||||
if( !size ) content[len] = 0; else if( !len ) content = (vbyte*)""; // final 0 for UTF8
|
||||
while( len > 0 ) {
|
||||
int d = (int)fread((char*)content + p,1,len,f);
|
||||
if( d <= 0 ) {
|
||||
hl_blocking(false);
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
p += d;
|
||||
len -= d;
|
||||
}
|
||||
fclose(f);
|
||||
hl_blocking(false);
|
||||
return content;
|
||||
}
|
||||
|
||||
#define _FILE _ABSTRACT(hl_fdesc)
|
||||
DEFINE_PRIM(_FILE, file_open, _BYTES _I32 _BOOL);
|
||||
DEFINE_PRIM(_VOID, file_close, _FILE);
|
||||
DEFINE_PRIM(_I32, file_write, _FILE _BYTES _I32 _I32);
|
||||
DEFINE_PRIM(_I32, file_read, _FILE _BYTES _I32 _I32);
|
||||
DEFINE_PRIM(_BOOL, file_write_char, _FILE _I32);
|
||||
DEFINE_PRIM(_I32, file_read_char, _FILE);
|
||||
DEFINE_PRIM(_BOOL, file_seek, _FILE _I32 _I32);
|
||||
DEFINE_PRIM(_I32, file_tell, _FILE);
|
||||
DEFINE_PRIM(_BOOL, file_seek2, _FILE _F64 _I32);
|
||||
DEFINE_PRIM(_F64, file_tell2, _FILE);
|
||||
DEFINE_PRIM(_BOOL, file_eof, _FILE);
|
||||
DEFINE_PRIM(_BOOL, file_flush, _FILE);
|
||||
DEFINE_PRIM(_FILE, file_stdin, _NO_ARG);
|
||||
DEFINE_PRIM(_FILE, file_stdout, _NO_ARG);
|
||||
DEFINE_PRIM(_FILE, file_stderr, _NO_ARG);
|
||||
DEFINE_PRIM(_BYTES, file_contents, _BYTES _REF(_I32));
|
||||
DEFINE_PRIM(_BOOL, file_is_locked, _BYTES);
|
||||
DEFINE_PRIM(_I32, file_error_code, _NO_ARG);
|
||||
|
479
Kha/Backends/Kinc-HL/hl/src/std/fun.c
Normal file
479
Kha/Backends/Kinc-HL/hl/src/std/fun.c
Normal file
@ -0,0 +1,479 @@
|
||||
/*
|
||||
* Copyright (C)2005-2016 Haxe Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <hl.h>
|
||||
|
||||
HL_PRIM int hl_closure_stack_capture = 0;
|
||||
|
||||
static void fun_var_args() {
|
||||
hl_error("Variable fun args was not cast to typed function");
|
||||
}
|
||||
|
||||
HL_PRIM vclosure *hl_alloc_closure_void( hl_type *t, void *fvalue ) {
|
||||
vclosure *c = (vclosure*)hl_gc_alloc_noptr(sizeof(vclosure));
|
||||
c->t = t;
|
||||
c->fun = fvalue;
|
||||
c->hasValue = 0;
|
||||
c->value = NULL;
|
||||
return c;
|
||||
}
|
||||
|
||||
static hl_type *hl_get_closure_type( hl_type *t ) {
|
||||
hl_type_fun *ft = t->fun;
|
||||
if( ft->closure_type.kind != HFUN ) {
|
||||
if( ft->nargs == 0 ) hl_fatal("assert");
|
||||
ft->closure_type.kind = HFUN;
|
||||
ft->closure_type.p = &ft->closure;
|
||||
ft->closure.nargs = ft->nargs - 1;
|
||||
ft->closure.args = ft->closure.nargs ? ft->args + 1 : NULL;
|
||||
ft->closure.ret = ft->ret;
|
||||
ft->closure.parent = t;
|
||||
}
|
||||
return (hl_type*)&ft->closure_type;
|
||||
}
|
||||
|
||||
int hl_internal_capture_stack( void **stack, int size );
|
||||
|
||||
HL_PRIM vclosure *hl_alloc_closure_ptr( hl_type *fullt, void *fvalue, void *v ) {
|
||||
hl_type *t = hl_get_closure_type(fullt);
|
||||
vclosure *c = (vclosure*)hl_gc_alloc(t, sizeof(vclosure) + sizeof(void*) * hl_closure_stack_capture);
|
||||
c->t = t;
|
||||
c->fun = fvalue;
|
||||
c->hasValue = 1;
|
||||
# ifdef HL_64
|
||||
int stack = 0;
|
||||
if( hl_closure_stack_capture ) stack = hl_internal_capture_stack((void**)(c + 1), hl_closure_stack_capture);
|
||||
c->stackCount = stack;
|
||||
# endif
|
||||
c->value = v;
|
||||
return c;
|
||||
}
|
||||
|
||||
HL_PRIM vdynamic *hl_no_closure( vdynamic *c ) {
|
||||
vclosure *cl = (vclosure*)c;
|
||||
if( !cl->hasValue ) return c;
|
||||
if( cl->hasValue == 2 )
|
||||
return hl_no_closure((vdynamic*)((vclosure_wrapper*)c)->wrappedFun);
|
||||
return (vdynamic*)hl_alloc_closure_void(cl->t->fun->parent,cl->fun);
|
||||
}
|
||||
|
||||
HL_PRIM vdynamic *hl_make_closure( vdynamic *c, vdynamic *v ) {
|
||||
vclosure *cl = (vclosure*)c;
|
||||
hl_type *t = cl->hasValue ? cl->t->fun->parent : cl->t;
|
||||
if( cl->hasValue == 2 )
|
||||
return hl_make_closure((vdynamic*)((vclosure_wrapper*)c)->wrappedFun, v);
|
||||
if( t->fun->nargs == 0 || !v || !hl_safe_cast(v->t,t->fun->args[0]) )
|
||||
return NULL;
|
||||
return (vdynamic*)hl_alloc_closure_ptr( t, cl->fun, v );
|
||||
}
|
||||
|
||||
HL_PRIM vdynamic* hl_get_closure_value( vdynamic *c ) {
|
||||
vclosure *cl = (vclosure*)c;
|
||||
if( !cl->hasValue )
|
||||
return NULL;
|
||||
if( cl->hasValue == 2 )
|
||||
return hl_get_closure_value((vdynamic*)((vclosure_wrapper*)c)->wrappedFun);
|
||||
if( cl->fun == fun_var_args )
|
||||
return NULL;
|
||||
return hl_make_dyn(&cl->value, cl->t->fun->parent->fun->args[0]);
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_fun_compare( vdynamic *a, vdynamic *b ) {
|
||||
vclosure *ca, *cb;
|
||||
if( a == b )
|
||||
return true;
|
||||
if( !a || !b )
|
||||
return false;
|
||||
if( a->t->kind != b->t->kind || a->t->kind != HFUN )
|
||||
return false;
|
||||
ca = (vclosure*)a;
|
||||
cb = (vclosure*)b;
|
||||
if( ca->fun != cb->fun )
|
||||
return false;
|
||||
if( ca->hasValue && ca->value != cb->value )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ------------ DYNAMIC CALLS
|
||||
|
||||
typedef void *(*fptr_static_call)(void *fun, hl_type *t, void **args, vdynamic *out);
|
||||
typedef void *(*fptr_get_wrapper)(hl_type *t);
|
||||
|
||||
static fptr_static_call hlc_static_call = NULL;
|
||||
static fptr_get_wrapper hlc_get_wrapper = NULL;
|
||||
static int hlc_call_flags = 0;
|
||||
|
||||
HL_PRIM void hl_setup_callbacks2( void *c, void *w, int flags ) {
|
||||
hlc_static_call = (fptr_static_call)c;
|
||||
hlc_get_wrapper = (fptr_get_wrapper)w;
|
||||
hlc_call_flags = flags;
|
||||
}
|
||||
|
||||
HL_PRIM void hl_setup_callbacks( void *c, void *w ) {
|
||||
hl_setup_callbacks2(c,w,0);
|
||||
}
|
||||
|
||||
|
||||
#define HL_MAX_ARGS 9
|
||||
|
||||
HL_PRIM vdynamic* hl_call_method( vdynamic *c, varray *args ) {
|
||||
vclosure *cl = (vclosure*)c;
|
||||
vdynamic **vargs = hl_aptr(args,vdynamic*);
|
||||
void *pargs[HL_MAX_ARGS];
|
||||
void *ret;
|
||||
union { double d; int i; float f; int64 i64; } tmp[HL_MAX_ARGS];
|
||||
hl_type *tret;
|
||||
vdynamic *dret;
|
||||
vdynamic out;
|
||||
int i;
|
||||
if( args->size > HL_MAX_ARGS )
|
||||
hl_error("Too many arguments");
|
||||
if( cl->hasValue ) {
|
||||
if( cl->fun == fun_var_args ) {
|
||||
cl = (vclosure*)cl->value;
|
||||
return cl->hasValue ? ((vdynamic* (*)(vdynamic*, varray*))cl->fun)(cl->value, args) : ((vdynamic* (*)(varray*))cl->fun)(args);
|
||||
}
|
||||
hl_error("Can't call closure with value");
|
||||
}
|
||||
if( args->size < cl->t->fun->nargs )
|
||||
hl_error("Missing arguments : %d expected but %d passed",cl->t->fun->nargs, args->size);
|
||||
for(i=0;i<cl->t->fun->nargs;i++) {
|
||||
vdynamic *v = vargs[i];
|
||||
hl_type *t = cl->t->fun->args[i];
|
||||
void *p;
|
||||
if( v == NULL ) {
|
||||
if( hl_is_ptr(t) )
|
||||
p = NULL;
|
||||
else {
|
||||
tmp[i].d = 0;
|
||||
p = &tmp[i].d;
|
||||
}
|
||||
} else switch( t->kind ) {
|
||||
case HBOOL:
|
||||
case HUI8:
|
||||
case HUI16:
|
||||
case HI32:
|
||||
tmp[i].i = hl_dyn_casti(vargs + i, &hlt_dyn,t);
|
||||
p = &tmp[i].i;
|
||||
break;
|
||||
case HI64:
|
||||
tmp[i].i64 = hl_dyn_casti64(vargs + i, &hlt_dyn);
|
||||
p = &tmp[i].i64;
|
||||
break;
|
||||
case HF32:
|
||||
tmp[i].f = hl_dyn_castf(vargs + i, &hlt_dyn);
|
||||
p = &tmp[i].f;
|
||||
break;
|
||||
case HF64:
|
||||
tmp[i].d = hl_dyn_castd(vargs + i, &hlt_dyn);
|
||||
p = &tmp[i].d;
|
||||
break;
|
||||
default:
|
||||
p = hl_dyn_castp(vargs + i,&hlt_dyn,t);
|
||||
break;
|
||||
}
|
||||
pargs[i] = p;
|
||||
}
|
||||
ret = hlc_static_call(hlc_call_flags & 1 ? &cl->fun : cl->fun,cl->t,pargs,&out);
|
||||
tret = cl->t->fun->ret;
|
||||
if( !hl_is_ptr(tret) ) {
|
||||
vdynamic *r;
|
||||
switch( tret->kind ) {
|
||||
case HVOID:
|
||||
return NULL;
|
||||
case HBOOL:
|
||||
return hl_alloc_dynbool(out.v.b);
|
||||
default:
|
||||
r = hl_alloc_dynamic(tret);
|
||||
r->t = tret;
|
||||
r->v.d = out.v.d; // copy
|
||||
return r;
|
||||
}
|
||||
}
|
||||
if( ret == NULL || hl_is_dynamic(tret) )
|
||||
return (vdynamic*)ret;
|
||||
dret = hl_alloc_dynamic(tret);
|
||||
dret->v.ptr = ret;
|
||||
return dret;
|
||||
}
|
||||
|
||||
HL_PRIM vdynamic *hl_dyn_call( vclosure *c, vdynamic **args, int nargs ) {
|
||||
struct {
|
||||
varray a;
|
||||
vdynamic *args[HL_MAX_ARGS+1];
|
||||
} tmp;
|
||||
vclosure ctmp;
|
||||
int i = 0;
|
||||
if( nargs > HL_MAX_ARGS ) hl_error("Too many arguments");
|
||||
tmp.a.t = &hlt_array;
|
||||
tmp.a.at = &hlt_dyn;
|
||||
tmp.a.size = nargs;
|
||||
if( c->hasValue && c->t->fun->nargs >= 0 ) {
|
||||
ctmp.t = c->t->fun->parent;
|
||||
ctmp.hasValue = 0;
|
||||
ctmp.fun = c->fun;
|
||||
tmp.args[0] = hl_make_dyn(&c->value,ctmp.t->fun->args[0]);
|
||||
tmp.a.size++;
|
||||
for(i=0;i<nargs;i++)
|
||||
tmp.args[i+1] = args[i];
|
||||
c = &ctmp;
|
||||
} else {
|
||||
for(i=0;i<nargs;i++)
|
||||
tmp.args[i] = args[i];
|
||||
}
|
||||
return hl_call_method((vdynamic*)c,&tmp.a);
|
||||
}
|
||||
|
||||
HL_PRIM void *hl_wrapper_call( void *_c, void **args, vdynamic *ret ) {
|
||||
vclosure_wrapper *c = (vclosure_wrapper*)_c;
|
||||
hl_type_fun *tfun = c->cl.t->fun;
|
||||
union { double d; int i; float f; int64 i64; } tmp[HL_MAX_ARGS];
|
||||
void *vargs[HL_MAX_ARGS+1];
|
||||
vdynamic out;
|
||||
vclosure *w = c->wrappedFun;
|
||||
int i;
|
||||
int p = 0;
|
||||
void *pret, *aret;
|
||||
if( ret == NULL )
|
||||
ret = &out;
|
||||
if( w->fun == fun_var_args ) {
|
||||
varray *a;
|
||||
w = (vclosure*)w->value; // the real callback
|
||||
a = hl_alloc_array(&hlt_dyn,tfun->nargs);
|
||||
for(i=0;i<tfun->nargs;i++) {
|
||||
hl_type *t = tfun->args[i];
|
||||
void *v = hl_is_ptr(t) ? args + i : args[i];
|
||||
hl_aptr(a,void*)[i] = hl_make_dyn(v,t);
|
||||
}
|
||||
if( w->hasValue )
|
||||
vargs[p++] = (vdynamic*)w->value;
|
||||
vargs[p++] = (vdynamic*)a;
|
||||
} else {
|
||||
if( w->hasValue )
|
||||
vargs[p++] = (vdynamic*)w->value;
|
||||
for(i=0;i<w->t->fun->nargs;i++) {
|
||||
hl_type *t = tfun->args[i];
|
||||
hl_type *to = w->t->fun->args[i];
|
||||
void *v = hl_is_ptr(t) ? args + i : args[i];
|
||||
switch( to->kind ) {
|
||||
case HUI8:
|
||||
case HUI16:
|
||||
case HI32:
|
||||
case HBOOL:
|
||||
tmp[i].i = hl_dyn_casti(v,t,to);
|
||||
v = &tmp[i].i;
|
||||
break;
|
||||
case HI64:
|
||||
tmp[i].i64 = hl_dyn_casti64(v,t);
|
||||
v = &tmp[i].i64;
|
||||
break;
|
||||
case HF32:
|
||||
tmp[i].f = hl_dyn_castf(v,t);
|
||||
v = &tmp[i].f;
|
||||
break;
|
||||
case HF64:
|
||||
tmp[i].d = hl_dyn_castd(v,t);
|
||||
v = &tmp[i].d;
|
||||
break;
|
||||
default:
|
||||
v = hl_dyn_castp(v,t,to);
|
||||
break;
|
||||
}
|
||||
vargs[p++] = v;
|
||||
}
|
||||
}
|
||||
pret = hlc_static_call(hlc_call_flags & 1 ? &w->fun : w->fun,w->hasValue ? w->t->fun->parent : w->t,vargs,ret);
|
||||
aret = hl_is_ptr(w->t->fun->ret) ? &pret : pret;
|
||||
if( aret == NULL ) aret = &pret;
|
||||
switch( tfun->ret->kind ) {
|
||||
case HVOID:
|
||||
return NULL;
|
||||
case HUI8:
|
||||
case HUI16:
|
||||
case HI32:
|
||||
case HBOOL:
|
||||
ret->v.i = hl_dyn_casti(aret,w->t->fun->ret,tfun->ret);
|
||||
break;
|
||||
case HI64:
|
||||
ret->v.i64 = hl_dyn_casti64(aret,w->t->fun->ret);
|
||||
break;
|
||||
case HF32:
|
||||
ret->v.f = hl_dyn_castf(aret,w->t->fun->ret);
|
||||
break;
|
||||
case HF64:
|
||||
ret->v.d = hl_dyn_castd(aret,w->t->fun->ret);
|
||||
break;
|
||||
default:
|
||||
pret = hl_dyn_castp(aret,w->t->fun->ret,tfun->ret);
|
||||
break;
|
||||
}
|
||||
return pret;
|
||||
}
|
||||
|
||||
HL_PRIM void *hl_dyn_call_obj( vdynamic *o, hl_type *ft, int hfield, void **args, vdynamic *ret ) {
|
||||
switch( o->t->kind ) {
|
||||
case HDYNOBJ:
|
||||
{
|
||||
vdynobj *d = (vdynobj*)o;
|
||||
hl_field_lookup *l = hl_lookup_find(d->lookup,d->nfields, hfield);
|
||||
if( l != NULL && l->t->kind != HFUN )
|
||||
hl_error("Field %s is of type %s and cannot be called", hl_field_name(hfield), hl_type_str(l->t));
|
||||
vclosure *tmp = (vclosure*)d->values[l->field_index];
|
||||
if( tmp ) {
|
||||
vclosure_wrapper w;
|
||||
w.cl.t = ft;
|
||||
w.cl.fun = hlc_get_wrapper(ft);
|
||||
w.cl.hasValue = 2;
|
||||
# ifdef HL_64
|
||||
w.cl.stackCount = 0;
|
||||
# endif
|
||||
w.cl.value = &w;
|
||||
w.wrappedFun = tmp;
|
||||
return hl_wrapper_call(&w,args,ret);
|
||||
}
|
||||
hl_error("%s has no method %s",hl_type_str(o->t),hl_field_name(hfield));
|
||||
}
|
||||
break;
|
||||
case HOBJ:
|
||||
{
|
||||
hl_runtime_obj *rt = o->t->obj->rt;
|
||||
while( true ) {
|
||||
hl_field_lookup *l = hl_lookup_find(rt->lookup,rt->nlookup, hfield);
|
||||
if( l != NULL && l->t->kind != HFUN )
|
||||
hl_error("Field %s is of type %s and cannot be called", hl_field_name(hfield), hl_type_str(l->t));
|
||||
if( l != NULL ) {
|
||||
vclosure_wrapper w;
|
||||
vclosure tmp;
|
||||
w.cl.t = ft;
|
||||
w.cl.fun = hlc_get_wrapper(ft);
|
||||
w.cl.hasValue = 2;
|
||||
# ifdef HL_64
|
||||
w.cl.stackCount = 0;
|
||||
# endif
|
||||
w.cl.value = &w;
|
||||
if( l->field_index < 0 ) {
|
||||
tmp.t = hl_get_closure_type(l->t);
|
||||
tmp.fun = o->t->obj->rt->methods[-l->field_index-1];
|
||||
tmp.hasValue = 1;
|
||||
# ifdef HL_64
|
||||
tmp.stackCount = 0;
|
||||
# endif
|
||||
tmp.value = o;
|
||||
w.wrappedFun = &tmp;
|
||||
} else {
|
||||
vclosure *tmp = *(vclosure**)((char*)o + l->field_index);
|
||||
if( !tmp ) break;
|
||||
w.wrappedFun = tmp;
|
||||
}
|
||||
return hl_wrapper_call(&w,args,ret);
|
||||
}
|
||||
rt = rt->parent;
|
||||
if( rt == NULL ) break;
|
||||
}
|
||||
hl_error("%s has no method %s",o->t->obj->name,hl_field_name(hfield));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
hl_error("Invalid field access");
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
HL_PRIM vclosure *hl_make_fun_wrapper( vclosure *v, hl_type *to ) {
|
||||
vclosure_wrapper *c;
|
||||
void *wrap = hlc_get_wrapper(to);
|
||||
if( wrap == NULL ) return NULL;
|
||||
if( v->fun != fun_var_args && v->t->fun->nargs != to->fun->nargs )
|
||||
return NULL;
|
||||
c = (vclosure_wrapper*)hl_gc_alloc(to, sizeof(vclosure_wrapper));
|
||||
c->cl.t = to;
|
||||
c->cl.fun = wrap;
|
||||
c->cl.hasValue = 2;
|
||||
# ifdef HL_64
|
||||
c->cl.stackCount = 0;
|
||||
# endif
|
||||
c->cl.value = c;
|
||||
c->wrappedFun = v;
|
||||
return (vclosure*)c;
|
||||
}
|
||||
|
||||
static hl_type hlt_var_args = { HFUN };
|
||||
static hl_type_fun hlt_var_fun = { NULL, &hlt_void, -1, &hlt_var_args, { HFUN, NULL }, { NULL, &hlt_void, -1, &hlt_var_args} };
|
||||
|
||||
HL_PRIM vdynamic *hl_make_var_args( vclosure *c ) {
|
||||
hlt_var_args.fun = &hlt_var_fun;
|
||||
hlt_var_fun.closure_type.p = &hlt_var_fun;
|
||||
return (vdynamic*)hl_alloc_closure_ptr(&hlt_var_args,fun_var_args,c);
|
||||
}
|
||||
|
||||
HL_PRIM void hl_prim_not_loaded() {
|
||||
hl_error("Primitive or library is missing");
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_is_prim_loaded( vdynamic *f ) {
|
||||
return f && f->t->kind == HFUN && ((vclosure*)f)->fun != hl_prim_not_loaded;
|
||||
}
|
||||
|
||||
DEFINE_PRIM(_DYN, no_closure, _DYN);
|
||||
DEFINE_PRIM(_DYN, make_closure, _DYN _DYN);
|
||||
DEFINE_PRIM(_DYN, get_closure_value, _DYN);
|
||||
DEFINE_PRIM(_BOOL, fun_compare, _DYN _DYN);
|
||||
DEFINE_PRIM(_DYN, make_var_args, _FUN(_DYN,_ARR));
|
||||
DEFINE_PRIM(_DYN, call_method, _DYN _ARR);
|
||||
DEFINE_PRIM(_BOOL, is_prim_loaded, _DYN);
|
||||
|
||||
#if defined(HL_VCC) && !defined(HL_XBO)
|
||||
static LONG CALLBACK global_handler( PEXCEPTION_POINTERS inf ) {
|
||||
switch( inf->ExceptionRecord->ExceptionCode ) {
|
||||
case EXCEPTION_ACCESS_VIOLATION: hl_error("Access violation");
|
||||
case EXCEPTION_STACK_OVERFLOW: hl_error("Stack overflow");
|
||||
default: break;
|
||||
}
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
#endif
|
||||
|
||||
HL_PRIM vdynamic *hl_dyn_call_safe( vclosure *c, vdynamic **args, int nargs, bool *isException ) {
|
||||
hl_trap_ctx trap;
|
||||
vdynamic *ret, *exc;
|
||||
*isException = false;
|
||||
hl_trap(trap, exc, on_exception);
|
||||
# if defined(HL_VCC) && !defined(HL_XBO)
|
||||
ULONG size = 32<<10;
|
||||
SetThreadStackGuarantee(&size);
|
||||
static bool first = true;
|
||||
if( first && !hl_detect_debugger() ) {
|
||||
first = false;
|
||||
AddVectoredExceptionHandler(1,global_handler);
|
||||
}
|
||||
# endif
|
||||
ret = hl_dyn_call(c,args,nargs);
|
||||
hl_endtrap(trap);
|
||||
return ret;
|
||||
on_exception:
|
||||
hl_endtrap(trap);
|
||||
*isException = true;
|
||||
return exc;
|
||||
}
|
291
Kha/Backends/Kinc-HL/hl/src/std/maps.c
Normal file
291
Kha/Backends/Kinc-HL/hl/src/std/maps.c
Normal file
@ -0,0 +1,291 @@
|
||||
/*
|
||||
* Copyright (C)2005-2016 Haxe Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <hl.h>
|
||||
#ifdef HL_VCC
|
||||
# pragma warning(disable:4034) // sizeof(void) == 0
|
||||
#endif
|
||||
|
||||
#define H_SIZE_INIT 3
|
||||
|
||||
// successive primes that double every time
|
||||
static int H_PRIMES[] = {
|
||||
7,17,37,79,163,331,673,1361,2729,5471,10949,21911,43853,87613,175229,350459,700919,1401857,2803727,5607457,11214943,22429903,44859823,89719661,179424673,373587883,776531401,1611623773
|
||||
};
|
||||
|
||||
// ----- FREE LIST ---------------------------------
|
||||
|
||||
typedef struct {
|
||||
int pos;
|
||||
int count;
|
||||
} hl_free_bucket;
|
||||
|
||||
typedef struct {
|
||||
hl_free_bucket *buckets;
|
||||
int head;
|
||||
int nbuckets;
|
||||
} hl_free_list;
|
||||
|
||||
static void hl_freelist_resize( hl_free_list *f, int newsize ) {
|
||||
hl_free_bucket *buckets = (hl_free_bucket*)hl_gc_alloc_noptr(sizeof(hl_free_bucket)*newsize);
|
||||
memcpy(buckets,f->buckets,f->head * sizeof(hl_free_bucket));
|
||||
f->buckets = buckets;
|
||||
f->nbuckets = newsize;
|
||||
}
|
||||
|
||||
static void hl_freelist_init( hl_free_list *f ) {
|
||||
memset(f,0,sizeof(hl_free_list));
|
||||
}
|
||||
|
||||
static void hl_freelist_add_range( hl_free_list *f, int pos, int count ) {
|
||||
hl_free_bucket *b = f->buckets;
|
||||
hl_free_bucket *prev = NULL;
|
||||
if( !b ) {
|
||||
// special handling for countinuous space
|
||||
if( f->nbuckets == 0 ) {
|
||||
f->head = pos;
|
||||
f->nbuckets = count;
|
||||
return;
|
||||
} else if( f->head + f->nbuckets == pos ) {
|
||||
f->nbuckets += count;
|
||||
return;
|
||||
} else if( pos + count == f->head ) {
|
||||
f->head -= count;
|
||||
f->nbuckets += count;
|
||||
return;
|
||||
} else {
|
||||
int cur_pos = f->head, cur_count = f->nbuckets;
|
||||
f->head = 0;
|
||||
f->nbuckets = 0;
|
||||
hl_freelist_resize(f,2);
|
||||
if( cur_count ) hl_freelist_add_range(f,cur_pos,cur_count);
|
||||
b = f->buckets;
|
||||
}
|
||||
}
|
||||
while( b < f->buckets + f->head ) {
|
||||
if( b->pos > pos ) break;
|
||||
prev = b;
|
||||
b++;
|
||||
}
|
||||
if( b < f->buckets + f->head && b->pos == pos + count ) {
|
||||
b->pos -= count;
|
||||
b->count += count;
|
||||
// merge
|
||||
if( prev && prev->pos + prev->count == b->pos ) {
|
||||
prev->count += b->count;
|
||||
memmove(b,b+1,((f->buckets + f->head) - (b+1)) * sizeof(hl_free_bucket));
|
||||
f->head--;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if( prev && prev->pos + prev->count == pos ) {
|
||||
prev->count += count;
|
||||
return;
|
||||
}
|
||||
// insert
|
||||
if( f->head == f->nbuckets ) {
|
||||
int pos = (int)(b - f->buckets);
|
||||
hl_freelist_resize(f,((f->nbuckets * 3) + 1) >> 1);
|
||||
b = f->buckets + pos;
|
||||
}
|
||||
memmove(b+1,b,((f->buckets + f->head) - b) * sizeof(hl_free_bucket));
|
||||
b->pos = pos;
|
||||
b->count = count;
|
||||
f->head++;
|
||||
}
|
||||
|
||||
static void hl_freelist_add( hl_free_list *f, int pos ) {
|
||||
hl_freelist_add_range(f,pos,1);
|
||||
}
|
||||
|
||||
static int hl_freelist_get( hl_free_list *f ) {
|
||||
hl_free_bucket *b;
|
||||
int p;
|
||||
if( !f->buckets ) {
|
||||
if( f->nbuckets == 0 ) return -1;
|
||||
f->nbuckets--;
|
||||
return f->head++;
|
||||
}
|
||||
if( f->head == 0 )
|
||||
return -1;
|
||||
b = f->buckets + f->head - 1;
|
||||
b->count--;
|
||||
p = b->pos + b->count;
|
||||
if( b->count == 0 ) {
|
||||
f->head--;
|
||||
if( f->head < (f->nbuckets>>1) )
|
||||
hl_freelist_resize(f,f->nbuckets>>1);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
// ----- INT MAP ---------------------------------
|
||||
|
||||
typedef struct {
|
||||
int key;
|
||||
} hl_hi_entry;
|
||||
|
||||
typedef struct {
|
||||
vdynamic *value;
|
||||
} hl_hi_value;
|
||||
|
||||
#define hlt_key hlt_i32
|
||||
#define hl_hifilter(key) key
|
||||
#define hl_hihash(h) ((unsigned)(h))
|
||||
#define _MKEY_TYPE int
|
||||
#define _MNAME(n) hl_hi##n
|
||||
#define _MMATCH(c) m->entries[c].key == key
|
||||
#define _MKEY(m,c) m->entries[c].key
|
||||
#define _MSET(c) m->entries[c].key = key
|
||||
#define _MERASE(c)
|
||||
|
||||
#include "maps.h"
|
||||
|
||||
|
||||
// ----- INT64 MAP ---------------------------------
|
||||
|
||||
typedef struct {
|
||||
int64 key;
|
||||
} hl_hi64_entry;
|
||||
|
||||
typedef struct {
|
||||
vdynamic *value;
|
||||
} hl_hi64_value;
|
||||
|
||||
#define hlt_key hlt_i64
|
||||
#define hl_hi64filter(key) key
|
||||
#define hl_hi64hash(h) (((unsigned int)h) ^ ((unsigned int)(h>>32)))
|
||||
#define _MKEY_TYPE int64
|
||||
#define _MNAME(n) hl_hi64##n
|
||||
#define _MMATCH(c) m->entries[c].key == key
|
||||
#define _MKEY(m,c) m->entries[c].key
|
||||
#define _MSET(c) m->entries[c].key = key
|
||||
#define _MERASE(c)
|
||||
|
||||
#include "maps.h"
|
||||
|
||||
// ----- BYTES MAP ---------------------------------
|
||||
|
||||
typedef struct {
|
||||
unsigned int hash;
|
||||
} hl_hb_entry;
|
||||
|
||||
typedef struct {
|
||||
uchar *key;
|
||||
vdynamic *value;
|
||||
} hl_hb_value;
|
||||
|
||||
#define hlt_key hlt_bytes
|
||||
#define hl_hbfilter(key) key
|
||||
#define hl_hbhash(key) ((unsigned)hl_hash_gen(key,false))
|
||||
#define _MKEY_TYPE uchar*
|
||||
#define _MNAME(n) hl_hb##n
|
||||
#define _MMATCH(c) m->entries[c].hash == hash && ucmp(m->values[c].key,key) == 0
|
||||
#define _MKEY(m,c) m->values[c].key
|
||||
#define _MSET(c) m->entries[c].hash = hash; m->values[c].key = key
|
||||
#define _MERASE(c) m->values[c].key = NULL
|
||||
|
||||
#include "maps.h"
|
||||
|
||||
// ----- OBJECT MAP ---------------------------------
|
||||
|
||||
typedef void hl_ho_entry;
|
||||
|
||||
typedef struct {
|
||||
vdynamic *key;
|
||||
vdynamic *value;
|
||||
} hl_ho_value;
|
||||
|
||||
static vdynamic *hl_hofilter( vdynamic *key ) {
|
||||
if( key )
|
||||
switch( key->t->kind ) {
|
||||
// erase virtual (prevent mismatch once virtualized)
|
||||
case HVIRTUAL:
|
||||
key = hl_virtual_make_value((vvirtual*)key);
|
||||
break;
|
||||
// store real pointer instead of dynamic wrapper
|
||||
case HBYTES:
|
||||
case HTYPE:
|
||||
case HABSTRACT:
|
||||
case HREF:
|
||||
case HENUM:
|
||||
key = (vdynamic*)key->v.ptr;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
#define hlt_key hlt_dyn
|
||||
#define hl_hohash(key) ((unsigned int)(int_val)(key))
|
||||
#define _MKEY_TYPE vdynamic*
|
||||
#define _MNAME(n) hl_ho##n
|
||||
#define _MMATCH(c) m->values[c].key == key
|
||||
#define _MKEY(m,c) m->values[c].key
|
||||
#define _MSET(c) m->values[c].key = key
|
||||
#define _MERASE(c) m->values[c].key = NULL
|
||||
|
||||
#include "maps.h"
|
||||
|
||||
#define _IMAP _ABSTRACT(hl_int_map)
|
||||
DEFINE_PRIM( _IMAP, hialloc, _NO_ARG );
|
||||
DEFINE_PRIM( _VOID, hiset, _IMAP _I32 _DYN );
|
||||
DEFINE_PRIM( _BOOL, hiexists, _IMAP _I32 );
|
||||
DEFINE_PRIM( _DYN, higet, _IMAP _I32 );
|
||||
DEFINE_PRIM( _BOOL, hiremove, _IMAP _I32 );
|
||||
DEFINE_PRIM( _ARR, hikeys, _IMAP );
|
||||
DEFINE_PRIM( _ARR, hivalues, _IMAP );
|
||||
DEFINE_PRIM( _VOID, hiclear, _IMAP );
|
||||
DEFINE_PRIM( _I32, hisize, _IMAP );
|
||||
|
||||
#define _I64MAP _ABSTRACT(hl_int64_map)
|
||||
DEFINE_PRIM( _I64MAP, hi64alloc, _NO_ARG );
|
||||
DEFINE_PRIM( _VOID, hi64set, _I64MAP _I64 _DYN );
|
||||
DEFINE_PRIM( _BOOL, hi64exists, _I64MAP _I64 );
|
||||
DEFINE_PRIM( _DYN, hi64get, _I64MAP _I64 );
|
||||
DEFINE_PRIM( _BOOL, hi64remove, _I64MAP _I64 );
|
||||
DEFINE_PRIM( _ARR, hi64keys, _I64MAP );
|
||||
DEFINE_PRIM( _ARR, hi64values, _I64MAP );
|
||||
DEFINE_PRIM( _VOID, hi64clear, _I64MAP );
|
||||
DEFINE_PRIM( _I32, hi64size, _I64MAP );
|
||||
|
||||
#define _BMAP _ABSTRACT(hl_bytes_map)
|
||||
DEFINE_PRIM( _BMAP, hballoc, _NO_ARG );
|
||||
DEFINE_PRIM( _VOID, hbset, _BMAP _BYTES _DYN );
|
||||
DEFINE_PRIM( _BOOL, hbexists, _BMAP _BYTES );
|
||||
DEFINE_PRIM( _DYN, hbget, _BMAP _BYTES );
|
||||
DEFINE_PRIM( _BOOL, hbremove, _BMAP _BYTES );
|
||||
DEFINE_PRIM( _ARR, hbkeys, _BMAP );
|
||||
DEFINE_PRIM( _ARR, hbvalues, _BMAP );
|
||||
DEFINE_PRIM( _VOID, hbclear, _BMAP );
|
||||
DEFINE_PRIM( _I32, hbsize, _BMAP );
|
||||
|
||||
#define _OMAP _ABSTRACT(hl_obj_map)
|
||||
DEFINE_PRIM( _OMAP, hoalloc, _NO_ARG );
|
||||
DEFINE_PRIM( _VOID, hoset, _OMAP _DYN _DYN );
|
||||
DEFINE_PRIM( _BOOL, hoexists, _OMAP _DYN );
|
||||
DEFINE_PRIM( _DYN, hoget, _OMAP _DYN );
|
||||
DEFINE_PRIM( _BOOL, horemove, _OMAP _DYN );
|
||||
DEFINE_PRIM( _ARR, hokeys, _OMAP );
|
||||
DEFINE_PRIM( _ARR, hovalues, _OMAP );
|
||||
DEFINE_PRIM( _VOID, hoclear, _OMAP );
|
||||
DEFINE_PRIM( _I32, hosize, _OMAP );
|
224
Kha/Backends/Kinc-HL/hl/src/std/maps.h
Normal file
224
Kha/Backends/Kinc-HL/hl/src/std/maps.h
Normal file
@ -0,0 +1,224 @@
|
||||
|
||||
#undef t_map
|
||||
#undef t_entry
|
||||
#undef t_value
|
||||
#undef t_key
|
||||
#define t_key _MKEY_TYPE
|
||||
#define t_map _MNAME(_map)
|
||||
#define t_entry _MNAME(_entry)
|
||||
#define t_value _MNAME(_value)
|
||||
#define _MLIMIT 128
|
||||
#define _MINDEX(m,ckey) ((m)->maxentries < _MLIMIT ? (int)((signed char*)(m)->cells)[ckey] : ((int*)(m)->cells)[ckey])
|
||||
#define _MNEXT(m,ckey) ((m)->maxentries < _MLIMIT ? (int)((signed char*)(m)->nexts)[ckey] : ((int*)(m)->nexts)[ckey])
|
||||
|
||||
typedef struct {
|
||||
void *cells;
|
||||
void *nexts;
|
||||
t_entry *entries;
|
||||
t_value *values;
|
||||
hl_free_list lfree;
|
||||
int ncells;
|
||||
int nentries;
|
||||
int maxentries;
|
||||
} t_map;
|
||||
|
||||
HL_PRIM t_map *_MNAME(alloc)() {
|
||||
t_map *m = (t_map*)hl_gc_alloc_raw(sizeof(t_map));
|
||||
memset(m,0,sizeof(t_map));
|
||||
return m;
|
||||
}
|
||||
|
||||
static vdynamic **_MNAME(find)( t_map *m, t_key key ) {
|
||||
int c, ckey;
|
||||
unsigned int hash;
|
||||
|
||||
if( !m->values ) return NULL;
|
||||
hash = _MNAME(hash)(key);
|
||||
ckey = hash % ((unsigned)m->ncells);
|
||||
c = _MINDEX(m,ckey);
|
||||
while( c >= 0 ) {
|
||||
if( _MMATCH(c) )
|
||||
return &m->values[c].value;
|
||||
c = _MNEXT(m,c);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void _MNAME(resize)( t_map *m );
|
||||
|
||||
static void _MNAME(set_impl)( t_map *m, t_key key, vdynamic *value ) {
|
||||
int c, ckey = 0;
|
||||
unsigned int hash = _MNAME(hash)(key);
|
||||
if( m->values ) {
|
||||
ckey = hash % ((unsigned)m->ncells);
|
||||
c = _MINDEX(m,ckey);
|
||||
while( c >= 0 ) {
|
||||
if( _MMATCH(c) ) {
|
||||
m->values[c].value = value;
|
||||
return;
|
||||
}
|
||||
c = _MNEXT(m,c);
|
||||
}
|
||||
}
|
||||
c = hl_freelist_get(&m->lfree);
|
||||
if( c < 0 ) {
|
||||
_MNAME(resize)(m);
|
||||
ckey = hash % ((unsigned)m->ncells);
|
||||
c = hl_freelist_get(&m->lfree);
|
||||
}
|
||||
_MSET(c);
|
||||
if( m->maxentries < _MLIMIT ) {
|
||||
((signed char*)m->nexts)[c] = ((signed char*)m->cells)[ckey];
|
||||
((signed char*)m->cells)[ckey] = (signed char)c;
|
||||
} else {
|
||||
((int*)m->nexts)[c] = ((int*)m->cells)[ckey];
|
||||
((int*)m->cells)[ckey] = c;
|
||||
}
|
||||
m->values[c].value = value;
|
||||
m->nentries++;
|
||||
}
|
||||
|
||||
static void _MNAME(resize)( t_map *m ) {
|
||||
// save
|
||||
t_map old = *m;
|
||||
|
||||
if( m->nentries != m->maxentries ) hl_error("assert");
|
||||
|
||||
// resize
|
||||
int i = 0;
|
||||
int nentries = m->maxentries ? ((m->maxentries * 3) + 1) >> 1 : H_SIZE_INIT;
|
||||
int ncells = nentries >> 2;
|
||||
|
||||
while( H_PRIMES[i] < ncells ) i++;
|
||||
ncells = H_PRIMES[i];
|
||||
|
||||
int ksize = nentries < _MLIMIT ? 1 : sizeof(int);
|
||||
m->entries = (t_entry*)hl_gc_alloc_noptr(nentries * sizeof(t_entry));
|
||||
m->values = (t_value*)hl_gc_alloc_raw(nentries * sizeof(t_value));
|
||||
m->maxentries = nentries;
|
||||
|
||||
if( old.ncells == ncells && (nentries < _MLIMIT || old.maxentries >= _MLIMIT) ) {
|
||||
// simply expand
|
||||
m->nexts = hl_gc_alloc_noptr(nentries * ksize);
|
||||
memcpy(m->entries,old.entries,old.maxentries * sizeof(t_entry));
|
||||
memcpy(m->values,old.values,old.maxentries * sizeof(t_value));
|
||||
memcpy(m->nexts,old.nexts,old.maxentries * ksize);
|
||||
memset(m->values + old.maxentries, 0, (nentries - old.maxentries) * sizeof(t_value));
|
||||
hl_freelist_add_range(&m->lfree,old.maxentries,m->maxentries - old.maxentries);
|
||||
} else {
|
||||
// expand and remap
|
||||
m->cells = hl_gc_alloc_noptr((ncells + nentries) * ksize);
|
||||
m->nexts = (signed char*)m->cells + ncells * ksize;
|
||||
m->ncells = ncells;
|
||||
m->nentries = 0;
|
||||
memset(m->cells,0xFF,ncells * ksize);
|
||||
memset(m->values, 0, nentries * sizeof(t_value));
|
||||
hl_freelist_init(&m->lfree);
|
||||
hl_freelist_add_range(&m->lfree,0,m->maxentries);
|
||||
for(i=0;i<old.ncells;i++) {
|
||||
int c = old.maxentries < _MLIMIT ? ((signed char*)old.cells)[i] : ((int*)old.cells)[i];
|
||||
while( c >= 0 ) {
|
||||
_MNAME(set_impl)(m,_MKEY((&old),c),old.values[c].value);
|
||||
c = _MNEXT(&old,c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HL_PRIM void _MNAME(set)( t_map *m, t_key key, vdynamic *value ) {
|
||||
_MNAME(set_impl)(m,_MNAME(filter)(key),value);
|
||||
}
|
||||
|
||||
HL_PRIM bool _MNAME(exists)( t_map *m, t_key key ) {
|
||||
return _MNAME(find)(m,_MNAME(filter)(key)) != NULL;
|
||||
}
|
||||
|
||||
HL_PRIM vdynamic* _MNAME(get)( t_map *m, t_key key ) {
|
||||
vdynamic **v = _MNAME(find)(m,_MNAME(filter)(key));
|
||||
if( v == NULL ) return NULL;
|
||||
return *v;
|
||||
}
|
||||
|
||||
HL_PRIM bool _MNAME(remove)( t_map *m, t_key key ) {
|
||||
int c, prev = -1, ckey;
|
||||
unsigned int hash;
|
||||
if( !m->cells ) return false;
|
||||
key = _MNAME(filter)(key);
|
||||
hash = _MNAME(hash)(key);
|
||||
ckey = hash % ((unsigned)m->ncells);
|
||||
c = _MINDEX(m,ckey);
|
||||
while( c >= 0 ) {
|
||||
if( _MMATCH(c) ) {
|
||||
hl_freelist_add(&m->lfree,c);
|
||||
m->nentries--;
|
||||
_MERASE(c);
|
||||
m->values[c].value = NULL;
|
||||
if( m->maxentries < _MLIMIT ) {
|
||||
if( prev >= 0 )
|
||||
((signed char*)m->nexts)[prev] = ((signed char*)m->nexts)[c];
|
||||
else
|
||||
((signed char*)m->cells)[ckey] = ((signed char*)m->nexts)[c];
|
||||
} else {
|
||||
if( prev >= 0 )
|
||||
((int*)m->nexts)[prev] = ((int*)m->nexts)[c];
|
||||
else
|
||||
((int*)m->cells)[ckey] = ((int*)m->nexts)[c];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
prev = c;
|
||||
c = _MNEXT(m,c);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
HL_PRIM varray* _MNAME(keys)( t_map *m ) {
|
||||
varray *a = hl_alloc_array(&hlt_key,m->nentries);
|
||||
t_key *keys = hl_aptr(a,t_key);
|
||||
int p = 0;
|
||||
int i;
|
||||
for(i=0;i<m->ncells;i++) {
|
||||
int c = _MINDEX(m,i);
|
||||
while( c >= 0 ) {
|
||||
keys[p++] = _MKEY(m,c);
|
||||
c = _MNEXT(m,c);
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
HL_PRIM varray* _MNAME(values)( t_map *m ) {
|
||||
varray *a = hl_alloc_array(&hlt_dyn,m->nentries);
|
||||
vdynamic **values = hl_aptr(a,vdynamic*);
|
||||
int p = 0;
|
||||
int i;
|
||||
for(i=0;i<m->ncells;i++) {
|
||||
int c = _MINDEX(m,i);
|
||||
while( c >= 0 ) {
|
||||
values[p++] = m->values[c].value;
|
||||
c = _MNEXT(m,c);
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
HL_PRIM void _MNAME(clear)( t_map *m ) {
|
||||
memset(m,0,sizeof(t_map));
|
||||
}
|
||||
|
||||
HL_PRIM int _MNAME(size)( t_map *m ) {
|
||||
return m->nentries;
|
||||
}
|
||||
|
||||
|
||||
#undef hlt_key
|
||||
#undef hl_hbhash
|
||||
#undef _MKEY_TYPE
|
||||
#undef _MNAME
|
||||
#undef _MMATCH
|
||||
#undef _MKEY
|
||||
#undef _MSET
|
||||
#undef _MERASE
|
||||
#undef _MOLD_KEY
|
||||
#undef _MINDEX
|
||||
#undef _MNEXT
|
155
Kha/Backends/Kinc-HL/hl/src/std/math.c
Normal file
155
Kha/Backends/Kinc-HL/hl/src/std/math.c
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (C)2005-2016 Haxe Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <hl.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifndef NAN
|
||||
static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff};
|
||||
#define NAN (*(const float *) __nan)
|
||||
#endif
|
||||
|
||||
HL_PRIM double hl_nan() {
|
||||
return NAN;
|
||||
}
|
||||
|
||||
HL_PRIM double hl_math_abs( double a ) {
|
||||
return fabs(a);
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_math_isnan( double a ) {
|
||||
#ifdef HL_WIN
|
||||
return isnan(a);
|
||||
#else
|
||||
return a != a; //does not work on some platforms
|
||||
#endif
|
||||
}
|
||||
|
||||
typedef union {
|
||||
double d;
|
||||
struct {
|
||||
unsigned int l;
|
||||
unsigned int h;
|
||||
} i;
|
||||
} qw;
|
||||
|
||||
HL_PRIM bool hl_math_isfinite( double a ) {
|
||||
qw q;
|
||||
unsigned int h, l;
|
||||
if( a != a )
|
||||
return false;
|
||||
q.d = a;
|
||||
h = q.i.h;
|
||||
l = q.i.l;
|
||||
l = l | (h & 0xFFFFF);
|
||||
h = h & 0x7FF00000;
|
||||
return h != 0x7FF00000 || l;
|
||||
}
|
||||
|
||||
HL_PRIM double hl_math_fceil( double d ) {
|
||||
return ceil(d);
|
||||
}
|
||||
|
||||
HL_PRIM double hl_math_fround( double d ) {
|
||||
return floor(d + 0.5);
|
||||
}
|
||||
|
||||
HL_PRIM double hl_math_ffloor( double d ) {
|
||||
return floor(d);
|
||||
}
|
||||
|
||||
HL_PRIM int hl_math_round( double d ) {
|
||||
return (int)hl_math_fround(d);
|
||||
}
|
||||
|
||||
HL_PRIM int hl_math_ceil( double d ) {
|
||||
return (int)hl_math_fceil(d);
|
||||
}
|
||||
|
||||
HL_PRIM int hl_math_floor( double d ) {
|
||||
return (int)hl_math_ffloor(d);
|
||||
}
|
||||
|
||||
HL_PRIM double hl_math_cos( double a ) {
|
||||
return cos(a);
|
||||
}
|
||||
|
||||
HL_PRIM double hl_math_sin( double a ) {
|
||||
return sin(a);
|
||||
}
|
||||
|
||||
HL_PRIM double hl_math_tan( double a ) {
|
||||
return tan(a);
|
||||
}
|
||||
|
||||
HL_PRIM double hl_math_acos( double a ) {
|
||||
return acos(a);
|
||||
}
|
||||
|
||||
HL_PRIM double hl_math_asin( double a ) {
|
||||
return asin(a);
|
||||
}
|
||||
|
||||
HL_PRIM double hl_math_atan( double a ) {
|
||||
return atan(a);
|
||||
}
|
||||
|
||||
HL_PRIM double hl_math_atan2( double a, double b ) {
|
||||
return atan2(a,b);
|
||||
}
|
||||
|
||||
HL_PRIM double hl_math_pow( double a, double b ) {
|
||||
return pow(a,b);
|
||||
}
|
||||
|
||||
HL_PRIM double hl_math_log( double a ) {
|
||||
return log(a);
|
||||
}
|
||||
|
||||
HL_PRIM double hl_math_exp( double a ) {
|
||||
return exp(a);
|
||||
}
|
||||
|
||||
HL_PRIM double hl_math_sqrt( double a ) {
|
||||
return sqrt(a);
|
||||
}
|
||||
|
||||
DEFINE_PRIM(_F64, nan, _NO_ARG);
|
||||
DEFINE_PRIM(_F64, math_abs, _F64);
|
||||
DEFINE_PRIM(_BOOL, math_isnan, _F64);
|
||||
DEFINE_PRIM(_BOOL, math_isfinite, _F64);
|
||||
DEFINE_PRIM(_F64, math_fceil, _F64);
|
||||
DEFINE_PRIM(_F64, math_fround, _F64);
|
||||
DEFINE_PRIM(_F64, math_ffloor, _F64);
|
||||
DEFINE_PRIM(_I32, math_round, _F64);
|
||||
DEFINE_PRIM(_I32, math_ceil, _F64);
|
||||
DEFINE_PRIM(_I32, math_floor, _F64);
|
||||
DEFINE_PRIM(_F64, math_cos, _F64);
|
||||
DEFINE_PRIM(_F64, math_sin, _F64);
|
||||
DEFINE_PRIM(_F64, math_tan, _F64);
|
||||
DEFINE_PRIM(_F64, math_acos, _F64);
|
||||
DEFINE_PRIM(_F64, math_asin, _F64);
|
||||
DEFINE_PRIM(_F64, math_atan, _F64);
|
||||
DEFINE_PRIM(_F64, math_atan2, _F64 _F64);
|
||||
DEFINE_PRIM(_F64, math_pow, _F64 _F64);
|
||||
DEFINE_PRIM(_F64, math_log, _F64);
|
||||
DEFINE_PRIM(_F64, math_exp, _F64);
|
||||
DEFINE_PRIM(_F64, math_sqrt, _F64);
|
1317
Kha/Backends/Kinc-HL/hl/src/std/obj.c
Normal file
1317
Kha/Backends/Kinc-HL/hl/src/std/obj.c
Normal file
File diff suppressed because it is too large
Load Diff
306
Kha/Backends/Kinc-HL/hl/src/std/process.c
Normal file
306
Kha/Backends/Kinc-HL/hl/src/std/process.c
Normal file
@ -0,0 +1,306 @@
|
||||
/*
|
||||
* Copyright (C)2005-2016 Haxe Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <hl.h>
|
||||
|
||||
#if defined(HL_CONSOLE)
|
||||
# include <posix/posix.h>
|
||||
#elif !defined(HL_WIN)
|
||||
# include <sys/types.h>
|
||||
# include <unistd.h>
|
||||
# include <errno.h>
|
||||
# include <signal.h>
|
||||
# if !defined(HL_MAC)
|
||||
# if defined(HL_BSD) || defined (HL_IOS) || defined (HL_TVOS)
|
||||
# include <sys/wait.h>
|
||||
# else
|
||||
# include <wait.h>
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct _vprocess vprocess;
|
||||
|
||||
struct _vprocess {
|
||||
void (*finalize)( vprocess * );
|
||||
#ifdef HL_WIN
|
||||
HANDLE oread;
|
||||
HANDLE eread;
|
||||
HANDLE iwrite;
|
||||
PROCESS_INFORMATION pinf;
|
||||
#else
|
||||
int oread;
|
||||
int eread;
|
||||
int iwrite;
|
||||
int pid;
|
||||
#endif
|
||||
};
|
||||
|
||||
static void process_finalize( vprocess *p ) {
|
||||
# ifdef HL_WIN
|
||||
CloseHandle(p->eread);
|
||||
CloseHandle(p->oread);
|
||||
CloseHandle(p->iwrite);
|
||||
CloseHandle(p->pinf.hProcess);
|
||||
CloseHandle(p->pinf.hThread);
|
||||
# else
|
||||
close(p->eread);
|
||||
close(p->oread);
|
||||
close(p->iwrite);
|
||||
# endif
|
||||
}
|
||||
|
||||
HL_PRIM vprocess *hl_process_run( vbyte *cmd, varray *vargs, bool detached ) {
|
||||
vprocess *p;
|
||||
# ifdef HL_WIN
|
||||
SECURITY_ATTRIBUTES sattr;
|
||||
STARTUPINFO sinf;
|
||||
HANDLE proc = GetCurrentProcess();
|
||||
HANDLE oread,eread,iwrite;
|
||||
if( vargs )
|
||||
return NULL; // should have been pre-processed by toplevel
|
||||
p = (vprocess*)hl_gc_alloc_finalizer(sizeof(vprocess));
|
||||
p->finalize = process_finalize;
|
||||
// startup process
|
||||
sattr.nLength = sizeof(sattr);
|
||||
sattr.bInheritHandle = detached ? FALSE : TRUE;
|
||||
sattr.lpSecurityDescriptor = NULL;
|
||||
memset(&sinf,0,sizeof(sinf));
|
||||
sinf.cb = sizeof(sinf);
|
||||
sinf.dwFlags = detached ? 0 : STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
|
||||
sinf.wShowWindow = SW_HIDE;
|
||||
if( !detached ) {
|
||||
CreatePipe(&oread,&sinf.hStdOutput,&sattr,0);
|
||||
CreatePipe(&eread,&sinf.hStdError,&sattr,0);
|
||||
CreatePipe(&sinf.hStdInput,&iwrite,&sattr,0);
|
||||
DuplicateHandle(proc,oread,proc,&p->oread,0,FALSE,DUPLICATE_SAME_ACCESS);
|
||||
DuplicateHandle(proc,eread,proc,&p->eread,0,FALSE,DUPLICATE_SAME_ACCESS);
|
||||
DuplicateHandle(proc,iwrite,proc,&p->iwrite,0,FALSE,DUPLICATE_SAME_ACCESS);
|
||||
CloseHandle(oread);
|
||||
CloseHandle(eread);
|
||||
CloseHandle(iwrite);
|
||||
} else {
|
||||
p->oread = NULL;
|
||||
p->eread = NULL;
|
||||
p->iwrite = NULL;
|
||||
}
|
||||
if( !CreateProcess(NULL,(uchar*)cmd,NULL,NULL,detached?FALSE:TRUE,detached?CREATE_NEW_CONSOLE:0,NULL,NULL,&sinf,&p->pinf) ) {
|
||||
// handles will be finalized
|
||||
return NULL;
|
||||
}
|
||||
// close unused pipes
|
||||
if( !detached ) {
|
||||
CloseHandle(sinf.hStdOutput);
|
||||
CloseHandle(sinf.hStdError);
|
||||
CloseHandle(sinf.hStdInput);
|
||||
}
|
||||
# else
|
||||
char **argv;
|
||||
if( !vargs ) {
|
||||
argv = (char**)malloc(sizeof(char*)*4);
|
||||
argv[0] = "/bin/sh";
|
||||
argv[1] = "-c";
|
||||
argv[2] = (char*)cmd;
|
||||
argv[3] = NULL;
|
||||
} else {
|
||||
int i;
|
||||
if( vargs->at->kind != HBYTES )
|
||||
return NULL;
|
||||
argv = (char**)malloc(sizeof(char*)*(vargs->size+2));
|
||||
argv[0] = (char*)cmd;
|
||||
for(i=0;i<vargs->size;i++)
|
||||
argv[i+1] = hl_aptr(vargs,char*)[i];
|
||||
argv[i+1] = NULL;
|
||||
}
|
||||
int input[2], output[2], error[2];
|
||||
if( pipe(input) || pipe(output) || pipe(error) )
|
||||
return NULL;
|
||||
p = (vprocess*)hl_gc_alloc_finalizer(sizeof(vprocess));
|
||||
#ifdef HL_TVOS
|
||||
hl_error("hl_process_run() not available for this platform");
|
||||
p->pid = -1;
|
||||
#else
|
||||
p->pid = fork();
|
||||
#endif
|
||||
if( p->pid == -1 ) {
|
||||
close(input[0]);
|
||||
close(input[1]);
|
||||
close(output[0]);
|
||||
close(output[1]);
|
||||
close(error[0]);
|
||||
close(error[1]);
|
||||
return NULL;
|
||||
}
|
||||
// child
|
||||
if( p->pid == 0 ) {
|
||||
close(input[1]);
|
||||
close(output[0]);
|
||||
close(error[0]);
|
||||
dup2(input[0],0);
|
||||
dup2(output[1],1);
|
||||
dup2(error[1],2);
|
||||
#ifdef HL_TVOS
|
||||
hl_error("hl_process_run() not available for this platform");
|
||||
#else
|
||||
execvp(argv[0],argv);
|
||||
#endif
|
||||
fprintf(stderr,"Command not found : %s\n",cmd);
|
||||
exit(1);
|
||||
}
|
||||
// parent
|
||||
close(input[0]);
|
||||
close(output[1]);
|
||||
close(error[1]);
|
||||
p->iwrite = input[1];
|
||||
p->oread = output[0];
|
||||
p->eread = error[0];
|
||||
# endif
|
||||
p->finalize = process_finalize;
|
||||
return p;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_process_stdout_read( vprocess *p, vbyte *str, int pos, int len ) {
|
||||
# ifdef HL_WIN
|
||||
DWORD nbytes;
|
||||
if( !ReadFile(p->oread,str+pos,len,&nbytes,NULL) )
|
||||
return -1;
|
||||
return nbytes;
|
||||
# else
|
||||
int nbytes = read(p->oread,str+pos,len);
|
||||
if( nbytes <= 0 )
|
||||
return -1;
|
||||
return nbytes;
|
||||
# endif
|
||||
}
|
||||
|
||||
HL_PRIM int hl_process_stderr_read( vprocess *p, vbyte *str, int pos, int len ) {
|
||||
# ifdef HL_WIN
|
||||
DWORD nbytes;
|
||||
if( !ReadFile(p->eread,str+pos,len,&nbytes,NULL) )
|
||||
return -1;
|
||||
return nbytes;
|
||||
# else
|
||||
int nbytes = read(p->eread,str+pos,len);
|
||||
if( nbytes <= 0 )
|
||||
return -1;
|
||||
return nbytes;
|
||||
# endif
|
||||
}
|
||||
|
||||
HL_PRIM int hl_process_stdin_write( vprocess *p, vbyte *str, int pos, int len ) {
|
||||
# ifdef HL_WIN
|
||||
DWORD nbytes;
|
||||
if( !WriteFile(p->iwrite,str+pos,len,&nbytes,NULL) )
|
||||
return -1;
|
||||
return nbytes;
|
||||
# else
|
||||
int nbytes = write(p->iwrite,str+pos,len);
|
||||
if( nbytes < 0 )
|
||||
return -1;
|
||||
return nbytes;
|
||||
# endif
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_process_stdin_close( vprocess *p ) {
|
||||
# ifdef HL_WIN
|
||||
if( !CloseHandle(p->iwrite) )
|
||||
return false;
|
||||
# else
|
||||
if( close(p->iwrite) )
|
||||
return false;
|
||||
p->iwrite = -1;
|
||||
# endif
|
||||
return true;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_process_exit( vprocess *p, bool *running ) {
|
||||
# ifdef HL_WIN
|
||||
DWORD rval;
|
||||
if( !running )
|
||||
WaitForSingleObject(p->pinf.hProcess,INFINITE);
|
||||
if( !GetExitCodeProcess(p->pinf.hProcess,&rval) )
|
||||
return -1;
|
||||
if( running ) {
|
||||
*running = rval == STILL_ACTIVE;
|
||||
if( *running ) rval = 0;
|
||||
}
|
||||
return rval;
|
||||
# else
|
||||
int rval = 0;
|
||||
int wret = waitpid(p->pid,&rval,running ? WNOHANG : 0);
|
||||
if( running ) *running = false;
|
||||
if( wret != p->pid ) {
|
||||
if( running ) {
|
||||
if( wret == 0 )
|
||||
*running = true;
|
||||
return 0;
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
if( !WIFEXITED(rval) ) {
|
||||
if( WIFSIGNALED(rval) )
|
||||
return 0x40000000 | WTERMSIG(rval);
|
||||
return -2;
|
||||
}
|
||||
return WEXITSTATUS(rval);
|
||||
# endif
|
||||
}
|
||||
|
||||
HL_PRIM int hl_process_pid( vprocess *p ) {
|
||||
# ifdef HL_WIN
|
||||
return p->pinf.dwProcessId;
|
||||
# else
|
||||
return p->pid;
|
||||
# endif
|
||||
}
|
||||
|
||||
HL_PRIM void hl_process_close( vprocess *p ) {
|
||||
if( !p->finalize ) return;
|
||||
p->finalize = NULL;
|
||||
process_finalize(p);
|
||||
}
|
||||
|
||||
HL_PRIM void hl_process_kill( vprocess *p ) {
|
||||
# ifdef HL_WIN
|
||||
TerminateProcess(p->pinf.hProcess,0xCDCDCDCD);
|
||||
# elif defined(HL_IOS) || defined(HL_TVOS)
|
||||
hl_error("hl_process_kill() not available on this platform");
|
||||
# else
|
||||
kill(p->pid,9);
|
||||
# endif
|
||||
}
|
||||
|
||||
#define _PROCESS _ABSTRACT(hl_process)
|
||||
|
||||
DEFINE_PRIM( _PROCESS, process_run, _BYTES _ARR _BOOL);
|
||||
DEFINE_PRIM( _I32, process_stdout_read, _PROCESS _BYTES _I32 _I32);
|
||||
DEFINE_PRIM( _I32, process_stderr_read, _PROCESS _BYTES _I32 _I32);
|
||||
DEFINE_PRIM( _BOOL, process_stdin_close, _PROCESS);
|
||||
DEFINE_PRIM( _I32, process_stdin_write, _PROCESS _BYTES _I32 _I32);
|
||||
DEFINE_PRIM( _I32, process_exit, _PROCESS _REF(_BOOL));
|
||||
DEFINE_PRIM( _I32, process_pid, _PROCESS);
|
||||
DEFINE_PRIM( _VOID, process_close, _PROCESS);
|
||||
DEFINE_PRIM( _VOID, process_kill, _PROCESS);
|
||||
|
||||
/* ************************************************************************ */
|
120
Kha/Backends/Kinc-HL/hl/src/std/random.c
Normal file
120
Kha/Backends/Kinc-HL/hl/src/std/random.c
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (C)2005-2016 Haxe Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <hl.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#if defined(HL_WIN_DESKTOP)
|
||||
# include <windows.h>
|
||||
# include <process.h>
|
||||
#elif defined(HL_CONSOLE)
|
||||
# include <posix/posix.h>
|
||||
#else
|
||||
# include <sys/time.h>
|
||||
# include <sys/types.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#define NSEEDS 25
|
||||
#define MAX 7
|
||||
|
||||
typedef struct _rnd rnd;
|
||||
|
||||
struct _rnd {
|
||||
unsigned long seeds[NSEEDS];
|
||||
unsigned long cur;
|
||||
};
|
||||
|
||||
static unsigned long mag01[2]={
|
||||
0x0, 0x8ebfd028 // magic, don't change
|
||||
};
|
||||
|
||||
static const unsigned long init_seeds[] = {
|
||||
0x95f24dab, 0x0b685215, 0xe76ccae7, 0xaf3ec239, 0x715fad23,
|
||||
0x24a590ad, 0x69e4b5ef, 0xbf456141, 0x96bc1b7b, 0xa7bdf825,
|
||||
0xc1de75b7, 0x8858a9c9, 0x2da87693, 0xb657f9dd, 0xffdc8a9f,
|
||||
0x8121da71, 0x8b823ecb, 0x885d05f5, 0x4e20cd47, 0x5a9ad5d9,
|
||||
0x512c0c03, 0xea857ccd, 0x4cc1d30f, 0x8891a8a1, 0xa6b7aadb
|
||||
};
|
||||
|
||||
HL_PRIM rnd *hl_rnd_alloc() {
|
||||
return (rnd*)hl_gc_alloc_noptr(sizeof(rnd));
|
||||
}
|
||||
|
||||
HL_PRIM void hl_rnd_set_seed( rnd *r, int s ) {
|
||||
int i;
|
||||
r->cur = 0;
|
||||
memcpy(r->seeds,init_seeds,sizeof(init_seeds));
|
||||
for(i=0;i<NSEEDS;i++)
|
||||
r->seeds[i] ^= s;
|
||||
}
|
||||
|
||||
HL_PRIM rnd *hl_rnd_init_system() {
|
||||
rnd *r = hl_rnd_alloc();
|
||||
int pid = getpid();
|
||||
unsigned int time;
|
||||
#ifdef HL_WIN
|
||||
time = GetTickCount();
|
||||
#else
|
||||
struct timeval t;
|
||||
gettimeofday(&t,NULL);
|
||||
time = t.tv_sec * 1000000 + t.tv_usec;
|
||||
#endif
|
||||
#ifdef HL_DEBUG_REPRO
|
||||
// fixed random seed
|
||||
time = 4644546;
|
||||
pid = 0;
|
||||
#endif
|
||||
hl_rnd_set_seed(r,time ^ (pid | (pid << 16)));
|
||||
return r;
|
||||
}
|
||||
|
||||
HL_PRIM unsigned int hl_rnd_int( rnd *r ) {
|
||||
unsigned int y;
|
||||
int pos = r->cur++;
|
||||
if( pos >= NSEEDS ) {
|
||||
int kk;
|
||||
for(kk=0;kk<NSEEDS-MAX;kk++)
|
||||
r->seeds[kk] = r->seeds[kk+MAX] ^ (r->seeds[kk] >> 1) ^ mag01[r->seeds[kk] % 2];
|
||||
for(;kk<NSEEDS;kk++)
|
||||
r->seeds[kk] = r->seeds[kk+(MAX-NSEEDS)] ^ (r->seeds[kk] >> 1) ^ mag01[r->seeds[kk] % 2];
|
||||
r->cur = 1;
|
||||
pos = 0;
|
||||
}
|
||||
y = r->seeds[pos];
|
||||
y ^= (y << 7) & 0x2b5b2500;
|
||||
y ^= (y << 15) & 0xdb8b0000;
|
||||
y ^= (y >> 16);
|
||||
return y;
|
||||
}
|
||||
|
||||
HL_PRIM double hl_rnd_float( rnd *r ) {
|
||||
double big = 4294967296.0;
|
||||
return ((hl_rnd_int(r) / big + hl_rnd_int(r)) / big + hl_rnd_int(r)) / big;
|
||||
}
|
||||
|
||||
#define _RND _ABSTRACT(hl_random)
|
||||
|
||||
DEFINE_PRIM(_RND,rnd_alloc,_NO_ARG);
|
||||
DEFINE_PRIM(_RND,rnd_init_system, _NO_ARG);
|
||||
DEFINE_PRIM(_VOID,rnd_set_seed, _RND _I32);
|
||||
DEFINE_PRIM(_I32,rnd_int, _RND);
|
||||
DEFINE_PRIM(_F64,rnd_float, _RND);
|
131
Kha/Backends/Kinc-HL/hl/src/std/regexp.c
Normal file
131
Kha/Backends/Kinc-HL/hl/src/std/regexp.c
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (C)2005-2016 Haxe Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <hl.h>
|
||||
|
||||
#define PCRE2_STATIC
|
||||
#include <pcre2.h>
|
||||
|
||||
typedef struct _ereg ereg;
|
||||
|
||||
struct _ereg {
|
||||
void (*finalize)( ereg * );
|
||||
/* The compiled regex code */
|
||||
pcre2_code *regex;
|
||||
/* Pointer to the allocated memory for match data */
|
||||
pcre2_match_data *match_data;
|
||||
/* Number of capture groups */
|
||||
int n_groups;
|
||||
/* Whether the last string was matched successfully */
|
||||
bool matched;
|
||||
};
|
||||
|
||||
static void regexp_finalize( ereg *e ) {
|
||||
pcre2_code_free(e->regex);
|
||||
pcre2_match_data_free(e->match_data);
|
||||
}
|
||||
|
||||
HL_PRIM ereg *hl_regexp_new_options( vbyte *str, vbyte *opts ) {
|
||||
ereg *r;
|
||||
int error_code;
|
||||
size_t error_offset;
|
||||
pcre2_code *p;
|
||||
uchar *o = (uchar*)opts;
|
||||
int options = PCRE2_UCP | PCRE2_UTF | PCRE2_ALT_BSUX | PCRE2_ALLOW_EMPTY_CLASS | PCRE2_MATCH_UNSET_BACKREF;
|
||||
while( *o ) {
|
||||
switch( *o++ ) {
|
||||
case 'i':
|
||||
options |= PCRE2_CASELESS;
|
||||
break;
|
||||
case 's':
|
||||
options |= PCRE2_DOTALL;
|
||||
break;
|
||||
case 'm':
|
||||
options |= PCRE2_MULTILINE;
|
||||
break;
|
||||
case 'u':
|
||||
break;
|
||||
case 'g':
|
||||
options |= PCRE2_UNGREEDY;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
p = pcre2_compile((PCRE2_SPTR)str,PCRE2_ZERO_TERMINATED,options,&error_code,&error_offset,NULL);
|
||||
if( p == NULL ) {
|
||||
hl_buffer *b = hl_alloc_buffer();
|
||||
vdynamic *d = hl_alloc_dynamic(&hlt_bytes);
|
||||
PCRE2_UCHAR error_buffer[256];
|
||||
pcre2_get_error_message(error_code,error_buffer,sizeof(error_buffer));
|
||||
hl_buffer_str(b,USTR("Regexp compilation error : "));
|
||||
hl_buffer_str(b,error_buffer);
|
||||
hl_buffer_str(b,USTR(" in "));
|
||||
hl_buffer_str(b,(uchar*)str);
|
||||
d->v.bytes = (vbyte*)hl_buffer_content(b,NULL);
|
||||
hl_throw(d);
|
||||
}
|
||||
r = (ereg*)hl_gc_alloc_finalizer(sizeof(ereg));
|
||||
r->finalize = regexp_finalize;
|
||||
r->regex = p;
|
||||
r->matched = 0;
|
||||
r->n_groups = 0;
|
||||
pcre2_pattern_info(p,PCRE2_INFO_CAPTURECOUNT,&r->n_groups);
|
||||
r->n_groups++;
|
||||
r->match_data = pcre2_match_data_create_from_pattern(r->regex,NULL);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_regexp_matched_pos( ereg *e, int m, int *len ) {
|
||||
int start;
|
||||
size_t *matches = pcre2_get_ovector_pointer(e->match_data);
|
||||
if( !e->matched )
|
||||
hl_error("Calling regexp_matched_pos() on an unmatched regexp");
|
||||
if( m < 0 || m >= e->n_groups )
|
||||
hl_error("Matched index %d outside bounds",m);
|
||||
start = matches[m*2];
|
||||
if( len ) *len = matches[m*2+1] - start;
|
||||
return start;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_regexp_matched_num( ereg *e ) {
|
||||
if( !e->matched )
|
||||
return -1;
|
||||
else
|
||||
return e->n_groups;
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_regexp_match( ereg *e, vbyte *s, int pos, int len ) {
|
||||
int res = pcre2_match(e->regex,(PCRE2_SPTR)s,pos+len,pos,PCRE2_NO_UTF_CHECK,e->match_data,NULL);
|
||||
e->matched = res >= 0;
|
||||
if( res >= 0 )
|
||||
return true;
|
||||
if( res != PCRE2_ERROR_NOMATCH )
|
||||
hl_error("An error occurred while running pcre2_match()");
|
||||
return false;
|
||||
}
|
||||
|
||||
#define _EREG _ABSTRACT(ereg)
|
||||
DEFINE_PRIM( _EREG, regexp_new_options, _BYTES _BYTES);
|
||||
DEFINE_PRIM( _I32, regexp_matched_pos, _EREG _I32 _REF(_I32));
|
||||
DEFINE_PRIM( _I32, regexp_matched_num, _EREG );
|
||||
DEFINE_PRIM( _BOOL, regexp_match, _EREG _BYTES _I32 _I32);
|
504
Kha/Backends/Kinc-HL/hl/src/std/socket.c
Normal file
504
Kha/Backends/Kinc-HL/hl/src/std/socket.c
Normal file
@ -0,0 +1,504 @@
|
||||
/*
|
||||
* Copyright (C)2005-2016 Haxe Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
|
||||
#define FD_SETSIZE 65536
|
||||
#pragma warning(disable:4548)
|
||||
|
||||
# include <string.h>
|
||||
# define _WINSOCKAPI_
|
||||
# include <hl.h>
|
||||
# include <winsock2.h>
|
||||
# define FDSIZE(n) (sizeof(void*) + (n) * sizeof(SOCKET))
|
||||
# define SHUT_WR SD_SEND
|
||||
# define SHUT_RD SD_RECEIVE
|
||||
# define SHUT_RDWR SD_BOTH
|
||||
typedef int _sockaddr;
|
||||
typedef int socklen_t;
|
||||
|
||||
#else
|
||||
|
||||
#if defined(__ORBIS__) || defined(__NX__)
|
||||
# include <hl.h>
|
||||
# include <posix/posix.h>
|
||||
#else
|
||||
# define _GNU_SOURCE
|
||||
# include <string.h>
|
||||
# include <sys/types.h>
|
||||
# include <sys/socket.h>
|
||||
# include <sys/time.h>
|
||||
# include <netinet/in.h>
|
||||
# include <netinet/tcp.h>
|
||||
# include <arpa/inet.h>
|
||||
# include <unistd.h>
|
||||
# include <netdb.h>
|
||||
# include <poll.h>
|
||||
# include <fcntl.h>
|
||||
# include <errno.h>
|
||||
# include <stdio.h>
|
||||
#endif
|
||||
typedef int SOCKET;
|
||||
# define closesocket close
|
||||
# define SOCKET_ERROR (-1)
|
||||
# define INVALID_SOCKET (-1)
|
||||
typedef unsigned int _sockaddr;
|
||||
#endif
|
||||
|
||||
#ifdef HL_LINUX
|
||||
# include <linux/version.h>
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44)
|
||||
# include <sys/epoll.h>
|
||||
# define HAS_EPOLL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef HAS_EPOLL
|
||||
# define EPOLLIN 0x001
|
||||
# define EPOLLOUT 0x004
|
||||
#endif
|
||||
|
||||
#include <hl.h>
|
||||
|
||||
#if defined(HL_WIN) || defined(HL_MAC) || defined(HL_IOS) || defined(HL_TVOS)
|
||||
# define MSG_NOSIGNAL 0
|
||||
#endif
|
||||
|
||||
typedef struct _hl_socket {
|
||||
SOCKET sock;
|
||||
} hl_socket;
|
||||
|
||||
static int block_error() {
|
||||
#ifdef HL_WIN
|
||||
int err = WSAGetLastError();
|
||||
if( err == WSAEWOULDBLOCK || err == WSAEALREADY || err == WSAETIMEDOUT )
|
||||
#else
|
||||
if( errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS || errno == EALREADY )
|
||||
#endif
|
||||
return -1;
|
||||
return -2;
|
||||
}
|
||||
|
||||
HL_PRIM void hl_socket_init() {
|
||||
#ifdef HL_WIN
|
||||
static bool init_done = false;
|
||||
static WSADATA init_data;
|
||||
if( !init_done ) {
|
||||
WSAStartup(MAKEWORD(2,0),&init_data);
|
||||
init_done = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
HL_PRIM hl_socket *hl_socket_new( bool udp ) {
|
||||
SOCKET s;
|
||||
if( udp )
|
||||
s = socket(AF_INET,SOCK_DGRAM,0);
|
||||
else
|
||||
s = socket(AF_INET,SOCK_STREAM,0);
|
||||
if( s == INVALID_SOCKET )
|
||||
return NULL;
|
||||
# ifdef HL_MAC
|
||||
setsockopt(s,SOL_SOCKET,SO_NOSIGPIPE,NULL,0);
|
||||
# endif
|
||||
# ifdef HL_POSIX
|
||||
// we don't want sockets to be inherited in case of exec
|
||||
{
|
||||
int old = fcntl(s,F_GETFD,0);
|
||||
if( old >= 0 ) fcntl(s,F_SETFD,old|FD_CLOEXEC);
|
||||
}
|
||||
# endif
|
||||
{
|
||||
hl_socket *hs = hl_gc_alloc_noptr(sizeof(hl_socket));
|
||||
hs->sock = s;
|
||||
return hs;
|
||||
}
|
||||
}
|
||||
|
||||
HL_PRIM void hl_socket_close( hl_socket *s ) {
|
||||
if( !s ) return;
|
||||
closesocket(s->sock);
|
||||
s->sock = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_socket_send_char( hl_socket *s, int c ) {
|
||||
char cc;
|
||||
cc = (char)(unsigned char)c;
|
||||
if( !s )
|
||||
return -2;
|
||||
if( send(s->sock,&cc,1,MSG_NOSIGNAL) == SOCKET_ERROR )
|
||||
return block_error();
|
||||
return 1;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_socket_send( hl_socket *s, vbyte *buf, int pos, int len ) {
|
||||
int r;
|
||||
if( !s )
|
||||
return -2;
|
||||
r = send(s->sock, (char*)buf + pos, len, MSG_NOSIGNAL);
|
||||
if( r == SOCKET_ERROR )
|
||||
return block_error();
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
HL_PRIM int hl_socket_recv( hl_socket *s, vbyte *buf, int pos, int len ) {
|
||||
int ret;
|
||||
if( !s )
|
||||
return -2;
|
||||
hl_blocking(true);
|
||||
ret = recv(s->sock, (char*)buf + pos, len, MSG_NOSIGNAL);
|
||||
hl_blocking(false);
|
||||
if( ret == SOCKET_ERROR )
|
||||
return block_error();
|
||||
return ret;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_socket_recv_char( hl_socket *s ) {
|
||||
char cc;
|
||||
int ret;
|
||||
if( !s ) return -2;
|
||||
hl_blocking(true);
|
||||
ret = recv(s->sock,&cc,1,MSG_NOSIGNAL);
|
||||
hl_blocking(false);
|
||||
if( ret == SOCKET_ERROR )
|
||||
return block_error();
|
||||
if( ret == 0 )
|
||||
return -2;
|
||||
return (unsigned char)cc;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_host_resolve( vbyte *host ) {
|
||||
unsigned int ip;
|
||||
hl_blocking(true);
|
||||
ip = inet_addr((char*)host);
|
||||
if( ip == INADDR_NONE ) {
|
||||
struct hostent *h;
|
||||
# if defined(HL_WIN) || defined(HL_MAC) || defined(HL_IOS) || defined(HL_TVOS) || defined (HL_CYGWIN) || defined(HL_CONSOLE)
|
||||
h = gethostbyname((char*)host);
|
||||
# else
|
||||
struct hostent hbase;
|
||||
char buf[1024];
|
||||
int errcode;
|
||||
gethostbyname_r((char*)host,&hbase,buf,1024,&h,&errcode);
|
||||
# endif
|
||||
if( h == NULL ) {
|
||||
hl_blocking(false);
|
||||
return -1;
|
||||
}
|
||||
ip = *((unsigned int*)h->h_addr_list[0]);
|
||||
}
|
||||
hl_blocking(false);
|
||||
return ip;
|
||||
}
|
||||
|
||||
HL_PRIM vbyte *hl_host_to_string( int ip ) {
|
||||
struct in_addr i;
|
||||
*(int*)&i = ip;
|
||||
return (vbyte*)inet_ntoa(i);
|
||||
}
|
||||
|
||||
HL_PRIM vbyte *hl_host_reverse( int ip ) {
|
||||
struct hostent *h;
|
||||
hl_blocking(true);
|
||||
# if defined(HL_WIN) || defined(HL_MAC) || defined(HL_IOS) || defined(HL_TVOS) || defined(HL_CYGWIN) || defined(HL_CONSOLE)
|
||||
h = gethostbyaddr((char *)&ip,4,AF_INET);
|
||||
# elif defined(__ANDROID__)
|
||||
hl_error("hl_host_reverse() not available for this platform");
|
||||
# else
|
||||
struct hostent htmp;
|
||||
int errcode;
|
||||
char buf[1024];
|
||||
gethostbyaddr_r((char*)&ip,4,AF_INET,&htmp,buf,1024,&h,&errcode);
|
||||
# endif
|
||||
hl_blocking(false);
|
||||
if( h == NULL )
|
||||
return NULL;
|
||||
return (vbyte*)h->h_name;
|
||||
}
|
||||
|
||||
HL_PRIM vbyte *hl_host_local() {
|
||||
char buf[256];
|
||||
if( gethostname(buf,256) == SOCKET_ERROR )
|
||||
return NULL;
|
||||
return hl_copy_bytes((vbyte*)buf,(int)strlen(buf)+1);
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_socket_connect( hl_socket *s, int host, int port ) {
|
||||
struct sockaddr_in addr;
|
||||
memset(&addr,0,sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons((unsigned short)port);
|
||||
*(int*)&addr.sin_addr.s_addr = host;
|
||||
if( !s ) return false;
|
||||
hl_blocking(true);
|
||||
if( connect(s->sock,(struct sockaddr*)&addr,sizeof(addr)) != 0 ) {
|
||||
int err = block_error();
|
||||
hl_blocking(false);
|
||||
if( err == -1 ) return true; // in progress
|
||||
return false;
|
||||
}
|
||||
hl_blocking(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_socket_listen( hl_socket *s, int n ) {
|
||||
if( !s ) return false;
|
||||
return listen(s->sock,n) != SOCKET_ERROR;
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_socket_bind( hl_socket *s, int host, int port ) {
|
||||
struct sockaddr_in addr;
|
||||
if( !s ) return false;
|
||||
memset(&addr,0,sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons((unsigned short)port);
|
||||
*(int*)&addr.sin_addr.s_addr = host;
|
||||
#ifndef HL_WIN
|
||||
int opt = 1;
|
||||
setsockopt(s->sock,SOL_SOCKET,SO_REUSEADDR,(char*)&opt,sizeof(opt));
|
||||
#endif
|
||||
return bind(s->sock,(struct sockaddr*)&addr,sizeof(addr)) != SOCKET_ERROR;
|
||||
}
|
||||
|
||||
HL_PRIM hl_socket *hl_socket_accept( hl_socket *s ) {
|
||||
struct sockaddr_in addr;
|
||||
_sockaddr addrlen = sizeof(addr);
|
||||
SOCKET nsock;
|
||||
hl_socket *hs;
|
||||
if( !s ) return NULL;
|
||||
hl_blocking(true);
|
||||
nsock = accept(s->sock,(struct sockaddr*)&addr,&addrlen);
|
||||
hl_blocking(false);
|
||||
if( nsock == INVALID_SOCKET )
|
||||
return NULL;
|
||||
hs = (hl_socket*)hl_gc_alloc_noptr(sizeof(hl_socket));
|
||||
hs->sock = nsock;
|
||||
return hs;
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_socket_peer( hl_socket *s, int *host, int *port ) {
|
||||
struct sockaddr_in addr;
|
||||
_sockaddr addrlen = sizeof(addr);
|
||||
if( !s || getpeername(s->sock,(struct sockaddr*)&addr,&addrlen) == SOCKET_ERROR )
|
||||
return false;
|
||||
*host = *(int*)&addr.sin_addr;
|
||||
*port = ntohs(addr.sin_port);
|
||||
return true;
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_socket_host( hl_socket *s, int *host, int *port ) {
|
||||
struct sockaddr_in addr;
|
||||
_sockaddr addrlen = sizeof(addr);
|
||||
if( !s || getsockname(s->sock,(struct sockaddr*)&addr,&addrlen) == SOCKET_ERROR )
|
||||
return false;
|
||||
*host = *(int*)&addr.sin_addr;
|
||||
*port = ntohs(addr.sin_port);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void init_timeval( double f, struct timeval *t ) {
|
||||
t->tv_usec = (int)((f - (int)f) * 1000000);
|
||||
t->tv_sec = (int)f;
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_socket_set_timeout( hl_socket *s, double t ) {
|
||||
#ifdef HL_WIN
|
||||
int time = (int)(t * 1000);
|
||||
#else
|
||||
struct timeval time;
|
||||
init_timeval(t,&time);
|
||||
#endif
|
||||
if( !s ) return false;
|
||||
if( setsockopt(s->sock,SOL_SOCKET,SO_SNDTIMEO,(char*)&time,sizeof(time)) != 0 )
|
||||
return false;
|
||||
if( setsockopt(s->sock,SOL_SOCKET,SO_RCVTIMEO,(char*)&time,sizeof(time)) != 0 )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_socket_shutdown( hl_socket *s, bool r, bool w ) {
|
||||
if( !s )
|
||||
return false;
|
||||
if( !r && !w )
|
||||
return true;
|
||||
return shutdown(s->sock,r?(w?SHUT_RDWR:SHUT_RD):SHUT_WR) == 0;
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_socket_set_blocking( hl_socket *s, bool b ) {
|
||||
#ifdef HL_WIN
|
||||
unsigned long arg = b?0:1;
|
||||
if( !s ) return false;
|
||||
return ioctlsocket(s->sock,FIONBIO,&arg) == 0;
|
||||
#else
|
||||
int rights;
|
||||
if( !s ) return false;
|
||||
rights = fcntl(s->sock,F_GETFL);
|
||||
if( rights == -1 )
|
||||
return false;
|
||||
if( b )
|
||||
rights &= ~O_NONBLOCK;
|
||||
else
|
||||
rights |= O_NONBLOCK;
|
||||
return fcntl(s->sock,F_SETFL,rights) != -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_socket_set_fast_send( hl_socket *s, bool b ) {
|
||||
int fast = b;
|
||||
if( !s ) return false;
|
||||
return setsockopt(s->sock,IPPROTO_TCP,TCP_NODELAY,(char*)&fast,sizeof(fast)) == 0;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_socket_send_to( hl_socket *s, char *data, int len, int host, int port ) {
|
||||
struct sockaddr_in addr;
|
||||
if( !s ) return -2;
|
||||
memset(&addr,0,sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons((unsigned short)port);
|
||||
*(int*)&addr.sin_addr.s_addr = host;
|
||||
len = sendto(s->sock, data, len, MSG_NOSIGNAL, (struct sockaddr*)&addr, sizeof(addr));
|
||||
if( len == SOCKET_ERROR )
|
||||
return block_error();
|
||||
return len;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_socket_recv_from( hl_socket *s, char *data, int len, int *host, int *port ) {
|
||||
struct sockaddr_in saddr;
|
||||
socklen_t slen = sizeof(saddr);
|
||||
if( !s ) return -2;
|
||||
hl_blocking(true);
|
||||
len = recvfrom(s->sock, data, len, MSG_NOSIGNAL, (struct sockaddr*)&saddr, &slen);
|
||||
hl_blocking(false);
|
||||
if( len == SOCKET_ERROR ) {
|
||||
#ifdef HL_WIN
|
||||
if( WSAGetLastError() == WSAECONNRESET )
|
||||
len = 0;
|
||||
else
|
||||
#endif
|
||||
return block_error();
|
||||
}
|
||||
*host = *(int*)&saddr.sin_addr;
|
||||
*port = ntohs(saddr.sin_port);
|
||||
return len;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_socket_fd_size( int size ) {
|
||||
if( size > FD_SETSIZE )
|
||||
return -1;
|
||||
# ifdef HL_WIN
|
||||
return FDSIZE(size);
|
||||
# else
|
||||
return sizeof(fd_set);
|
||||
# endif
|
||||
}
|
||||
|
||||
static fd_set *make_socket_set( varray *a, char **tmp, int *tmp_size, unsigned int *max ) {
|
||||
fd_set *set = (fd_set*)*tmp;
|
||||
int i, req;
|
||||
if( a == NULL )
|
||||
return set;
|
||||
req = hl_socket_fd_size(a->size);
|
||||
if( *tmp_size < req )
|
||||
return NULL;
|
||||
*tmp_size -= req;
|
||||
*tmp += req;
|
||||
FD_ZERO(set);
|
||||
for(i=0;i<a->size;i++) {
|
||||
hl_socket *s= hl_aptr(a,hl_socket*)[i];
|
||||
if( s== NULL ) break;
|
||||
if( s->sock > *max ) *max = (int)s->sock;
|
||||
FD_SET(s->sock,set);
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
static void make_array_result( fd_set *set, varray *a ) {
|
||||
int i;
|
||||
int pos = 0;
|
||||
hl_socket **aptr = hl_aptr(a,hl_socket*);
|
||||
if( a == NULL )
|
||||
return;
|
||||
for(i=0;i<a->size;i++) {
|
||||
hl_socket *s = aptr[i];
|
||||
if( s == NULL )
|
||||
break;
|
||||
if( FD_ISSET(s->sock,set) )
|
||||
aptr[pos++] = s;
|
||||
}
|
||||
if( pos < a->size )
|
||||
aptr[pos++] = NULL;
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_socket_select( varray *ra, varray *wa, varray *ea, char *tmp, int tmp_size, double timeout ) {
|
||||
struct timeval tval, *tt;
|
||||
fd_set *rs, *ws, *es;
|
||||
unsigned int max = 0;
|
||||
rs = make_socket_set(ra,&tmp,&tmp_size,&max);
|
||||
ws = make_socket_set(wa,&tmp,&tmp_size,&max);
|
||||
es = make_socket_set(ea,&tmp,&tmp_size,&max);
|
||||
if( rs == NULL || ws == NULL || es == NULL )
|
||||
return false;
|
||||
if( timeout < 0 )
|
||||
tt = NULL;
|
||||
else {
|
||||
tt = &tval;
|
||||
init_timeval(timeout,tt);
|
||||
}
|
||||
hl_blocking(true);
|
||||
if( select((int)(max+1),ra?rs:NULL,wa?ws:NULL,ea?es:NULL,tt) == SOCKET_ERROR ) {
|
||||
hl_blocking(false);
|
||||
return false;
|
||||
}
|
||||
hl_blocking(false);
|
||||
make_array_result(rs,ra);
|
||||
make_array_result(ws,wa);
|
||||
make_array_result(es,ea);
|
||||
return true;
|
||||
}
|
||||
|
||||
#define _SOCK _ABSTRACT(hl_socket)
|
||||
DEFINE_PRIM(_VOID,socket_init,_NO_ARG);
|
||||
DEFINE_PRIM(_SOCK,socket_new,_BOOL);
|
||||
DEFINE_PRIM(_VOID,socket_close,_SOCK);
|
||||
DEFINE_PRIM(_I32,socket_send_char,_SOCK _I32);
|
||||
DEFINE_PRIM(_I32,socket_send,_SOCK _BYTES _I32 _I32 );
|
||||
DEFINE_PRIM(_I32,socket_recv,_SOCK _BYTES _I32 _I32 );
|
||||
DEFINE_PRIM(_I32,socket_recv_char, _SOCK);
|
||||
DEFINE_PRIM(_I32,host_resolve,_BYTES);
|
||||
DEFINE_PRIM(_BYTES,host_to_string,_I32);
|
||||
DEFINE_PRIM(_BYTES,host_reverse,_I32);
|
||||
DEFINE_PRIM(_BYTES,host_local,_NO_ARG);
|
||||
DEFINE_PRIM(_BOOL,socket_connect,_SOCK _I32 _I32);
|
||||
DEFINE_PRIM(_BOOL,socket_listen,_SOCK _I32);
|
||||
DEFINE_PRIM(_BOOL,socket_bind,_SOCK _I32 _I32);
|
||||
DEFINE_PRIM(_SOCK,socket_accept,_SOCK);
|
||||
DEFINE_PRIM(_BOOL,socket_peer,_SOCK _REF(_I32) _REF(_I32));
|
||||
DEFINE_PRIM(_BOOL,socket_host,_SOCK _REF(_I32) _REF(_I32));
|
||||
DEFINE_PRIM(_BOOL,socket_set_timeout,_SOCK _F64);
|
||||
DEFINE_PRIM(_BOOL,socket_shutdown,_SOCK _BOOL _BOOL);
|
||||
DEFINE_PRIM(_BOOL,socket_set_blocking,_SOCK _BOOL);
|
||||
DEFINE_PRIM(_BOOL,socket_set_fast_send,_SOCK _BOOL);
|
||||
|
||||
DEFINE_PRIM(_I32, socket_send_to, _SOCK _BYTES _I32 _I32 _I32);
|
||||
DEFINE_PRIM(_I32, socket_recv_from, _SOCK _BYTES _I32 _REF(_I32) _REF(_I32));
|
||||
DEFINE_PRIM(_I32, socket_fd_size, _I32 );
|
||||
DEFINE_PRIM(_BOOL, socket_select, _ARR _ARR _ARR _BYTES _I32 _F64);
|
130
Kha/Backends/Kinc-HL/hl/src/std/sort.h
Normal file
130
Kha/Backends/Kinc-HL/hl/src/std/sort.h
Normal file
@ -0,0 +1,130 @@
|
||||
#define m_sort TID(m_sort)
|
||||
#define ms_compare TID(ms_compare)
|
||||
#define ms_swap TID(ms_swap)
|
||||
#define ms_lower TID(ms_lower)
|
||||
#define ms_upper TID(ms_upper)
|
||||
#define ms_rotate TID(ms_rotate)
|
||||
#define ms_do_merge TID(ms_do_merge)
|
||||
#define merge_sort_rec TID(merge_sort_rec)
|
||||
|
||||
typedef struct {
|
||||
TSORT *arr;
|
||||
vclosure *c;
|
||||
} m_sort;
|
||||
|
||||
static int ms_compare( m_sort *m, int a, int b ) {
|
||||
return m->c->hasValue ? ((int(*)(void*,TSORT,TSORT))m->c->fun)(m->c->value,m->arr[a],m->arr[b]) : ((int(*)(TSORT,TSORT))m->c->fun)(m->arr[a],m->arr[b]);
|
||||
}
|
||||
|
||||
static void ms_swap( m_sort *m, int a, int b ) {
|
||||
TSORT tmp = m->arr[a];
|
||||
m->arr[a] = m->arr[b];
|
||||
m->arr[b] = tmp;
|
||||
}
|
||||
|
||||
static int ms_lower( m_sort *m, int from, int to, int val ) {
|
||||
int len = to - from, half, mid;
|
||||
while( len > 0 ) {
|
||||
half = len>>1;
|
||||
mid = from + half;
|
||||
if( ms_compare(m, mid, val) < 0 ) {
|
||||
from = mid+1;
|
||||
len = len - half -1;
|
||||
} else
|
||||
len = half;
|
||||
}
|
||||
return from;
|
||||
}
|
||||
|
||||
static int ms_upper( m_sort *m, int from, int to, int val ) {
|
||||
int len = to - from, half, mid;
|
||||
while( len > 0 ) {
|
||||
half = len>>1;
|
||||
mid = from + half;
|
||||
if( ms_compare(m, val, mid) < 0 )
|
||||
len = half;
|
||||
else {
|
||||
from = mid+1;
|
||||
len = len - half -1;
|
||||
}
|
||||
}
|
||||
return from;
|
||||
}
|
||||
|
||||
static void ms_rotate( m_sort *m, int from, int mid, int to ) {
|
||||
int n;
|
||||
if( from==mid || mid==to ) return;
|
||||
n = ms_gcd(to - from, mid - from);
|
||||
while (n-- != 0) {
|
||||
TSORT val = m->arr[from+n];
|
||||
int shift = mid - from;
|
||||
int p1 = from+n, p2=from+n+shift;
|
||||
while (p2 != from + n) {
|
||||
m->arr[p1] = m->arr[p2];
|
||||
p1=p2;
|
||||
if( to - p2 > shift) p2 += shift;
|
||||
else p2=from + (shift - (to - p2));
|
||||
}
|
||||
m->arr[p1] = val;
|
||||
}
|
||||
}
|
||||
static void ms_do_merge( m_sort *m, int from, int pivot, int to, int len1, int len2 ) {
|
||||
int first_cut, second_cut, len11, len22, new_mid;
|
||||
if( len1 == 0 || len2==0 )
|
||||
return;
|
||||
if( len1+len2 == 2 ) {
|
||||
if( ms_compare(m, pivot, from) < 0 )
|
||||
ms_swap(m, pivot, from);
|
||||
return;
|
||||
}
|
||||
if (len1 > len2) {
|
||||
len11=len1>>1;
|
||||
first_cut = from + len11;
|
||||
second_cut = ms_lower(m, pivot, to, first_cut);
|
||||
len22 = second_cut - pivot;
|
||||
} else {
|
||||
len22 = len2>>1;
|
||||
second_cut = pivot + len22;
|
||||
first_cut = ms_upper(m, from, pivot, second_cut);
|
||||
len11=first_cut - from;
|
||||
}
|
||||
ms_rotate(m, first_cut, pivot, second_cut);
|
||||
new_mid=first_cut+len22;
|
||||
ms_do_merge(m, from, first_cut, new_mid, len11, len22);
|
||||
ms_do_merge(m, new_mid, second_cut, to, len1 - len11, len2 - len22);
|
||||
}
|
||||
|
||||
static void merge_sort_rec( m_sort *m, int from, int to ) {
|
||||
int middle;
|
||||
if( to - from < 12 ) {
|
||||
// insert sort
|
||||
int i;
|
||||
if( to <= from ) return;
|
||||
for(i=from+1;i<to;i++) {
|
||||
int j = i;
|
||||
while( j > from ) {
|
||||
if( ms_compare(m,j,j-1) < 0 )
|
||||
ms_swap(m,j-1,j);
|
||||
else
|
||||
break;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
middle = (from + to)>>1;
|
||||
merge_sort_rec(m, from, middle);
|
||||
merge_sort_rec(m, middle, to);
|
||||
ms_do_merge(m, from, middle, to, middle-from, to - middle);
|
||||
}
|
||||
|
||||
#undef ms_compare
|
||||
#undef ms_swap
|
||||
#undef ms_lower
|
||||
#undef ms_upper
|
||||
#undef ms_rotate
|
||||
#undef ms_do_merge
|
||||
#undef merge_sort_rec
|
||||
#undef m_sort
|
||||
#undef TSORT
|
||||
#undef TID
|
383
Kha/Backends/Kinc-HL/hl/src/std/string.c
Normal file
383
Kha/Backends/Kinc-HL/hl/src/std/string.c
Normal file
@ -0,0 +1,383 @@
|
||||
/*
|
||||
* Copyright (C)2005-2016 Haxe Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <hl.h>
|
||||
|
||||
HL_PRIM vbyte *hl_itos( int i, int *len ) {
|
||||
uchar tmp[24];
|
||||
int k = (int)usprintf(tmp,24,USTR("%d"),i);
|
||||
*len = k;
|
||||
return hl_copy_bytes((vbyte*)tmp,(k + 1)<<1);
|
||||
}
|
||||
|
||||
HL_PRIM vbyte *hl_ftos( double d, int *len ) {
|
||||
uchar tmp[24];
|
||||
int k;
|
||||
if( d != d ) {
|
||||
*len = 3;
|
||||
return hl_copy_bytes((vbyte*)USTR("NaN"),8);
|
||||
}
|
||||
// don't use the last digit (eg 5.1 = 5.09999..996)
|
||||
// also cut one more digit for some numbers (eg 86.57 and 85.18) <- to fix since we lose one PI digit
|
||||
k = (int)usprintf(tmp,24,USTR("%.15g"),d);
|
||||
# if defined(HL_WIN) && _MSC_VER <= 1800
|
||||
// fix for window : 1e-5 is printed as 1e-005 whereas it's 1e-05 on other platforms
|
||||
// note : this is VS2013 std bug, VS2015 works correctly
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<k;i++)
|
||||
if( tmp[i] == 'e' ) {
|
||||
if( tmp[i+1] == '+' || tmp[i+1] == '-' ) i++;
|
||||
if( tmp[i+1] != '0' || tmp[i+2] != '0' ) break;
|
||||
memmove(tmp+i+1,tmp+i+2,(k-(i+1))*2);
|
||||
k--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
*len = k;
|
||||
return hl_copy_bytes((vbyte*)tmp,(k + 1) << 1);
|
||||
}
|
||||
|
||||
HL_PRIM vbyte *hl_value_to_string( vdynamic *d, int *len ) {
|
||||
if( d == NULL ) {
|
||||
*len = 4;
|
||||
return (vbyte*)USTR("null");
|
||||
}
|
||||
switch( d->t->kind ) {
|
||||
case HI32:
|
||||
return hl_itos(d->v.i,len);
|
||||
case HF64:
|
||||
return hl_ftos(d->v.d,len);
|
||||
default:
|
||||
{
|
||||
hl_buffer *b = hl_alloc_buffer();
|
||||
hl_buffer_val(b, d);
|
||||
return (vbyte*)hl_buffer_content(b,len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HL_PRIM int hl_ucs2length( vbyte *str, int pos ) {
|
||||
return (int)ustrlen((uchar*)(str + pos));
|
||||
}
|
||||
|
||||
HL_PRIM int hl_utf8_length( const vbyte *s, int pos ) {
|
||||
int len = 0;
|
||||
s += pos;
|
||||
while( true ) {
|
||||
unsigned char c = (unsigned)*s;
|
||||
len++;
|
||||
if( c < 0x80 ) {
|
||||
if( c == 0 ) {
|
||||
len--;
|
||||
break;
|
||||
}
|
||||
s++;
|
||||
} else if( c < 0xC0 )
|
||||
return len - 1;
|
||||
else if( c < 0xE0 ) {
|
||||
if( (s[1]&0x80) == 0 ) return len - 1;
|
||||
s += 2;
|
||||
} else if( c < 0xF0 ) {
|
||||
if( ((s[1]&s[2])&0x80) == 0 ) return len - 1;
|
||||
s+=3;
|
||||
} else if( c < 0xF8 ) {
|
||||
if( ((s[1]&s[2]&s[3])&0x80) == 0 ) return len - 1;
|
||||
len++; // surrogate pair
|
||||
s+=4;
|
||||
} else
|
||||
return len;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_from_utf8( uchar *out, int outLen, const char *str ) {
|
||||
int p = 0;
|
||||
unsigned int c, c2, c3;
|
||||
while( p++ < outLen ) {
|
||||
c = *(unsigned char *)str++;
|
||||
if( c < 0x80 ) {
|
||||
if( c == 0 ) break;
|
||||
// nothing
|
||||
} else if( c < 0xE0 ) {
|
||||
c = ((c & 0x3F) << 6) | ((*str++)&0x7F);
|
||||
} else if( c < 0xF0 ) {
|
||||
c2 = (unsigned)*str++;
|
||||
c = ((c & 0x1F) << 12) | ((c2 & 0x7F) << 6) | ((*str++) & 0x7F);
|
||||
} else {
|
||||
c2 = (unsigned)*str++;
|
||||
c3 = (unsigned)*str++;
|
||||
c = (((c & 0x0F) << 18) | ((c2 & 0x7F) << 12) | ((c3 & 0x7F) << 6) | ((*str++) & 0x7F)) - 0x10000;
|
||||
// surrogate pair
|
||||
if( p++ == outLen ) break;
|
||||
*out++ = (uchar)((c >> 10) + 0xD800);
|
||||
*out++ = (uchar)((c & 0x3FF) | 0xDC00);
|
||||
continue;
|
||||
}
|
||||
*out++ = (uchar)c;
|
||||
}
|
||||
*out = 0;
|
||||
return --p;
|
||||
}
|
||||
|
||||
HL_PRIM uchar *hl_to_utf16( const char *str ) {
|
||||
int len = hl_utf8_length((vbyte*)str,0);
|
||||
uchar *out = (uchar*)hl_gc_alloc_noptr((len + 1) * sizeof(uchar));
|
||||
hl_from_utf8(out,len,str);
|
||||
return out;
|
||||
}
|
||||
|
||||
HL_PRIM vbyte* hl_utf8_to_utf16( vbyte *str, int pos, int *size ) {
|
||||
int ulen = hl_utf8_length(str, pos);
|
||||
uchar *s = (uchar*)hl_gc_alloc_noptr((ulen + 1)*sizeof(uchar));
|
||||
hl_from_utf8(s,ulen,(char*)(str+pos));
|
||||
*size = ulen << 1;
|
||||
return (vbyte*)s;
|
||||
}
|
||||
|
||||
#include "unicase.h"
|
||||
|
||||
HL_PRIM vbyte* hl_ucs2_upper( vbyte *str, int pos, int len ) {
|
||||
uchar *cstr = (uchar*)(str + pos);
|
||||
uchar *out = (uchar*)hl_gc_alloc_noptr((len + 1) * sizeof(uchar));
|
||||
int i;
|
||||
uchar *cout = out;
|
||||
memcpy(out,cstr,len << 1);
|
||||
for(i=0;i<len;i++) {
|
||||
unsigned int c = *cstr++;
|
||||
int up = c >> UL_BITS;
|
||||
if( up < UMAX ) {
|
||||
unsigned int c2 = UPPER[up][c&((1<<UL_BITS)-1)];
|
||||
if( c2 != 0 ) *cout = (uchar)c2;
|
||||
}
|
||||
cout++;
|
||||
}
|
||||
*cout = 0;
|
||||
return (vbyte*)out;
|
||||
}
|
||||
|
||||
HL_PRIM vbyte* hl_ucs2_lower( vbyte *str, int pos, int len ) {
|
||||
uchar *cstr = (uchar*)(str + pos);
|
||||
uchar *out = (uchar*)hl_gc_alloc_noptr((len + 1) * sizeof(uchar));
|
||||
uchar *cout = out;
|
||||
int i;
|
||||
memcpy(out,cstr,len << 1);
|
||||
for(i=0;i<len;i++) {
|
||||
unsigned int c = *cstr++;
|
||||
int up = c >> UL_BITS;
|
||||
if( up < LMAX ) {
|
||||
unsigned int c2 = LOWER[up][c&((1<<UL_BITS)-1)];
|
||||
if( c2 != 0 ) *cout = (uchar)c2;
|
||||
}
|
||||
cout++;
|
||||
}
|
||||
*cout = 0;
|
||||
return (vbyte*)out;
|
||||
}
|
||||
|
||||
HL_PRIM vbyte *hl_utf16_to_utf8( vbyte *str, int len, int *size ) {
|
||||
vbyte *out;
|
||||
uchar *c = (uchar*)str;
|
||||
uchar *end = len == 0 ? NULL : c + len;
|
||||
int utf8bytes = 0;
|
||||
int p = 0;
|
||||
while( c != end ) {
|
||||
unsigned int v = (unsigned int)*c;
|
||||
if( v == 0 && end == NULL ) break;
|
||||
if( v < 0x80 )
|
||||
utf8bytes++;
|
||||
else if( v < 0x800 )
|
||||
utf8bytes += 2;
|
||||
else if( v >= 0xD800 && v <= 0xDFFF ) {
|
||||
utf8bytes += 4;
|
||||
c++;
|
||||
} else
|
||||
utf8bytes += 3;
|
||||
c++;
|
||||
}
|
||||
out = hl_gc_alloc_noptr(utf8bytes + 1);
|
||||
c = (uchar*)str;
|
||||
while( c != end ) {
|
||||
unsigned int v = (unsigned int)*c;
|
||||
if( v < 0x80 ) {
|
||||
out[p++] = (vbyte)v;
|
||||
if( v == 0 && end == NULL ) break;
|
||||
} else if( v < 0x800 ) {
|
||||
out[p++] = (vbyte)(0xC0|(v>>6));
|
||||
out[p++] = (vbyte)(0x80|(v&63));
|
||||
} else if( v >= 0xD800 && v <= 0xDFFF ) {
|
||||
int k = ((((int)v - 0xD800) << 10) | (((int)*++c) - 0xDC00)) + 0x10000;
|
||||
out[p++] = (vbyte)(0xF0|(k>>18));
|
||||
out[p++] = (vbyte)(0x80 | ((k >> 12) & 63));
|
||||
out[p++] = (vbyte)(0x80 | ((k >> 6) & 63));
|
||||
out[p++] = (vbyte)(0x80 | (k & 63));
|
||||
} else {
|
||||
out[p++] = (vbyte)(0xE0|(v>>12));
|
||||
out[p++] = (vbyte)(0x80|((v>>6)&63));
|
||||
out[p++] = (vbyte)(0x80|(v&63));
|
||||
}
|
||||
c++;
|
||||
}
|
||||
if( size ) *size = utf8bytes;
|
||||
return out;
|
||||
}
|
||||
|
||||
HL_PRIM char *hl_to_utf8( const uchar *bytes ) {
|
||||
int size;
|
||||
return (char*)hl_utf16_to_utf8((vbyte*)bytes, 0, &size);
|
||||
}
|
||||
|
||||
static void hl_buffer_hex( hl_buffer *b, int c ) {
|
||||
static const uchar *hex = USTR("0123456789ABCDEF");
|
||||
hl_buffer_char(b,'%');
|
||||
hl_buffer_char(b,hex[c>>4]);
|
||||
hl_buffer_char(b,hex[c&0xF]);
|
||||
}
|
||||
|
||||
HL_PRIM vbyte *hl_url_encode( vbyte *str, int *len ) {
|
||||
hl_buffer *b = hl_alloc_buffer();
|
||||
uchar *cstr = (uchar*)str;
|
||||
unsigned int sur;
|
||||
while( true ) {
|
||||
unsigned int c = (unsigned)*cstr++;
|
||||
if( c == 0 ) break;
|
||||
if( (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_' || c == '-' || c == '.' )
|
||||
hl_buffer_char(b,(uchar)c);
|
||||
else {
|
||||
if( c < 0x80 ) {
|
||||
hl_buffer_hex(b,c);
|
||||
} else if( c < 0x800 ) {
|
||||
hl_buffer_hex(b, 0xC0|(c>>6));
|
||||
hl_buffer_hex(b, 0x80|(c&63));
|
||||
} else if( c >= 0xD800 && c <= 0xDBFF ) {
|
||||
sur = (unsigned)*cstr;
|
||||
if( sur >= 0xDC00 && sur < 0xDFFF ) {
|
||||
cstr++;
|
||||
c = ((((int)c - 0xD800) << 10) | ((int)sur - 0xDC00)) + 0x10000;
|
||||
hl_buffer_hex(b, 0xF0|(c>>18));
|
||||
hl_buffer_hex(b, 0x80|((c >> 12) & 63));
|
||||
hl_buffer_hex(b, 0x80|((c >> 6) & 63));
|
||||
hl_buffer_hex(b, 0x80|(c & 63));
|
||||
} else {
|
||||
hl_buffer_hex(b, 0xE0|(c>>12));
|
||||
hl_buffer_hex(b, 0x80|((c>>6)&63));
|
||||
hl_buffer_hex(b, 0x80|(c&63));
|
||||
}
|
||||
} else {
|
||||
hl_buffer_hex(b, 0xE0|(c>>12));
|
||||
hl_buffer_hex(b, 0x80|((c>>6)&63));
|
||||
hl_buffer_hex(b, 0x80|(c&63));
|
||||
}
|
||||
}
|
||||
}
|
||||
return (vbyte*)hl_buffer_content(b,len);
|
||||
}
|
||||
|
||||
static uchar decode_hex_char( uchar c ) {
|
||||
if( c >= '0' && c <= '9' )
|
||||
c -= '0';
|
||||
else if( c >= 'a' && c <= 'f' )
|
||||
c -= 'a' - 10;
|
||||
else if( c >= 'A' && c <= 'F' )
|
||||
c -= 'A' - 10;
|
||||
else
|
||||
return (uchar)-1;
|
||||
return c;
|
||||
}
|
||||
|
||||
static uchar decode_hex( uchar **cstr ) {
|
||||
uchar *c = *cstr;
|
||||
uchar p1 = decode_hex_char(c[0]);
|
||||
uchar p2;
|
||||
if( p1 == (uchar)-1 ) return p1;
|
||||
p2 = decode_hex_char(c[1]);
|
||||
if( p2 == (uchar)-1 ) return p2;
|
||||
*cstr = c + 2;
|
||||
return (p1 << 4) | p2;
|
||||
}
|
||||
|
||||
HL_PRIM vbyte *hl_url_decode( vbyte *str, int *len ) {
|
||||
hl_buffer *b = hl_alloc_buffer();
|
||||
uchar *cstr = (uchar*)str;
|
||||
while( true ) {
|
||||
uchar c = *cstr++;
|
||||
if( c == 0 )
|
||||
return (vbyte*)hl_buffer_content(b,len);
|
||||
if( c == '+' )
|
||||
c = ' ';
|
||||
else if( c == '%' ) {
|
||||
uchar p1 = decode_hex(&cstr);
|
||||
if( p1 == (uchar)-1 ) {
|
||||
hl_buffer_char(b,'%');
|
||||
continue;
|
||||
}
|
||||
if( p1 < 0x80 ) {
|
||||
c = p1;
|
||||
} else if( p1 < 0xE0 ) {
|
||||
uchar p2;
|
||||
if( *cstr++ != '%' ) break;
|
||||
p2 = decode_hex(&cstr);
|
||||
if( p2 < 0 ) break;
|
||||
c = ((p1 & 0x3F) << 6) | (p2&0x7F);
|
||||
} else if( p1 < 0xF0 ) {
|
||||
uchar p2, p3;
|
||||
if( *cstr++ != '%' ) break;
|
||||
p2 = decode_hex(&cstr);
|
||||
if( p2 < 0 ) break;
|
||||
if( *cstr++ != '%' ) break;
|
||||
p3 = decode_hex(&cstr);
|
||||
if( p3 < 0 ) break;
|
||||
c = ((p1 & 0x1F) << 12) | ((p2 & 0x7F) << 6) | (p3 & 0x7F);
|
||||
} else {
|
||||
int k;
|
||||
uchar p2, p3, p4;
|
||||
if( *cstr++ != '%' ) break;
|
||||
p2 = decode_hex(&cstr);
|
||||
if( p2 < 0 ) break;
|
||||
if( *cstr++ != '%' ) break;
|
||||
p3 = decode_hex(&cstr);
|
||||
if( p3 < 0 ) break;
|
||||
if( *cstr++ != '%' ) break;
|
||||
p4 = decode_hex(&cstr);
|
||||
if( p4 < 0 ) break;
|
||||
k = (((p1 & 0x0F) << 18) | ((p2 & 0x7F) << 12) | ((p3 & 0x7F) << 6) | (p4 & 0x7F)) - 0x10000;
|
||||
hl_buffer_char(b,(uchar)((k >> 10) + 0xD800));
|
||||
c = (uchar)((k & 0x3FF) | 0xDC00);
|
||||
}
|
||||
}
|
||||
hl_buffer_char(b,c);
|
||||
}
|
||||
hl_error("Malformed URL encoded");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DEFINE_PRIM(_BYTES,itos,_I32 _REF(_I32));
|
||||
DEFINE_PRIM(_BYTES,ftos,_F64 _REF(_I32));
|
||||
DEFINE_PRIM(_BYTES,value_to_string,_DYN _REF(_I32));
|
||||
DEFINE_PRIM(_I32,ucs2length,_BYTES _I32);
|
||||
DEFINE_PRIM(_BYTES,utf8_to_utf16,_BYTES _I32 _REF(_I32));
|
||||
DEFINE_PRIM(_BYTES,utf16_to_utf8,_BYTES _I32 _REF(_I32));
|
||||
DEFINE_PRIM(_BYTES,ucs2_upper,_BYTES _I32 _I32);
|
||||
DEFINE_PRIM(_BYTES,ucs2_lower,_BYTES _I32 _I32);
|
||||
DEFINE_PRIM(_BYTES,url_encode,_BYTES _REF(_I32));
|
||||
DEFINE_PRIM(_BYTES,url_decode,_BYTES _REF(_I32));
|
||||
|
720
Kha/Backends/Kinc-HL/hl/src/std/sys.c
Normal file
720
Kha/Backends/Kinc-HL/hl/src/std/sys.c
Normal file
@ -0,0 +1,720 @@
|
||||
/*
|
||||
* Copyright (C)2005-2016 Haxe Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <hl.h>
|
||||
|
||||
#ifdef HL_CONSOLE
|
||||
# include <posix/posix.h>
|
||||
#endif
|
||||
#if !defined(HL_CONSOLE) || defined(HL_WIN_DESKTOP)
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <locale.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if defined(HL_WIN)
|
||||
# include <windows.h>
|
||||
# include <direct.h>
|
||||
# include <conio.h>
|
||||
# include <fcntl.h>
|
||||
# include <io.h>
|
||||
# define getenv _wgetenv
|
||||
# define putenv _wputenv
|
||||
# define getcwd(buf,size) (void*)(int_val)GetCurrentDirectoryW(size,buf)
|
||||
# define chdir !SetCurrentDirectoryW
|
||||
# define system _wsystem
|
||||
typedef struct _stat32 pstat;
|
||||
# define stat _wstat32
|
||||
# define unlink _wunlink
|
||||
# define rename _wrename
|
||||
# define mkdir(path,mode) _wmkdir(path)
|
||||
# define rmdir _wrmdir
|
||||
#else
|
||||
# include <errno.h>
|
||||
# include <unistd.h>
|
||||
# include <limits.h>
|
||||
# include <sys/time.h>
|
||||
# include <dirent.h>
|
||||
# include <termios.h>
|
||||
# include <sys/times.h>
|
||||
# include <sys/wait.h>
|
||||
# include <locale.h>
|
||||
# define HL_UTF8PATH
|
||||
typedef struct stat pstat;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HL_UTF8PATH
|
||||
typedef char pchar;
|
||||
#define pstrchr strchr
|
||||
#define pstrlen strlen
|
||||
#else
|
||||
typedef uchar pchar;
|
||||
#define pstrchr wcschr
|
||||
#define pstrlen ustrlen
|
||||
#endif
|
||||
|
||||
#ifdef HL_MAC
|
||||
# include <sys/syslimits.h>
|
||||
# include <limits.h>
|
||||
# include <mach-o/dyld.h>
|
||||
#endif
|
||||
|
||||
#ifndef CLK_TCK
|
||||
# define CLK_TCK 100
|
||||
#endif
|
||||
|
||||
static pchar *pstrdup( const pchar *s, int len ) {
|
||||
pchar *ret;
|
||||
if( len < 0 ) len = (int)pstrlen(s);
|
||||
ret = (pchar*)hl_copy_bytes((vbyte*)s,sizeof(pchar)*(len+1));;
|
||||
ret[len] = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_sys_utf8_path() {
|
||||
#ifdef HL_UTF8PATH
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
HL_PRIM vbyte *hl_sys_string() {
|
||||
#if defined(HL_CONSOLE)
|
||||
return (vbyte*)sys_platform_name();
|
||||
#elif defined(HL_WIN) || defined(HL_CYGWIN) || defined(HL_MINGW)
|
||||
return (vbyte*)USTR("Windows");
|
||||
#elif defined(HL_BSD)
|
||||
return (vbyte*)USTR("BSD");
|
||||
#elif defined(HL_MAC)
|
||||
return (vbyte*)USTR("Mac");
|
||||
#elif defined(HL_IOS)
|
||||
return (vbyte*)USTR("iOS");
|
||||
#elif defined(HL_TVOS)
|
||||
return (vbyte*)USTR("tvOS");
|
||||
#elif defined(HL_ANDROID)
|
||||
return (vbyte*)USTR("Android");
|
||||
#elif defined(HL_GNUKBSD)
|
||||
return (vbyte*)USTR("GNU/kFreeBSD");
|
||||
#elif defined(HL_LINUX)
|
||||
return (vbyte*)USTR("Linux");
|
||||
#else
|
||||
#error Unknown system string
|
||||
#endif
|
||||
}
|
||||
|
||||
HL_PRIM vbyte *hl_sys_locale() {
|
||||
#if defined(HL_WIN_DESKTOP)
|
||||
wchar_t loc[LOCALE_NAME_MAX_LENGTH];
|
||||
int len = GetSystemDefaultLocaleName(loc,LOCALE_NAME_MAX_LENGTH);
|
||||
return len == 0 ? NULL : hl_copy_bytes((vbyte*)loc,(len+1)*2);
|
||||
#elif defined(HL_CONSOLE)
|
||||
return (vbyte*)sys_get_user_lang();
|
||||
#else
|
||||
return (vbyte*)getenv("LANG");
|
||||
#endif
|
||||
}
|
||||
|
||||
#define PR_WIN_UTF8 1
|
||||
#define PR_AUTO_FLUSH 2
|
||||
static int print_flags = PR_AUTO_FLUSH;
|
||||
|
||||
HL_PRIM int hl_sys_set_flags( int flags ) {
|
||||
return print_flags = flags;
|
||||
}
|
||||
|
||||
HL_PRIM void hl_sys_print( vbyte *msg ) {
|
||||
hl_blocking(true);
|
||||
# ifdef HL_XBO
|
||||
OutputDebugStringW((LPCWSTR)msg);
|
||||
# else
|
||||
# ifdef HL_WIN_DESKTOP
|
||||
if( print_flags & PR_WIN_UTF8 ) _setmode(_fileno(stdout),_O_U8TEXT);
|
||||
# endif
|
||||
uprintf(USTR("%s"),(uchar*)msg);
|
||||
if( print_flags & PR_AUTO_FLUSH ) fflush(stdout);
|
||||
# ifdef HL_WIN_DESKTOP
|
||||
if( print_flags & PR_WIN_UTF8 ) _setmode(_fileno(stdout),_O_TEXT);
|
||||
# endif
|
||||
|
||||
# endif
|
||||
hl_blocking(false);
|
||||
}
|
||||
|
||||
|
||||
static void *f_before_exit = NULL;
|
||||
static void *f_profile_event = NULL;
|
||||
HL_PRIM void hl_setup_profiler( void *profile_event, void *before_exit ) {
|
||||
f_before_exit = before_exit;
|
||||
f_profile_event = profile_event;
|
||||
}
|
||||
|
||||
HL_PRIM void hl_sys_profile_event( int code, vbyte *data, int dataLen ) {
|
||||
if( f_profile_event ) ((void(*)(int,vbyte*,int))f_profile_event)(code,data,dataLen);
|
||||
}
|
||||
|
||||
HL_PRIM void hl_sys_exit( int code ) {
|
||||
if( f_before_exit ) ((void(*)())f_before_exit)();
|
||||
exit(code);
|
||||
}
|
||||
|
||||
#ifdef HL_DEBUG_REPRO
|
||||
static double CURT = 0;
|
||||
#endif
|
||||
|
||||
HL_PRIM double hl_sys_time() {
|
||||
#ifdef HL_DEBUG_REPRO
|
||||
CURT += 0.001;
|
||||
return CURT;
|
||||
#endif
|
||||
#ifdef HL_WIN
|
||||
#define EPOCH_DIFF (134774*24*60*60.0)
|
||||
static double time_diff = 0.;
|
||||
static double freq = 0.;
|
||||
LARGE_INTEGER time;
|
||||
|
||||
if( freq == 0 ) {
|
||||
QueryPerformanceFrequency(&time);
|
||||
freq = (double)time.QuadPart;
|
||||
}
|
||||
QueryPerformanceCounter(&time);
|
||||
if( time_diff == 0 ) {
|
||||
FILETIME ft;
|
||||
LARGE_INTEGER start_time;
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
start_time.LowPart = ft.dwLowDateTime;
|
||||
start_time.HighPart = ft.dwHighDateTime;
|
||||
time_diff = (((double)start_time.QuadPart) / 10000000.0) - (((double)time.QuadPart) / freq) - EPOCH_DIFF;
|
||||
}
|
||||
return time_diff + ((double)time.QuadPart) / freq;
|
||||
#else
|
||||
struct timeval tv;
|
||||
if( gettimeofday(&tv,NULL) != 0 )
|
||||
return 0.;
|
||||
return tv.tv_sec + ((double)tv.tv_usec) / 1000000.0;
|
||||
#endif
|
||||
}
|
||||
|
||||
HL_PRIM vbyte *hl_sys_get_env( vbyte *v ) {
|
||||
return (vbyte*)getenv((pchar*)v);
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_sys_put_env( vbyte *e, vbyte *v ) {
|
||||
#if defined(HL_WIN)
|
||||
hl_buffer *b = hl_alloc_buffer();
|
||||
hl_buffer_str(b,(uchar*)e);
|
||||
hl_buffer_char(b,'=');
|
||||
if( v ) hl_buffer_str(b,(uchar*)v);
|
||||
return putenv(hl_buffer_content(b,NULL)) == 0;
|
||||
#else
|
||||
if( v == NULL ) return unsetenv((char*)e) == 0;
|
||||
return setenv((char*)e,(char*)v,1) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HL_MAC
|
||||
# define environ (*_NSGetEnviron())
|
||||
#endif
|
||||
|
||||
#ifdef HL_WIN_DESKTOP
|
||||
# undef environ
|
||||
# define environ _wenviron
|
||||
#else
|
||||
extern pchar **environ;
|
||||
#endif
|
||||
|
||||
HL_PRIM varray *hl_sys_env() {
|
||||
varray *a;
|
||||
pchar **e = environ;
|
||||
pchar **arr;
|
||||
int count = 0;
|
||||
# ifdef HL_WIN_DESKTOP
|
||||
if( e == NULL ) {
|
||||
_wgetenv(L"");
|
||||
e = environ;
|
||||
}
|
||||
# endif
|
||||
while( *e ) {
|
||||
pchar *x = pstrchr(*e,'=');
|
||||
if( x == NULL ) {
|
||||
e++;
|
||||
continue;
|
||||
}
|
||||
count++;
|
||||
e++;
|
||||
}
|
||||
a = hl_alloc_array(&hlt_bytes,count*2);
|
||||
e = environ;
|
||||
arr = hl_aptr(a,pchar*);
|
||||
while( *e ) {
|
||||
pchar *x = pstrchr(*e,'=');
|
||||
if( x == NULL ) {
|
||||
e++;
|
||||
continue;
|
||||
}
|
||||
*arr++ = pstrdup(*e,(int)(x - *e));
|
||||
*arr++ = pstrdup(x+1,-1);
|
||||
e++;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
HL_PRIM void hl_sys_sleep( double f ) {
|
||||
hl_blocking(true);
|
||||
#if defined(HL_WIN)
|
||||
Sleep((DWORD)(f * 1000));
|
||||
#else
|
||||
struct timespec t;
|
||||
t.tv_sec = (int)f;
|
||||
t.tv_nsec = (int)((f - t.tv_sec) * 1e9);
|
||||
nanosleep(&t,NULL);
|
||||
#endif
|
||||
hl_blocking(false);
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_sys_set_time_locale( vbyte *l ) {
|
||||
#ifdef HL_POSIX
|
||||
locale_t lc, old;
|
||||
lc = newlocale(LC_TIME_MASK,(char*)l,NULL);
|
||||
if( lc == NULL ) return false;
|
||||
old = uselocale(lc);
|
||||
if( old == NULL ) {
|
||||
freelocale(lc);
|
||||
return false;
|
||||
}
|
||||
if( old != LC_GLOBAL_LOCALE )
|
||||
freelocale(old);
|
||||
return true;
|
||||
#else
|
||||
return setlocale(LC_TIME,(char*)l) != NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
HL_PRIM vbyte *hl_sys_get_cwd() {
|
||||
pchar buf[256];
|
||||
int l;
|
||||
if( getcwd(buf,256) == NULL )
|
||||
return NULL;
|
||||
l = (int)pstrlen(buf);
|
||||
if( buf[l-1] != '/' && buf[l-1] != '\\' ) {
|
||||
buf[l] = '/';
|
||||
buf[l+1] = 0;
|
||||
}
|
||||
return (vbyte*)pstrdup(buf,-1);
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_sys_set_cwd( vbyte *dir ) {
|
||||
return chdir((pchar*)dir) == 0;
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_sys_is64() {
|
||||
#ifdef HL_64
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
HL_PRIM int hl_sys_command( vbyte *cmd ) {
|
||||
#if defined(HL_WIN)
|
||||
int ret;
|
||||
hl_blocking(true);
|
||||
ret = system((pchar*)cmd);
|
||||
hl_blocking(false);
|
||||
return ret;
|
||||
#else
|
||||
int status;
|
||||
hl_blocking(true);
|
||||
#if defined(HL_IOS) || defined(HL_TVOS)
|
||||
status = 0;
|
||||
hl_error("hl_sys_command() not available on this platform");
|
||||
#else
|
||||
status = system((pchar*)cmd);
|
||||
#endif
|
||||
hl_blocking(false);
|
||||
return WEXITSTATUS(status) | (WTERMSIG(status) << 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_sys_exists( vbyte *path ) {
|
||||
pstat st;
|
||||
return stat((pchar*)path,&st) == 0;
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_sys_delete( vbyte *path ) {
|
||||
return unlink((pchar*)path) == 0;
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_sys_rename( vbyte *path, vbyte *newname ) {
|
||||
return rename((pchar*)path,(pchar*)newname) == 0;
|
||||
}
|
||||
|
||||
HL_PRIM varray *hl_sys_stat( vbyte *path ) {
|
||||
pstat s;
|
||||
varray *a;
|
||||
int *i;
|
||||
if( stat((pchar*)path,&s) != 0 )
|
||||
return NULL;
|
||||
a = hl_alloc_array(&hlt_i32,12);
|
||||
i = hl_aptr(a,int);
|
||||
*i++ = s.st_gid;
|
||||
*i++ = s.st_uid;
|
||||
*i++ = s.st_atime;
|
||||
*i++ = s.st_mtime;
|
||||
*i++ = s.st_ctime;
|
||||
*i++ = s.st_size;
|
||||
*i++ = s.st_dev;
|
||||
*i++ = s.st_ino;
|
||||
*i++ = s.st_nlink;
|
||||
*i++ = s.st_rdev;
|
||||
*i++ = s.st_mode;
|
||||
return a;
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_sys_is_dir( vbyte *path ) {
|
||||
pstat s;
|
||||
if( stat((pchar*)path,&s) != 0 )
|
||||
return false;
|
||||
return (s.st_mode & S_IFDIR) != 0;
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_sys_create_dir( vbyte *path, int mode ) {
|
||||
return mkdir((pchar*)path,mode) == 0;
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_sys_remove_dir( vbyte *path ) {
|
||||
return rmdir((pchar*)path) == 0;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_sys_getpid() {
|
||||
#ifdef HL_WIN
|
||||
return GetCurrentProcessId();
|
||||
#else
|
||||
return getpid();
|
||||
#endif
|
||||
}
|
||||
|
||||
HL_PRIM double hl_sys_cpu_time() {
|
||||
#if defined(HL_WIN)
|
||||
FILETIME unused;
|
||||
FILETIME stime;
|
||||
FILETIME utime;
|
||||
if( !GetProcessTimes(GetCurrentProcess(),&unused,&unused,&stime,&utime) )
|
||||
return 0.;
|
||||
return ((double)(utime.dwHighDateTime+stime.dwHighDateTime)) * 65.536 * 6.5536 + (((double)utime.dwLowDateTime + (double)stime.dwLowDateTime) / 10000000);
|
||||
#else
|
||||
struct tms t = {0};
|
||||
times(&t);
|
||||
return ((double)(t.tms_utime + t.tms_stime)) / CLK_TCK;
|
||||
#endif
|
||||
}
|
||||
|
||||
HL_PRIM double hl_sys_thread_cpu_time() {
|
||||
#if defined(HL_WIN)
|
||||
FILETIME unused;
|
||||
FILETIME utime;
|
||||
if( !GetThreadTimes(GetCurrentThread(),&unused,&unused,&unused,&utime) )
|
||||
return 0.;
|
||||
return ((double)utime.dwHighDateTime) * 65.536 * 6.5536 + (((double)utime.dwLowDateTime) / 10000000);
|
||||
#elif defined(HL_MAC) || defined(HL_CONSOLE)
|
||||
hl_error("sys_thread_cpu_time not implemented on this platform");
|
||||
return 0.;
|
||||
#else
|
||||
struct timespec t;
|
||||
if( clock_gettime(CLOCK_THREAD_CPUTIME_ID,&t) )
|
||||
return 0.;
|
||||
return t.tv_sec + t.tv_nsec * 1e-9;
|
||||
#endif
|
||||
}
|
||||
|
||||
HL_PRIM varray *hl_sys_read_dir( vbyte *_path ) {
|
||||
pchar *path = (pchar*)_path;
|
||||
int count = 0;
|
||||
int pos = 0;
|
||||
varray *a = NULL;
|
||||
pchar **current = NULL;
|
||||
|
||||
#ifdef HL_WIN
|
||||
WIN32_FIND_DATAW d;
|
||||
HANDLE handle;
|
||||
hl_buffer *b = hl_alloc_buffer();
|
||||
int len = (int)pstrlen(path);
|
||||
hl_buffer_str(b,path);
|
||||
if( len && path[len-1] != '/' && path[len-1] != '\\' )
|
||||
hl_buffer_str(b,USTR("/*.*"));
|
||||
else
|
||||
hl_buffer_str(b,USTR("*.*"));
|
||||
path = hl_buffer_content(b,NULL);
|
||||
handle = FindFirstFileW(path,&d);
|
||||
if( handle == INVALID_HANDLE_VALUE )
|
||||
return NULL;
|
||||
while( true ) {
|
||||
// skip magic dirs
|
||||
if( d.cFileName[0] != '.' || (d.cFileName[1] != 0 && (d.cFileName[1] != '.' || d.cFileName[2] != 0)) ) {
|
||||
if( pos == count ) {
|
||||
int ncount = count == 0 ? 16 : count * 2;
|
||||
varray *narr = hl_alloc_array(&hlt_bytes,ncount);
|
||||
pchar **ncur = hl_aptr(narr,pchar*);
|
||||
memcpy(ncur,current,count*sizeof(void*));
|
||||
current = ncur;
|
||||
a = narr;
|
||||
count = ncount;
|
||||
}
|
||||
current[pos++] = pstrdup(d.cFileName,-1);
|
||||
}
|
||||
if( !FindNextFileW(handle,&d) )
|
||||
break;
|
||||
}
|
||||
FindClose(handle);
|
||||
#else
|
||||
DIR *d;
|
||||
struct dirent *e;
|
||||
d = opendir(path);
|
||||
if( d == NULL )
|
||||
return NULL;
|
||||
while( true ) {
|
||||
e = readdir(d);
|
||||
if( e == NULL )
|
||||
break;
|
||||
// skip magic dirs
|
||||
if( e->d_name[0] == '.' && (e->d_name[1] == 0 || (e->d_name[1] == '.' && e->d_name[2] == 0)) )
|
||||
continue;
|
||||
if( pos == count ) {
|
||||
int ncount = count == 0 ? 16 : count * 2;
|
||||
varray *narr = hl_alloc_array(&hlt_bytes,ncount);
|
||||
pchar **ncur = hl_aptr(narr,pchar*);
|
||||
memcpy(ncur,current,count*sizeof(void*));
|
||||
current = ncur;
|
||||
a = narr;
|
||||
count = ncount;
|
||||
}
|
||||
current[pos++] = pstrdup(e->d_name,-1);
|
||||
}
|
||||
closedir(d);
|
||||
#endif
|
||||
if( a == NULL ) a = hl_alloc_array(&hlt_bytes,0);
|
||||
a->size = pos;
|
||||
return a;
|
||||
}
|
||||
|
||||
HL_PRIM vbyte *hl_sys_full_path( vbyte *path ) {
|
||||
#if defined(HL_WIN)
|
||||
pchar out[MAX_PATH+1];
|
||||
int len, i, last;
|
||||
HANDLE handle;
|
||||
WIN32_FIND_DATA data;
|
||||
const char sep = '\\';
|
||||
if( GetFullPathNameW((pchar*)path,MAX_PATH+1,out,NULL) == 0 )
|
||||
return NULL;
|
||||
len = (int)ustrlen(out);
|
||||
i = 0;
|
||||
|
||||
if (len >= 2 && out[1] == ':') {
|
||||
// convert drive letter to uppercase
|
||||
if (out[0] >= 'a' && out[0] <= 'z')
|
||||
out[0] += (pchar)('A' - 'a');
|
||||
if (len >= 3 && out[2] == sep)
|
||||
i = 3;
|
||||
else
|
||||
i = 2;
|
||||
}
|
||||
|
||||
last = i;
|
||||
|
||||
while (i < len) {
|
||||
// skip until separator
|
||||
while (i < len && out[i] != sep)
|
||||
i++;
|
||||
|
||||
// temporarily strip string to last found component
|
||||
out[i] = 0;
|
||||
|
||||
// get actual file/dir name with proper case
|
||||
if ((handle = FindFirstFileW(out, &data)) != INVALID_HANDLE_VALUE) {
|
||||
// replace the component with proper case
|
||||
memcpy(out + last, data.cFileName, i - last);
|
||||
FindClose(handle);
|
||||
}
|
||||
|
||||
// if we're not at the end, restore the path
|
||||
if (i < len)
|
||||
out[i] = sep;
|
||||
|
||||
// advance
|
||||
i++;
|
||||
last = i;
|
||||
}
|
||||
return (vbyte*)pstrdup(out,len);
|
||||
#else
|
||||
pchar buf[PATH_MAX];
|
||||
if( realpath((pchar*)path,buf) == NULL )
|
||||
return NULL;
|
||||
return (vbyte*)pstrdup(buf,-1);
|
||||
#endif
|
||||
}
|
||||
|
||||
HL_PRIM vbyte *hl_sys_exe_path() {
|
||||
#if defined(HL_WIN)
|
||||
pchar path[MAX_PATH];
|
||||
if( GetModuleFileNameW(NULL,path,MAX_PATH) == 0 )
|
||||
return NULL;
|
||||
return (vbyte*)pstrdup(path,-1);
|
||||
#elif defined(HL_MAC)
|
||||
pchar path[PATH_MAX+1];
|
||||
uint32_t path_len = PATH_MAX;
|
||||
if( _NSGetExecutablePath(path, &path_len) )
|
||||
return NULL;
|
||||
return (vbyte*)pstrdup(path,-1);
|
||||
#elif defined(HL_CONSOLE)
|
||||
return sys_exe_path();
|
||||
#else
|
||||
const pchar *p = getenv("_");
|
||||
if( p != NULL )
|
||||
return (vbyte*)pstrdup(p,-1);
|
||||
{
|
||||
pchar path[PATH_MAX];
|
||||
int length = readlink("/proc/self/exe", path, sizeof(path));
|
||||
if( length < 0 )
|
||||
return NULL;
|
||||
path[length] = '\0';
|
||||
return (vbyte*)pstrdup(path,-1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
HL_PRIM int hl_sys_get_char( bool b ) {
|
||||
# if defined(HL_WIN_DESKTOP)
|
||||
return b?getche():getch();
|
||||
# elif defined(HL_CONSOLE)
|
||||
return -1;
|
||||
# else
|
||||
// took some time to figure out how to do that
|
||||
// without relying on ncurses, which clear the
|
||||
// terminal on initscr()
|
||||
int c;
|
||||
struct termios term, old;
|
||||
tcgetattr(fileno(stdin), &old);
|
||||
term = old;
|
||||
cfmakeraw(&term);
|
||||
tcsetattr(fileno(stdin), 0, &term);
|
||||
c = getchar();
|
||||
tcsetattr(fileno(stdin), 0, &old);
|
||||
if( b ) fputc(c,stdout);
|
||||
return c;
|
||||
# endif
|
||||
}
|
||||
|
||||
static pchar **sys_args;
|
||||
static int sys_nargs;
|
||||
|
||||
HL_PRIM varray *hl_sys_args() {
|
||||
varray *a = hl_alloc_array(&hlt_bytes,sys_nargs);
|
||||
int i;
|
||||
for(i=0;i<sys_nargs;i++)
|
||||
hl_aptr(a,pchar*)[i] = sys_args[i];
|
||||
return a;
|
||||
}
|
||||
|
||||
static void *hl_file = NULL;
|
||||
|
||||
HL_PRIM void hl_sys_init(void **args, int nargs, void *hlfile) {
|
||||
sys_args = (pchar**)args;
|
||||
sys_nargs = nargs;
|
||||
hl_file = hlfile;
|
||||
# ifdef HL_WIN_DESKTOP
|
||||
setlocale(LC_CTYPE, ""); // printf to current locale
|
||||
# endif
|
||||
}
|
||||
|
||||
HL_PRIM vbyte *hl_sys_hl_file() {
|
||||
return (vbyte*)hl_file;
|
||||
}
|
||||
|
||||
static void *reload_fun = NULL;
|
||||
static void *reload_param = NULL;
|
||||
HL_PRIM void hl_setup_reload_check( void *freload, void *param ) {
|
||||
reload_fun = freload;
|
||||
reload_param = param;
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_sys_check_reload( vbyte *debug_alt_file ) {
|
||||
if( debug_alt_file && reload_param ) {
|
||||
*((vbyte**)reload_param) = debug_alt_file;
|
||||
}
|
||||
return reload_fun && ((bool(*)(void*))reload_fun)(reload_param);
|
||||
}
|
||||
|
||||
extern int hl_closure_stack_capture;
|
||||
|
||||
HL_PRIM bool hl_sys_has_debugger() {
|
||||
return hl_closure_stack_capture != 0;
|
||||
}
|
||||
|
||||
#ifndef HL_MOBILE
|
||||
const char *hl_sys_special( const char *key ) {
|
||||
hl_error("Unknown sys_special key");
|
||||
return NULL;
|
||||
}
|
||||
DEFINE_PRIM(_BYTES, sys_special, _BYTES);
|
||||
#endif
|
||||
|
||||
DEFINE_PRIM(_BYTES, sys_hl_file, _NO_ARG);
|
||||
DEFINE_PRIM(_BOOL, sys_utf8_path, _NO_ARG);
|
||||
DEFINE_PRIM(_BYTES, sys_string, _NO_ARG);
|
||||
DEFINE_PRIM(_BYTES, sys_locale, _NO_ARG);
|
||||
DEFINE_PRIM(_VOID, sys_print, _BYTES);
|
||||
DEFINE_PRIM(_VOID, sys_exit, _I32);
|
||||
DEFINE_PRIM(_F64, sys_time, _NO_ARG);
|
||||
DEFINE_PRIM(_BYTES, sys_get_env, _BYTES);
|
||||
DEFINE_PRIM(_BOOL, sys_put_env, _BYTES _BYTES);
|
||||
DEFINE_PRIM(_ARR, sys_env, _NO_ARG);
|
||||
DEFINE_PRIM(_VOID, sys_sleep, _F64);
|
||||
DEFINE_PRIM(_BOOL, sys_set_time_locale, _BYTES);
|
||||
DEFINE_PRIM(_BYTES, sys_get_cwd, _NO_ARG);
|
||||
DEFINE_PRIM(_BOOL, sys_set_cwd, _BYTES);
|
||||
DEFINE_PRIM(_BOOL, sys_is64, _NO_ARG);
|
||||
DEFINE_PRIM(_I32, sys_command, _BYTES);
|
||||
DEFINE_PRIM(_BOOL, sys_exists, _BYTES);
|
||||
DEFINE_PRIM(_BOOL, sys_delete, _BYTES);
|
||||
DEFINE_PRIM(_BOOL, sys_rename, _BYTES _BYTES);
|
||||
DEFINE_PRIM(_ARR, sys_stat, _BYTES);
|
||||
DEFINE_PRIM(_BOOL, sys_is_dir, _BYTES);
|
||||
DEFINE_PRIM(_BOOL, sys_create_dir, _BYTES _I32);
|
||||
DEFINE_PRIM(_BOOL, sys_remove_dir, _BYTES);
|
||||
DEFINE_PRIM(_F64, sys_cpu_time, _NO_ARG);
|
||||
DEFINE_PRIM(_F64, sys_thread_cpu_time, _NO_ARG);
|
||||
DEFINE_PRIM(_ARR, sys_read_dir, _BYTES);
|
||||
DEFINE_PRIM(_BYTES, sys_full_path, _BYTES);
|
||||
DEFINE_PRIM(_BYTES, sys_exe_path, _NO_ARG);
|
||||
DEFINE_PRIM(_I32, sys_get_char, _BOOL);
|
||||
DEFINE_PRIM(_ARR, sys_args, _NO_ARG);
|
||||
DEFINE_PRIM(_I32, sys_getpid, _NO_ARG);
|
||||
DEFINE_PRIM(_BOOL, sys_check_reload, _BYTES);
|
||||
DEFINE_PRIM(_VOID, sys_profile_event, _I32 _BYTES _I32);
|
||||
DEFINE_PRIM(_I32, sys_set_flags, _I32);
|
||||
DEFINE_PRIM(_BOOL, sys_has_debugger, _NO_ARG);
|
242
Kha/Backends/Kinc-HL/hl/src/std/sys_android.c
Normal file
242
Kha/Backends/Kinc-HL/hl/src/std/sys_android.c
Normal file
@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Copyright (C)2005-2018 Haxe Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <hl.h>
|
||||
|
||||
#if defined(HL_MOBILE) && defined(HL_ANDROID)
|
||||
|
||||
#ifndef HL_ANDROID_ACTIVITY
|
||||
# define HL_ANDROID_ACTIVITY "org/haxe/HashLinkActivity"
|
||||
#endif
|
||||
|
||||
#include <jni.h>
|
||||
#include <android/log.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef HL_JNI_LOG_TAG
|
||||
#define HL_JNI_LOG_TAG "HL_JNI"
|
||||
#endif
|
||||
|
||||
#define HL_ANDROID_EXTERNAL_STORAGE_NOT_MOUNTED (0)
|
||||
#define HL_ANDROID_EXTERNAL_STORAGE_MOUNTED_RO (1)
|
||||
#define HL_ANDROID_EXTERNAL_STORAGE_MOUNTED_RW (2 | HL_ANDROID_EXTERNAL_STORAGE_MOUNTED_RO)
|
||||
|
||||
/* #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,HL_JNI_LOG_TAG,__VA_ARGS__) */
|
||||
/* #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,HL_JNI_LOG_TAG,__VA_ARGS__) */
|
||||
#define LOGI(...) do {} while (0)
|
||||
#define LOGE(...) do {} while (0)
|
||||
|
||||
/* Forward declaration for JNI thread management */
|
||||
static void hl_android_jni_thread_destructor(void*);
|
||||
|
||||
/* pthread key for proper JVM thread handling */
|
||||
static pthread_key_t hl_java_thread_key;
|
||||
|
||||
/* Java VM reference */
|
||||
static JavaVM* hl_java_vm;
|
||||
|
||||
/* Main activity */
|
||||
static jclass hl_java_activity_class;
|
||||
|
||||
/* Method signatures */
|
||||
static jmethodID hl_java_method_id_get_context;
|
||||
|
||||
/* Paths */
|
||||
static char *hl_android_external_files_path = NULL;
|
||||
static char *hl_android_internal_files_path = NULL;
|
||||
|
||||
/* Function to retrieve JNI environment, and dealing with threading */
|
||||
static JNIEnv* hl_android_jni_get_env(void)
|
||||
{
|
||||
/* Always try to attach if calling from a non-attached thread */
|
||||
JNIEnv *env;
|
||||
if((*hl_java_vm)->AttachCurrentThread(hl_java_vm, &env, NULL) < 0) {
|
||||
LOGE("failed to attach current thread");
|
||||
return 0;
|
||||
}
|
||||
pthread_setspecific(hl_java_thread_key, (void*) env);
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
/* JNI_OnLoad is automatically called when loading shared library through System.loadLibrary() Java call */
|
||||
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
|
||||
{
|
||||
JNIEnv *env;
|
||||
jclass cls;
|
||||
|
||||
hl_java_vm = vm;
|
||||
if ((*hl_java_vm)->GetEnv(hl_java_vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
|
||||
__android_log_print(ANDROID_LOG_ERROR, HL_JNI_LOG_TAG, "Failed to get the environment using GetEnv()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Create pthread "destructor" pthread key to detach properly all threads */
|
||||
if (pthread_key_create(&hl_java_thread_key, hl_android_jni_thread_destructor) != 0) {
|
||||
__android_log_print(ANDROID_LOG_ERROR, HL_JNI_LOG_TAG, "Error initializing pthread key");
|
||||
}
|
||||
|
||||
/* Make sure we are attached (we should) and setup pthread destructor */
|
||||
env = hl_android_jni_get_env();
|
||||
|
||||
/* Try to retrieve local reference to our Activity class */
|
||||
cls = (*env)->FindClass(env, HL_ANDROID_ACTIVITY);
|
||||
if (!cls) {
|
||||
__android_log_print(ANDROID_LOG_ERROR, HL_JNI_LOG_TAG, "Error cannot find HashLink Activity class");
|
||||
}
|
||||
|
||||
/* Create a global reference for our Activity class */
|
||||
hl_java_activity_class = (jclass)((*env)->NewGlobalRef(env, cls));
|
||||
|
||||
/* Retrieve the getContext() method id */
|
||||
hl_java_method_id_get_context = (*env)->GetStaticMethodID(env, hl_java_activity_class, "getContext","()Landroid/content/Context;");
|
||||
if (!hl_java_method_id_get_context) {
|
||||
__android_log_print(ANDROID_LOG_ERROR, HL_JNI_LOG_TAG, "Error cannot get getContext() method on specified Activity class (not an Activity ?)");
|
||||
}
|
||||
|
||||
return JNI_VERSION_1_4;
|
||||
}
|
||||
|
||||
static void hl_android_jni_thread_destructor(void* value)
|
||||
{
|
||||
/* The thread is being destroyed, detach it from the Java VM and set the hl_java_thread_key value to NULL as required */
|
||||
JNIEnv *env = (JNIEnv*) value;
|
||||
if (env != NULL) {
|
||||
(*hl_java_vm)->DetachCurrentThread(hl_java_vm);
|
||||
pthread_setspecific(hl_java_thread_key, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static int hl_sys_android_get_external_storage_state(void)
|
||||
{
|
||||
jmethodID mid;
|
||||
jclass cls;
|
||||
jstring stateString;
|
||||
const char *state;
|
||||
int status = HL_ANDROID_EXTERNAL_STORAGE_NOT_MOUNTED;
|
||||
|
||||
JNIEnv *env = hl_android_jni_get_env();
|
||||
if (!env) {
|
||||
LOGE("Couldn't get Android JNIEnv !");
|
||||
return status;
|
||||
}
|
||||
|
||||
cls = (*env)->FindClass(env, "android/os/Environment");
|
||||
mid = (*env)->GetStaticMethodID(env, cls, "getExternalStorageState", "()Ljava/lang/String;");
|
||||
stateString = (jstring)(*env)->CallStaticObjectMethod(env, cls, mid);
|
||||
if (!stateString) {
|
||||
LOGE("Call to getExternalStorageState failed");
|
||||
return status;
|
||||
}
|
||||
|
||||
state = (*env)->GetStringUTFChars(env, stateString, NULL);
|
||||
if (strcmp(state, "mounted") == 0) {
|
||||
status = HL_ANDROID_EXTERNAL_STORAGE_MOUNTED_RW;
|
||||
} else if (strcmp(state, "mounted_ro") == 0) {
|
||||
status = HL_ANDROID_EXTERNAL_STORAGE_MOUNTED_RO;
|
||||
}
|
||||
(*env)->ReleaseStringUTFChars(env, stateString, state);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static char* hl_sys_android_get_absolute_path_from(const char* method, const char* signature)
|
||||
{
|
||||
jmethodID mid;
|
||||
jobject context;
|
||||
jobject fileObject;
|
||||
jstring pathString;
|
||||
const char *path;
|
||||
char* retrievedPath = NULL;
|
||||
|
||||
JNIEnv *env = hl_android_jni_get_env();
|
||||
if (!env) {
|
||||
LOGE("Couldn't get Android JNIEnv !");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
context = (*env)->CallStaticObjectMethod(env, hl_java_activity_class, hl_java_method_id_get_context);
|
||||
if (!context) {
|
||||
LOGE("Couldn't get Android context!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context), method, signature);
|
||||
fileObject = (*env)->CallObjectMethod(env, context, mid, NULL);
|
||||
if (!fileObject) {
|
||||
LOGE("Couldn't call %s%s on the specified context", method, signature);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, fileObject), "getAbsolutePath", "()Ljava/lang/String;");
|
||||
pathString = (jstring)(*env)->CallObjectMethod(env, fileObject, mid);
|
||||
if (!pathString) {
|
||||
LOGE("Couldn't retrieve absolute path");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Retrieve as C string */
|
||||
path = (*env)->GetStringUTFChars(env, pathString, NULL);
|
||||
retrievedPath = strdup(path);
|
||||
(*env)->ReleaseStringUTFChars(env, pathString, path);
|
||||
|
||||
return retrievedPath;
|
||||
}
|
||||
|
||||
static const char* hl_sys_android_get_external_storage_path(void)
|
||||
{
|
||||
/* Make sure external storage is mounted (at least read-only) */
|
||||
if (hl_sys_android_get_external_storage_state()==HL_ANDROID_EXTERNAL_STORAGE_NOT_MOUNTED)
|
||||
return NULL;
|
||||
|
||||
if (!hl_android_external_files_path) {
|
||||
hl_android_external_files_path = hl_sys_android_get_absolute_path_from("getExternalFilesDir", "(Ljava/lang/String;)Ljava/io/File;");
|
||||
}
|
||||
|
||||
return hl_android_external_files_path;
|
||||
}
|
||||
|
||||
static const char* hl_sys_android_get_internal_storage_path(void)
|
||||
{
|
||||
/* Internal storage is always available */
|
||||
if (!hl_android_internal_files_path) {
|
||||
hl_android_internal_files_path = hl_sys_android_get_absolute_path_from("getFilesDir", "(Ljava/lang/String;)Ljava/io/File;");
|
||||
}
|
||||
|
||||
return hl_android_internal_files_path;
|
||||
}
|
||||
|
||||
const char *hl_sys_special( const char *key ) {
|
||||
if (strcmp(key, "android_external_storage_path")==0)
|
||||
return hl_sys_android_get_external_storage_path();
|
||||
else if (strcmp(key, "android_internal_storage_path")==0)
|
||||
return hl_sys_android_get_internal_storage_path();
|
||||
else
|
||||
hl_error("Unknown sys_special key");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DEFINE_PRIM(_BYTES, sys_special, _BYTES);
|
||||
|
||||
#endif
|
73
Kha/Backends/Kinc-HL/hl/src/std/sys_ios.m
Normal file
73
Kha/Backends/Kinc-HL/hl/src/std/sys_ios.m
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C)2005-2018 Haxe Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <hl.h>
|
||||
|
||||
#if defined(HL_MOBILE) && defined(HL_IOS)
|
||||
|
||||
#include <sys/utsname.h>
|
||||
#include <Foundation/Foundation.h>
|
||||
#include <UIKit/UIKit.h>
|
||||
|
||||
static const char* ios_get_document_path()
|
||||
{
|
||||
NSString* string = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
|
||||
const char* path = strdup([string fileSystemRepresentation]);
|
||||
return path;
|
||||
}
|
||||
|
||||
static const char* ios_get_resource_path()
|
||||
{
|
||||
NSString* string = [[NSBundle mainBundle] resourcePath];
|
||||
const char* path = strdup([string UTF8String]);
|
||||
return path;
|
||||
}
|
||||
|
||||
static const char* ios_get_device_name()
|
||||
{
|
||||
struct utsname systemInfo;
|
||||
uname(&systemInfo);
|
||||
return strdup(systemInfo.machine);
|
||||
}
|
||||
|
||||
static int ios_get_retina_scale_factor()
|
||||
{
|
||||
return [[UIScreen mainScreen] scale];
|
||||
}
|
||||
|
||||
const char *hl_sys_special( const char *key ) {
|
||||
if (strcmp(key, "ios_resource_path")==0)
|
||||
return ios_get_resource_path();
|
||||
else if (strcmp(key, "ios_document_path")==0)
|
||||
return ios_get_document_path();
|
||||
else if (strcmp(key, "ios_retina_scale_factor")==0)
|
||||
return ios_get_retina_scale_factor();
|
||||
else if (strcmp(key, "ios_device_name")==0)
|
||||
return ios_get_device_name();
|
||||
else
|
||||
hl_error("Unknown sys_special key");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DEFINE_PRIM(_BYTES, sys_special, _BYTES);
|
||||
|
||||
#endif
|
1145
Kha/Backends/Kinc-HL/hl/src/std/thread.c
Normal file
1145
Kha/Backends/Kinc-HL/hl/src/std/thread.c
Normal file
File diff suppressed because it is too large
Load Diff
299
Kha/Backends/Kinc-HL/hl/src/std/track.c
Normal file
299
Kha/Backends/Kinc-HL/hl/src/std/track.c
Normal file
@ -0,0 +1,299 @@
|
||||
/*
|
||||
* Copyright (C)2005-2017 Haxe Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "hl.h"
|
||||
#include <stdio.h>
|
||||
|
||||
static int track_depth = 10;
|
||||
static int max_depth = 0;
|
||||
|
||||
#ifdef HL_TRACK_ENABLE
|
||||
hl_track_info hl_track = {0};
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
KALLOC,
|
||||
KCAST,
|
||||
KDYNFIELD,
|
||||
KDYNCALL,
|
||||
_KLAST
|
||||
} bucket_kind;
|
||||
|
||||
typedef struct {
|
||||
hl_type *t;
|
||||
void **stack;
|
||||
int stack_count;
|
||||
int hit_count;
|
||||
int info;
|
||||
} bucket;
|
||||
|
||||
typedef struct {
|
||||
unsigned int *hashes;
|
||||
bucket *buckets;
|
||||
int bcount;
|
||||
int max_buckets;
|
||||
unsigned int prev_hash;
|
||||
unsigned int prev_hash2;
|
||||
bucket *prev_b;
|
||||
bucket *prev_b2;
|
||||
} bucket_list;
|
||||
|
||||
static bucket_list all_data[_KLAST] = {{0}};
|
||||
static hl_mutex *track_lock = NULL;
|
||||
|
||||
int hl_internal_capture_stack( void **stack, int size );
|
||||
|
||||
static bucket *bucket_find_insert( bucket_list *data, unsigned int hash, void **stack, int count ) {
|
||||
int min = 0, mid;
|
||||
int max = data->bcount;
|
||||
bucket *b;
|
||||
while( min < max ) {
|
||||
mid = (min + max) >> 1;
|
||||
if( data->hashes[mid] < hash )
|
||||
min = mid + 1;
|
||||
else if( data->hashes[mid] > hash )
|
||||
max = mid;
|
||||
else {
|
||||
b = data->buckets + mid;
|
||||
if( b->stack_count != count ) {
|
||||
if( b->stack_count < count )
|
||||
min = mid + 1;
|
||||
else
|
||||
max = mid;
|
||||
} else {
|
||||
int i;
|
||||
for(i=0;i<count;i++)
|
||||
if( b->stack[i] != stack[i] ) {
|
||||
if( b->stack[i] < stack[i] )
|
||||
min = mid + 1;
|
||||
else
|
||||
max = mid;
|
||||
break;
|
||||
}
|
||||
if( i == count )
|
||||
return b;
|
||||
}
|
||||
}
|
||||
}
|
||||
mid = (min + max) >> 1;
|
||||
if( data->bcount == data->max_buckets ) {
|
||||
int nbuckets = data->max_buckets ? data->max_buckets << 1 : 256;
|
||||
bucket *bnew = (bucket*)malloc(sizeof(bucket)*nbuckets);
|
||||
unsigned int *hnew = (unsigned int*)malloc(sizeof(int)*nbuckets);
|
||||
memcpy(bnew,data->buckets,data->bcount*sizeof(bucket));
|
||||
memcpy(hnew,data->hashes,data->bcount*sizeof(int));
|
||||
free(data->buckets);
|
||||
free(data->hashes);
|
||||
data->buckets = bnew;
|
||||
data->hashes = hnew;
|
||||
data->max_buckets = nbuckets;
|
||||
}
|
||||
b = data->buckets + mid;
|
||||
if( data->hashes[mid] == hash && b->stack_count == count ) {
|
||||
int i;
|
||||
for(i=0;i<count;i++)
|
||||
if( b->stack[i] != stack[i] )
|
||||
break;
|
||||
if( i == count )
|
||||
return b;
|
||||
}
|
||||
memmove(data->buckets + (mid + 1), data->buckets + mid, (data->bcount - mid) * sizeof(bucket));
|
||||
memmove(data->hashes + (mid + 1), data->hashes + mid, (data->bcount - mid) * sizeof(int));
|
||||
memset(b, 0, sizeof(bucket));
|
||||
b->stack = malloc(sizeof(void*)*count);
|
||||
memcpy(b->stack, stack, sizeof(void*)*count);
|
||||
b->stack_count = count;
|
||||
data->hashes[mid] = hash;
|
||||
data->bcount++;
|
||||
return b;
|
||||
}
|
||||
|
||||
static void init_lock() {
|
||||
hl_thread_info *tinf = hl_get_thread();
|
||||
int flags = tinf->flags;
|
||||
tinf->flags &= ~(HL_TRACK_ALLOC<<HL_TREAD_TRACK_SHIFT);
|
||||
track_lock = hl_mutex_alloc(true);
|
||||
hl_add_root(&track_lock);
|
||||
tinf->flags = flags;
|
||||
}
|
||||
|
||||
static bucket *fetch_bucket( bucket_kind kind ) {
|
||||
int count, i;
|
||||
unsigned int hash;
|
||||
hl_thread_info *tinf = hl_get_thread();
|
||||
bucket_list *data = &all_data[kind];
|
||||
bucket *b;
|
||||
if( track_lock == NULL ) init_lock();
|
||||
count = hl_internal_capture_stack(tinf->exc_stack_trace,track_depth);
|
||||
if( count > max_depth ) max_depth = count;
|
||||
hash = -count;
|
||||
for(i=0;i<count;i++)
|
||||
hash = (hash * 31) + (((unsigned int)(int_val)tinf->exc_stack_trace[i]) >> 1);
|
||||
// look for bucket
|
||||
hl_mutex_acquire(track_lock);
|
||||
if( hash == data->prev_hash && data->prev_b ) {
|
||||
b = data->prev_b;
|
||||
} else if( hash == data->prev_hash2 && data->prev_b2 ) {
|
||||
b = data->prev_b2;
|
||||
} else {
|
||||
b = bucket_find_insert(data, hash, tinf->exc_stack_trace, count);
|
||||
data->prev_hash2 = data->prev_hash;
|
||||
data->prev_b2 = data->prev_b;
|
||||
data->prev_hash = hash;
|
||||
data->prev_b = b;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
static void on_alloc( hl_type *t, int size, int flags, void *ptr ) {
|
||||
bucket *b = fetch_bucket(KALLOC);
|
||||
b->t = t;
|
||||
b->hit_count++;
|
||||
b->info += size;
|
||||
hl_mutex_release(track_lock);
|
||||
}
|
||||
|
||||
static void on_cast( hl_type *t1, hl_type *t2 ) {
|
||||
bucket *b = fetch_bucket(KCAST);
|
||||
b->t = t1;
|
||||
b->hit_count++;
|
||||
b->info = t2->kind;
|
||||
hl_mutex_release(track_lock);
|
||||
}
|
||||
|
||||
static void on_dynfield( vdynamic *d, int hfield ) {
|
||||
bucket *b = fetch_bucket(KDYNFIELD);
|
||||
b->t = d?d->t:&hlt_dyn;
|
||||
b->hit_count++;
|
||||
b->info = hfield;
|
||||
hl_mutex_release(track_lock);
|
||||
}
|
||||
|
||||
static void on_dyncall( vdynamic *d, int hfield ) {
|
||||
bucket *b = fetch_bucket(KDYNCALL);
|
||||
b->t = d?d->t:&hlt_dyn;
|
||||
b->hit_count++;
|
||||
b->info = hfield;
|
||||
hl_mutex_release(track_lock);
|
||||
}
|
||||
|
||||
HL_PRIM void hl_track_init() {
|
||||
#ifdef HL_TRACK_ENABLE
|
||||
char *env = getenv("HL_TRACK");
|
||||
if( env )
|
||||
hl_track.flags = atoi(env);
|
||||
hl_track.on_alloc = on_alloc;
|
||||
hl_track.on_cast = on_cast;
|
||||
hl_track.on_dynfield = on_dynfield;
|
||||
hl_track.on_dyncall = on_dyncall;
|
||||
#endif
|
||||
}
|
||||
|
||||
HL_PRIM void hl_track_lock( bool lock ) {
|
||||
#ifdef HL_TRACK_ENABLE
|
||||
if( !track_lock ) init_lock();
|
||||
if( lock )
|
||||
hl_mutex_acquire(track_lock);
|
||||
else
|
||||
hl_mutex_release(track_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
HL_PRIM int hl_track_count( int *depth ) {
|
||||
int value = 0;
|
||||
int i;
|
||||
for(i=0;i<_KLAST;i++)
|
||||
value += all_data[i].bcount;
|
||||
*depth = max_depth;
|
||||
return value;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_track_entry( int id, hl_type **t, int *count, int *info, varray *stack ) {
|
||||
static bucket_list *cur = NULL;
|
||||
static int prev_id = -10;
|
||||
static int count_before = 0;
|
||||
bucket *b = NULL;
|
||||
if( id == prev_id + 1 ) {
|
||||
if( id - count_before == cur->bcount ) {
|
||||
if( cur - all_data == _KLAST ) return -1;
|
||||
count_before += cur->bcount;
|
||||
cur++;
|
||||
}
|
||||
b = cur->buckets + (id - count_before);
|
||||
prev_id++;
|
||||
} else {
|
||||
int i;
|
||||
count_before = 0;
|
||||
for(i=0;i<_KLAST;i++) {
|
||||
bucket_list *data = &all_data[i];
|
||||
if( id - count_before < data->bcount ) break;
|
||||
count_before += data->bcount;
|
||||
}
|
||||
if( i == _KLAST ) return -1; // out of range
|
||||
prev_id = id;
|
||||
cur = &all_data[i];
|
||||
b = cur->buckets;
|
||||
}
|
||||
*t = b->t;
|
||||
*count = b->hit_count;
|
||||
*info = b->info;
|
||||
stack->size = b->stack_count;
|
||||
memcpy(hl_aptr(stack,void*), b->stack, b->stack_count * sizeof(void*));
|
||||
return (int)(cur - all_data);
|
||||
}
|
||||
|
||||
HL_PRIM int hl_track_get_bits( bool thread ) {
|
||||
# ifdef HL_TRACK_ENABLE
|
||||
return (thread ? (hl_get_thread()->flags>>HL_TREAD_TRACK_SHIFT) : hl_track.flags) & HL_TRACK_MASK;
|
||||
# else
|
||||
return 0;
|
||||
# endif
|
||||
}
|
||||
|
||||
HL_PRIM void hl_track_set_depth( int d ) {
|
||||
track_depth = d;
|
||||
}
|
||||
|
||||
HL_PRIM void hl_track_set_bits( int flags, bool thread ) {
|
||||
# ifdef HL_TRACK_ENABLE
|
||||
if( thread ) {
|
||||
hl_thread_info *t = hl_get_thread();
|
||||
if( t ) t->flags = (t->flags & ~(HL_TRACK_MASK<<HL_TREAD_TRACK_SHIFT)) | ((flags & HL_TRACK_MASK) << HL_TREAD_TRACK_SHIFT);
|
||||
} else {
|
||||
hl_track.flags = (hl_track.flags & ~HL_TRACK_MASK) | (flags & HL_TRACK_MASK);
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
HL_PRIM void hl_track_reset() {
|
||||
int i;
|
||||
for(i=0;i<_KLAST;i++)
|
||||
all_data[i].bcount = 0;
|
||||
}
|
||||
|
||||
DEFINE_PRIM(_VOID, track_init, _NO_ARG);
|
||||
DEFINE_PRIM(_I32, track_count, _REF(_I32));
|
||||
DEFINE_PRIM(_I32, track_entry, _I32 _REF(_TYPE) _REF(_I32) _REF(_I32) _ARR);
|
||||
DEFINE_PRIM(_VOID, track_lock, _BOOL);
|
||||
DEFINE_PRIM(_VOID, track_set_depth, _I32);
|
||||
DEFINE_PRIM(_I32, track_get_bits, _BOOL);
|
||||
DEFINE_PRIM(_VOID, track_set_bits, _I32 _BOOL);
|
||||
DEFINE_PRIM(_VOID, track_reset, _NO_ARG);
|
973
Kha/Backends/Kinc-HL/hl/src/std/types.c
Normal file
973
Kha/Backends/Kinc-HL/hl/src/std/types.c
Normal file
@ -0,0 +1,973 @@
|
||||
/*
|
||||
* Copyright (C)2005-2016 Haxe Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <hl.h>
|
||||
|
||||
HL_PRIM hl_type hlt_array = { HARRAY };
|
||||
HL_PRIM hl_type hlt_bytes = { HBYTES };
|
||||
HL_PRIM hl_type hlt_dynobj = { HDYNOBJ };
|
||||
HL_PRIM hl_type hlt_dyn = { HDYN };
|
||||
HL_PRIM hl_type hlt_i32 = { HI32 };
|
||||
HL_PRIM hl_type hlt_i64 = { HI64 };
|
||||
HL_PRIM hl_type hlt_f32 = { HF32 };
|
||||
HL_PRIM hl_type hlt_f64 = { HF64 };
|
||||
HL_PRIM hl_type hlt_void = { HVOID };
|
||||
HL_PRIM hl_type hlt_bool = { HBOOL };
|
||||
HL_PRIM hl_type hlt_abstract = { HABSTRACT, {USTR("<abstract>")} };
|
||||
|
||||
static const uchar *TSTR[] = {
|
||||
USTR("void"), USTR("i8"), USTR("i16"), USTR("i32"), USTR("i64"), USTR("f32"), USTR("f64"),
|
||||
USTR("bool"), USTR("bytes"), USTR("dynamic"), NULL, NULL,
|
||||
USTR("array"), USTR("type"), NULL, NULL, USTR("dynobj"),
|
||||
NULL, NULL, NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
static int T_SIZES[] = {
|
||||
0, // VOID
|
||||
1, // I8
|
||||
2, // I16
|
||||
4, // I32
|
||||
8, // I64
|
||||
4, // F32
|
||||
8, // F64
|
||||
sizeof(bool), // BOOL
|
||||
HL_WSIZE, // BYTES
|
||||
HL_WSIZE, // DYN
|
||||
HL_WSIZE, // FUN
|
||||
HL_WSIZE, // OBJ
|
||||
HL_WSIZE, // ARRAY
|
||||
HL_WSIZE, // TYPE
|
||||
HL_WSIZE, // REF
|
||||
HL_WSIZE, // VIRTUAL
|
||||
HL_WSIZE, // DYNOBJ
|
||||
HL_WSIZE, // ABSTRACT
|
||||
HL_WSIZE, // ENUM
|
||||
HL_WSIZE, // NULL
|
||||
HL_WSIZE, // METHOD
|
||||
HL_WSIZE, // STRUCT
|
||||
0, // PACKED
|
||||
};
|
||||
|
||||
HL_PRIM int hl_type_size( hl_type *t ) {
|
||||
return T_SIZES[t->kind];
|
||||
}
|
||||
|
||||
HL_PRIM int hl_pad_struct( int size, hl_type *t ) {
|
||||
int align = sizeof(void*);
|
||||
# define GET_ALIGN(type) { struct { unsigned char a; type b; } s = {0}; align = (int)((unsigned char *)&s.b - (unsigned char*)&s); }
|
||||
switch( t->kind ) {
|
||||
case HVOID:
|
||||
return 0;
|
||||
case HUI8:
|
||||
GET_ALIGN(unsigned char);
|
||||
break;
|
||||
case HUI16:
|
||||
GET_ALIGN(unsigned short);
|
||||
break;
|
||||
case HI32:
|
||||
GET_ALIGN(unsigned int);
|
||||
break;
|
||||
case HI64:
|
||||
GET_ALIGN(int64);
|
||||
break;
|
||||
case HF32:
|
||||
GET_ALIGN(float);
|
||||
break;
|
||||
case HF64:
|
||||
GET_ALIGN(double);
|
||||
break;
|
||||
case HBOOL:
|
||||
GET_ALIGN(bool);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (-size) & (align - 1);
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_same_type( hl_type *a, hl_type *b ) {
|
||||
if( a == b )
|
||||
return true;
|
||||
if( a->kind != b->kind )
|
||||
return false;
|
||||
switch( a->kind ) {
|
||||
case HVOID:
|
||||
case HUI8:
|
||||
case HUI16:
|
||||
case HI32:
|
||||
case HI64:
|
||||
case HF32:
|
||||
case HF64:
|
||||
case HBOOL:
|
||||
case HTYPE:
|
||||
case HBYTES:
|
||||
case HDYN:
|
||||
case HARRAY:
|
||||
case HDYNOBJ:
|
||||
return true;
|
||||
case HREF:
|
||||
case HNULL:
|
||||
case HPACKED:
|
||||
return hl_same_type(a->tparam, b->tparam);
|
||||
case HFUN:
|
||||
case HMETHOD:
|
||||
{
|
||||
int i;
|
||||
if( a->fun->nargs != b->fun->nargs )
|
||||
return false;
|
||||
for(i=0;i<a->fun->nargs;i++)
|
||||
if( !hl_same_type(a->fun->args[i],b->fun->args[i]) )
|
||||
return false;
|
||||
return hl_same_type(a->fun->ret, b->fun->ret);
|
||||
}
|
||||
case HOBJ:
|
||||
case HSTRUCT:
|
||||
return a->obj == b->obj;
|
||||
case HVIRTUAL:
|
||||
return a->virt == b->virt;
|
||||
case HABSTRACT:
|
||||
return a->abs_name == b->abs_name;
|
||||
case HENUM:
|
||||
return a->tenum == b->tenum;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_is_dynamic( hl_type *t ) {
|
||||
static bool T_IS_DYNAMIC[] = {
|
||||
false, // HVOID,
|
||||
false, // HI8
|
||||
false, // HI16
|
||||
false, // HI32
|
||||
false, // HI64
|
||||
false, // HF32
|
||||
false, // HF64
|
||||
false, // HBOOL
|
||||
false, // HBYTES
|
||||
true, // HDYN
|
||||
true, // HFUN
|
||||
true, // HOBJ
|
||||
true, // HARRAY
|
||||
false, // HTYPE
|
||||
false, // HREF
|
||||
true, // HVIRTUAL
|
||||
true, // HDYNOBJ
|
||||
false, // HABSTRACT
|
||||
true, // HENUM
|
||||
true, // HNULL
|
||||
false, // HMETHOD
|
||||
false, // HSTRUCT
|
||||
false, // HPACKED
|
||||
};
|
||||
return T_IS_DYNAMIC[t->kind];
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_safe_cast( hl_type *t, hl_type *to ) {
|
||||
if( t == to )
|
||||
return true;
|
||||
if( to->kind == HDYN )
|
||||
return hl_is_dynamic(t);
|
||||
if( t->kind != to->kind )
|
||||
return false;
|
||||
switch( t->kind ) {
|
||||
case HVIRTUAL:
|
||||
if( to->virt->nfields < t->virt->nfields ) {
|
||||
int i;
|
||||
for(i=0;i<to->virt->nfields;i++) {
|
||||
hl_obj_field *f1 = t->virt->fields + i;
|
||||
hl_obj_field *f2 = to->virt->fields + i;
|
||||
if( f1->hashed_name != f2->hashed_name || !hl_same_type(f1->t,f2->t) )
|
||||
break;
|
||||
}
|
||||
if( i == to->virt->nfields )
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case HOBJ:
|
||||
case HSTRUCT:
|
||||
{
|
||||
hl_type_obj *o = t->obj;
|
||||
hl_type_obj *oto = to->obj;
|
||||
while( true ) {
|
||||
if( o == oto ) return true;
|
||||
if( o->super == NULL ) return false;
|
||||
o = o->super->obj;
|
||||
}
|
||||
}
|
||||
case HFUN:
|
||||
case HMETHOD:
|
||||
if( t->fun->nargs == to->fun->nargs ) {
|
||||
int i;
|
||||
if( !hl_safe_cast(t->fun->ret,to->fun->ret) )
|
||||
return false;
|
||||
for(i=0;i<t->fun->nargs;i++) {
|
||||
hl_type *t1 = t->fun->args[i];
|
||||
hl_type *t2 = to->fun->args[i];
|
||||
if( !hl_safe_cast(t2,t1) && (t1->kind != HDYN || !hl_is_dynamic(t2)) )
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case HPACKED:
|
||||
return hl_safe_cast(t->tparam, to);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return hl_same_type(t,to);
|
||||
}
|
||||
|
||||
typedef struct tlist {
|
||||
hl_type *t;
|
||||
struct tlist *next;
|
||||
} tlist;
|
||||
|
||||
static void hl_type_str_rec( hl_buffer *b, hl_type *t, tlist *parents ) {
|
||||
const uchar *c = TSTR[t->kind];
|
||||
tlist *l, cur;
|
||||
int i;
|
||||
if( c != NULL ) {
|
||||
hl_buffer_str(b,c);
|
||||
return;
|
||||
}
|
||||
l = parents;
|
||||
while( l ) {
|
||||
if( l->t == t ) {
|
||||
hl_buffer_str(b,USTR("<...>"));
|
||||
return;
|
||||
}
|
||||
l = l->next;
|
||||
}
|
||||
cur.t = t;
|
||||
cur.next = parents;
|
||||
l = &cur;
|
||||
switch( t->kind ) {
|
||||
case HFUN:
|
||||
case HMETHOD:
|
||||
hl_buffer_char(b,'(');
|
||||
hl_type_str_rec(b,t->fun->ret,l);
|
||||
hl_buffer_char(b,' ');
|
||||
hl_buffer_char(b,'(');
|
||||
for(i=0; i<t->fun->nargs; i++) {
|
||||
if( i ) hl_buffer_char(b,',');
|
||||
hl_type_str_rec(b,t->fun->args[i],l);
|
||||
}
|
||||
hl_buffer_char(b,')');
|
||||
hl_buffer_char(b,')');
|
||||
break;
|
||||
case HSTRUCT:
|
||||
hl_buffer_char(b,'@');
|
||||
case HOBJ:
|
||||
hl_buffer_str(b,t->obj->name);
|
||||
break;
|
||||
case HREF:
|
||||
hl_buffer_str(b,USTR("ref<"));
|
||||
hl_type_str_rec(b,t->tparam,l);
|
||||
hl_buffer_char(b,'>');
|
||||
break;
|
||||
case HVIRTUAL:
|
||||
hl_buffer_str(b,USTR("virtual<"));
|
||||
for(i=0; i<t->virt->nfields; i++) {
|
||||
hl_obj_field *f = t->virt->fields + i;
|
||||
if( i ) hl_buffer_char(b,',');
|
||||
hl_buffer_str(b,f->name);
|
||||
hl_buffer_char(b,':');
|
||||
hl_type_str_rec(b,f->t,l);
|
||||
}
|
||||
hl_buffer_char(b,'>');
|
||||
break;
|
||||
case HABSTRACT:
|
||||
hl_buffer_str(b,t->abs_name);
|
||||
break;
|
||||
case HENUM:
|
||||
hl_buffer_str(b,USTR("enum"));
|
||||
if( t->tenum->name ) {
|
||||
hl_buffer_char(b,'<');
|
||||
hl_buffer_str(b,t->tenum->name);
|
||||
hl_buffer_char(b,'>');
|
||||
}
|
||||
break;
|
||||
case HNULL:
|
||||
hl_buffer_str(b,USTR("null<"));
|
||||
hl_type_str_rec(b,t->tparam,l);
|
||||
hl_buffer_char(b,'>');
|
||||
break;
|
||||
case HPACKED:
|
||||
hl_buffer_str(b, USTR("packed<"));
|
||||
hl_type_str_rec(b,t->tparam,l);
|
||||
hl_buffer_char(b,'>');
|
||||
break;
|
||||
default:
|
||||
hl_buffer_str(b,USTR("???"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
HL_PRIM const uchar *hl_type_str( hl_type *t ) {
|
||||
const uchar *c = TSTR[t->kind];
|
||||
hl_buffer *b;
|
||||
if( c != NULL )
|
||||
return c;
|
||||
b = hl_alloc_buffer();
|
||||
hl_type_str_rec(b,t,NULL);
|
||||
return hl_buffer_content(b,NULL);
|
||||
}
|
||||
|
||||
HL_PRIM vbyte* hl_type_name( hl_type *t ) {
|
||||
switch( t->kind ) {
|
||||
case HOBJ:
|
||||
case HSTRUCT:
|
||||
return (vbyte*)t->obj->name;
|
||||
case HENUM:
|
||||
return (vbyte*)t->tenum->name;
|
||||
case HABSTRACT:
|
||||
return (vbyte*)t->abs_name;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_mark_size( int data_size );
|
||||
|
||||
HL_PRIM void hl_init_enum( hl_type *et, hl_module_context *m ) {
|
||||
int i, j;
|
||||
int mark_size = 0;
|
||||
unsigned int *mark;
|
||||
for(i=0;i<et->tenum->nconstructs;i++) {
|
||||
hl_enum_construct *c = et->tenum->constructs + i;
|
||||
c->hasptr = false;
|
||||
c->size = sizeof(void*)+sizeof(int); // t + index
|
||||
for(j=0;j<c->nparams;j++) {
|
||||
hl_type *t = c->params[j];
|
||||
c->size += hl_pad_struct(c->size,t);
|
||||
c->offsets[j] = c->size;
|
||||
if( hl_is_ptr(t) ) c->hasptr = true;
|
||||
c->size += hl_type_size(t);
|
||||
}
|
||||
if( c->hasptr ) {
|
||||
int max_pos = i * sizeof(int) + hl_mark_size(c->size - HL_WSIZE*2);
|
||||
if( max_pos > mark_size ) mark_size = max_pos;
|
||||
}
|
||||
}
|
||||
|
||||
mark = (unsigned int*)hl_zalloc(&m->alloc,mark_size);
|
||||
for(i=0;i<et->tenum->nconstructs;i++) {
|
||||
hl_enum_construct *c = et->tenum->constructs + i;
|
||||
if( !c->hasptr ) continue;
|
||||
for(j=0;j<c->nparams;j++)
|
||||
if( hl_is_ptr(c->params[j]) ) {
|
||||
int pos = (c->offsets[j] / HL_WSIZE) - 2;
|
||||
mark[i + (pos >> 5)] |= 1 << (pos & 31);
|
||||
}
|
||||
}
|
||||
et->mark_bits = mark;
|
||||
}
|
||||
|
||||
HL_PRIM varray* hl_type_enum_fields( hl_type *t ) {
|
||||
varray *a = hl_alloc_array(&hlt_bytes,t->tenum->nconstructs);
|
||||
int i;
|
||||
for( i=0; i<t->tenum->nconstructs;i++)
|
||||
hl_aptr(a,vbyte*)[i] = (vbyte*)t->tenum->constructs[i].name;
|
||||
return a;
|
||||
}
|
||||
|
||||
HL_PRIM varray* hl_type_enum_values( hl_type *t ) {
|
||||
varray *a = hl_alloc_array(&hlt_dyn,t->tenum->nconstructs);
|
||||
int i;
|
||||
for( i=0; i<t->tenum->nconstructs;i++) {
|
||||
hl_enum_construct *c = t->tenum->constructs + i;
|
||||
if(c->nparams == 0)
|
||||
hl_aptr(a,venum*)[i] = hl_alloc_enum(t, i);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
HL_PRIM int hl_type_args_count( hl_type *t ) {
|
||||
if( t->kind == HFUN || t->kind == HMETHOD )
|
||||
return t->fun->nargs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
HL_PRIM varray *hl_type_instance_fields( hl_type *t ) {
|
||||
varray *a;
|
||||
const uchar **names;
|
||||
int mcount = 0;
|
||||
int out = 0;
|
||||
hl_type_obj *o;
|
||||
hl_runtime_obj *rt;
|
||||
if( t->kind == HVIRTUAL ) {
|
||||
int i;
|
||||
a = hl_alloc_array(&hlt_bytes,t->virt->nfields);
|
||||
names = hl_aptr(a,const uchar *);
|
||||
for(i=0;i<t->virt->nfields;i++)
|
||||
names[i] = t->virt->fields[i].name;
|
||||
return a;
|
||||
}
|
||||
if( t->kind != HOBJ && t->kind != HSTRUCT )
|
||||
return NULL;
|
||||
o = t->obj;
|
||||
while( true ) {
|
||||
int i;
|
||||
for(i=0;i<o->nproto;i++) {
|
||||
hl_obj_proto *p = o->proto + i;
|
||||
if( p->pindex < 0 ) mcount++;
|
||||
}
|
||||
if( o->super == NULL ) break;
|
||||
o = o->super->obj;
|
||||
}
|
||||
rt = hl_get_obj_rt(t);
|
||||
a = hl_alloc_array(&hlt_bytes,mcount + rt->nproto + rt->nfields);
|
||||
names = hl_aptr(a,const uchar*);
|
||||
o = t->obj;
|
||||
while( true ) {
|
||||
int i;
|
||||
int pproto = rt->parent ? rt->parent->nproto : 0;
|
||||
for(i=0;i<o->nproto;i++) {
|
||||
hl_obj_proto *p = o->proto + i;
|
||||
if( p->pindex < 0 || p->pindex >= pproto )
|
||||
names[out++] = p->name;
|
||||
}
|
||||
for(i=0;i<o->nfields;i++) {
|
||||
hl_obj_field *f = o->fields + i;
|
||||
names[out++] = f->name;
|
||||
}
|
||||
if( o->super == NULL ) break;
|
||||
o = o->super->obj;
|
||||
rt = o->rt;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
HL_PRIM hl_type *hl_type_super( hl_type *t ) {
|
||||
if( (t->kind == HOBJ || t->kind == HSTRUCT) && t->obj->super )
|
||||
return t->obj->super;
|
||||
return &hlt_void;
|
||||
}
|
||||
|
||||
HL_PRIM vdynamic *hl_type_get_global( hl_type *t ) {
|
||||
switch( t->kind ) {
|
||||
case HOBJ:
|
||||
case HSTRUCT:
|
||||
return t->obj->global_value ? *(vdynamic**)t->obj->global_value : NULL;
|
||||
case HENUM:
|
||||
return *(vdynamic**)t->tenum->global_value;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_type_set_global( hl_type *t, vdynamic *v ) {
|
||||
switch( t->kind ) {
|
||||
case HOBJ:
|
||||
case HSTRUCT:
|
||||
if( t->obj->global_value ) {
|
||||
*(vdynamic**)t->obj->global_value = v;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case HENUM:
|
||||
if( t->tenum->global_value ) {
|
||||
*(vdynamic**)t->tenum->global_value = v;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
HL_PRIM bool hl_type_enum_eq( venum *a, venum *b ) {
|
||||
int i;
|
||||
hl_enum_construct *c;
|
||||
if( a == b )
|
||||
return true;
|
||||
if( !a || !b || a->t != b->t )
|
||||
return false;
|
||||
if( a->index != b->index )
|
||||
return false;
|
||||
c = a->t->tenum->constructs + a->index;
|
||||
for(i=0;i<c->nparams;i++) {
|
||||
hl_type *t = c->params[i];
|
||||
switch( t->kind ) {
|
||||
case HENUM:
|
||||
{
|
||||
venum *pa = *(venum**)((char*)a + c->offsets[i]);
|
||||
venum *pb = *(venum**)((char*)b + c->offsets[i]);
|
||||
if( !hl_type_enum_eq(pa,pb) )
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
vdynamic *pa = hl_make_dyn((char*)a + c->offsets[i],t);
|
||||
vdynamic *pb = hl_make_dyn((char*)b + c->offsets[i],t);
|
||||
if( pa && pb && pa->t->kind == HENUM && pb->t->kind == HENUM ) {
|
||||
if( !hl_type_enum_eq((venum*)pa,(venum*)pb) )
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
if( hl_dyn_compare(pa,pb) )
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
HL_PRIM venum *hl_alloc_enum( hl_type *t, int index ) {
|
||||
hl_enum_construct *c = t->tenum->constructs + index;
|
||||
venum *v = (venum*)hl_gc_alloc_gen(t, c->size, MEM_KIND_DYNAMIC | (c->hasptr ? 0 : MEM_KIND_NOPTR) | MEM_ZERO);
|
||||
v->t = t;
|
||||
v->index = index;
|
||||
return v;
|
||||
}
|
||||
|
||||
HL_PRIM venum *hl_alloc_enum_dyn( hl_type *t, int index, varray *args, int nargs ) {
|
||||
hl_enum_construct *c = t->tenum->constructs + index;
|
||||
venum *e;
|
||||
int i;
|
||||
if( c->nparams < nargs || args->size < nargs )
|
||||
return NULL;
|
||||
if( nargs < c->nparams ) {
|
||||
// allow missing params if they are null-able
|
||||
for(i=nargs;i<c->nparams;i++)
|
||||
if( !hl_is_ptr(c->params[i]) )
|
||||
return NULL;
|
||||
}
|
||||
e = hl_alloc_enum(t, index);
|
||||
for(i=0;i<nargs;i++)
|
||||
hl_write_dyn((char*)e+c->offsets[i],c->params[i],hl_aptr(args,vdynamic*)[i],false);
|
||||
return e;
|
||||
}
|
||||
|
||||
HL_PRIM varray *hl_enum_parameters( venum *e ) {
|
||||
varray *a;
|
||||
hl_enum_construct *c = e->t->tenum->constructs + e->index;
|
||||
int i;
|
||||
a = hl_alloc_array(&hlt_dyn,c->nparams);
|
||||
for(i=0;i<c->nparams;i++)
|
||||
hl_aptr(a,vdynamic*)[i] = hl_make_dyn((char*)e+c->offsets[i],c->params[i]);
|
||||
return a;
|
||||
}
|
||||
|
||||
DEFINE_PRIM(_BYTES, type_str, _TYPE);
|
||||
DEFINE_PRIM(_BYTES, type_name, _TYPE);
|
||||
DEFINE_PRIM(_I32, type_args_count, _TYPE);
|
||||
DEFINE_PRIM(_ARR, type_instance_fields, _TYPE);
|
||||
DEFINE_PRIM(_TYPE, type_super, _TYPE);
|
||||
DEFINE_PRIM(_DYN, type_get_global, _TYPE);
|
||||
DEFINE_PRIM(_ARR, type_enum_fields, _TYPE);
|
||||
DEFINE_PRIM(_ARR, type_enum_values, _TYPE);
|
||||
DEFINE_PRIM(_BOOL, type_enum_eq, _DYN _DYN);
|
||||
DEFINE_PRIM(_DYN, alloc_enum_dyn, _TYPE _I32 _ARR _I32);
|
||||
DEFINE_PRIM(_ARR, enum_parameters, _DYN);
|
||||
DEFINE_PRIM(_BOOL, type_set_global, _TYPE _DYN);
|
||||
|
||||
|
||||
typedef struct {
|
||||
char *buf;
|
||||
int buf_pos;
|
||||
int buf_size;
|
||||
int *offsets;
|
||||
int offsets_pos;
|
||||
int offsets_size;
|
||||
void **lookup;
|
||||
int *lookup_index;
|
||||
int lookup_pos;
|
||||
int lookup_size;
|
||||
int *remap_target;
|
||||
int remap_pos;
|
||||
int remap_size;
|
||||
void **todos;
|
||||
int todos_pos;
|
||||
int todos_size;
|
||||
int flags;
|
||||
} mem_context;
|
||||
|
||||
#define compact_grow(buf,pos,size,req,type) \
|
||||
if( ctx->pos + req > ctx->size ) { \
|
||||
int nsize = ctx->size; \
|
||||
if( nsize == 0 ) nsize = 256 /sizeof(type); \
|
||||
while( nsize < ctx->pos + req ) nsize = (nsize * 3) / 2; \
|
||||
type *nbuf = (type*)malloc(nsize * sizeof(type)); \
|
||||
memcpy(nbuf,ctx->buf,ctx->pos * sizeof(type)); \
|
||||
free(ctx->buf); \
|
||||
ctx->buf = nbuf; \
|
||||
ctx->size = nsize; \
|
||||
}
|
||||
|
||||
|
||||
static void compact_write_mem( mem_context *ctx, void *mem, int size ) {
|
||||
compact_grow(buf,buf_pos,buf_size,size,char);
|
||||
memcpy(ctx->buf + ctx->buf_pos, mem, size);
|
||||
ctx->buf_pos += size;
|
||||
}
|
||||
|
||||
static void compact_write_ptr( mem_context *ctx, void *ptr ) {
|
||||
compact_write_mem(ctx,&ptr,sizeof(void*));
|
||||
}
|
||||
|
||||
static void compact_write_int( mem_context *ctx, int v ) {
|
||||
compact_write_mem(ctx,&v,4);
|
||||
}
|
||||
|
||||
static void compact_write_offset( mem_context *ctx, int position ) {
|
||||
compact_grow(offsets,offsets_pos,offsets_size,1,int);
|
||||
ctx->offsets[ctx->offsets_pos++] = ctx->buf_pos;
|
||||
compact_write_ptr(ctx,(void*)(int_val)position);
|
||||
}
|
||||
|
||||
static int compact_lookup_index( mem_context *ctx, void *addr ) {
|
||||
int min = 0;
|
||||
int max = ctx->lookup_pos;
|
||||
while( min < max ) {
|
||||
int mid = (min + max) >> 1;
|
||||
void *a = ctx->lookup[mid];
|
||||
if( a < addr ) min = mid + 1; else if( a > addr ) max = mid; else return mid;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define BYTE_MARK 0x40000000
|
||||
|
||||
static int compact_lookup_ref( mem_context *ctx, void *addr, bool is_bytes ) {
|
||||
int min = 0;
|
||||
int max = ctx->lookup_pos;
|
||||
while( min < max ) {
|
||||
int mid = (min + max) >> 1;
|
||||
void *a = ctx->lookup[mid];
|
||||
if( a < addr ) min = mid + 1; else if( a > addr ) max = mid; else return ctx->remap_target[ctx->lookup_index[mid]&~BYTE_MARK];
|
||||
}
|
||||
if( ctx->lookup_pos == ctx->lookup_size ) {
|
||||
int nsize = ctx->lookup_size == 0 ? 128 : (ctx->lookup_size * 3) / 2;
|
||||
void **nlookup = (void**)malloc(nsize * sizeof(void*));
|
||||
int *nindex = (int*)malloc(nsize * sizeof(int));
|
||||
memcpy(nlookup,ctx->lookup,ctx->lookup_pos * sizeof(void*));
|
||||
memcpy(nindex,ctx->lookup_index,ctx->lookup_pos * sizeof(int));
|
||||
free(ctx->lookup);
|
||||
free(ctx->lookup_index);
|
||||
ctx->lookup = nlookup;
|
||||
ctx->lookup_index = nindex;
|
||||
ctx->lookup_size = nsize;
|
||||
}
|
||||
int pos = (min + max) >> 1;
|
||||
memmove(ctx->lookup + pos + 1, ctx->lookup + pos, (ctx->lookup_pos - pos) * sizeof(void*));
|
||||
memmove(ctx->lookup_index + pos + 1, ctx->lookup_index + pos, (ctx->lookup_pos - pos) * sizeof(int));
|
||||
int id = ctx->lookup_pos++;
|
||||
ctx->lookup[pos] = addr;
|
||||
ctx->lookup_index[pos] = id | (is_bytes ? BYTE_MARK : 0);
|
||||
compact_grow(todos,todos_pos,todos_size,1,void*);
|
||||
ctx->todos[ctx->todos_pos++] = addr;
|
||||
compact_grow(remap_target,remap_pos,remap_size,1,int);
|
||||
int target = -id-1;
|
||||
ctx->remap_target[ctx->remap_pos++] = target;
|
||||
return target;
|
||||
}
|
||||
|
||||
static void compact_write_ref( mem_context *ctx, void *ptr, bool is_bytes ) {
|
||||
if( !ptr ) {
|
||||
compact_write_ptr(ctx, NULL);
|
||||
return;
|
||||
}
|
||||
int ref = compact_lookup_ref(ctx,ptr,is_bytes);
|
||||
compact_write_offset(ctx, ref);
|
||||
}
|
||||
|
||||
static void compact_write_data( mem_context *ctx, hl_type *t, void *addr ) {
|
||||
if( hl_is_dynamic(t) ) {
|
||||
vdynamic *v = *(vdynamic**)addr;
|
||||
if( v == NULL || (v->t->kind == HENUM && v->t->tenum->constructs[((venum*)v)->index].nparams == 0) ) {
|
||||
compact_write_ptr(ctx,v);
|
||||
return;
|
||||
}
|
||||
compact_write_ref(ctx,v,false);
|
||||
return;
|
||||
}
|
||||
switch( t->kind ) {
|
||||
case HUI8:
|
||||
compact_write_mem(ctx, addr, 1);
|
||||
break;
|
||||
case HUI16:
|
||||
compact_write_mem(ctx, addr, 2);
|
||||
break;
|
||||
case HI32:
|
||||
case HF32:
|
||||
compact_write_mem(ctx, addr, 4);
|
||||
break;
|
||||
case HF64:
|
||||
case HI64:
|
||||
compact_write_mem(ctx, addr, 8);
|
||||
break;
|
||||
case HBOOL:
|
||||
compact_write_mem(ctx, addr, sizeof(bool));
|
||||
break;
|
||||
case HBYTES:
|
||||
{
|
||||
void *bytes = *(void**)addr;
|
||||
if( bytes == NULL || !hl_is_gc_ptr(bytes) ) {
|
||||
compact_write_ptr(ctx, bytes);
|
||||
break;
|
||||
}
|
||||
compact_write_ref(ctx, bytes, true);
|
||||
}
|
||||
break;
|
||||
case HABSTRACT:
|
||||
hl_error("Unsupported abstract %s", t->abs_name);
|
||||
break;
|
||||
default:
|
||||
hl_error("Unsupported type %d", t->kind);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void compact_pad( mem_context *ctx, hl_type *t ) {
|
||||
int sz = hl_pad_size(ctx->buf_pos,t);
|
||||
ctx->buf_pos += sz;
|
||||
}
|
||||
|
||||
static void compact_write_content( mem_context *ctx, vdynamic *d ) {
|
||||
int i;
|
||||
hl_type *t = d->t;
|
||||
if( !hl_is_ptr(t) ) {
|
||||
compact_write_ptr(ctx, t);
|
||||
compact_write_mem(ctx,&d->v,hl_type_size(t));
|
||||
return;
|
||||
}
|
||||
switch( t->kind ) {
|
||||
case HOBJ: {
|
||||
char *obj_data = (char*)d;
|
||||
hl_runtime_obj *rt = hl_get_obj_rt(t);
|
||||
compact_grow(buf,buf_pos,buf_size,rt->size,char);
|
||||
memset(ctx->buf + ctx->buf_pos, 0xCD, rt->size);
|
||||
int buf_start = ctx->buf_pos;
|
||||
int fstart = rt->nfields;
|
||||
compact_write_ptr(ctx,t);
|
||||
while( t ) {
|
||||
fstart -= t->obj->nfields;
|
||||
for(i=0;i<t->obj->nfields;i++) {
|
||||
int fid = i + fstart;
|
||||
ctx->buf_pos = buf_start + rt->fields_indexes[fid];
|
||||
compact_write_data(ctx, t->obj->fields[i].t, obj_data + rt->fields_indexes[fid]);
|
||||
}
|
||||
t = t->obj->super;
|
||||
}
|
||||
ctx->buf_pos = buf_start + rt->size;
|
||||
break;
|
||||
}
|
||||
case HVIRTUAL: {
|
||||
vvirtual *v = (vvirtual*)d;
|
||||
int start = ctx->buf_pos;
|
||||
compact_write_ptr(ctx, t);
|
||||
if( ctx->flags & 4 )
|
||||
compact_write_offset(ctx, start); // virtual self value
|
||||
else if( ctx->flags & 2 )
|
||||
compact_write_ptr(ctx, NULL); // optimize virtuals
|
||||
else
|
||||
compact_write_data(ctx, &hlt_dyn, &v->value);
|
||||
compact_write_data(ctx, &hlt_dyn, &v->next);
|
||||
if( !v->value || (ctx->flags&6) ) {
|
||||
int target = ctx->buf_pos + t->virt->nfields * sizeof(void*);
|
||||
for(i=0;i<t->virt->nfields;i++) {
|
||||
hl_type *ft = t->virt->fields[i].t;
|
||||
target += hl_pad_size(target, ft);
|
||||
compact_write_offset(ctx, target);
|
||||
target += hl_type_size(ft);
|
||||
}
|
||||
for(i=0;i<t->virt->nfields;i++) {
|
||||
void *addr = ((void**)(v + 1))[i];
|
||||
hl_type *ft = t->virt->fields[i].t;
|
||||
compact_pad(ctx,ft);
|
||||
if( !addr ) {
|
||||
if( !hl_is_ptr(ft) ) hl_error("assert");
|
||||
compact_write_ptr(ctx,NULL);
|
||||
} else
|
||||
compact_write_data(ctx,ft,addr);
|
||||
}
|
||||
} else {
|
||||
vdynobj *obj = (vdynobj*)v->value;
|
||||
if( obj->t->kind != HDYNOBJ ) hl_error("assert");
|
||||
int todo_save = ctx->todos_pos;
|
||||
for(i=0;i<t->virt->nfields;i++) {
|
||||
void *addr = ((void**)(v + 1))[i];
|
||||
compact_write_ref(ctx, addr, false);
|
||||
}
|
||||
ctx->todos_pos = todo_save;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HDYNOBJ: {
|
||||
vdynobj *obj = (vdynobj*)d;
|
||||
int lookup_data = ctx->buf_pos + sizeof(vdynobj);
|
||||
int raw_data = lookup_data + obj->nfields * sizeof(hl_field_lookup);
|
||||
int values_data = raw_data + obj->raw_size;
|
||||
values_data += hl_pad_size(values_data,&hlt_dyn);
|
||||
|
||||
compact_write_ptr(ctx, t);
|
||||
if( obj->lookup )
|
||||
compact_write_offset(ctx, lookup_data);
|
||||
else
|
||||
compact_write_ptr(ctx, NULL);
|
||||
if( obj->raw_data )
|
||||
compact_write_offset(ctx, raw_data);
|
||||
else
|
||||
compact_write_ptr(ctx, NULL);
|
||||
if( obj->values )
|
||||
compact_write_offset(ctx, values_data);
|
||||
else
|
||||
compact_write_ptr(ctx, NULL);
|
||||
compact_write_int(ctx,obj->nfields);
|
||||
compact_write_int(ctx,obj->raw_size);
|
||||
compact_write_int(ctx,obj->nvalues);
|
||||
# ifdef HL_64
|
||||
compact_write_int(ctx,0);
|
||||
# endif
|
||||
compact_write_ref(ctx,obj->virtuals,false);
|
||||
if( obj->lookup )
|
||||
compact_write_mem(ctx,obj->lookup,sizeof(hl_field_lookup) * obj->nfields);
|
||||
if( obj->raw_data )
|
||||
compact_write_mem(ctx,obj->raw_data,obj->raw_size);
|
||||
if( obj->values ) {
|
||||
compact_pad(ctx,&hlt_dyn);
|
||||
for(i=0;i<obj->nvalues;i++) {
|
||||
int j;
|
||||
for(j=0;i<obj->nfields;j++) {
|
||||
if( obj->lookup[j].field_index == i && hl_is_ptr(obj->lookup[j].t) ) {
|
||||
compact_write_data(ctx, obj->lookup[j].t, obj->values + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int save_pos = ctx->todos_pos;
|
||||
for(i=0;i<obj->nfields;i++) {
|
||||
hl_field_lookup *f = obj->lookup + i;
|
||||
int idx = compact_lookup_ref(ctx, hl_is_ptr(f->t) ? (char*)(obj->values + f->field_index) : (char*)(obj->raw_data + f->field_index), false);
|
||||
idx = -idx-1;
|
||||
ctx->remap_target[idx] = hl_is_ptr(f->t) ? values_data + sizeof(void*)*f->field_index : raw_data + f->field_index;
|
||||
}
|
||||
ctx->todos_pos = save_pos;
|
||||
break;
|
||||
}
|
||||
case HARRAY: {
|
||||
varray *a = (varray*)d;
|
||||
compact_write_ptr(ctx, a->t);
|
||||
compact_write_ptr(ctx, a->at);
|
||||
compact_write_int(ctx, a->size);
|
||||
compact_write_int(ctx, 0);
|
||||
char *array_data = (char*)(a + 1);
|
||||
int stride = hl_type_size(a->at);
|
||||
for(i=0;i<a->size;i++) {
|
||||
compact_write_data(ctx,a->at, array_data + stride * i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HENUM: {
|
||||
venum *e = (venum*)d;
|
||||
hl_enum_construct *c = &t->tenum->constructs[e->index];
|
||||
int buf_start = ctx->buf_pos;
|
||||
compact_write_ptr(ctx, e->t);
|
||||
compact_write_int(ctx, e->index);
|
||||
for(i=0;i<c->nparams;i++) {
|
||||
compact_pad(ctx,c->params[i]);
|
||||
compact_write_data(ctx,c->params[i],(char*)e+(ctx->buf_pos-buf_start));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
hl_error("Unsupported type %d", t->kind);
|
||||
}
|
||||
}
|
||||
|
||||
HL_PRIM vdynamic *hl_mem_compact( vdynamic *d, varray *exclude, int flags, int *outCount ) {
|
||||
mem_context _ctx;
|
||||
mem_context *ctx = &_ctx;
|
||||
int i;
|
||||
int object_count = 0;
|
||||
memset(ctx,0,sizeof(mem_context));
|
||||
ctx->flags = flags;
|
||||
compact_lookup_ref(ctx,d,false);
|
||||
if( exclude ) {
|
||||
for(i=0;i<exclude->size;i++) {
|
||||
vdynamic *ptr = (vdynamic*)hl_aptr(exclude,void*)[i];
|
||||
compact_lookup_ref(ctx,ptr,false);
|
||||
ctx->todos_pos--;
|
||||
}
|
||||
}
|
||||
while( ctx->todos_pos > 0 ) {
|
||||
void *addr = ctx->todos[--ctx->todos_pos];
|
||||
int pos = compact_lookup_index(ctx, addr);
|
||||
int index = ctx->lookup_index[pos];
|
||||
compact_pad(ctx, &hlt_dyn);
|
||||
ctx->remap_target[index&~BYTE_MARK] = ctx->buf_pos;
|
||||
if( index & BYTE_MARK ) {
|
||||
int size = hl_gc_get_memsize(addr);
|
||||
if( size < 0 ) hl_error("assert");
|
||||
compact_write_mem(ctx, addr, size);
|
||||
} else
|
||||
compact_write_content(ctx, (vdynamic*)addr);
|
||||
object_count++;
|
||||
}
|
||||
vbyte *data = NULL;
|
||||
# ifdef HL_WIN
|
||||
if( flags & 1 )
|
||||
data = (vbyte*)VirtualAlloc(NULL,ctx->buf_pos,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);
|
||||
# endif
|
||||
if( data == NULL )
|
||||
data = hl_gc_alloc_noptr(ctx->buf_pos);
|
||||
memcpy(data,ctx->buf,ctx->buf_pos);
|
||||
int exclude_count = exclude ? exclude->size : 0;
|
||||
for(i=0;i<ctx->offsets_pos;i++) {
|
||||
int pos = ctx->offsets[i];
|
||||
int target = *(int*)(data + pos);
|
||||
if( target < 0 ) {
|
||||
int eid = -target-1;
|
||||
if( eid > 0 && eid <= exclude_count ) {
|
||||
*(void**)(data+pos) = hl_aptr(exclude,void*)[eid-1];
|
||||
continue;
|
||||
}
|
||||
target = ctx->remap_target[eid];
|
||||
}
|
||||
*(void**)(data+pos) = data + target;
|
||||
}
|
||||
free(ctx->buf);
|
||||
free(ctx->offsets);
|
||||
free(ctx->lookup);
|
||||
free(ctx->lookup_index);
|
||||
free(ctx->remap_target);
|
||||
free(ctx->todos);
|
||||
# ifdef HL_WIN
|
||||
if( flags & 1 ) {
|
||||
DWORD old = 0;
|
||||
VirtualProtect(data,ctx->buf_pos,PAGE_READONLY,&old);
|
||||
}
|
||||
# endif
|
||||
if( outCount )
|
||||
*outCount = object_count;
|
||||
return (vdynamic*)data;
|
||||
}
|
||||
|
||||
DEFINE_PRIM(_DYN, mem_compact, _DYN _ARR _I32 _REF(_I32));
|
274
Kha/Backends/Kinc-HL/hl/src/std/ucs2.c
Normal file
274
Kha/Backends/Kinc-HL/hl/src/std/ucs2.c
Normal file
@ -0,0 +1,274 @@
|
||||
/*
|
||||
* Copyright (C)2005-2016 Haxe Foundation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <hl.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifndef HL_NATIVE_UCHAR_FUN
|
||||
|
||||
#ifdef HL_ANDROID
|
||||
# include <android/log.h>
|
||||
# ifndef HL_ANDROID_LOG_TAG
|
||||
# define HL_ANDROID_LOG_TAG "hl"
|
||||
# endif
|
||||
# ifndef HL_ANDROID_LOG_LEVEL
|
||||
# define HL_ANDROID_LOG_LEVEL ANDROID_LOG_DEBUG
|
||||
# endif
|
||||
# define LOG_ANDROID(cfmt,cstr) __android_log_print(HL_ANDROID_LOG_LEVEL, HL_ANDROID_LOG_TAG, cfmt, cstr);
|
||||
#endif
|
||||
|
||||
int ustrlen( const uchar *str ) {
|
||||
const uchar *p = str;
|
||||
while( *p ) p++;
|
||||
return (int)(p - str);
|
||||
}
|
||||
|
||||
static int ustrlen_utf8( const uchar *str ) {
|
||||
int size = 0;
|
||||
while(1) {
|
||||
uchar c = *str++;
|
||||
if( c == 0 ) break;
|
||||
if( c < 0x80 )
|
||||
size++;
|
||||
else if( c < 0x800 )
|
||||
size += 2;
|
||||
else if( c >= 0xD800 && c <= 0xDFFF ) {
|
||||
str++;
|
||||
size += 4;
|
||||
} else
|
||||
size += 3;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
uchar *ustrdup( const uchar *str ) {
|
||||
int len = ustrlen(str);
|
||||
int size = (len + 1) << 1;
|
||||
uchar *d = (uchar*)malloc(size);
|
||||
memcpy(d,str,size);
|
||||
return d;
|
||||
}
|
||||
|
||||
double utod( const uchar *str, uchar **end ) {
|
||||
char buf[31];
|
||||
char *bend;
|
||||
double result;
|
||||
int i = 0;
|
||||
while( i < 30 ) {
|
||||
int c = str[i];
|
||||
if( (c < '0' || c > '9') && c != '.' && c != 'e' && c != 'E' && c != '-' && c != '+' )
|
||||
break;
|
||||
buf[i++] = (char)c;
|
||||
}
|
||||
buf[i] = 0;
|
||||
result = strtod(buf,&bend);
|
||||
*end = str + (bend - buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
int utoi( const uchar *str, uchar **end ) {
|
||||
char buf[17];
|
||||
char *bend;
|
||||
int result;
|
||||
int i = 0;
|
||||
uchar sign = str[0];
|
||||
if( sign == '-' || sign == '+' ) {
|
||||
buf[i++] = (char)sign;
|
||||
}
|
||||
while( i < 16 ) {
|
||||
int c = str[i];
|
||||
if( c < '0' || c > '9' )
|
||||
break;
|
||||
buf[i++] = (char)c;
|
||||
}
|
||||
buf[i] = 0;
|
||||
result = strtol(buf,&bend,10);
|
||||
*end = str + (bend - buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
int ucmp( const uchar *a, const uchar *b ) {
|
||||
while(true) {
|
||||
int d = (unsigned)*a - (unsigned)*b;
|
||||
if( d ) return d;
|
||||
if( !*a ) return 0;
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
}
|
||||
|
||||
int usprintf( uchar *out, int out_size, const uchar *fmt, ... ) {
|
||||
va_list args;
|
||||
int ret;
|
||||
va_start(args, fmt);
|
||||
ret = uvszprintf(out, out_size, fmt, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// USE UTF-8 encoding
|
||||
int utostr( char *out, int out_size, const uchar *str ) {
|
||||
char *start = out;
|
||||
char *end = out + out_size - 1; // final 0
|
||||
if( out_size <= 0 ) return 0;
|
||||
while( out < end ) {
|
||||
unsigned int c = *str++;
|
||||
if( c == 0 ) break;
|
||||
if( c < 0x80 )
|
||||
*out++ = (char)c;
|
||||
else if( c < 0x800 ) {
|
||||
if( out + 2 > end ) break;
|
||||
*out++ = (char)(0xC0|(c>>6));
|
||||
*out++ = 0x80|(c&63);
|
||||
} else if( c >= 0xD800 && c <= 0xDFFF ) { // surrogate pair
|
||||
if( out + 4 > end ) break;
|
||||
unsigned int full = (((c - 0xD800) << 10) | ((*str++) - 0xDC00)) + 0x10000;
|
||||
*out++ = (char)(0xF0|(full>>18));
|
||||
*out++ = 0x80|((full>>12)&63);
|
||||
*out++ = 0x80|((full>>6)&63);
|
||||
*out++ = 0x80|(full&63);
|
||||
} else {
|
||||
if( out + 3 > end ) break;
|
||||
*out++ = (char)(0xE0|(c>>12));
|
||||
*out++ = 0x80|((c>>6)&63);
|
||||
*out++ = 0x80|(c&63);
|
||||
}
|
||||
}
|
||||
*out = 0;
|
||||
return (int)(out - start);
|
||||
}
|
||||
|
||||
static char *utos( const uchar *s ) {
|
||||
int len = ustrlen_utf8(s);
|
||||
char *out = (char*)malloc(len + 1);
|
||||
if( utostr(out,len+1,s) < 0 )
|
||||
*out = 0;
|
||||
return out;
|
||||
}
|
||||
|
||||
void uprintf( const uchar *fmt, const uchar *str ) {
|
||||
char *cfmt = utos(fmt);
|
||||
char *cstr = utos(str);
|
||||
#ifdef HL_ANDROID
|
||||
LOG_ANDROID(cfmt,cstr);
|
||||
#else
|
||||
printf(cfmt,cstr);
|
||||
#endif
|
||||
free(cfmt);
|
||||
free(cstr);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(HL_NATIVE_UCHAR_FUN) || defined(HL_WIN)
|
||||
|
||||
#ifdef HL_VCC
|
||||
#pragma warning(disable:4774)
|
||||
#endif
|
||||
|
||||
HL_PRIM int uvszprintf( uchar *out, int out_size, const uchar *fmt, va_list arglist ) {
|
||||
uchar *start = out;
|
||||
uchar *end = out + out_size - 1;
|
||||
char cfmt[20];
|
||||
char tmp[32];
|
||||
uchar c;
|
||||
while(true) {
|
||||
sprintf_loop:
|
||||
c = *fmt++;
|
||||
if( out == end ) c = 0;
|
||||
switch( c ) {
|
||||
case 0:
|
||||
*out = 0;
|
||||
return (int)(out - start);
|
||||
case '%':
|
||||
{
|
||||
int i = 0, size = 0;
|
||||
cfmt[i++] = '%';
|
||||
while( true ) {
|
||||
c = *fmt++;
|
||||
cfmt[i++] = (char)c;
|
||||
switch( c ) {
|
||||
case 'd':
|
||||
cfmt[i++] = 0;
|
||||
if( cfmt[i-3] == 'l' ) {
|
||||
size = sprintf(tmp,cfmt,va_arg(arglist,int64));
|
||||
} else {
|
||||
size = sprintf(tmp,cfmt,va_arg(arglist,int));
|
||||
}
|
||||
goto sprintf_add;
|
||||
case 'f':
|
||||
cfmt[i++] = 0;
|
||||
size = sprintf(tmp,cfmt,va_arg(arglist,double)); // according to GCC warning, float is promoted to double in var_args
|
||||
goto sprintf_add;
|
||||
case 'g':
|
||||
cfmt[i++] = 0;
|
||||
size = sprintf(tmp,cfmt,va_arg(arglist,double));
|
||||
goto sprintf_add;
|
||||
case 'x':
|
||||
case 'X':
|
||||
cfmt[i++] = 0;
|
||||
if( cfmt[i-3] == 'l' )
|
||||
size = sprintf(tmp,cfmt,va_arg(arglist,void*));
|
||||
else
|
||||
size = sprintf(tmp,cfmt,va_arg(arglist,int));
|
||||
goto sprintf_add;
|
||||
case 's':
|
||||
if( i != 2 ) hl_fatal("Unsupported printf format"); // no support for precision qualifier
|
||||
{
|
||||
uchar *s = va_arg(arglist,uchar *);
|
||||
while( *s && out < end )
|
||||
*out++ = *s++;
|
||||
goto sprintf_loop;
|
||||
}
|
||||
case '.':
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case 'l':
|
||||
break;
|
||||
default:
|
||||
hl_fatal("Unsupported printf format");
|
||||
break;
|
||||
}
|
||||
}
|
||||
sprintf_add:
|
||||
// copy from c string to u string
|
||||
i = 0;
|
||||
while( i < size && out < end )
|
||||
*out++ = tmp[i++];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
*out++ = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
97
Kha/Backends/Kinc-HL/hl/src/std/unicase.h
Normal file
97
Kha/Backends/Kinc-HL/hl/src/std/unicase.h
Normal file
@ -0,0 +1,97 @@
|
||||
#define UL_BITS 6
|
||||
#define UL_SIZE 64
|
||||
static uchar _E[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar L1[UL_SIZE] = {0,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar L3[UL_SIZE] = {224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,0,248,249,250,251,252,253,254,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar L4[UL_SIZE] = {257,0,259,0,261,0,263,0,265,0,267,0,269,0,271,0,273,0,275,0,277,0,279,0,281,0,283,0,285,0,287,0,289,0,291,0,293,0,295,0,297,0,299,0,301,0,303,0,105,0,307,0,309,0,311,0,0,314,0,316,0,318,0,320};
|
||||
static uchar L5[UL_SIZE] = {0,322,0,324,0,326,0,328,0,0,331,0,333,0,335,0,337,0,339,0,341,0,343,0,345,0,347,0,349,0,351,0,353,0,355,0,357,0,359,0,361,0,363,0,365,0,367,0,369,0,371,0,373,0,375,0,255,378,0,380,0,382,0,0};
|
||||
static uchar L6[UL_SIZE] = {0,595,387,0,389,0,596,392,0,598,599,396,0,0,477,601,603,402,0,608,611,0,617,616,409,0,0,0,623,626,0,629,417,0,419,0,421,0,640,424,0,643,0,0,429,0,648,432,0,650,651,436,0,438,0,658,441,0,0,0,445,0,0,0};
|
||||
static uchar L7[UL_SIZE] = {0,0,0,0,454,454,0,457,457,0,460,460,0,462,0,464,0,466,0,468,0,470,0,472,0,474,0,476,0,0,479,0,481,0,483,0,485,0,487,0,489,0,491,0,493,0,495,0,0,499,499,0,501,0,405,447,505,0,507,0,509,0,511,0};
|
||||
static uchar L8[UL_SIZE] = {513,0,515,0,517,0,519,0,521,0,523,0,525,0,527,0,529,0,531,0,533,0,535,0,537,0,539,0,541,0,543,0,414,0,547,0,549,0,551,0,553,0,555,0,557,0,559,0,561,0,563,0,0,0,0,0,0,0,11365,572,0,410,11366,0};
|
||||
static uchar L9[UL_SIZE] = {0,578,0,384,649,652,583,0,585,0,587,0,589,0,591,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar L13[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,881,0,883,0,0,0,887,0,0,0,0,0,0,0,0,1011};
|
||||
static uchar L14[UL_SIZE] = {0,0,0,0,0,0,940,0,941,942,943,0,972,0,973,974,0,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,0,963,964,965,966,967,968,969,970,971,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar L15[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,983,0,0,0,0,0,0,0,0,985,0,987,0,989,0,991,0,993,0,995,0,997,0,999,0,1001,0,1003,0,1005,0,1007,0,0,0,0,0,952,0,0,1016,0,1010,1019,0,0,891,892,893};
|
||||
static uchar L16[UL_SIZE] = {1104,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1117,1118,1119,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar L17[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1121,0,1123,0,1125,0,1127,0,1129,0,1131,0,1133,0,1135,0,1137,0,1139,0,1141,0,1143,0,1145,0,1147,0,1149,0,1151,0};
|
||||
static uchar L18[UL_SIZE] = {1153,0,0,0,0,0,0,0,0,0,1163,0,1165,0,1167,0,1169,0,1171,0,1173,0,1175,0,1177,0,1179,0,1181,0,1183,0,1185,0,1187,0,1189,0,1191,0,1193,0,1195,0,1197,0,1199,0,1201,0,1203,0,1205,0,1207,0,1209,0,1211,0,1213,0,1215,0};
|
||||
static uchar L19[UL_SIZE] = {1231,1218,0,1220,0,1222,0,1224,0,1226,0,1228,0,1230,0,0,1233,0,1235,0,1237,0,1239,0,1241,0,1243,0,1245,0,1247,0,1249,0,1251,0,1253,0,1255,0,1257,0,1259,0,1261,0,1263,0,1265,0,1267,0,1269,0,1271,0,1273,0,1275,0,1277,0,1279,0};
|
||||
static uchar L20[UL_SIZE] = {1281,0,1283,0,1285,0,1287,0,1289,0,1291,0,1293,0,1295,0,1297,0,1299,0,1301,0,1303,0,1305,0,1307,0,1309,0,1311,0,1313,0,1315,0,1317,0,1319,0,1321,0,1323,0,1325,0,1327,0,0,1377,1378,1379,1380,1381,1382,1383,1384,1385,1386,1387,1388,1389,1390,1391};
|
||||
static uchar L21[UL_SIZE] = {1392,1393,1394,1395,1396,1397,1398,1399,1400,1401,1402,1403,1404,1405,1406,1407,1408,1409,1410,1411,1412,1413,1414,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar L66[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11520,11521,11522,11523,11524,11525,11526,11527,11528,11529,11530,11531,11532,11533,11534,11535,11536,11537,11538,11539,11540,11541,11542,11543,11544,11545,11546,11547,11548,11549,11550,11551};
|
||||
static uchar L67[UL_SIZE] = {11552,11553,11554,11555,11556,11557,0,11559,0,0,0,0,0,11565,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar L78[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,43888,43889,43890,43891,43892,43893,43894,43895,43896,43897,43898,43899,43900,43901,43902,43903,43904,43905,43906,43907,43908,43909,43910,43911,43912,43913,43914,43915,43916,43917,43918,43919};
|
||||
static uchar L79[UL_SIZE] = {43920,43921,43922,43923,43924,43925,43926,43927,43928,43929,43930,43931,43932,43933,43934,43935,43936,43937,43938,43939,43940,43941,43942,43943,43944,43945,43946,43947,43948,43949,43950,43951,43952,43953,43954,43955,43956,43957,43958,43959,43960,43961,43962,43963,43964,43965,43966,43967,5112,5113,5114,5115,5116,5117,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar L120[UL_SIZE] = {7681,0,7683,0,7685,0,7687,0,7689,0,7691,0,7693,0,7695,0,7697,0,7699,0,7701,0,7703,0,7705,0,7707,0,7709,0,7711,0,7713,0,7715,0,7717,0,7719,0,7721,0,7723,0,7725,0,7727,0,7729,0,7731,0,7733,0,7735,0,7737,0,7739,0,7741,0,7743,0};
|
||||
static uchar L121[UL_SIZE] = {7745,0,7747,0,7749,0,7751,0,7753,0,7755,0,7757,0,7759,0,7761,0,7763,0,7765,0,7767,0,7769,0,7771,0,7773,0,7775,0,7777,0,7779,0,7781,0,7783,0,7785,0,7787,0,7789,0,7791,0,7793,0,7795,0,7797,0,7799,0,7801,0,7803,0,7805,0,7807,0};
|
||||
static uchar L122[UL_SIZE] = {7809,0,7811,0,7813,0,7815,0,7817,0,7819,0,7821,0,7823,0,7825,0,7827,0,7829,0,0,0,0,0,0,0,0,0,223,0,7841,0,7843,0,7845,0,7847,0,7849,0,7851,0,7853,0,7855,0,7857,0,7859,0,7861,0,7863,0,7865,0,7867,0,7869,0,7871,0};
|
||||
static uchar L123[UL_SIZE] = {7873,0,7875,0,7877,0,7879,0,7881,0,7883,0,7885,0,7887,0,7889,0,7891,0,7893,0,7895,0,7897,0,7899,0,7901,0,7903,0,7905,0,7907,0,7909,0,7911,0,7913,0,7915,0,7917,0,7919,0,7921,0,7923,0,7925,0,7927,0,7929,0,7931,0,7933,0,7935,0};
|
||||
static uchar L124[UL_SIZE] = {0,0,0,0,0,0,0,0,7936,7937,7938,7939,7940,7941,7942,7943,0,0,0,0,0,0,0,0,7952,7953,7954,7955,7956,7957,0,0,0,0,0,0,0,0,0,0,7968,7969,7970,7971,7972,7973,7974,7975,0,0,0,0,0,0,0,0,7984,7985,7986,7987,7988,7989,7990,7991};
|
||||
static uchar L125[UL_SIZE] = {0,0,0,0,0,0,0,0,8000,8001,8002,8003,8004,8005,0,0,0,0,0,0,0,0,0,0,0,8017,0,8019,0,8021,0,8023,0,0,0,0,0,0,0,0,8032,8033,8034,8035,8036,8037,8038,8039,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar L126[UL_SIZE] = {0,0,0,0,0,0,0,0,8064,8065,8066,8067,8068,8069,8070,8071,0,0,0,0,0,0,0,0,8080,8081,8082,8083,8084,8085,8086,8087,0,0,0,0,0,0,0,0,8096,8097,8098,8099,8100,8101,8102,8103,0,0,0,0,0,0,0,0,8112,8113,8048,8049,8115,0,0,0};
|
||||
static uchar L127[UL_SIZE] = {0,0,0,0,0,0,0,0,8050,8051,8052,8053,8131,0,0,0,0,0,0,0,0,0,0,0,8144,8145,8054,8055,0,0,0,0,0,0,0,0,0,0,0,0,8160,8161,8058,8059,8165,0,0,0,0,0,0,0,0,0,0,0,8056,8057,8060,8061,8179,0,0,0};
|
||||
static uchar L132[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,969,0,0,0,107,229,0,0,0,0,0,0,8526,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar L133[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8560,8561,8562,8563,8564,8565,8566,8567,8568,8569,8570,8571,8572,8573,8574,8575,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar L134[UL_SIZE] = {0,0,0,8580,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar L146[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9424,9425,9426,9427,9428,9429,9430,9431,9432,9433};
|
||||
static uchar L147[UL_SIZE] = {9434,9435,9436,9437,9438,9439,9440,9441,9442,9443,9444,9445,9446,9447,9448,9449,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar L176[UL_SIZE] = {11312,11313,11314,11315,11316,11317,11318,11319,11320,11321,11322,11323,11324,11325,11326,11327,11328,11329,11330,11331,11332,11333,11334,11335,11336,11337,11338,11339,11340,11341,11342,11343,11344,11345,11346,11347,11348,11349,11350,11351,11352,11353,11354,11355,11356,11357,11358,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar L177[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11361,0,619,7549,637,0,0,11368,0,11370,0,11372,0,593,625,592,594,0,11379,0,0,11382,0,0,0,0,0,0,0,0,575,576};
|
||||
static uchar L178[UL_SIZE] = {11393,0,11395,0,11397,0,11399,0,11401,0,11403,0,11405,0,11407,0,11409,0,11411,0,11413,0,11415,0,11417,0,11419,0,11421,0,11423,0,11425,0,11427,0,11429,0,11431,0,11433,0,11435,0,11437,0,11439,0,11441,0,11443,0,11445,0,11447,0,11449,0,11451,0,11453,0,11455,0};
|
||||
static uchar L179[UL_SIZE] = {11457,0,11459,0,11461,0,11463,0,11465,0,11467,0,11469,0,11471,0,11473,0,11475,0,11477,0,11479,0,11481,0,11483,0,11485,0,11487,0,11489,0,11491,0,0,0,0,0,0,0,0,11500,0,11502,0,0,0,0,11507,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar L665[UL_SIZE] = {42561,0,42563,0,42565,0,42567,0,42569,0,42571,0,42573,0,42575,0,42577,0,42579,0,42581,0,42583,0,42585,0,42587,0,42589,0,42591,0,42593,0,42595,0,42597,0,42599,0,42601,0,42603,0,42605,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar L666[UL_SIZE] = {42625,0,42627,0,42629,0,42631,0,42633,0,42635,0,42637,0,42639,0,42641,0,42643,0,42645,0,42647,0,42649,0,42651,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar L668[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42787,0,42789,0,42791,0,42793,0,42795,0,42797,0,42799,0,0,0,42803,0,42805,0,42807,0,42809,0,42811,0,42813,0,42815,0};
|
||||
static uchar L669[UL_SIZE] = {42817,0,42819,0,42821,0,42823,0,42825,0,42827,0,42829,0,42831,0,42833,0,42835,0,42837,0,42839,0,42841,0,42843,0,42845,0,42847,0,42849,0,42851,0,42853,0,42855,0,42857,0,42859,0,42861,0,42863,0,0,0,0,0,0,0,0,0,0,42874,0,42876,0,7545,42879,0};
|
||||
static uchar L670[UL_SIZE] = {42881,0,42883,0,42885,0,42887,0,0,0,0,42892,0,613,0,0,42897,0,42899,0,0,0,42903,0,42905,0,42907,0,42909,0,42911,0,42913,0,42915,0,42917,0,42919,0,42921,0,614,604,609,620,0,0,670,647,669,43859,42933,0,42935,0,0,0,0,0,0,0,0,0};
|
||||
static uchar L1020[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65345,65346,65347,65348,65349,65350,65351,65352,65353,65354,65355,65356,65357,65358,65359,65360,65361,65362,65363,65364,65365,65366,65367,65368,65369,65370,0,0,0,0,0};
|
||||
static uchar U1[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,0,0,0,0,0};
|
||||
static uchar U2[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,924,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar U3[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,0,216,217,218,219,220,221,222,376};
|
||||
static uchar U4[UL_SIZE] = {0,256,0,258,0,260,0,262,0,264,0,266,0,268,0,270,0,272,0,274,0,276,0,278,0,280,0,282,0,284,0,286,0,288,0,290,0,292,0,294,0,296,0,298,0,300,0,302,0,73,0,306,0,308,0,310,0,0,313,0,315,0,317,0};
|
||||
static uchar U5[UL_SIZE] = {319,0,321,0,323,0,325,0,327,0,0,330,0,332,0,334,0,336,0,338,0,340,0,342,0,344,0,346,0,348,0,350,0,352,0,354,0,356,0,358,0,360,0,362,0,364,0,366,0,368,0,370,0,372,0,374,0,0,377,0,379,0,381,83};
|
||||
static uchar U6[UL_SIZE] = {579,0,0,386,0,388,0,0,391,0,0,0,395,0,0,0,0,0,401,0,0,502,0,0,0,408,573,0,0,0,544,0,0,416,0,418,0,420,0,0,423,0,0,0,0,428,0,0,431,0,0,0,435,0,437,0,0,440,0,0,0,444,0,503};
|
||||
static uchar U7[UL_SIZE] = {0,0,0,0,453,453,453,456,456,456,459,459,459,0,461,0,463,0,465,0,467,0,469,0,471,0,473,0,475,398,0,478,0,480,0,482,0,484,0,486,0,488,0,490,0,492,0,494,0,498,498,498,0,500,0,0,0,504,0,506,0,508,0,510};
|
||||
static uchar U8[UL_SIZE] = {0,512,0,514,0,516,0,518,0,520,0,522,0,524,0,526,0,528,0,530,0,532,0,534,0,536,0,538,0,540,0,542,0,0,0,546,0,548,0,550,0,552,0,554,0,556,0,558,0,560,0,562,0,0,0,0,0,0,0,0,571,0,0,11390};
|
||||
static uchar U9[UL_SIZE] = {11391,0,577,0,0,0,0,582,0,584,0,586,0,588,0,590,11375,11373,11376,385,390,0,393,394,0,399,0,400,42923,0,0,0,403,42924,0,404,0,42893,42922,0,407,406,0,11362,42925,0,0,412,0,11374,413,0,0,415,0,0,0,0,0,0,0,11364,0,0};
|
||||
static uchar U10[UL_SIZE] = {422,0,0,425,0,0,0,42929,430,580,433,434,581,0,0,0,0,0,439,0,0,0,0,0,0,0,0,0,0,42930,42928,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar U13[UL_SIZE] = {0,0,0,0,0,921,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,880,0,882,0,0,0,886,0,0,0,1021,1022,1023,0,0};
|
||||
static uchar U14[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,902,904,905,906,0,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927};
|
||||
static uchar U15[UL_SIZE] = {928,929,931,931,932,933,934,935,936,937,938,939,908,910,911,0,914,920,0,0,0,934,928,975,0,984,0,986,0,988,0,990,0,992,0,994,0,996,0,998,0,1000,0,1002,0,1004,0,1006,922,929,1017,895,0,917,0,0,1015,0,0,1018,0,0,0,0};
|
||||
static uchar U16[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055};
|
||||
static uchar U17[UL_SIZE] = {1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,0,1120,0,1122,0,1124,0,1126,0,1128,0,1130,0,1132,0,1134,0,1136,0,1138,0,1140,0,1142,0,1144,0,1146,0,1148,0,1150};
|
||||
static uchar U18[UL_SIZE] = {0,1152,0,0,0,0,0,0,0,0,0,1162,0,1164,0,1166,0,1168,0,1170,0,1172,0,1174,0,1176,0,1178,0,1180,0,1182,0,1184,0,1186,0,1188,0,1190,0,1192,0,1194,0,1196,0,1198,0,1200,0,1202,0,1204,0,1206,0,1208,0,1210,0,1212,0,1214};
|
||||
static uchar U19[UL_SIZE] = {0,0,1217,0,1219,0,1221,0,1223,0,1225,0,1227,0,1229,1216,0,1232,0,1234,0,1236,0,1238,0,1240,0,1242,0,1244,0,1246,0,1248,0,1250,0,1252,0,1254,0,1256,0,1258,0,1260,0,1262,0,1264,0,1266,0,1268,0,1270,0,1272,0,1274,0,1276,0,1278};
|
||||
static uchar U20[UL_SIZE] = {0,1280,0,1282,0,1284,0,1286,0,1288,0,1290,0,1292,0,1294,0,1296,0,1298,0,1300,0,1302,0,1304,0,1306,0,1308,0,1310,0,1312,0,1314,0,1316,0,1318,0,1320,0,1322,0,1324,0,1326,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar U21[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359};
|
||||
static uchar U22[UL_SIZE] = {1360,1361,1362,1363,1364,1365,1366,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar U79[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5104,5105,5106,5107,5108,5109,0,0};
|
||||
static uchar U117[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42877,0,0,0,11363,0,0};
|
||||
static uchar U120[UL_SIZE] = {0,7680,0,7682,0,7684,0,7686,0,7688,0,7690,0,7692,0,7694,0,7696,0,7698,0,7700,0,7702,0,7704,0,7706,0,7708,0,7710,0,7712,0,7714,0,7716,0,7718,0,7720,0,7722,0,7724,0,7726,0,7728,0,7730,0,7732,0,7734,0,7736,0,7738,0,7740,0,7742};
|
||||
static uchar U121[UL_SIZE] = {0,7744,0,7746,0,7748,0,7750,0,7752,0,7754,0,7756,0,7758,0,7760,0,7762,0,7764,0,7766,0,7768,0,7770,0,7772,0,7774,0,7776,0,7778,0,7780,0,7782,0,7784,0,7786,0,7788,0,7790,0,7792,0,7794,0,7796,0,7798,0,7800,0,7802,0,7804,0,7806};
|
||||
static uchar U122[UL_SIZE] = {0,7808,0,7810,0,7812,0,7814,0,7816,0,7818,0,7820,0,7822,0,7824,0,7826,0,7828,0,0,0,0,0,7776,0,0,0,0,0,7840,0,7842,0,7844,0,7846,0,7848,0,7850,0,7852,0,7854,0,7856,0,7858,0,7860,0,7862,0,7864,0,7866,0,7868,0,7870};
|
||||
static uchar U123[UL_SIZE] = {0,7872,0,7874,0,7876,0,7878,0,7880,0,7882,0,7884,0,7886,0,7888,0,7890,0,7892,0,7894,0,7896,0,7898,0,7900,0,7902,0,7904,0,7906,0,7908,0,7910,0,7912,0,7914,0,7916,0,7918,0,7920,0,7922,0,7924,0,7926,0,7928,0,7930,0,7932,0,7934};
|
||||
static uchar U124[UL_SIZE] = {7944,7945,7946,7947,7948,7949,7950,7951,0,0,0,0,0,0,0,0,7960,7961,7962,7963,7964,7965,0,0,0,0,0,0,0,0,0,0,7976,7977,7978,7979,7980,7981,7982,7983,0,0,0,0,0,0,0,0,7992,7993,7994,7995,7996,7997,7998,7999,0,0,0,0,0,0,0,0};
|
||||
static uchar U125[UL_SIZE] = {8008,8009,8010,8011,8012,8013,0,0,0,0,0,0,0,0,0,0,0,8025,0,8027,0,8029,0,8031,0,0,0,0,0,0,0,0,8040,8041,8042,8043,8044,8045,8046,8047,0,0,0,0,0,0,0,0,8122,8123,8136,8137,8138,8139,8154,8155,8184,8185,8170,8171,8186,8187,0,0};
|
||||
static uchar U126[UL_SIZE] = {8072,8073,8074,8075,8076,8077,8078,8079,0,0,0,0,0,0,0,0,8088,8089,8090,8091,8092,8093,8094,8095,0,0,0,0,0,0,0,0,8104,8105,8106,8107,8108,8109,8110,8111,0,0,0,0,0,0,0,0,8120,8121,0,8124,0,0,0,0,0,0,0,0,0,0,921,0};
|
||||
static uchar U127[UL_SIZE] = {0,0,0,8140,0,0,0,0,0,0,0,0,0,0,0,0,8152,8153,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8168,8169,0,0,0,8172,0,0,0,0,0,0,0,0,0,0,0,0,0,8188,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar U133[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,8498,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8544,8545,8546,8547,8548,8549,8550,8551,8552,8553,8554,8555,8556,8557,8558,8559};
|
||||
static uchar U134[UL_SIZE] = {0,0,0,0,8579,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar U147[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9398,9399,9400,9401,9402,9403,9404,9405,9406,9407,9408,9409,9410,9411,9412,9413,9414,9415,9416,9417,9418,9419,9420,9421,9422,9423,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar U176[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11264,11265,11266,11267,11268,11269,11270,11271,11272,11273,11274,11275,11276,11277,11278,11279};
|
||||
static uchar U177[UL_SIZE] = {11280,11281,11282,11283,11284,11285,11286,11287,11288,11289,11290,11291,11292,11293,11294,11295,11296,11297,11298,11299,11300,11301,11302,11303,11304,11305,11306,11307,11308,11309,11310,0,0,11360,0,0,0,570,574,0,11367,0,11369,0,11371,0,0,0,0,0,0,11378,0,0,11381,0,0,0,0,0,0,0,0,0};
|
||||
static uchar U178[UL_SIZE] = {0,11392,0,11394,0,11396,0,11398,0,11400,0,11402,0,11404,0,11406,0,11408,0,11410,0,11412,0,11414,0,11416,0,11418,0,11420,0,11422,0,11424,0,11426,0,11428,0,11430,0,11432,0,11434,0,11436,0,11438,0,11440,0,11442,0,11444,0,11446,0,11448,0,11450,0,11452,0,11454};
|
||||
static uchar U179[UL_SIZE] = {0,11456,0,11458,0,11460,0,11462,0,11464,0,11466,0,11468,0,11470,0,11472,0,11474,0,11476,0,11478,0,11480,0,11482,0,11484,0,11486,0,11488,0,11490,0,0,0,0,0,0,0,0,11499,0,11501,0,0,0,0,11506,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar U180[UL_SIZE] = {4256,4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271,4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,4287,4288,4289,4290,4291,4292,4293,0,4295,0,0,0,0,0,4301,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar U665[UL_SIZE] = {0,42560,0,42562,0,42564,0,42566,0,42568,0,42570,0,42572,0,42574,0,42576,0,42578,0,42580,0,42582,0,42584,0,42586,0,42588,0,42590,0,42592,0,42594,0,42596,0,42598,0,42600,0,42602,0,42604,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar U666[UL_SIZE] = {0,42624,0,42626,0,42628,0,42630,0,42632,0,42634,0,42636,0,42638,0,42640,0,42642,0,42644,0,42646,0,42648,0,42650,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
static uchar U668[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42786,0,42788,0,42790,0,42792,0,42794,0,42796,0,42798,0,0,0,42802,0,42804,0,42806,0,42808,0,42810,0,42812,0,42814};
|
||||
static uchar U669[UL_SIZE] = {0,42816,0,42818,0,42820,0,42822,0,42824,0,42826,0,42828,0,42830,0,42832,0,42834,0,42836,0,42838,0,42840,0,42842,0,42844,0,42846,0,42848,0,42850,0,42852,0,42854,0,42856,0,42858,0,42860,0,42862,0,0,0,0,0,0,0,0,0,0,42873,0,42875,0,0,42878};
|
||||
static uchar U670[UL_SIZE] = {0,42880,0,42882,0,42884,0,42886,0,0,0,0,42891,0,0,0,0,42896,0,42898,0,0,0,42902,0,42904,0,42906,0,42908,0,42910,0,42912,0,42914,0,42916,0,42918,0,42920,0,0,0,0,0,0,0,0,0,0,0,42932,0,42934,0,0,0,0,0,0,0,0};
|
||||
static uchar U685[UL_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42931,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5024,5025,5026,5027,5028,5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,5039};
|
||||
static uchar U686[UL_SIZE] = {5040,5041,5042,5043,5044,5045,5046,5047,5048,5049,5050,5051,5052,5053,5054,5055,5056,5057,5058,5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,5069,5070,5071,5072,5073,5074,5075,5076,5077,5078,5079,5080,5081,5082,5083,5084,5085,5086,5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102,5103};
|
||||
static uchar U1021[UL_SIZE] = {0,65313,65314,65315,65316,65317,65318,65319,65320,65321,65322,65323,65324,65325,65326,65327,65328,65329,65330,65331,65332,65333,65334,65335,65336,65337,65338,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
#define LMAX 1021
|
||||
#define UMAX 1022
|
||||
static uchar *LOWER[LMAX] = {_E,L1,_E,L3,L4,L5,L6,L7,L8,L9,_E,_E,_E,L13,L14,L15,L16,L17,L18,L19,L20,L21,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,L66,L67,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,L78,L79,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,L120,L121,L122,L123,L124,L125,L126,L127,_E,_E,_E,_E,L132,L133,L134,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,L146,L147,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,L176,L177,L178,L179,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,L665,L666,_E,L668,L669,L670,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,L1020};
|
||||
static uchar *UPPER[UMAX] = {_E,U1,U2,U3,U4,U5,U6,U7,U8,U9,U10,_E,_E,U13,U14,U15,U16,U17,U18,U19,U20,U21,U22,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,U79,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,U117,_E,_E,U120,U121,U122,U123,U124,U125,U126,U127,_E,_E,_E,_E,_E,U133,U134,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,U147,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,U176,U177,U178,U179,U180,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,U665,U666,_E,U668,U669,U670,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,U685,U686,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,_E,U1021};
|
Reference in New Issue
Block a user