/* ************************************************************************ */ /* */ /* Neko Virtual Machine */ /* Copyright (c)2005 Motion-Twin */ /* */ /* This library is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU Lesser General Public */ /* License as published by the Free Software Foundation; either */ /* version 2.1 of the License, or (at your option) any later version. */ /* */ /* This library is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ /* Lesser General Public License or the LICENSE file for more details. */ /* */ /* ************************************************************************ */ #include #include #include #include "neko_vm.h" #ifdef NEKO_WINDOWS # include #else # include #endif #ifdef NEKO_MAC # include # include #endif #ifdef NEKO_POSIX # include #endif #ifdef NEKO_STANDALONE extern void neko_standalone_init(); extern void neko_standalone_error( const char *str ); extern value neko_standalone_loader( char **arv, int argc ); # define default_loader neko_standalone_loader #else # define default_loader neko_default_loader #endif static FILE *self; extern void neko_stats_measure( neko_vm *vm, const char *kind, int start ); extern value neko_stats_build( neko_vm *vm ); static char *executable_path() { #if defined(NEKO_WINDOWS) static char path[MAX_PATH]; if( GetModuleFileName(NULL,path,MAX_PATH) == 0 ) return NULL; return path; #elif defined(NEKO_MAC) static char path[MAXPATHLEN+1]; uint32_t path_len = MAXPATHLEN; if ( _NSGetExecutablePath(path, &path_len) ) return NULL; return path; #else static char path[200]; int length = readlink("/proc/self/exe", path, sizeof(path)); if( length < 0 || length >= 200 ) { char *p = getenv(" "); // for upx if( p == NULL ) p = getenv("_"); return p; } path[length] = '\0'; return path; #endif } int neko_has_embedded_module( neko_vm *vm ) { char *exe = executable_path(); unsigned char id[8]; int pos; if( exe == NULL ) return 0; self = fopen(exe,"rb"); if( self == NULL ) return 0; fseek(self,-8,SEEK_END); fread(id,1,8,self); if( id[0] != 'N' || id[1] != 'E' || id[2] != 'K' || id[3] != 'O' ) { fclose(self); return 0; } pos = id[4] | id[5] << 8 | id[6] << 16; fseek(self,pos,SEEK_SET); // flags if( (id[7] & 1) == 0 ) neko_vm_jit(vm,1); return 1; } 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 #else # define _CrtSetDbgFlag(x) #endif #ifdef NEKO_POSIX static void handle_signal( int signal ) { val_throw(alloc_string("Segmentation fault")); } #endif 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-2008 Motion-Twin\n Usage : neko \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; } /* ************************************************************************ */