void serialize_rec( sbuffer *b, value o ) { b->nrec++; if( b->nrec > 350 ) failure("Serialization stack overflow"); switch( val_type(o) ) { case VAL_NULL: write_char(b,'N'); break; case VAL_BOOL: if( val_bool(o) ) write_char(b,'T'); else write_char(b,'F'); break; case VAL_INT: write_char(b,'i'); write_int(b,val_int(o)); break; case VAL_FLOAT: write_char(b,'f'); write_str(b,sizeof(tfloat),&val_float(o)); break; case VAL_STRING: if( !write_ref(b,o,NULL) ) { write_char(b,'s'); write_int(b,val_strlen(o)); write_str(b,val_strlen(o),val_string(o)); } break; case VAL_OBJECT: { value s; if( !write_ref(b,o,&s) ) { if( s != NULL ) { // reference was not written if( !val_is_function(s) || (val_fun_nargs(s) != 0 && val_fun_nargs(s) != VAR_ARGS) ) failure("Invalid __serialize method"); write_char(b,'x'); serialize_rec(b,((neko_module*)((vfunction*)s)->module)->name); serialize_rec(b,val_ocall0(o,id_serialize)); // put reference back write_ref(b,o,NULL); break; } write_char(b,'o'); val_iter_fields(o,serialize_fields_rec,b); write_int(b,0); o = (value)((vobject*)o)->proto; if( o == NULL ) write_char(b,'z'); else { write_char(b,'p'); serialize_rec(b,o); } } } break; case VAL_ARRAY: if( !write_ref(b,o,NULL) ) { int i; int n = val_array_size(o); write_char(b,'a'); write_int(b,n); for(i=0;i<n;i++) serialize_rec(b,val_array_ptr(o)[i]); } break; case VAL_FUNCTION: if( !write_ref(b,o,NULL) ) { neko_module *m; if( val_tag(o) == VAL_PRIMITIVE ) { // assume that alloc_array(0) return a constant array ptr // we don't want to access custom memory (maybe not a ptr) if( ((vfunction*)o)->env != alloc_array(0) ) failure("Cannot Serialize Primitive with environment"); write_char(b,'p'); write_int(b,((vfunction*)o)->nargs); serialize_rec(b,((vfunction*)o)->module); break; } if( val_tag(o) == VAL_JITFUN ) failure("Cannot Serialize JIT method"); write_char(b,'L'); m = (neko_module*)((vfunction*)o)->module; serialize_rec(b,m->name); write_int(b,(int)((int_val*)((vfunction*)o)->addr - m->code)); write_int(b,((vfunction*)o)->nargs); serialize_rec(b,((vfunction*)o)->env); } break; case VAL_INT32: write_char(b,'I'); write_int(b,val_int32(o)); break; case VAL_ABSTRACT: if( val_is_kind(o,k_hash) ) { int i; vhash *h = val_hdata(o); write_char(b,'h'); write_int(b,h->ncells); write_int(b,h->nitems); for(i=0;i<h->ncells;i++) { hcell *c = h->cells[i]; while( c != NULL ) { write_int(b,c->hkey); serialize_rec(b,c->key); serialize_rec(b,c->val); c = c->next; } } break; } default: failure("Cannot Serialize Abstract"); break; } b->nrec--; }
int main( int argc, char *argv[] ) { neko_vm *vm; value mload; int r; _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); neko_global_init(); vm = neko_vm_alloc(NULL); neko_vm_select(vm); # ifdef NEKO_STANDALONE neko_standalone_init(); # endif if( !neko_has_embedded_module(vm) ) { int jit = 1; int stats = 0; while( argc > 1 ) { if( strcmp(argv[1],"-interp") == 0 ) { argc--; argv++; jit = 0; continue; } if( strcmp(argv[1],"-stats") == 0 ) { argc--; argv++; stats = 1; neko_vm_set_stats(vm,neko_stats_measure,neko_stats_measure); neko_stats_measure(vm,"total",1); continue; } break; } # ifdef NEKO_POSIX if( jit ) { struct sigaction act; act.sa_sigaction = NULL; act.sa_handler = handle_signal; act.sa_flags = 0; sigemptyset(&act.sa_mask); sigaction(SIGSEGV,&act,NULL); } # endif neko_vm_jit(vm,jit); if( argc == 1 ) { # ifdef NEKO_STANDALONE report(vm,alloc_string("No embedded module in this executable"),0); # else printf("NekoVM %d.%d.%d (c)2005-2009 Motion-Twin\n Usage : neko <file>\n",NEKO_VERSION/100,(NEKO_VERSION/10)%10,NEKO_VERSION%10); # endif mload = NULL; r = 1; } else { mload = default_loader(argv+2,argc-2); r = execute_file(vm,argv[1],mload); } if( stats ) { value v; neko_stats_measure(vm,"total",0); v = neko_stats_build(vm); val_print(alloc_string("TOT\tTIME\tCOUNT\tNAME\n")); while( v != val_null ) { char buf[256]; value *s = val_array_ptr(v); int errors = val_int(s[4]); sprintf(buf,"%d\t%d\t%d\t%s%c", val_int(s[1]), val_int(s[2]), val_int(s[3]), val_string(s[0]), errors?' ':'\n'); if( errors ) sprintf(buf+strlen(buf),"ERRORS=%d\n",errors); val_print(alloc_string(buf)); v = s[5]; } } } else { mload = default_loader(argv+1,argc-1); r = neko_execute_self(vm,mload); } if( mload != NULL && val_field(mload,val_id("dump_prof")) != val_null ) val_ocall0(mload,val_id("dump_prof")); vm = NULL; mload = NULL; neko_vm_select(NULL); neko_global_free(); return r; }
// Call object field value api_val_ocall0(value arg1,int arg2) { return val_ocall0(arg1,arg2); }
value ftIterateGlyphs( value font, value callbacks ) { if( !val_is_object(callbacks) ) { ft_failure_v("not a callback function object: ", callbacks ); } // printf("A\n"); field endGlyph = val_id("endGlyph"); field startContour = val_id("startContour"); field endContour = val_id("endContour"); field lineTo = val_id("lineTo"); field curveTo = val_id("curveTo"); // printf("B\n"); if( !val_is_object(font) ) { ft_failure_v("not a freetype font face: ", font ); } value __f = val_field( font, val_id("__f") ); if( __f == NULL || !val_is_abstract( __f ) || !val_is_kind( __f, k_ft_face ) ) { ft_failure_v("not a freetype font face: ", font ); } FT_Face *face = val_data( __f ); // printf("C\n"); FT_UInt glyph_index; FT_ULong character; FT_Outline *outline; field f_character = val_id("character"); field f_advance = val_id("advance"); character = FT_Get_First_Char( *face, &glyph_index ); // printf("D\n"); while( character != 0 ) { if( FT_Load_Glyph( *face, glyph_index, FT_LOAD_NO_BITMAP ) ) { // ignore (TODO report?) } else if( (*face)->glyph->format != FT_GLYPH_FORMAT_OUTLINE ) { // ignore (TODO) } else { outline = &((*face)->glyph->outline); int start = 0, end, contour, p; char control, cubic; int n,i; // printf(" 1\n"); for( contour = 0; contour < outline->n_contours; contour++ ) { end = outline->contours[contour]; n=0; for( p = start; p<=end; p++ ) { control = !(outline->tags[p] & 0x01); cubic = outline->tags[p] & 0x02; if( p==start ) { val_ocall2( callbacks, startContour, alloc_int( outline->points[p-n].x ), alloc_int( outline->points[p-n].y ) ); } if( !control && n > 0 ) { importGlyphPoints( &(outline->points[(p-n)+1]), n-1, callbacks, lineTo, curveTo, cubic ); n=1; } else { n++; } } if( n ) { // special case: repeat first point FT_Vector points[n+1]; int s=(end-n)+2; for( i=0; i<n-1; i++ ) { points[i].x = outline->points[s+i].x; points[i].y = outline->points[s+i].y; } points[n-1].x = outline->points[start].x; points[n-1].y = outline->points[start].y; importGlyphPoints( points, n-1, callbacks, lineTo, curveTo, false ); } start = end+1; val_ocall0( callbacks, endContour ); } // printf(" 2\n"); val_ocall2( callbacks, endGlyph, alloc_int( character ), alloc_int( (*face)->glyph->advance.x ) ); // printf(" 3\n"); } // printf(" E\n"); character = FT_Get_Next_Char( *face, character, &glyph_index ); // printf(" F\n"); } // printf(" Goo\n"); return val_true; }
static void do_parse_xml( const char *xml, const char **lp, int *line, value callb, const char *parentname ) { STATE state = BEGIN; STATE next = BEGIN; field aname = (field)0; value attribs = NULL_VAL; value nodename = NULL_VAL; const char *start = NULL; const char *p = *lp; char c = *p; int nsubs = 0, nbrackets = 0; while( c ) { switch( state ) { case IGNORE_SPACES: switch( c ) { case '\n': case '\r': case '\t': case ' ': break; default: state = next; continue; } break; case BEGIN: switch( c ) { case '<': state = IGNORE_SPACES; next = BEGIN_NODE; break; default: start = p; state = PCDATA; continue; } break; case PCDATA: if( c == '<' ) { val_ocall1(callb,id_pcdata,copy_string(start,p-start)); nsubs++; state = IGNORE_SPACES; next = BEGIN_NODE; } break; case CDATA: if( c == ']' && p[1] == ']' && p[2] == '>' ) { val_ocall1(callb,id_cdata,copy_string(start,p-start)); nsubs++; p += 2; state = BEGIN; } break; case BEGIN_NODE: switch( c ) { case '!': if( p[1] == '[' ) { p += 2; if( (p[0] != 'C' && p[0] != 'c') || (p[1] != 'D' && p[1] != 'd') || (p[2] != 'A' && p[2] != 'a') || (p[3] != 'T' && p[3] != 't') || (p[4] != 'A' && p[4] != 'a') || (p[5] != '[') ) ERROR("Expected <![CDATA["); p += 5; state = CDATA; start = p + 1; break; } if( p[1] == 'D' || p[1] == 'd' ) { if( (p[2] != 'O' && p[2] != 'o') || (p[3] != 'C' && p[3] != 'c') || (p[4] != 'T' && p[4] != 't') || (p[5] != 'Y' && p[5] != 'y') || (p[6] != 'P' && p[6] != 'p') || (p[7] != 'E' && p[7] != 'e') ) ERROR("Expected <!DOCTYPE"); p += 7; state = DOCTYPE; start = p + 1; break; } if( p[1] != '-' || p[2] != '-' ) ERROR("Expected <!--"); p += 2; state = COMMENT; start = p + 1; break; case '?': state = HEADER; start = p; break; case '/': if( parentname == NULL ) ERROR("Expected node name"); start = p + 1; state = IGNORE_SPACES; next = CLOSE; break; default: state = TAG_NAME; start = p; continue; } break; case TAG_NAME: if( !is_valid_char(c) ) { if( p == start ) ERROR("Expected node name"); nodename = copy_string(start,p-start); attribs = alloc_empty_object(); state = IGNORE_SPACES; next = BODY; continue; } break; case BODY: switch( c ) { case '/': state = WAIT_END; nsubs++; val_ocall2(callb,id_xml,nodename,attribs); break; case '>': state = CHILDS; nsubs++; val_ocall2(callb,id_xml,nodename,attribs); break; default: state = ATTRIB_NAME; start = p; continue; } break; case ATTRIB_NAME: if( !is_valid_char(c) ) { value tmp; if( start == p ) ERROR("Expected attribute name"); tmp = copy_string(start,p-start); aname = val_id(val_string(tmp)); if( !val_is_null(val_field(attribs,aname)) ) ERROR("Duplicate attribute"); state = IGNORE_SPACES; next = EQUALS; continue; } break; case EQUALS: switch( c ) { case '=': state = IGNORE_SPACES; next = ATTVAL_BEGIN; break; default: ERROR("Expected ="); } break; case ATTVAL_BEGIN: switch( c ) { case '"': case '\'': state = ATTRIB_VAL; start = p; break; default: ERROR("Expected \""); } break; case ATTRIB_VAL: if( c == *start ) { value aval = copy_string(start+1,p-start-1); alloc_field(attribs,aname,aval); state = IGNORE_SPACES; next = BODY; } break; case CHILDS: *lp = p; do_parse_xml(xml,lp,line,callb,val_string(nodename)); p = *lp; start = p; state = BEGIN; break; case WAIT_END: switch( c ) { case '>': val_ocall0(callb,id_done); state = BEGIN; break; default : ERROR("Expected >"); } break; case WAIT_END_RET: switch( c ) { case '>': if( nsubs == 0 ) val_ocall1(callb,id_pcdata,alloc_string("")); val_ocall0(callb,id_done); *lp = p; return; default : ERROR("Expected >"); } break; case CLOSE: if( !is_valid_char(c) ) { if( start == p ) ERROR("Expected node name"); { value v = copy_string(start,p - start); if( _strcmpi(parentname,val_string(v)) != 0 ) { buffer b = alloc_buffer("Expected </"); buffer_append(b,parentname); buffer_append(b,">"); ERROR(buffer_data(b)); } } state = IGNORE_SPACES; next = WAIT_END_RET; continue; } break; case COMMENT: if( c == '-' && p[1] == '-' && p[2] == '>' ) { val_ocall1(callb,id_comment,copy_string(start,p-start)); p += 2; state = BEGIN; } break; case DOCTYPE: if( c == '[' ) nbrackets++; else if( c == ']' ) nbrackets--; else if( c == '>' && nbrackets == 0 ) { val_ocall1(callb,id_doctype,copy_string(start,p-start)); state = BEGIN; } break; case HEADER: if( c == '?' && p[1] == '>' ) { p++; val_ocall1(callb,id_comment,copy_string(start,p-start)); state = BEGIN; } break; } c = *++p; if( c == '\n' ) (*line)++; } if( state == BEGIN ) { start = p; state = PCDATA; } if( parentname == NULL && state == PCDATA ) { if( p != start || nsubs == 0 ) val_ocall1(callb,id_pcdata,copy_string(start,p-start)); return; } ERROR("Unexpected end"); }