value hx_zmq_setint64sockopt(value socket_handle_,value option_, value hi_optval_, value lo_optval_) { val_check_kind(socket_handle_, k_zmq_socket_handle); if (!val_is_int(option_)) { val_throw(alloc_int(EINVAL)); return alloc_null(); } if (!val_is_int(hi_optval_) || !val_is_int(lo_optval_)) { val_throw(alloc_int(EINVAL)); return alloc_null(); } uint64_t _optval64 = val_int(hi_optval_); _optval64 <<= 32; // Shift the hi int into the top half of the uint64_t value _optval64 += val_int(lo_optval_); int rc = 0; int err = 0; int option = val_int(option_); size_t optvallen = sizeof(_optval64); rc = zmq_setsockopt (val_data(socket_handle_), option, &_optval64, optvallen); err = zmq_errno(); if (rc != 0) { val_throw(alloc_int(err)); return alloc_null(); } return alloc_int(rc); }
/* See Socket.cpp from jzmq library */ value hx_zmq_setintsockopt(value socket_handle_,value option_, value optval_) { val_check_kind(socket_handle_, k_zmq_socket_handle); if (!val_is_int(option_)) { val_throw(alloc_int(EINVAL)); return alloc_null(); } if (!val_is_int(optval_)) { val_throw(alloc_int(EINVAL)); return alloc_null(); } int rc = 0; int err = 0; int ival = val_int(optval_); int option = val_int(option_); size_t optvallen = sizeof(ival); rc = zmq_setsockopt (val_data(socket_handle_), option, &ival, optvallen); err = zmq_errno(); if (rc != 0) { val_throw(alloc_int(err)); return alloc_null(); } return alloc_int(rc); }
value hx_zmq_getbytessockopt(value socket_handle_,value option_) { val_check_kind(socket_handle_, k_zmq_socket_handle); if (!val_is_int(option_)) { val_throw(alloc_int(EINVAL)); return alloc_null(); } int rc = 0; int err = 0; char optval [255]; size_t optvallen = 255; rc = zmq_getsockopt(val_data(socket_handle_),val_int(option_),&optval, &optvallen); err = zmq_errno(); if (rc != 0) { val_throw(alloc_int(err)); return alloc_int(0); } // Return data to Haxe // Create a return buffer byte array, by memcopying the message data, then discard the ZMQ message buffer b = alloc_buffer(NULL); buffer_append_sub(b,optval,optvallen); err = zmq_errno(); if (rc != 0) { val_throw(alloc_int(err)); return alloc_null(); } return buffer_val(b); }
value hx_zmq_getint64sockopt(value socket_handle_,value option_) { val_check_kind(socket_handle_, k_zmq_socket_handle); if (!val_is_int(option_)) { val_throw(alloc_int(EINVAL)); return alloc_null(); } int rc = 0; int err = 0; uint64_t optval = 0; size_t optvallen = sizeof(optval); rc = zmq_getsockopt(val_data(socket_handle_),val_int(option_),&optval, &optvallen); err = zmq_errno(); if (rc != 0) { val_throw(alloc_int(err)); return alloc_int(0); } value ret = alloc_empty_object(); alloc_field(ret, val_id("hi"),alloc_int(optval >> 32)); alloc_field(ret, val_id("lo"),alloc_int(optval & 0xFFFFFFFF)); return ret; }
value hx_zmq_construct (value io_threads) { if (!val_is_int(io_threads)) return alloc_null(); int _io_threads = val_int(io_threads); if (_io_threads <= 0) { val_throw(alloc_int(EINVAL)); return alloc_null(); } void *c = zmq_init (_io_threads); int err = zmq_errno(); if (c == NULL) { val_throw (alloc_int(err)); return alloc_null(); } // See: http://nekovm.org/doc/ffi#abstracts_and_kinds value v = alloc_abstract(k_zmq_context_handle,c); val_gc(v,finalize_context); // finalize_context is called when the abstract value is garbage collected return v; }
//Be very careful with this, it does not support offsets into buffers yet value vertexAttribPointer( value *args, int count ) { enum {index,size,type,normalized,stride,pointer}; if (count != 6) { throw "vertexAttribPointer invalid parameter length"; } char *ptr = NULL; if (val_is_buffer (args[pointer])) { std::cout << "vertexAttribPointer does not accept data for pointer arg" << std::endl; //ptr = buffer_data( val_to_buffer ( args[pointer] ) ); } else if (val_is_int (args[pointer])) { ptr = ((char *)NULL + val_int(args[pointer])); } glVertexAttribPointer( (GLuint)val_int( args[index] ), (GLint)val_int( args[size] ), (GLenum)val_int( args[type] ), (GLboolean)val_bool( args[normalized] ), (GLsizei)val_int( args[stride] ), (const GLvoid *)ptr ); return alloc_null( ); }
EXTERN int val_compare( value a, value b ) { char tmp_buf[32]; switch( C(val_type(a),val_type(b)) ) { case C(VAL_INT,VAL_INT): return icmp(val_int(a),val_int(b)); case C(VAL_INT32,VAL_INT): return icmp(val_int32(a),val_int(b)); case C(VAL_INT,VAL_INT32): return icmp(val_int(a),val_int32(b)); case C(VAL_INT32,VAL_INT32): return icmp(val_int32(a),val_int32(b)); case C(VAL_INT,VAL_FLOAT): return fcmp(val_int(a),val_float(b)); case C(VAL_INT32,VAL_FLOAT): return fcmp(val_int32(a),val_float(b)); case C(VAL_INT,VAL_STRING): return scmp(tmp_buf,sprintf(tmp_buf,"%d",val_int(a)),val_string(b),val_strlen(b)); case C(VAL_INT32,VAL_STRING): return scmp(tmp_buf,sprintf(tmp_buf,"%d",val_int32(a)),val_string(b),val_strlen(b)); case C(VAL_FLOAT,VAL_INT): return fcmp(val_float(a),val_int(b)); case C(VAL_FLOAT,VAL_INT32): return fcmp(val_float(a),val_int32(b)); case C(VAL_FLOAT,VAL_FLOAT): return fcmp(val_float(a),val_float(b)); case C(VAL_FLOAT,VAL_STRING): return scmp(tmp_buf,sprintf(tmp_buf,FLOAT_FMT,val_float(a)),val_string(b),val_strlen(b)); case C(VAL_STRING,VAL_INT): return scmp(val_string(a),val_strlen(a),tmp_buf,sprintf(tmp_buf,"%d",val_int(b))); case C(VAL_STRING,VAL_INT32): return scmp(val_string(a),val_strlen(a),tmp_buf,sprintf(tmp_buf,"%d",val_int32(b))); case C(VAL_STRING,VAL_FLOAT): return scmp(val_string(a),val_strlen(a),tmp_buf,sprintf(tmp_buf,FLOAT_FMT,val_float(b))); case C(VAL_STRING,VAL_BOOL): return scmp(val_string(a),val_strlen(a),val_bool(b)?"true":"false",val_bool(b)?4:5); case C(VAL_BOOL,VAL_STRING): return scmp(val_bool(a)?"true":"false",val_bool(a)?4:5,val_string(b),val_strlen(b)); case C(VAL_STRING,VAL_STRING): return scmp(val_string(a),val_strlen(a),val_string(b),val_strlen(b)); case C(VAL_BOOL,VAL_BOOL): return (a == b) ? 0 : (val_bool(a) ? 1 : -1); case C(VAL_OBJECT,VAL_OBJECT): if( a == b ) return 0; { value tmp = val_field(a,id_compare); if( tmp == val_null ) return invalid_comparison; a = val_callEx(a,tmp,&b,1,NULL); } if( val_is_int(a) ) return val_int(a); return invalid_comparison; default: if( a == b ) return 0; return invalid_comparison; } }
/** result_set_conv_date : 'result -> function:1 -> void <doc>Set the function that will convert a Date or DateTime string to the corresponding value.</doc> **/ static value result_set_conv_date( value o, value c ) { val_check_function(c,1); if( val_is_int(o) ) return val_true; val_check_kind(o,k_result); RESULT(o)->conv_date = c; return val_true; }
// String access int api_val_strlen(value arg1) { if (val_is_string(arg1)) return val_strlen(arg1); value l = val_field(arg1,length_id); if (val_is_int(l)) return val_int(l); return 0; }
value hx_zmq_setbytessockopt(value socket_handle_, value option_, value bytes_optval_) { val_check_kind(socket_handle_, k_zmq_socket_handle); if (!val_is_int(option_)) { printf("option_ is not int"); val_throw(alloc_int(EINVAL)); return alloc_null(); } size_t size = 0; uint8_t *data = 0; // If data from neko if (val_is_string(bytes_optval_)) { size = val_strlen(bytes_optval_); data = (uint8_t *)val_string(bytes_optval_); } // else from C++ else if (val_is_buffer(bytes_optval_)) { buffer buf = val_to_buffer(bytes_optval_); size = buffer_size(buf); data = (uint8_t *)buffer_data(buf); } else { printf("bytes_optval_ not string or buffer"); val_throw(alloc_int(EINVAL)); return alloc_null(); } int rc = 0; int err = 0; int option = val_int(option_); rc = zmq_setsockopt (val_data(socket_handle_), option, data, size); err = zmq_errno(); if (rc != 0) { printf("err:%d",err); val_throw(alloc_int(err)); return alloc_null(); } return alloc_int(rc); }
static int read_proxy( readp p, void *buf, int size ) { value fread = val_array_ptr(p)[0]; value vbuf = val_array_ptr(p)[1]; value ret; int len; if( size < 0 ) return -1; if( size > READ_BUFSIZE ) vbuf = alloc_empty_string(size); ret = val_call3(fread,vbuf,alloc_int(0),alloc_int(size)); if( !val_is_int(ret) ) return -1; len = val_int(ret); if( len < 0 || len > size ) return -1; memcpy(buf,val_string(vbuf),len); return len; }
//FIXME indices and bytearrays do not particularly mix //Does val_to_buffer throw an error on null? value drawElements( value mode, value count, value type, value indices ) { char *ptr = NULL; if (val_is_buffer(indices)) { ptr = buffer_data( val_to_buffer ( indices ) ); } else if (val_is_int(indices)) { ptr = ((char *)NULL+val_int(indices)); } glDrawElements( (GLenum)val_int( mode ), (GLsizei)val_int( count ), (GLenum)val_int( type ), (const GLvoid *)ptr ); return alloc_null( ); }
value hx_zmq_construct_socket (value context_handle,value type) { val_is_kind(context_handle,k_zmq_context_handle); if (!val_is_int(type)) { val_throw(alloc_int(EINVAL)); return alloc_null(); } void *s = zmq_socket (val_data(context_handle),val_int(type)); int err = zmq_errno(); if (s == NULL) { val_throw (alloc_int(err)); return alloc_null(); } // See: http://nekovm.org/doc/ffi#abstracts_and_kinds value v = alloc_abstract(k_zmq_socket_handle,s); val_gc(v,finalize_socket); // finalize_socket is called when the abstract value is garbage collected return v; }
/** result_get_length : 'result -> int <doc>Return the number of rows returned or affected</doc> **/ static value result_get_length( value o ) { if( val_is_int(o) ) return o; val_check_kind(o,k_result); return alloc_int( (int)mysql_num_rows(RESULT(o)->r) ); }
static void report( neko_vm *vm, value exc ) { #if OSX CFStringRef title = CFSTR("Uncaught exception"); CFStringRef message; #endif int i = 0; buffer b = alloc_buffer(NULL); value st = neko_exc_stack(vm); if( val_array_size(st) > 20 ) { i = val_array_size(st) - 20; buffer_append(b,"...\n"); } for(i;i<val_array_size(st);i++) { value s = val_array_ptr(st)[i]; if( val_is_null(s) ) buffer_append(b,"Called from a C function\n"); else if( val_is_string(s) ) { buffer_append(b,"Called from "); buffer_append(b,val_string(s)); buffer_append(b," (no debug available)\n"); } else if( val_is_array(s) && val_array_size(s) == 2 && val_is_string(val_array_ptr(s)[0]) && val_is_int(val_array_ptr(s)[1]) ) { buffer_append(b,"Called from "); buffer_append(b,val_string(val_array_ptr(s)[0])); buffer_append(b," line "); val_buffer(b,val_array_ptr(s)[1]); buffer_append(b,"\n"); } else { buffer_append(b,"Called from "); val_buffer(b,s); buffer_append(b,"\n"); } } val_buffer(b,exc); #if _WIN32 MessageBox(NULL,val_string(buffer_to_string(b)),"Uncaught exception",MB_OK | MB_ICONERROR); #elif OSX message = CFStringCreateWithCString(NULL,val_string(buffer_to_string(b)), kCFStringEncodingUTF8); CFUserNotificationDisplayNotice(0,0,NULL,NULL,NULL,title,message,NULL); #elif LINUX fprintf(stderr,"Uncaught Exception: %s\n",val_string(buffer_to_string(b))); #endif }
/** $not : any -> bool <doc>Return true if [v] is [false] or [null] or [0]</doc> **/ static value builtin_not( value f ) { return alloc_bool(f == val_false || f == val_null || f == alloc_int(0) || (!val_is_int(f) && val_tag(f) == VAL_INT32 && val_int32(f) == 0)); }
static void report( neko_vm *vm, value exc, int isexc ) { int i; buffer b = alloc_buffer(NULL); value st = neko_exc_stack(vm); for(i=0;i<val_array_size(st);i++) { value s = val_array_ptr(st)[i]; buffer_append(b,"Called from "); if( val_is_null(s) ) buffer_append(b,"a C function"); else if( val_is_string(s) ) { buffer_append(b,val_string(s)); buffer_append(b," (no debug available)"); } else if( val_is_array(s) && val_array_size(s) == 2 && val_is_string(val_array_ptr(s)[0]) && val_is_int(val_array_ptr(s)[1]) ) { val_buffer(b,val_array_ptr(s)[0]); buffer_append(b," line "); val_buffer(b,val_array_ptr(s)[1]); } else val_buffer(b,s); buffer_append_char(b,'\n'); } if( isexc ) buffer_append(b,"Uncaught exception - "); val_buffer(b,exc); # ifdef NEKO_STANDALONE neko_standalone_error(val_string(buffer_to_string(b))); # else fprintf(stderr,"%s\n",val_string(buffer_to_string(b))); # endif }
static int ms_compare( m_sort *m, int a, int b ) { value v = val_call2(m->cmp,m->arr[a],m->arr[b]); if( !val_is_int(v) ) return -1; return val_int(v); }
DEFINE_FUNC_5(webp_encode_argb, data_buffer_value, width_value, height_value, lossless_value, quality_factor_value) { int width = 0; int height = 0; float quality_factor = 100; int lossless = 1; int stride = 0; uint8_t* abgr = NULL; uint8_t* rgba = NULL; uint8_t* output = NULL; int output_size = 0; int pixels_size; int bytes_size; buffer data_buffer; if (val_is_int(width_value)) width = val_int(width_value); if (val_is_int(height_value)) height = val_int(height_value); if (val_is_bool(lossless_value)) lossless = val_bool(lossless_value); if (val_is_float(quality_factor_value)) quality_factor = val_float(quality_factor_value); stride = width * 4; pixels_size = width * height; bytes_size = pixels_size * 4; if (!val_is_buffer(data_buffer_value)) { val_throw(alloc_string("webp_encode_argb: Expected to be a buffer")); return alloc_null(); } data_buffer = val_to_buffer(data_buffer_value); if (bytes_size != buffer_size(data_buffer)) { val_throw(alloc_string("webp_encode_argb: Invalid buffer size")); return alloc_null(); } //if () abgr = (uint8_t *)buffer_data(data_buffer); rgba = (uint8_t *)malloc(bytes_size); uint8_t* _abgr = abgr; uint8_t* _rgba = rgba; int _pixels_size = pixels_size; while (_pixels_size-- > 0) { //_rgba[0] = _abgr[3]; _rgba[0] = _abgr[1]; _rgba[1] = _abgr[2]; _rgba[2] = _abgr[3]; _rgba[3] = _abgr[0]; _abgr += 4; _rgba += 4; } if (lossless) { output_size = WebPEncodeLosslessRGBA( rgba, //abgr, width, height, stride, &output ); } else { output_size = WebPEncodeRGBA( rgba, //abgr, width, height, stride, quality_factor, &output ); } printf("output_size: (%d, %d, %d) : %d\n", width, height, stride, output_size); buffer output_buffer = alloc_buffer_len(0); buffer_append_sub(output_buffer, (char *)output, output_size); buffer_set_size(output_buffer, output_size); if (output != NULL) free(output); if (rgba != NULL) free(rgba); return buffer_val(output_buffer); }
/** * Receive data from socket * Based on code in https://github.com/zeromq/jzmq/blob/master/src/Socket.cpp */ value hx_zmq_send(value socket_handle_, value msg_data, value flags) { val_check_kind(socket_handle_, k_zmq_socket_handle); if (!val_is_null(flags) && !val_is_int(flags)) { val_throw(alloc_int(EINVAL)); return alloc_null(); } size_t size = 0; uint8_t *data = 0; zmq_msg_t message; // Extract byte data from either Neko string or C++ buffer // see: http://waxe.googlecode.com/svn-history/r32/trunk/src/waxe/HaxeAPI.cpp "Val2ByteData" if (val_is_string(msg_data)) { // Neko size = val_strlen(msg_data); data = (uint8_t *)val_string(msg_data); } else if (val_is_buffer(msg_data)) { // CPP buffer buf = val_to_buffer(msg_data); size = buffer_size(buf); data = (uint8_t *)buffer_data(buf); } else { val_throw(alloc_int(EINVAL)); return alloc_null(); } // Set up send message buffer by referencing the provided bytes data //zero copy version: int rc = zmq_msg_init_data (&message, data, size,NULL,NULL); int rc = zmq_msg_init_size(&message, size); memcpy (zmq_msg_data(&message), data, size); int err = zmq_errno(); if (rc != 0) { val_throw(alloc_int(err)); return alloc_null(); } gc_enter_blocking(); // Send #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0) rc = zmq_sendmsg (val_data(socket_handle_), &message, val_int(flags)); #else rc = zmq_send (val_data(socket_handle_), &message, val_int(flags)); #endif err = zmq_errno(); gc_exit_blocking(); // If NOBLOCK, but cant send message now, close message first before quitting if (rc == -1 && err == EAGAIN) { rc = zmq_msg_close (&message); err = zmq_errno(); if (rc != 0) { val_throw(alloc_int(err)); return alloc_null(); } return alloc_null(); } if (rc == -1) { val_throw(alloc_int(err)); rc = zmq_msg_close (&message); err = zmq_errno(); if (rc != 0) { val_throw(alloc_int(err)); return alloc_null(); } return alloc_null(); } rc = zmq_msg_close (&message); err = zmq_errno(); if (rc != 0) { val_throw(alloc_int(err)); return alloc_null(); } return alloc_null(); }
void NekoCodeChunk::neko_dump(std::string const & indent) const { for (const_iterator it = begin(); it != end(); ++it) { std::cout << indent << it->first << ": "; print_neko_instruction((OPCODE) it->second.first, it->second.second, parameter_table[it->second.first]); std::cout << "; // "; { int ppc = (int)((int_val *)it->first - m->code); int idx = m->dbgidxs[ppc>>5].base + bitcount(m->dbgidxs[ppc>>5].bits >> (31 - (ppc & 31))); value s = val_array_ptr(m->dbgtbl)[idx]; if( val_is_string(s) ) printf("%s",val_string(s)); else if( val_is_array(s) && val_array_size(s) == 2 && val_is_string(val_array_ptr(s)[0]) && val_is_int(val_array_ptr(s)[1]) ) printf("file %s line %d",val_string(val_array_ptr(s)[0]),val_int(val_array_ptr(s)[1])); else printf("???"); } std::cout << std::endl; } }
/** * Receive data from socket * Based on code in https://github.com/zeromq/jzmq/blob/master/src/Socket.cpp */ value hx_zmq_rcv(value socket_handle_, value flags) { val_check_kind(socket_handle_, k_zmq_socket_handle); if (!val_is_null(flags) && !val_is_int(flags)) { val_throw(alloc_int(EINVAL)); return alloc_null(); } zmq_msg_t message; int rc = zmq_msg_init (&message); int err = zmq_errno(); if (rc != 0) { val_throw(alloc_int(err)); return alloc_null(); } gc_enter_blocking(); #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0) rc = zmq_recvmsg (val_data(socket_handle_), &message, val_int(flags)); #else rc = zmq_recv (val_data(socket_handle_), &message, val_int(flags)); #endif gc_exit_blocking(); err = zmq_errno(); if (rc == -1 && err == EAGAIN) { rc = zmq_msg_close (&message); err = zmq_errno(); if (rc != 0) { val_throw(alloc_int(err)); return alloc_null(); } return alloc_null(); } if (rc == -1) { rc = zmq_msg_close (&message); int err1 = zmq_errno(); if (rc != 0) { val_throw(alloc_int(err1)); return alloc_null(); } val_throw(alloc_int(err)); return alloc_null(); } // Return data to Haxe int sz = zmq_msg_size (&message); const char* pd = (char *)zmq_msg_data (&message); // Create a return buffer byte array, by memcopying the message data, then discard the ZMQ message buffer b = alloc_buffer(NULL); buffer_append_sub(b,pd,sz); rc = zmq_msg_close (&message); err = zmq_errno(); if (rc != 0) { val_throw(alloc_int(err)); return alloc_null(); } return buffer_val(b); }
EXTERN value val_callEx( value vthis, value f, value *args, int nargs, value *exc ) { neko_vm *vm = NEKO_VM(); value old_this = vm->vthis; value old_env = vm->env; value ret = val_null; jmp_buf oldjmp; if( vthis != NULL ) vm->vthis = vthis; if( exc ) { memcpy(&oldjmp,&vm->start,sizeof(jmp_buf)); if( setjmp(vm->start) ) { *exc = vm->vthis; neko_process_trap(vm); vm->vthis = old_this; vm->env = old_env; memcpy(&vm->start,&oldjmp,sizeof(jmp_buf)); return val_null; } neko_setup_trap(vm); } if( (uintptr_t)&vm < (uintptr_t)vm->c_stack_max ) val_throw(alloc_string("C Stack Overflow")); if( val_is_int(f) ) val_throw(alloc_string("Invalid call")); if( val_tag(f) == VAL_PRIMITIVE ) { vm->env = ((vfunction *)f)->env; if( nargs == ((vfunction*)f)->nargs ) { if( nargs > CALL_MAX_ARGS ) failure("Too many arguments for a call"); switch( nargs ) { case 0: ret = ((c_prim0)((vfunction*)f)->addr)(); break; case 1: ret = ((c_prim1)((vfunction*)f)->addr)(args[0]); break; case 2: ret = ((c_prim2)((vfunction*)f)->addr)(args[0],args[1]); break; case 3: ret = ((c_prim3)((vfunction*)f)->addr)(args[0],args[1],args[2]); break; case 4: ret = ((c_prim4)((vfunction*)f)->addr)(args[0],args[1],args[2],args[3]); break; case 5: ret = ((c_prim5)((vfunction*)f)->addr)(args[0],args[1],args[2],args[3],args[4]); break; } } else if( ((vfunction*)f)->nargs == -1 ) ret = (value)((c_primN)((vfunction*)f)->addr)(args,nargs); else val_throw(alloc_string("Invalid call")); if( ret == NULL ) val_throw( (value)((vfunction*)f)->module ); } else if( val_short_tag(f) == VAL_FUNCTION ) { if( nargs == ((vfunction*)f)->nargs ) { int n; if( vm->csp + 4 >= vm->sp - nargs && !neko_stack_expand(vm->sp,vm->csp,vm) ) { if( exc ) { neko_process_trap(vm); memcpy(&vm->start,&oldjmp,sizeof(jmp_buf)); } failure("Stack Overflow"); } else { for(n=0;n<nargs;n++) *--vm->sp = (int_val)args[n]; vm->env = ((vfunction*)f)->env; if( val_tag(f) == VAL_FUNCTION ) { *++vm->csp = (int_val)callback_return; *++vm->csp = 0; *++vm->csp = 0; *++vm->csp = 0; ret = neko_interp(vm,((vfunction*)f)->module,(int_val)val_null,(int_val*)((vfunction*)f)->addr); } else { neko_module *m = (neko_module*)((vfunction*)f)->module; ret = ((jit_prim)jit_boot_seq)(vm,((vfunction*)f)->addr,val_null,m); } } } else val_throw(alloc_string("Invalid call")); } else val_throw(alloc_string("Invalid call")); if( exc ) { neko_process_trap(vm); memcpy(&vm->start,&oldjmp,sizeof(jmp_buf)); } vm->vthis = old_this; vm->env = old_env; return ret; }
static int neko_handler_rec( request_rec *r ) { mcontext ctx; neko_vm *vm; const char *ctype; value exc = NULL; /* Seems to crash on Windows. And on Linux, we rarely have libGC 7.x installed anyway # if defined(APACHE_2_X) || defined(NEKO_WINDOWS) // we are using threads, so let's make sure that the current thread is registered neko_thread_register(true); # endif */ config.hits++; ctx.r = r; ctx.main = cache_find(r); ctx.post_data = val_null; ctx.headers_sent = false; ctx.content_type = alloc_string("text/html"); r->content_type = val_string(ctx.content_type); if( ap_setup_client_block(r,REQUEST_CHUNKED_ERROR) != 0 ) { send_headers(&ctx); apache_error(APLOG_WARNING,r,"ap_setup_client_block failed"); return OK; } ctype = ap_table_get(r->headers_in,"Content-Type"); if( (!ctype || strstr(ctype,"multipart/form-data") == NULL) && ap_should_client_block(r) ) { # define MAXLEN 1024 char buf[MAXLEN]; int len; int tlen = 0; buffer b = alloc_buffer(NULL); while( (len = ap_get_client_block(r,buf,MAXLEN)) > 0 ) { if( tlen < config.max_post_size ) buffer_append_sub(b,buf,len); tlen += len; } if( tlen >= config.max_post_size ) { send_headers(&ctx); apache_error(APLOG_WARNING,r,"Maximum POST data exceeded. Try using multipart encoding"); return OK; } ctx.post_data = buffer_to_string(b); } vm = neko_vm_alloc(NULL); if( config.use_stats ) neko_vm_set_stats(vm,neko_stats_measure,config.use_prim_stats?neko_stats_measure:NULL); neko_vm_set_custom(vm,k_mod_neko,&ctx); if( config.use_jit && !neko_vm_jit(vm,1) ) { send_headers(&ctx); apache_error(APLOG_WARNING,r,"JIT required by env. var but not enabled in NekoVM"); return OK; } neko_vm_redirect(vm,request_print,&ctx); neko_vm_select(vm); if( ctx.main != NULL ) { value old = ctx.main; if( config.use_stats ) neko_stats_measure(vm,r->filename,1); val_callEx(val_null,old,NULL,0,&exc); if( config.use_stats ) neko_stats_measure(vm,r->filename,0); if( old != ctx.main ) cache_module(r->filename,FTIME(r),ctx.main); } else { char *base_uri = request_base_uri(r); value mload = neko_default_loader(&base_uri,1); value args[] = { alloc_string(r->filename), mload }; char *p = strrchr(val_string(args[0]),'.'); if( p != NULL ) *p = 0; val_callEx(mload,val_field(mload,val_id("loadmodule")),args,2,&exc); if( ctx.main != NULL && config.use_cache ) cache_module(r->filename,FTIME(r),ctx.main); } if( exc != NULL ) { buffer b = alloc_buffer(NULL); value v; int i; const char *p, *start; value st = neko_exc_stack(vm); val_buffer(b,exc); config.exceptions++; ap_soft_timeout("Client Timeout",r); send_headers(&ctx); v = buffer_to_string(b); p = val_string(v); start = p; ap_rprintf(r,"Uncaught exception - "); while( *p ) { if( *p == '<' || *p == '>' ) { ap_rwrite(start,(int)(p - start),r); ap_rwrite((*p == '<')?"<":">",4, r); start = p + 1; } p++; } ap_rwrite(start,(int)(p - start),r); ap_rprintf(r,"<br/><br/>"); for(i=0;i<val_array_size(st);i++) { value s = val_array_ptr(st)[i]; if( val_is_null(s) ) ap_rprintf(r,"Called from a C function<br/>"); else if( val_is_string(s) ) { ap_rprintf(r,"Called from %s (no debug available)<br/>",val_string(s)); } else if( val_is_array(s) && val_array_size(s) == 2 && val_is_string(val_array_ptr(s)[0]) && val_is_int(val_array_ptr(s)[1]) ) ap_rprintf(r,"Called from %s line %d<br/>",val_string(val_array_ptr(s)[0]),val_int(val_array_ptr(s)[1])); else { b = alloc_buffer(NULL); val_buffer(b,s); ap_rprintf(r,"Called from %s<br/>",val_string(buffer_to_string(b))); } } ap_kill_timeout(r); return OK; } send_headers(&ctx); return OK; }
/** $istrue : v:any -> bool <doc>Return true if [v] is not [false], not [null] and not 0</doc> **/ static value builtin_istrue( value f ) { return alloc_bool(f != val_false && f != val_null && f != alloc_int(0) && (val_is_int(f) || val_tag(f) != VAL_INT32 || val_int32(f) != 0)); }