/* * SPL - The SPL Programming Language * Copyright (C) 2004, 2005 Clifford Wolf * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * util.c: Helper functions for fast development with SPL */ #include #include #include #include #include #include #ifndef USEWIN32API # include #endif #include "spl.h" #include "compat.h" int spl_eval(struct spl_vm *vm, struct spl_node *ctx, char *module, const char *program) { static const char undumpable_reason[] = "Inside an spl_eval() call"; struct spl_asm *as = spl_asm_create(); int rc = 0; spl_undumpable_inc(vm, undumpable_reason); as->vm = vm; if ( spl_compiler(as, program, "eval", 0, 0) ) { spl_asm_destroy(as); spl_undumpable_dec(vm, undumpable_reason); return -1; } spl_asm_add(as, SPL_OP_HALT, 0); struct spl_task *task = spl_task_create(vm, 0); if ( module ) task->module = module; if ( ctx ) { spl_put(vm, task->ctx); task->ctx = ctx; } spl_task_setcode(task, spl_asm_dump(as)); spl_asm_destroy(as); while ( task->code && !(rc = spl_exec(task)) ) { } spl_task_destroy(vm, task); spl_undumpable_dec(vm, undumpable_reason); return rc; } int spl_eval_bytecode(struct spl_vm *vm, struct spl_node *ctx, char *module, struct spl_code *bytecode) { int rc = 0; struct spl_task *task = spl_task_create(vm, 0); if ( module ) task->module = module; if ( ctx ) { spl_put(vm, task->ctx); task->ctx = ctx; } spl_task_setcode(task, bytecode); while ( task->code && !(rc = spl_exec(task)) ) { } spl_task_destroy(vm, task); return rc; } struct spl_task *spl_schedule(struct spl_task *task) { struct spl_task *orig_task = task; struct spl_vm *vm = task->vm; if ( !task ) return 0; if ( task->flags & SPL_TASK_FLAG_SYSTEM ) if ( (task->flags & SPL_TASK_FLAG_PAUSED) == 0 ) return task; while (1) { if ( (task->flags & SPL_TASK_FLAG_ZOMBIE) && (task->flags & SPL_TASK_FLAG_PAUSED) ) { spl_task_destroy(vm, task); task = orig_task = vm->task_list; if ( !task ) return 0; } task = task->next; if ( !task ) task = vm->task_list; if ( (task->flags & (SPL_TASK_FLAG_PAUSED|SPL_TASK_FLAG_BUSY)) == 0 ) return task; if ( task == orig_task ) break; } return 0; } int spl_simple_runloop(struct spl_vm *vm, struct spl_task *wait_task) { int rc = 0; spl_runloop_function *old_rl = vm->runloop; vm->runloop = spl_simple_runloop; struct spl_task *task = wait_task ? wait_task : vm->task_list; while ( task && task->code ) { spl_gc_maybe(vm); task = spl_schedule(task); if ( spl_exec(task) < 0 ) goto got_error; } if (wait_task && wait_task != task) got_error: rc = -1; vm->runloop = old_rl; return rc; } void *spl_mmap_file(const char *filename, int *size) { #ifndef USEWIN32API int fd = open(filename, O_RDONLY|MY_O_BINARY); if (fd < 0) return 0; struct stat stbuf; fstat(fd, &stbuf); int mapsize = stbuf.st_size; int pagesize = getpagesize(); if ( mapsize % pagesize ) mapsize += pagesize - (mapsize % pagesize); char *ret = mmap(0, mapsize, PROT_READ, MAP_PRIVATE, fd, 0); if (ret && size) *size = stbuf.st_size; close(fd); return ret; #else return spl_malloc_file(filename, size); #endif } void *spl_malloc_file(const char *filename, int *size) { int fd = open(filename, O_RDONLY|MY_O_BINARY); if (fd < 0) return 0; struct stat stbuf; fstat(fd, &stbuf); char *ret = malloc(stbuf.st_size+1); for (int i=0, rc; i