summaryrefslogtreecommitdiff
path: root/hieroglyph/vm.c
diff options
context:
space:
mode:
Diffstat (limited to 'hieroglyph/vm.c')
-rw-r--r--hieroglyph/vm.c1848
1 files changed, 459 insertions, 1389 deletions
diff --git a/hieroglyph/vm.c b/hieroglyph/vm.c
index 5b24eb7..1d86abb 100644
--- a/hieroglyph/vm.c
+++ b/hieroglyph/vm.c
@@ -1,10 +1,10 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* vm.c
- * Copyright (C) 2005-2006 Akira TAGOH
+ * Copyright (C) 2005-2007 Akira TAGOH
*
* Authors:
- * Akira TAGOH <at@gclab.org>
+ * Akira TAGOH <akira@tagoh.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -22,1593 +22,663 @@
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include "config.h"
#endif
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
+#include <glib/gmem.h>
+#include <hieroglyph/hgdict.h>
+#include <hieroglyph/hgfile.h>
+#include <hieroglyph/hgobject.h>
+#include <hieroglyph/hgoperator.h>
+#include <hieroglyph/hgstack.h>
#include "vm.h"
-#include "hgallocator-bfit.h"
-#include "hgmem.h"
-#include "hgarray.h"
-#include "hgdict.h"
-#include "hgfile.h"
-#include "hglineedit.h"
-#include "hglist.h"
-#include "hglog.h"
-#include "hgplugins.h"
-#include "hgstack.h"
-#include "hgstring.h"
-#include "hgvaluenode.h"
-#include "hggraphics.h"
-#include "operator.h"
-#include "scanner.h"
-
-
-#define _hg_vm_set_error(v, o, e, d) \
- G_STMT_START { \
- HgValueNode *__hg_op_node; \
- \
- HG_VALUE_MAKE_OPERATOR (__hg_op_node, (o)); \
- hg_vm_set_error((v), __hg_op_node, (e), (d)); \
- } G_STMT_END
-#define _hg_vm_set_error_from_file(v, o, e, d) \
- G_STMT_START { \
- HgValueNode *__hg_op_node; \
- \
- HG_VALUE_MAKE_OPERATOR (__hg_op_node, (o)); \
- hg_vm_set_error_from_file((v), __hg_op_node, (e), (d)); \
- } G_STMT_END
-
-
-struct _HieroGlyphVirtualMachine {
- HgObject object;
-
- /* vm */
- HgVMEmulationType emulation_type;
- gboolean use_global_pool : 1;
- gboolean has_error : 1;
- HgDict *name_dict;
- GTimeVal initialized_time;
- GRand *random_generator;
- gint32 error_code;
- gboolean shutdown;
- gint32 security_level;
-
- /* memory pool */
- HgAllocator *local_allocator;
- HgAllocator *global_allocator;
- HgAllocator *graphic_allocator;
- HgMemPool *local_pool;
- HgMemPool *global_pool;
- HgMemPool *graphic_pool;
-
- /* stacks */
- HgStack *ostack;
- HgStack *estack;
- HgStack *dstack;
-
- /* local dictionaries */
- HgDict *errordict;
- HgDict *error;
- HgDict *statusdict;
- HgDict *serverdict;
- HgDict *font;
-
- /* global dictionaries */
- HgDict *systemdict;
- HgDict *globalfont;
-
- /* file */
- HgFileObject *stdin;
- HgFileObject *stdout;
- HgFileObject *stderr;
- HgLineEdit *lineeditor;
-
- /* graphics */
- HgGraphics *graphics;
-
- /* plugin */
- HgDict *plugin_table;
- GList *plugin_list;
-};
-
-static void _hg_vm_real_free (gpointer data);
-static void _hg_vm_real_relocate(gpointer data,
- HgMemRelocateInfo *info);
+typedef struct hg_vm_private_s hg_vm_private_t;
-static gboolean __hg_vm_is_initialized = FALSE;
-static HgAllocator *__hg_vm_allocator = NULL;
-static HgMemPool *__hg_vm_mem_pool = NULL;
-HgValueNode *__hg_vm_errorname[VM_e_END] = { NULL };
-static HgObjectVTable __hg_vm_vtable = {
- .free = _hg_vm_real_free,
- .set_flags = NULL,
- .relocate = _hg_vm_real_relocate,
- .dup = NULL,
- .copy = NULL,
- .to_string = NULL,
+struct hg_vm_private_s {
+ hg_vm_t instance;
+ hg_error_t error;
+ hg_emulation_type_t current_level;
+ hg_object_t *io[HG_FILE_TYPE_END];
+ hg_stack_t *stack[HG_STACK_TYPE_END];
+ hg_object_t *dict;
};
-/*
- * special operators
- */
-static gboolean
-_hg_vm_op_rollbacksecuritylevel(HgOperator *op,
- gpointer data)
-{
- HgVM *vm = data;
- gboolean retval = TRUE;
- HgStack *estack = hg_vm_get_estack(vm);
- guint edepth = hg_stack_depth(estack);
- HgValueNode *nself, *node;
-
- /* ignore the errors */
- if (edepth > 2) {
- nself = hg_stack_index(estack, 0);
- node = hg_stack_index(estack, 1);
- if (HG_IS_VALUE_INTEGER (node)) {
- vm->security_level = HG_VALUE_GET_INTEGER (node);
- hg_stack_pop(estack);
- hg_stack_pop(estack);
- retval = hg_stack_push(estack, nself); /* dummy */
- /* it must be true */
- }
- }
- return retval;
-}
+static gboolean _hg_vm_lineedit_open (gpointer user_data,
+ error_t *error);
+static gsize _hg_vm_lineedit_read (gpointer user_data,
+ gpointer buffer,
+ gsize size,
+ gsize n,
+ error_t *error);
+static gsize _hg_vm_lineedit_write (gpointer user_data,
+ gconstpointer buffer,
+ gsize size,
+ gsize n,
+ error_t *error);
+static gboolean _hg_vm_lineedit_flush (gpointer user_data,
+ error_t *error);
+static gssize _hg_vm_lineedit_seek (gpointer user_data,
+ gssize offset,
+ hg_filepos_t whence,
+ error_t *error);
+static void _hg_vm_lineedit_close (gpointer user_data,
+ error_t *error);
+static gboolean _hg_vm_lineedit_is_closed (gpointer user_data);
+static gboolean _hg_vm_lineedit_is_eof (gpointer user_data);
+static void _hg_vm_lineedit_clear_eof (gpointer user_data);
+static gboolean _hg_vm_statementedit_open (gpointer user_data,
+ error_t *error);
+static gsize _hg_vm_statementedit_read (gpointer user_data,
+ gpointer buffer,
+ gsize size,
+ gsize n,
+ error_t *error);
+static gsize _hg_vm_statementedit_write (gpointer user_data,
+ gconstpointer buffer,
+ gsize size,
+ gsize n,
+ error_t *error);
+static gboolean _hg_vm_statementedit_flush (gpointer user_data,
+ error_t *error);
+static gssize _hg_vm_statementedit_seek (gpointer user_data,
+ gssize offset,
+ hg_filepos_t whence,
+ error_t *error);
+static void _hg_vm_statementedit_close (gpointer user_data,
+ error_t *error);
+static gboolean _hg_vm_statementedit_is_closed(gpointer user_data);
+static gboolean _hg_vm_statementedit_is_eof (gpointer user_data);
+static void _hg_vm_statementedit_clear_eof(gpointer user_data);
+
+
+static hg_filetable_t _hg_vm_lineedit_table = {
+ .open = _hg_vm_lineedit_open,
+ .read = _hg_vm_lineedit_read,
+ .write = _hg_vm_lineedit_write,
+ .flush = _hg_vm_lineedit_flush,
+ .seek = _hg_vm_lineedit_seek,
+ .close = _hg_vm_lineedit_close,
+ .is_closed = _hg_vm_lineedit_is_closed,
+ .is_eof = _hg_vm_lineedit_is_eof,
+ .clear_eof = _hg_vm_lineedit_clear_eof,
+};
+static hg_filetable_t _hg_vm_statementedit_table = {
+ .open = _hg_vm_statementedit_open,
+ .read = _hg_vm_statementedit_read,
+ .write = _hg_vm_statementedit_write,
+ .flush = _hg_vm_statementedit_flush,
+ .seek = _hg_vm_statementedit_seek,
+ .close = _hg_vm_statementedit_close,
+ .is_closed = _hg_vm_statementedit_is_closed,
+ .is_eof = _hg_vm_statementedit_is_eof,
+ .clear_eof = _hg_vm_statementedit_clear_eof,
+};
/*
- * Private Functions
+ * Private functions
*/
-static void
-_hg_vm_init_errorname(void)
+static gboolean
+_hg_vm_lineedit_open(gpointer user_data,
+ error_t *error)
{
-#define MAKE_ERRNAME(sym) \
- G_STMT_START { \
- HgValueNode *__hg_vm_err_node; \
- \
- HG_VALUE_MAKE_NAME_STATIC (__hg_vm_mem_pool, \
- __hg_vm_err_node, \
- #sym); \
- __hg_vm_errorname[VM_e_##sym] = __hg_vm_err_node; \
- hg_mem_pool_add_root_node(__hg_vm_mem_pool, __hg_vm_err_node); \
- } G_STMT_END
-
- MAKE_ERRNAME(dictfull);
- MAKE_ERRNAME(dictstackoverflow);
- MAKE_ERRNAME(dictstackunderflow);
- MAKE_ERRNAME(execstackoverflow);
- MAKE_ERRNAME(handleerror);
- MAKE_ERRNAME(interrupt);
- MAKE_ERRNAME(invalidaccess);
- MAKE_ERRNAME(invalidexit);
- MAKE_ERRNAME(invalidfileaccess);
- MAKE_ERRNAME(invalidfont);
- MAKE_ERRNAME(invalidrestore);
- MAKE_ERRNAME(ioerror);
- MAKE_ERRNAME(limitcheck);
- MAKE_ERRNAME(nocurrentpoint);
- MAKE_ERRNAME(rangecheck);
- MAKE_ERRNAME(stackoverflow);
- MAKE_ERRNAME(stackunderflow);
- MAKE_ERRNAME(syntaxerror);
- MAKE_ERRNAME(timeout);
- MAKE_ERRNAME(typecheck);
- MAKE_ERRNAME(undefined);
- MAKE_ERRNAME(undefinedfilename);
- MAKE_ERRNAME(undefinedresult);
- MAKE_ERRNAME(unmatchedmark);
- MAKE_ERRNAME(unregistered);
- MAKE_ERRNAME(VMerror);
- MAKE_ERRNAME(configurationerror);
- MAKE_ERRNAME(undefinedresource);
-
-#undef MAKE_ERRNAME
+ /* XXX */
+ return FALSE;
}
-static void
-_hg_vm_real_free(gpointer data)
+static gsize
+_hg_vm_lineedit_read(gpointer user_data,
+ gpointer buffer,
+ gsize size,
+ gsize n,
+ error_t *error)
{
- HgVM *vm = data;
-
- if (vm->random_generator)
- g_rand_free(vm->random_generator);
- if (vm->local_pool)
- hg_mem_pool_destroy(vm->local_pool);
-#ifdef ENABLE_GLOBAL_POOL
- if (vm->global_pool)
- hg_mem_pool_destroy(vm->global_pool);
-#endif
- if (vm->graphic_pool)
- hg_mem_pool_destroy(vm->graphic_pool);
- hg_allocator_destroy(vm->local_allocator);
- hg_allocator_destroy(vm->global_allocator);
- hg_allocator_destroy(vm->graphic_allocator);
+ /* XXX */
+ return 0;
}
-static void
-_hg_vm_real_relocate(gpointer data,
- HgMemRelocateInfo *info)
+static gsize
+_hg_vm_lineedit_write(gpointer user_data,
+ gconstpointer buffer,
+ gsize size,
+ gsize n,
+ error_t *error)
{
- HgVM *vm = data;
-
-#define _hg_vm_update_addr(_name) \
- G_STMT_START { \
- if ((gsize)vm->_name >= info->start && \
- (gsize)vm->_name <= info->end) { \
- vm->_name = (gpointer)((gsize)vm->_name + info->diff); \
- } \
- } G_STMT_END
-
- _hg_vm_update_addr(name_dict);
- _hg_vm_update_addr(ostack);
- _hg_vm_update_addr(estack);
- _hg_vm_update_addr(dstack);
- _hg_vm_update_addr(errordict);
- _hg_vm_update_addr(error);
- _hg_vm_update_addr(statusdict);
- _hg_vm_update_addr(serverdict);
- _hg_vm_update_addr(font);
- _hg_vm_update_addr(systemdict);
- _hg_vm_update_addr(globalfont);
- _hg_vm_update_addr(stdin);
- _hg_vm_update_addr(stdout);
- _hg_vm_update_addr(stderr);
-
-#undef _hg_vm_update_addr
+ /* XXX */
+ return 0;
}
static gboolean
-_hg_vm_eval_file(HgVM *vm,
- HgFileObject *file,
- gboolean *error)
+_hg_vm_lineedit_flush(gpointer user_data,
+ error_t *error)
{
- HgStack *estack = hg_vm_get_estack(vm);
- gboolean retval = FALSE;
- HgValueNode *node;
-
- while (1) {
- if (!hg_file_object_has_error(file)) {
- HG_VALUE_MAKE_FILE (node, file);
- if (node == NULL) {
- _hg_vm_set_error(vm, file, VM_e_VMerror, FALSE);
- *error = TRUE;
- break;
- }
- hg_stack_clear(estack);
- hg_vm_reset_error(vm);
- hg_object_executable((HgObject *)node);
- retval = hg_stack_push(estack, node);
- if (!retval) {
- hg_vm_set_error(vm, node, VM_e_execstackoverflow, FALSE);
- *error = TRUE;
- break;
- }
- hg_vm_main(vm);
- hg_mem_free(node);
- hg_mem_free(file);
- if (hg_vm_has_error(vm) ||
- ((node = hg_dict_lookup_with_string(vm->error, "newerror")) != NULL &&
- HG_IS_VALUE_BOOLEAN (node) &&
- HG_VALUE_GET_BOOLEAN (node) == TRUE)) {
- if (error)
- *error = TRUE;
- } else {
- retval = TRUE;
- if (error)
- *error = FALSE;
- }
- }
- break;
- }
-
- return retval;
+ /* XXX */
+ return FALSE;
}
-static gboolean
-_hg_vm_run(HgVM *vm,
- const gchar *filename,
- gboolean *error)
+static gssize
+_hg_vm_lineedit_seek(gpointer user_data,
+ gssize offset,
+ hg_filepos_t whence,
+ error_t *error)
{
- HgMemPool *pool = hg_vm_get_current_pool(vm);
- HgFileObject *file = hg_file_object_new(pool,
- HG_FILE_TYPE_FILE,
- HG_FILE_MODE_READ,
- filename);
-
- return _hg_vm_eval_file(vm, file, error);
+ /* XXX */
+ return 0;
}
static void
-hg_vm_set_ostack(HgVM *vm,
- HgStack *ostack)
+_hg_vm_lineedit_close(gpointer user_data,
+ error_t *error)
{
- g_return_if_fail (vm != NULL);
- g_return_if_fail (ostack != NULL);
-
- vm->ostack = ostack;
+ /* XXX */
}
-static void
-hg_vm_set_estack(HgVM *vm,
- HgStack *estack)
+static gboolean
+_hg_vm_lineedit_is_closed(gpointer user_data)
{
- g_return_if_fail (vm != NULL);
- g_return_if_fail (estack != NULL);
-
- vm->estack = estack;
+ /* XXX */
+ return FALSE;
}
-static void
-hg_vm_set_dstack(HgVM *vm,
- HgStack *dstack)
+static gboolean
+_hg_vm_lineedit_is_eof(gpointer user_data)
{
- g_return_if_fail (vm != NULL);
- g_return_if_fail (dstack != NULL);
-
- vm->dstack = dstack;
+ /* XXX */
+ return FALSE;
}
-/*
- * Public Functions
- */
-
-/* initializer */
-void
-hg_vm_init(void)
+static void
+_hg_vm_lineedit_clear_eof(gpointer user_data)
{
- if (!__hg_vm_is_initialized) {
- hg_mem_init();
- hg_value_node_init();
- hg_file_init();
- hg_list_init();
- hg_log_init();
-
- __hg_vm_allocator = hg_allocator_new(hg_allocator_bfit_get_vtable());
- /* XXX: Ordinarily this pool should be a global pool according
- * to this purpose. However it causes the pool check error
- * to store the objects to the object, such as the node to
- * the array when it happens during the error handling
- * so that hg_vm_get_current_pool() returns
- * __hg_vm_mem_pool to avoid another VMerror.
- */
- __hg_vm_mem_pool = hg_mem_pool_new(__hg_vm_allocator,
- "Hieroglyph VM Memory Pool",
- 8192,
- HG_MEM_RESIZABLE);
- hg_mem_pool_use_garbage_collection(__hg_vm_mem_pool, FALSE);
- _hg_vm_init_errorname();
- __hg_vm_is_initialized = TRUE;
- }
+ /* XXX */
}
-void
-hg_vm_finalize(void)
+static gboolean
+_hg_vm_statementedit_open(gpointer user_data,
+ error_t *error)
{
- if (__hg_vm_is_initialized) {
- hg_mem_pool_destroy(__hg_vm_mem_pool);
- hg_allocator_destroy(__hg_vm_allocator);
-
- hg_file_finalize();
- hg_log_finalize();
- /* it may be better to be finalized after logger,
- * because it uses HgDict, which is referring to HgList.
- */
- hg_list_finalize();
- hg_value_node_finalize();
- hg_mem_finalize();
-
- __hg_vm_is_initialized = FALSE;
- }
+ /* XXX */
+ return FALSE;
}
-gboolean
-hg_vm_is_initialized(void)
+static gsize
+_hg_vm_statementedit_read(gpointer user_data,
+ gpointer buffer,
+ gsize size,
+ gsize n,
+ error_t *error)
{
- return __hg_vm_is_initialized;
+ /* XXX */
+ return 0;
}
-/* virtual machine */
-HgVM *
-hg_vm_new(HgVMEmulationType type)
+static gsize
+_hg_vm_statementedit_write(gpointer user_data,
+ gconstpointer buffer,
+ gsize size,
+ gsize n,
+ error_t *error)
{
- HgVM *retval;
- gchar *name;
- gboolean allow_resize = FALSE;
-
- g_return_val_if_fail (__hg_vm_is_initialized, NULL);
-
- retval = hg_mem_alloc_with_flags(__hg_vm_mem_pool, sizeof (HgVM),
- HG_FL_HGOBJECT);
- if (retval == NULL) {
- hg_log_warning("Failed to create a virtual machine.");
- return NULL;
- }
- HG_OBJECT_INIT_STATE (&retval->object);
- HG_OBJECT_SET_STATE (&retval->object, hg_mem_pool_get_default_access_mode(__hg_vm_mem_pool));
- hg_object_set_vtable(&retval->object, &__hg_vm_vtable);
-
- retval->emulation_type = type;
- retval->use_global_pool = FALSE;
- retval->has_error = FALSE;
- retval->shutdown = FALSE;
- retval->error_code = 0;
-
- if (type >= VM_EMULATION_LEVEL_2) {
- allow_resize = TRUE;
- retval->use_global_pool = TRUE;
- }
-
- /* initialize the memory pools */
- retval->local_allocator = hg_allocator_new(hg_allocator_bfit_get_vtable());
- retval->global_allocator = hg_allocator_new(hg_allocator_bfit_get_vtable());
- retval->graphic_allocator = hg_allocator_new(hg_allocator_bfit_get_vtable());
- name = g_strdup_printf("VM %p:local pool", retval);
- retval->local_pool = hg_mem_pool_new(retval->local_allocator,
- name,
- HG_LOCAL_POOL_SIZE,
- (allow_resize ? HG_MEM_RESIZABLE : 0));
- g_free(name);
- if (retval->local_pool == NULL) {
- hg_log_warning("Failed to create a local memory pool");
- return NULL;
- }
-#ifdef ENABLE_GLOBAL_POOL
- name = g_strdup_printf("VM %p: global pool", retval);
- retval->global_pool = hg_mem_pool_new(retval->global_allocator,
- name,
- HG_GLOBAL_POOL_SIZE,
- HG_MEM_GLOBAL | (allow_resize ? HG_MEM_RESIZABLE : 0));
- hg_mem_pool_use_global_mode(retval->global_pool, TRUE);
- g_free(name);
- if (retval->global_pool == NULL) {
- hg_log_warning("Failed to create a global memory pool");
- return NULL;
- }
-#else
- retval->global_pool = retval->local_pool;
-#endif
- name = g_strdup_printf("VM %p:graphic pool", retval);
- retval->graphic_pool = hg_mem_pool_new(retval->graphic_allocator,
- name,
- HG_GRAPHIC_POOL_SIZE,
- (allow_resize ? HG_MEM_RESIZABLE : 0));
- g_free(name);
- if (retval->graphic_pool == NULL) {
- hg_log_warning("Failed to create a graphic memory pool");
- return NULL;
- }
-
- /* internal use */
- retval->name_dict = hg_dict_new(retval->global_pool, 1024);
- if (retval->name_dict == NULL) {
- hg_log_warning("Failed to create a name dict.");
- return NULL;
- }
- hg_mem_pool_add_root_node(retval->global_pool, retval->name_dict);
-
- g_get_current_time(&retval->initialized_time);
- retval->random_generator = g_rand_new();
-
- /* initialize the stacks */
- retval->ostack = hg_stack_new(retval->local_pool, 500);
- retval->estack = hg_stack_new(retval->local_pool, 250);
- retval->dstack = hg_stack_new(retval->local_pool, 20);
- if (retval->ostack == NULL ||
- retval->estack == NULL ||
- retval->dstack == NULL) {
- hg_log_warning("Failed to create stacks.");
- return NULL;
- }
- hg_mem_pool_add_root_node(retval->local_pool, retval->ostack);
- hg_mem_pool_add_root_node(retval->local_pool, retval->estack);
- hg_mem_pool_add_root_node(retval->local_pool, retval->dstack);
-
- /* initialize local dictionaries */
- retval->errordict = hg_dict_new(retval->local_pool, 128);
- retval->error = hg_dict_new(retval->local_pool, 128);
- retval->statusdict = hg_dict_new(retval->local_pool, 128);
- retval->serverdict = hg_dict_new(retval->local_pool, 128);
- retval->font = hg_dict_new(retval->local_pool, 128);
- if (retval->errordict == NULL ||
- retval->error == NULL ||
- retval->statusdict == NULL ||
- retval->serverdict == NULL ||
- retval->font == NULL) {
- hg_log_warning("Failed to create local dictionaries.");
- return NULL;
- }
- hg_mem_pool_add_root_node(retval->local_pool, retval->errordict);
- hg_mem_pool_add_root_node(retval->local_pool, retval->error);
- hg_mem_pool_add_root_node(retval->local_pool, retval->statusdict);
- hg_mem_pool_add_root_node(retval->local_pool, retval->serverdict);
- hg_mem_pool_add_root_node(retval->local_pool, retval->font);
-
- /* initialize global dictionaries */
- retval->systemdict = hg_dict_new(retval->global_pool, 384);
- retval->globalfont = hg_dict_new(retval->global_pool, 128);
- if (retval->systemdict == NULL ||
- retval->globalfont == NULL) {
- hg_log_warning("Failed to create global dictionaries.");
- return NULL;
- }
- hg_mem_pool_add_root_node(retval->global_pool, retval->systemdict);
- hg_mem_pool_add_root_node(retval->global_pool, retval->globalfont);
-
- /* initialize file object */
- retval->stdin = __hg_file_stdin;
- retval->stdout = __hg_file_stdout;
- retval->stderr = __hg_file_stderr;
- retval->lineeditor = hg_line_edit_new(retval->local_pool, NULL,
- retval->stdin, retval->stdout);
- hg_mem_pool_add_root_node(retval->local_pool, retval->lineeditor);
-
- /* initialize graphics */
- retval->graphics = hg_graphics_new(retval->graphic_pool);
- hg_mem_pool_add_root_node(retval->graphic_pool, retval->graphics);
-
- /* plugin support */
- retval->plugin_table = hg_dict_new(retval->local_pool, 256);
- retval->plugin_list = NULL;
- hg_mem_pool_add_root_node(retval->local_pool, retval->plugin_table);
-
- hg_mem_pool_add_root_node(__hg_vm_mem_pool, retval);
-
- return retval;
+ /* XXX */
+ return 0;
}
-void
-hg_vm_set_emulation_level(HgVM *vm,
- HgVMEmulationType type)
+static gboolean
+_hg_vm_statementedit_flush(gpointer user_data,
+ error_t *error)
{
- gboolean allow_resize = FALSE;
-
- g_return_if_fail (vm != NULL);
-
- vm->emulation_type = type;
- if (type >= VM_EMULATION_LEVEL_2)
- allow_resize = TRUE;
-
- hg_mem_pool_allow_resize(vm->global_pool, allow_resize);
- hg_mem_pool_allow_resize(vm->local_pool, allow_resize);
- hg_vm_startjob(vm, NULL, FALSE);
+ /* XXX */
+ return FALSE;
}
-HgVMEmulationType
-hg_vm_get_emulation_level(HgVM *vm)
+static gssize
+_hg_vm_statementedit_seek(gpointer user_data,
+ gssize offset,
+ hg_filepos_t whence,
+ error_t *error)
{
- g_return_val_if_fail (vm != NULL, VM_EMULATION_LEVEL_1);
-
- return vm->emulation_type;
+ /* XXX */
+ return FALSE;
}
-HgStack *
-hg_vm_get_ostack(HgVM *vm)
+static void
+_hg_vm_statementedit_close(gpointer user_data,
+ error_t *error)
{
- return vm->ostack;
+ /* XXX */
}
-HgStack *
-hg_vm_get_estack(HgVM *vm)
+static gboolean
+_hg_vm_statementedit_is_closed(gpointer user_data)
{
- return vm->estack;
+ /* XXX */
+ return FALSE;
}
-HgStack *
-hg_vm_get_dstack(HgVM *vm)
+static gboolean
+_hg_vm_statementedit_is_eof(gpointer user_data)
{
- return vm->dstack;
+ /* XXX */
+ return FALSE;
}
-HgDict *
-hg_vm_get_dict_errordict(HgVM *vm)
+static void
+_hg_vm_statementedit_clear_eof(gpointer user_data)
{
- return vm->errordict;
+ /* XXX */
}
-HgDict *
-hg_vm_get_dict_error(HgVM *vm)
-{
- return vm->error;
+/*
+ * Public functions
+ */
+hg_vm_t *
+hg_vm_new(void)
+{
+ hg_vm_private_t *retval = g_new0(hg_vm_private_t, 1);
+ hg_stack_type_t i;
+
+ /* initialize VM */
+ retval->current_level = HG_EMU_BEGIN;
+ for (i = HG_STACK_TYPE_OSTACK; i < HG_STACK_TYPE_END; i++)
+ retval->stack[i] = NULL;
+ retval->dict = NULL;
+
+ /* complete the initialization here */
+ retval->io[HG_FILE_TYPE_STDIN] = hg_object_file_new((hg_vm_t *)retval,
+ "%stdin",
+ HG_FILE_MODE_READ);
+ retval->io[HG_FILE_TYPE_STDOUT] = hg_object_file_new((hg_vm_t *)retval,
+ "%stdout",
+ HG_FILE_MODE_WRITE);
+ retval->io[HG_FILE_TYPE_STDERR] = hg_object_file_new((hg_vm_t *)retval,
+ "%stderr",
+ HG_FILE_MODE_WRITE);
+ retval->io[HG_FILE_TYPE_LINEEDIT] = hg_object_file_new_with_custom((hg_vm_t *)retval,
+ &_hg_vm_lineedit_table,
+ HG_FILE_MODE_READ);
+ retval->io[HG_FILE_TYPE_STATEMENTEDIT] = hg_object_file_new_with_custom((hg_vm_t *)retval,
+ &_hg_vm_statementedit_table,
+ HG_FILE_MODE_READ);
+
+ return (hg_vm_t *)retval;
}
-HgDict *
-hg_vm_get_dict_statusdict(HgVM *vm)
+void
+hg_vm_destroy(hg_vm_t *vm)
{
- return vm->statusdict;
-}
+ hg_return_if_fail (vm != NULL);
-HgDict *
-hg_vm_get_dict_serverdict(HgVM *vm)
-{
- return vm->serverdict;
+ /* XXX */
+ g_free(vm);
}
-HgDict *
-hg_vm_get_dict_font(HgVM *vm)
+gpointer
+hg_vm_malloc(hg_vm_t *vm,
+ gsize size)
{
- return vm->font;
-}
+ gpointer retval;
-HgDict *
-hg_vm_get_dict_systemdict(HgVM *vm)
-{
- return vm->systemdict;
-}
+ hg_return_val_if_fail (vm != NULL, NULL);
-HgDict *
-hg_vm_get_dict_globalfont(HgVM *vm)
-{
- return vm->globalfont;
+ /* XXX */
+ retval = g_malloc(size);
+
+ return retval;
}
-HgMemPool *
-hg_vm_get_current_pool(HgVM *vm)
+gpointer
+hg_vm_realloc(hg_vm_t *vm,
+ gpointer object,
+ gsize size)
{
- g_return_val_if_fail (vm != NULL, NULL);
+ gpointer retval;
- if (vm->has_error) {
- /* return a special memory pool to avoid recursive VMerror */
- return __hg_vm_mem_pool;
- }
- if (vm->use_global_pool)
- return vm->global_pool;
+ hg_return_val_if_fail (vm != NULL, NULL);
- return vm->local_pool;
-}
+ /* XXX */
+ retval = g_realloc(object, size);
-gboolean
-hg_vm_is_global_pool_used(HgVM *vm)
-{
- g_return_val_if_fail (vm != NULL, FALSE);
-
- return vm->use_global_pool;
+ return retval;
}
void
-hg_vm_use_global_pool(HgVM *vm,
- gboolean use_global)
+hg_vm_mfree(hg_vm_t *vm,
+ gpointer data)
{
- g_return_if_fail (vm != NULL);
+ hg_return_if_fail (vm != NULL);
- vm->use_global_pool = use_global;
+ /* XXX */
+ g_free(data);
}
-gboolean
-hg_vm_is_global_object(HgVM *vm,
- HgValueNode *node)
+guchar
+hg_vm_get_object_format(hg_vm_t *vm)
{
- HgMemObject *obj;
- gboolean retval = FALSE;
- gpointer p;
-
- g_return_val_if_fail (vm != NULL, TRUE);
- g_return_val_if_fail (node != NULL, TRUE);
-
- switch (HG_VALUE_GET_VALUE_TYPE (node)) {
- case HG_TYPE_VALUE_BOOLEAN:
- case HG_TYPE_VALUE_INTEGER:
- case HG_TYPE_VALUE_REAL:
- case HG_TYPE_VALUE_NAME:
- case HG_TYPE_VALUE_NULL:
- case HG_TYPE_VALUE_OPERATOR:
- case HG_TYPE_VALUE_MARK:
- break;
- case HG_TYPE_VALUE_ARRAY:
- case HG_TYPE_VALUE_STRING:
- case HG_TYPE_VALUE_DICT:
- case HG_TYPE_VALUE_FILE:
- case HG_TYPE_VALUE_SNAPSHOT:
- p = HG_VALUE_GET_VALUE_NODE (node, Pointer);
- hg_mem_get_object__inline(p, obj);
- retval = (vm->local_pool != obj->pool);
- break;
- default:
- hg_log_warning("Failed to consider if the object is a global object due to the unknown type ID: %d", HG_VALUE_GET_VALUE_TYPE (node));
- break;
- }
+ hg_return_val_if_fail (vm != NULL, 0);
- return retval;
+ /* XXX */
+ return 0;
}
-HgGraphics *
-hg_vm_get_graphics(HgVM *vm)
+void
+hg_vm_get_attributes(hg_vm_t *vm,
+ hg_attribute_t *attr)
{
- g_return_val_if_fail (vm != NULL, NULL);
+ hg_return_if_fail (vm != NULL);
+ hg_return_if_fail (attr != NULL);
- return vm->graphics;
+ /* XXX */
+ attr->bit.is_accessible = TRUE;
+ attr->bit.is_readable = TRUE;
+ attr->bit.is_executeonly = FALSE;
+ attr->bit.is_locked = FALSE;
+ attr->bit.reserved4 = FALSE;
+ attr->bit.reserved5 = FALSE;
+ attr->bit.is_global = FALSE;
+ attr->bit.is_checked = FALSE;
}
-gint32
-hg_vm_get_current_time(HgVM *vm)
+void
+hg_vm_set_error(hg_vm_t *vm,
+ hg_error_t error)
{
- GTimeVal t;
- gint32 retval, i;
+ hg_vm_private_t *priv;
+
+ hg_return_if_fail (vm != NULL);
- g_get_current_time(&t);
- if (t.tv_sec == vm->initialized_time.tv_sec) {
- retval = (t.tv_usec - vm->initialized_time.tv_usec) / 1000;
+ priv = (hg_vm_private_t *)vm;
+ if (priv->error == 0) {
+ priv->error = error;
} else {
- i = t.tv_sec - vm->initialized_time.tv_sec;
- if (t.tv_usec > vm->initialized_time.tv_usec) {
- retval = i * 1000 + (t.tv_usec - vm->initialized_time.tv_usec) / 1000;
- } else {
- i--;
- retval = i * 1000 + ((1 * 1000000 - vm->initialized_time.tv_usec) + t.tv_usec) / 1000;
- }
+ /* XXX */
}
-
- return retval;
}
-GRand *
-hg_vm_get_random_generator(HgVM *vm)
+hg_error_t
+hg_vm_get_error(hg_vm_t *vm)
{
- g_return_val_if_fail (vm != NULL, 0);
+ hg_vm_private_t *priv;
- return vm->random_generator;
-}
+ hg_return_val_if_fail (vm != NULL, HG_e_VMerror);
-HgFileObject *
-hg_vm_get_io(HgVM *vm,
- HgVMIOType type)
-{
- g_return_val_if_fail (vm != NULL, NULL);
-
- switch (type) {
- case VM_IO_STDIN:
- return vm->stdin;
- case VM_IO_STDOUT:
- return vm->stdout;
- case VM_IO_STDERR:
- return vm->stderr;
- default:
- hg_log_warning("Unknown I/O type %d", type);
- break;
- }
+ priv = (hg_vm_private_t *)vm;
- return NULL;
+ return priv->error;
}
void
-hg_vm_set_io(HgVM *vm,
- HgVMIOType type,
- HgFileObject *file)
+hg_vm_clear_error(hg_vm_t *vm)
{
- g_return_if_fail (vm != NULL);
- g_return_if_fail (file != NULL);
-
- switch (type) {
- case VM_IO_STDIN:
- vm->stdin = file;
- hg_line_edit_set_stdin(vm->lineeditor, file);
- break;
- case VM_IO_STDOUT:
- vm->stdout = file;
- hg_line_edit_set_stdout(vm->lineeditor, file);
- break;
- case VM_IO_STDERR:
- vm->stderr = file;
- break;
- default:
- hg_log_warning("Unknown I/O type %d", type);
- break;
- }
-}
+ hg_vm_private_t *priv;
-HgLineEdit *
-hg_vm_get_line_editor(HgVM *vm)
-{
- g_return_val_if_fail (vm != NULL, NULL);
+ hg_return_if_fail (vm != NULL);
- return vm->lineeditor;
+ priv = (hg_vm_private_t *)vm;
+ priv->error = 0;
}
-void
-hg_vm_set_line_editor(HgVM *vm,
- HgLineEdit *editor)
+hg_object_t *
+hg_vm_get_io(hg_vm_t *vm,
+ hg_filetype_t iotype)
{
- g_return_if_fail (vm != NULL);
- g_return_if_fail (editor != NULL);
+ hg_vm_private_t *priv;
- vm->lineeditor = editor;
-}
+ hg_return_val_if_fail (vm != NULL, NULL);
-gboolean
-hg_vm_load_plugin(HgVM *vm,
- const gchar *filename)
-{
- HgPlugin *plugin;
- HgValueNode *key, *val;
-
- g_return_val_if_fail (vm != NULL, FALSE);
- g_return_val_if_fail (filename != NULL, FALSE);
+ priv = (hg_vm_private_t *)vm;
- if (hg_dict_lookup_with_string(vm->plugin_table, filename) != NULL) {
- hg_log_warning("`%s' plugin is already loaded.", filename);
- return FALSE;
- }
- plugin = hg_plugin_open(vm->local_pool, filename, HG_PLUGIN_EXTENSION);
- if (plugin) {
- HG_VALUE_MAKE_NAME_STATIC (vm->local_pool, key, filename);
- HG_VALUE_MAKE_PLUGIN (val, plugin);
- hg_dict_insert(vm->local_pool, vm->plugin_table, key, val);
- vm->plugin_list = g_list_append(vm->plugin_list, plugin);
- }
-
- return plugin != NULL;
+ return priv->io[iotype];
}
void
-hg_vm_load_plugins_all(HgVM *vm)
+hg_vm_set_io(hg_vm_t *vm,
+ hg_object_t *object)
{
- GList *l;
+ hg_vm_private_t *priv;
- /* load all the plugins after the VM initialization is finished */
- for (l = vm->plugin_list; l != NULL; l = g_list_next(l)) {
- HgPlugin *plugin = l->data;
+ hg_return_if_fail (vm != NULL);
+ hg_return_if_fail (object != NULL);
+ hg_return_if_fail (HG_OBJECT_IS_FILE (object));
- hg_plugin_load(plugin, vm);
- }
+ priv = (hg_vm_private_t *)vm;
+ priv->io[HG_OBJECT_FILE_DATA (object)->iotype] = object;
}
gboolean
-hg_vm_unload_plugin(HgVM *vm,
- const gchar *filename)
+hg_vm_initialize(hg_vm_t *vm)
{
- HgValueNode *val;
-
- g_return_val_if_fail (vm != NULL, FALSE);
- g_return_val_if_fail (filename != NULL, FALSE);
-
- if ((val = hg_dict_lookup_with_string(vm->plugin_table, filename)) == NULL) {
- hg_log_warning("`%s' plugin isn't yet loaded.", filename);
- return FALSE;
- }
-
- return hg_plugin_unload(HG_VALUE_GET_PLUGIN (val), vm);
-}
+ hg_vm_private_t *priv;
+ gboolean retval;
-guint
-hg_vm_get_save_level(HgVM *vm)
-{
- g_return_val_if_fail (vm != NULL, 0);
-
- return hg_mem_pool_get_n_snapshots(hg_vm_get_current_pool(vm));
-}
-
-HgValueNode *
-_hg_vm_get_name_node(HgVM *vm,
- const gchar *name)
-{
- HgValueNode *node;
-
- g_return_val_if_fail (vm != NULL, NULL);
- g_return_val_if_fail (name != NULL, NULL);
-
- node = hg_dict_lookup_with_string(vm->name_dict, name);
- if (node == NULL) {
- HG_VALUE_MAKE_NAME_STATIC (vm->global_pool, node, name);
- hg_dict_insert(vm->global_pool, vm->name_dict, node, node);
- }
+ hg_return_val_if_fail (vm != NULL, FALSE);
- return node;
-}
+ priv = (hg_vm_private_t *)vm;
+ priv->stack[HG_STACK_TYPE_OSTACK] = hg_stack_new(vm, 65535);
+ priv->stack[HG_STACK_TYPE_ESTACK] = hg_stack_new(vm, 65535);
+ priv->stack[HG_STACK_TYPE_DSTACK] = hg_stack_new(vm, 65535);
+ priv->dict = hg_object_dict_new(vm, 65535);
-HgValueNode *
-hg_vm_get_name_node(HgVM *vm,
- const gchar *name)
-{
- HgValueNode *retval = NULL, *node;
+ /* push globaldict to dstack */
+ hg_stack_push(priv->stack[HG_STACK_TYPE_DSTACK], priv->dict);
- node = _hg_vm_get_name_node(vm, name);
- if (node) {
- HG_VALUE_MAKE_NAME (retval, HG_VALUE_GET_NAME (node));
- }
+ /* initialize operators */
+ retval = hg_object_operator_initialize(vm, HG_EMU_PS_LEVEL_3);
- return retval;
+ return TRUE;
}
-HgValueNode *
-hg_vm_lookup(HgVM *vm,
- HgValueNode *key)
+gboolean
+hg_vm_finalize(hg_vm_t *vm)
{
- guint depth, i;
- HgValueNode *node, *retval = NULL;
-
- g_return_val_if_fail (vm != NULL, NULL);
- g_return_val_if_fail (key != NULL, NULL);
+ hg_vm_private_t *priv;
- depth = hg_stack_depth(vm->dstack);
- for (i = 0; i < depth; i++) {
- HgDict *dict;
+ hg_return_val_if_fail (vm != NULL, FALSE);
- node = hg_stack_index(vm->dstack, i);
- if (node == NULL || !HG_IS_VALUE_DICT (node)) {
- hg_log_error("dictionary stack was broken.");
- break;
- }
- dict = HG_VALUE_GET_DICT (node);
- if ((retval = hg_dict_lookup(dict, key)) != NULL)
- break;
- }
+ priv = (hg_vm_private_t *)vm;
+ /* XXX */
- return retval;
+ return TRUE;
}
-HgValueNode *
-hg_vm_lookup_with_string(HgVM *vm,
- const gchar *key)
+hg_emulation_type_t
+hg_vm_get_emulation_level(hg_vm_t *vm)
{
- guint depth, i;
- HgValueNode *node, *retval = NULL;
+ hg_vm_private_t *priv;
- g_return_val_if_fail (vm != NULL, NULL);
- g_return_val_if_fail (key != NULL, NULL);
+ hg_return_val_if_fail (vm != NULL, HG_EMU_BEGIN);
- depth = hg_stack_depth(vm->dstack);
- for (i = 0; i < depth; i++) {
- node = hg_stack_index(vm->dstack, i);
- if (node == NULL || !HG_IS_VALUE_DICT (node)) {
- hg_log_error("dictionary stack was broken.");
- break;
- }
- if ((retval = hg_dict_lookup_with_string(HG_VALUE_GET_DICT (node), key)) != NULL)
- break;
- }
+ priv = (hg_vm_private_t *)vm;
- return retval;
+ return priv->current_level;
}
gboolean
-hg_vm_startjob(HgVM *vm,
- const gchar *initializer,
- gboolean encapsulated)
+hg_vm_set_emulation_level(hg_vm_t *vm,
+ hg_emulation_type_t level)
{
- HgValueNode *node, *nkey;
- HgMemSnapshot *snap;
- gboolean retval = TRUE;
-
- g_return_val_if_fail (vm != NULL, FALSE);
+ hg_vm_private_t *priv;
- hg_stack_clear(vm->ostack);
- hg_stack_clear(vm->dstack);
+ hg_return_val_if_fail (vm != NULL, FALSE);
- hg_mem_garbage_collection(vm->global_pool);
- hg_mem_garbage_collection(vm->local_pool);
+ priv = (hg_vm_private_t *)vm;
- if (hg_mem_pool_get_n_snapshots(vm->global_pool) > 0) {
- snap = hg_mem_pool_get_snapshot(vm->global_pool, 0);
- hg_mem_pool_remove_root_node(vm->global_pool, snap);
- if (!hg_mem_pool_restore_snapshot(vm->global_pool, snap, 0)) {
- hg_log_warning("[BUG] failed to rollback the VM state.");
- }
- hg_mem_pool_clear_snapshot(vm->global_pool);
- }
- if (hg_mem_pool_get_n_snapshots(vm->local_pool) > 0) {
- snap = hg_mem_pool_get_snapshot(vm->local_pool, 0);
- hg_mem_pool_remove_root_node(vm->local_pool, snap);
- if (!hg_mem_pool_restore_snapshot(vm->local_pool, snap, 0)) {
- hg_log_warning("[BUG] failed to rollback the VM state.");
- }
- hg_mem_pool_clear_snapshot(vm->local_pool);
- }
-
- if (encapsulated) {
- HgMemSnapshot *gsnapshot = hg_mem_pool_save_snapshot(vm->global_pool);
- HgMemSnapshot *lsnapshot = hg_mem_pool_save_snapshot(vm->local_pool);
-
- hg_mem_pool_add_root_node(vm->global_pool, gsnapshot);
- hg_mem_pool_add_root_node(vm->local_pool, lsnapshot);
- }
-
- HG_VALUE_MAKE_DICT (node, vm->systemdict);
- hg_stack_push(vm->dstack, node);
-
- if (!hg_operator_init(vm))
+ if (hg_object_operator_finalize(vm, level - 1) == FALSE)
return FALSE;
- /* initialize the special operators */
-#define BUILD_OP(_vm_, _pool_, _sdict_, _name_, _func_) \
- G_STMT_START { \
- HgOperator *__hg_op; \
- \
- hg_operator_build_operator__inline(_hg_vm_op_, (_vm_), (_pool_), (_sdict_), _name_, _func_, __hg_op); \
- } G_STMT_END
-
- BUILD_OP (vm, vm->global_pool, vm->systemdict, %rollback_securitylevel, rollbacksecuritylevel);
-
-#undef BUILD_OP
-
- /* FIXME: initialize graphics */
-
- hg_vm_use_global_pool(vm, FALSE);
-
- HG_VALUE_MAKE_NAME_STATIC (vm->local_pool, nkey, "%initialized");
- node = hg_dict_lookup(vm->statusdict, nkey);
- if (node == NULL ||
- !HG_IS_VALUE_BOOLEAN (node) ||
- HG_VALUE_GET_BOOLEAN (node) == FALSE) {
- HgValueNode *ntrue = hg_dict_lookup_with_string(vm->systemdict, "true");
-
- retval = hg_vm_run(vm, "hg_init.ps");
-
- /* set read-only attribute for systemdict */
- hg_object_unwritable((HgObject *)vm->systemdict);
-
- /* initialization is done */
- hg_dict_insert(vm->local_pool, vm->serverdict, nkey, ntrue);
- }
-
- if (initializer && initializer[0] == 0) {
- /* just initialize VM */
- return TRUE;
- } else if (initializer) {
- gchar *eval = g_strdup_printf("{prompt (%s)(r)file dup type /filetype eq {cvx exec} if} stopped {$error /newerror get {errordict /handleerror get exec 1 .quit} if} if", initializer);
+ if (hg_object_operator_initialize(vm, level) == FALSE)
+ return FALSE;
- retval = hg_vm_eval(vm, eval, NULL, NULL, NULL, NULL);
- g_free(eval);
+ priv->current_level = level;
- return retval;
- }
- return (retval ? hg_vm_eval(vm, "systemdict /.loadhistory known {(.hghistory) .loadhistory} if start systemdict /.savehistory known {(.hghistory) .savehistory} if", NULL, NULL, NULL, NULL) : FALSE);
+ return TRUE;
}
gboolean
-hg_vm_has_error(HgVM *vm)
-{
- g_return_val_if_fail (vm != NULL, TRUE);
-
- return vm->has_error;
-}
-
-void
-hg_vm_clear_error(HgVM *vm)
-{
- g_return_if_fail (vm != NULL);
-
- vm->has_error = FALSE;
-}
-
-void
-hg_vm_reset_error(HgVM *vm)
+hg_vm_step(hg_vm_t *vm)
{
- HgValueNode *key, *nfalse, *nnull;
-
- g_return_if_fail (vm != NULL);
-
- hg_vm_clear_error(vm);
- _hg_stack_use_stack_validator(vm->ostack, TRUE);
- _hg_stack_use_stack_validator(vm->estack, TRUE);
- _hg_stack_use_stack_validator(vm->dstack, TRUE);
- nnull = hg_dict_lookup_with_string(vm->systemdict, "null");
- nfalse = hg_dict_lookup_with_string(vm->systemdict, "false");
- key = _hg_vm_get_name_node(vm, "newerror");
- hg_dict_insert(vm->local_pool, vm->error, key, nfalse);
- key = _hg_vm_get_name_node(vm, ".isstop");
- hg_dict_insert(vm->local_pool, vm->error, key, nfalse);
- key = _hg_vm_get_name_node(vm, "errorname");
- hg_dict_insert(vm->local_pool, vm->error, key, nnull);
-}
-
-void
-hg_vm_set_error(HgVM *vm,
- HgValueNode *errnode,
- HgVMError error,
- gboolean need_self)
-{
- HgValueNode *proc, *copy_proc, *self;
-
- g_return_if_fail (vm != NULL);
- g_return_if_fail (errnode != NULL);
- g_return_if_fail (error < VM_e_END);
-
- if (vm->has_error) {
- HgValueNode *enode = hg_dict_lookup_with_string(vm->error, "errorname");
- HgValueNode *wnode = hg_dict_lookup_with_string(vm->error, "command");
- HgString *hs = NULL, *hs2;
- gchar *name, *p = NULL;
-
- if (wnode == NULL) {
- p = name = g_strdup("--unknown--");
- } else {
- hs = hg_object_to_string((HgObject *)wnode);
- name = hg_string_get_string(hs);
- }
- hs2 = hg_object_to_string((HgObject *)errnode);
- if (enode == NULL) {
- hg_log_warning("Multiple errors occurred.\n prevoius error: unknown or this happened before set /errorname in %s\n current error: %s in %s\n", name, HG_VALUE_GET_NAME (__hg_vm_errorname[error]), hg_string_get_string(hs2));
- } else {
- hg_log_warning("Multiple errors occurred.\n previous error: %s in %s\n current error: %s in %s\n", HG_VALUE_GET_NAME (enode), name, HG_VALUE_GET_NAME (__hg_vm_errorname[error]), hg_string_get_string(hs2));
- }
- if (p)
- g_free(p);
- hg_mem_free(hs2);
- hg_mem_free(hs);
- proc = hg_dict_lookup_with_string(vm->systemdict, ".abort");
- hg_operator_invoke(HG_VALUE_GET_OPERATOR (proc), vm);
- }
- _hg_stack_use_stack_validator(vm->ostack, FALSE);
- _hg_stack_use_stack_validator(vm->estack, FALSE);
- _hg_stack_use_stack_validator(vm->dstack, FALSE);
- proc = hg_dict_lookup(vm->errordict, __hg_vm_errorname[error]);
- if (proc == NULL) {
- hg_log_warning("[BUG] no error handler for /%s\n", HG_VALUE_GET_NAME (__hg_vm_errorname[error]));
- hg_file_object_printf(vm->stderr, "\nOperand stack:\n");
- hg_stack_dump(vm->ostack, vm->stderr);
- hg_file_object_printf(vm->stderr, "\nExecution stack:\n");
- hg_stack_dump(vm->estack, vm->stderr);
- hg_file_object_printf(vm->stderr, "\nDictionary stack:\n");
- hg_stack_dump(vm->dstack, vm->stderr);
- abort();
- }
- copy_proc = hg_object_copy((HgObject *)proc);
- if (copy_proc == NULL) {
- hg_log_error("FATAL: failed to allocate a memory for an error handler. there are no way to recover it unfortunately.");
- abort();
- }
- self = hg_stack_pop(vm->estack);
- _hg_stack_push(vm->estack, copy_proc);
- if (need_self)
- _hg_stack_push(vm->estack, self);
- _hg_stack_push(vm->ostack, errnode);
- vm->has_error = TRUE;
-}
-
-void
-hg_vm_set_error_from_file(HgVM *vm,
- HgValueNode *errnode,
- HgFileObject *file,
- gboolean need_self)
-{
- gchar buffer[4096];
-
- g_return_if_fail (vm != NULL);
- g_return_if_fail (file != NULL);
-
- switch (hg_file_object_get_error(file)) {
- case 0:
- /* no error */
- break;
- case EACCES:
- case EBADF:
- case EEXIST:
- case ENOTDIR:
- case ENOTEMPTY:
- case EPERM:
- case EROFS:
- hg_vm_set_error(vm, errnode, VM_e_invalidfileaccess, need_self);
- break;
- case EAGAIN:
- if (file == vm->stdin) {
- /* probably no data from stdin found. */
+ hg_vm_private_t *priv;
+ hg_stack_t *estack, *ostack;
+ hg_object_t *object, *result;
+ gboolean retval = TRUE;
+ gsize index;
+
+ hg_return_val_if_fail (vm != NULL, FALSE);
+
+ priv = (hg_vm_private_t *)vm;
+ estack = priv->stack[HG_STACK_TYPE_ESTACK];
+ ostack = priv->stack[HG_STACK_TYPE_OSTACK];
+ object = hg_stack_index(estack, 0);
+
+ evaluate:
+ switch (HG_OBJECT_GET_TYPE (object)) {
+ case HG_OBJECT_TYPE_ARRAY:
+ case HG_OBJECT_TYPE_NAME:
+ if (HG_OBJECT_ATTR_IS_EXECUTABLE (object)) {
+ if (HG_OBJECT_GET_TYPE (object) == HG_OBJECT_TYPE_NAME) {
+ result = hg_vm_dict_lookup(vm, object);
+ if (result == NULL) {
+ hg_vm_set_error(vm, HG_e_undefined);
+ return FALSE;
+ }
+ } else {
+ result = object;
+ }
+ if (!hg_stack_push(estack, result)) {
+ hg_vm_set_error(vm, HG_e_execstackoverflow);
+ return FALSE;
+ }
+ hg_stack_roll(estack, 2, 1);
+ hg_stack_pop(estack);
break;
}
- case EBUSY:
- case EIO:
- case ENOSPC:
- hg_vm_set_error(vm, errnode, VM_e_ioerror, need_self);
- break;
- case EMFILE:
- hg_vm_set_error(vm, errnode, VM_e_limitcheck, need_self);
+ case HG_OBJECT_TYPE_NULL:
+ case HG_OBJECT_TYPE_INTEGER:
+ case HG_OBJECT_TYPE_REAL:
+ case HG_OBJECT_TYPE_BOOLEAN:
+ case HG_OBJECT_TYPE_STRING:
+ case HG_OBJECT_TYPE_DICT:
+ case HG_OBJECT_TYPE_MARK:
+ if (hg_stack_push(ostack, object) == FALSE) {
+ hg_vm_set_error(vm, HG_e_stackoverflow);
+ retval = FALSE;
+ }
+ hg_stack_pop(estack);
break;
- case ENAMETOOLONG:
- case ENODEV:
- case ENOENT:
- hg_vm_set_error(vm, errnode, VM_e_undefinedfilename, need_self);
+ case HG_OBJECT_TYPE_EVAL:
+ result = hg_vm_dict_lookup(vm, object);
+ if (result == NULL) {
+ hg_vm_set_error(vm, HG_e_undefined);
+ return FALSE;
+ }
+ object = result;
+ goto evaluate;
+ case HG_OBJECT_TYPE_FILE:
+ /* XXX: read a token and push to estack */
break;
- case ENOMEM:
- hg_vm_set_error(vm, errnode, VM_e_VMerror, need_self);
+ case HG_OBJECT_TYPE_OPERATOR:
+ index = hg_stack_length(estack);
+ retval = hg_object_operator_invoke(vm, object);
+ hg_stack_roll(estack, hg_stack_length(estack) - index + 1, 1);
+ hg_stack_pop(estack);
break;
default:
- strerror_r(hg_file_object_get_error(file), buffer, 4096);
- hg_log_warning("%s: need to support errno %d\n %s\n",
- __FUNCTION__, hg_file_object_get_error(file), buffer);
+ g_warning("[BUG] Unknown object type `%d'", HG_OBJECT_GET_TYPE (object));
break;
}
- hg_file_object_clear_error(file);
+
+ return retval;
}
-gboolean
-hg_vm_main(HgVM *vm)
+hg_object_t *
+hg_vm_get_dict(hg_vm_t *vm)
{
- HgValueNode *node;
- HgOperator *op;
- HgFileObject *file;
- guint depth;
- gboolean retval = TRUE;
+ hg_vm_private_t *priv;
- g_return_val_if_fail (vm != NULL, FALSE);
-
- vm->shutdown = FALSE;
- file = hg_file_object_new(hg_vm_get_current_pool(vm),
- HG_FILE_TYPE_BUFFER,
- HG_FILE_MODE_READ,
- "%system",
- "", 0);
- while (!vm->shutdown) {
- depth = hg_stack_depth(vm->estack);
- if (depth == 0)
- break;
- node = hg_stack_index(vm->estack, 0);
- if (node == NULL) {
- retval = FALSE;
- break;
- }
-
-#ifdef DEBUG
- G_STMT_START {
- HgString *s;
-
- s = hg_object_to_string((HgObject *)node);
- hg_log_debug(DEBUG_VM, "processing %s on %s", hg_string_get_string(s),
- hg_value_node_get_type_name(HG_VALUE_GET_VALUE_TYPE (node)));
- hg_mem_free(s);
- } G_STMT_END;
-#endif /* DEBUG */
- switch (HG_VALUE_GET_VALUE_TYPE (node)) {
- case HG_TYPE_VALUE_BOOLEAN:
- case HG_TYPE_VALUE_INTEGER:
- case HG_TYPE_VALUE_REAL:
- case HG_TYPE_VALUE_DICT:
- case HG_TYPE_VALUE_NULL:
- case HG_TYPE_VALUE_MARK:
- hg_log_warning("[BUG] %s: an object (node type %d) which isn't actually executable, was pushed into the estack.",
- __FUNCTION__, HG_VALUE_GET_VALUE_TYPE (node));
- hg_stack_pop(vm->estack);
- retval = hg_stack_push(vm->ostack, node);
- if (!retval) {
- _hg_vm_set_error(vm, file, VM_e_stackoverflow, FALSE);
- }
- break;
- case HG_TYPE_VALUE_ARRAY:
- if (hg_object_is_executable((HgObject *)node)) {
- HgArray *array;
- HgValueNode *tmp;
-
- array = HG_VALUE_GET_ARRAY (node);
- if (hg_array_length(array) == 0) {
- /* this might be an empty array */
- hg_stack_pop(vm->estack);
- break;
- }
- tmp = hg_array_index(array, 0);
- hg_array_remove(array, 0);
- if (hg_array_length(array) == 0)
- hg_stack_pop(vm->estack);
- if (hg_object_is_executable((HgObject *)tmp) &&
- (HG_IS_VALUE_NAME (tmp) || HG_IS_VALUE_OPERATOR (tmp))) {
- retval = hg_stack_push(vm->estack, tmp);
- if (!retval)
- _hg_vm_set_error(vm, file, VM_e_execstackoverflow, FALSE);
- } else {
- retval = hg_stack_push(vm->ostack, tmp);
- if (!retval)
- _hg_vm_set_error(vm, file, VM_e_stackoverflow, FALSE);
- }
- } else {
- hg_log_warning("[BUG] %s: an object (node type %d) which isn't actually executable, was pushed into the estack.",
- __FUNCTION__, HG_VALUE_GET_VALUE_TYPE (node));
- hg_stack_pop(vm->estack);
- retval = hg_stack_push(vm->ostack, node);
- if (!retval) {
- _hg_vm_set_error(vm, file, VM_e_stackoverflow, FALSE);
- }
- }
- break;
- case HG_TYPE_VALUE_STRING:
- if (hg_object_is_executable((HgObject *)node)) {
- HgString *hs = HG_VALUE_GET_STRING (node);
- guint state = hg_object_get_state((HgObject *)node);
-
- file = hg_file_object_new(hg_vm_get_current_pool(vm),
- HG_FILE_TYPE_BUFFER,
- HG_FILE_MODE_READ,
- "%eval_string",
- hg_string_get_string(hs),
- hg_string_maxlength(hs));
- hg_stack_pop(vm->estack);
- HG_VALUE_MAKE_FILE (node, file);
- hg_object_set_state((HgObject *)node, state);
- retval = hg_stack_push(vm->estack, node);
- } else {
- hg_log_warning("[BUG] %s: an object (node type %d) which isn't actually executable, was pushed into the estack.",
- __FUNCTION__, HG_VALUE_GET_VALUE_TYPE (node));
- hg_stack_pop(vm->estack);
- retval = hg_stack_push(vm->ostack, node);
- }
- if (!retval) {
- _hg_vm_set_error(vm, file, VM_e_stackoverflow, FALSE);
- }
- break;
- case HG_TYPE_VALUE_NAME:
- if (hg_object_is_executable((HgObject *)node)) {
- HgValueNode *op_node = hg_vm_lookup(vm, node), *tmp;
-
- if (op_node == NULL) {
- hg_vm_set_error(vm, node, VM_e_undefined, FALSE);
- } else {
- hg_stack_pop(vm->estack);
- if (hg_object_is_executable((HgObject *)op_node)) {
- tmp = hg_object_copy((HgObject *)op_node);
- if (tmp == NULL) {
- _hg_vm_set_error(vm, file, VM_e_VMerror, FALSE);
- } else {
- retval = hg_stack_push(vm->estack, tmp);
- if (!retval)
- _hg_vm_set_error(vm, file, VM_e_execstackoverflow, FALSE);
- }
- } else {
- retval = hg_stack_push(vm->ostack, op_node);
- if (!retval)
- _hg_vm_set_error(vm, file, VM_e_stackoverflow, FALSE);
- }
- }
- } else {
- hg_log_warning("[BUG] %s: an object (node type %d) which isn't actually executable, was pushed into the estack.",
- __FUNCTION__, HG_VALUE_GET_VALUE_TYPE (node));
- hg_stack_pop(vm->estack);
- retval = hg_stack_push(vm->ostack, node);
- if (!retval) {
- _hg_vm_set_error(vm, file, VM_e_stackoverflow, FALSE);
- }
- }
- break;
- case HG_TYPE_VALUE_OPERATOR:
- op = HG_VALUE_GET_OPERATOR (node);
- retval = hg_operator_invoke(op, vm);
- hg_stack_pop(vm->estack);
- break;
- case HG_TYPE_VALUE_FILE:
- if (hg_object_is_executable((HgObject *)node)) {
- file = HG_VALUE_GET_FILE (node);
- if (hg_file_object_has_error(file)) {
- hg_stack_pop(vm->estack);
- _hg_vm_set_error_from_file(vm, file, file, FALSE);
- } else {
- HgValueNode *tmp_node;
-
- tmp_node = hg_scanner_get_object(vm, file);
- if (tmp_node != NULL) {
-#ifdef DEBUG
- G_STMT_START {
- HgString *__str__ = hg_object_to_string((HgObject *)tmp_node);
-
- hg_log_debug(DEBUG_SCANNER, "scanning %s",
- hg_string_get_string(__str__));
- hg_mem_free(__str__);
- } G_STMT_END;
-#endif /* DEBUG */
- if (hg_object_is_executable((HgObject *)tmp_node) &&
- (HG_IS_VALUE_NAME (tmp_node) ||
- HG_IS_VALUE_OPERATOR (tmp_node))) {
- hg_stack_push(vm->estack, tmp_node);
- } else {
- hg_stack_push(vm->ostack, tmp_node);
- }
- } else {
- if (hg_file_object_is_eof(file)) {
- hg_stack_pop(vm->estack);
- }
- }
- }
- } else {
- hg_log_warning("[BUG] %s: an object (node type %d) which isn't actually executable, was pushed into the estack.",
- __FUNCTION__, HG_VALUE_GET_VALUE_TYPE (node));
- hg_stack_pop(vm->estack);
- retval = hg_stack_push(vm->ostack, node);
- if (!retval) {
- _hg_vm_set_error(vm, file, VM_e_stackoverflow, FALSE);
- }
- }
- break;
- default:
- hg_log_warning("[BUG] Unknown node type %d was given into the estack.",
- HG_VALUE_GET_VALUE_TYPE (node));
- hg_stack_pop(vm->estack);
- break;
- }
- if (!retval && !hg_vm_has_error(vm)) {
- hg_log_warning("[BUG] probably unknown error happened.");
- break;
- }
- }
+ hg_return_val_if_fail (vm != NULL, NULL);
- return retval;
+ priv = (hg_vm_private_t *)vm;
+
+ return priv->dict;
}
-gchar *
-hg_vm_find_libfile(HgVM *vm,
- const gchar *file)
+hg_object_t *
+hg_vm_dict_lookup(hg_vm_t *vm,
+ hg_object_t *object)
{
- const gchar *env = g_getenv("HIEROGLYPH_LIB_PATH");
- gchar **paths, *filename = NULL, *basename = g_path_get_basename(file);
- gint i = 0;
- struct stat st;
-
- /* for the security reason, ignore the original path identifier */
- if (env != NULL) {
- paths = g_strsplit(env, ":", 0);
- if (paths != NULL) {
- while (paths[i] != NULL) {
- filename = g_build_filename(paths[i], basename, NULL);
- if (stat(filename, &st) == 0) {
- break;
- }
- g_free(filename);
- filename = NULL;
- i++;
- }
- }
- g_strfreev(paths);
- }
- if (filename == NULL) {
- /* if the PS file couldn't load, try the default path. */
- filename = g_build_filename(HIEROGLYPH_LIBDIR, basename, NULL);
- if (stat(filename, &st) == -1) {
- g_free(filename);
- filename = NULL;
- }
- }
- if (basename)
- g_free(basename);
+ hg_vm_private_t *priv;
+ hg_stack_t *dstack;
+ hg_object_t *dict, *retval;
+ gsize i, length;
- return filename;
-}
+ hg_return_val_if_fail (vm != NULL, NULL);
+ hg_return_val_if_fail (object != NULL, NULL);
-gboolean
-hg_vm_run(HgVM *vm,
- const gchar *file)
-{
- const gchar *env = g_getenv("HIEROGLYPH_LIB_PATH");
- gchar **paths, *filename, *path = g_path_get_dirname(file), *basename = g_path_get_basename(file);
- gint i = 0;
- gboolean retval = FALSE, error = FALSE;
-
- if (path != NULL && strcmp(path, ".") != 0) {
- /* file contains any path. try it first */
- retval = _hg_vm_run(vm, file, &error);
- if (error) {
- /* don't retry anymore */
- return FALSE;
- }
- if (retval)
+ priv = (hg_vm_private_t *)vm;
+ dstack = priv->stack[HG_STACK_TYPE_DSTACK];
+ length = hg_stack_length(dstack);
+ for (i = 0; i < length; i++) {
+ dict = hg_stack_index(dstack, i);
+ if ((retval = hg_object_dict_lookup(dict, object)) != NULL)
return retval;
}
- if (path)
- g_free(path);
- if (env != NULL) {
- paths = g_strsplit(env, ":", 0);
- if (paths != NULL) {
- while (paths[i] != NULL) {
- filename = g_build_filename(paths[i], basename, NULL);
- retval = _hg_vm_run(vm, filename, &error);
- g_free(filename);
- if (retval ||
- error)
- break;
- i++;
- }
- }
- g_strfreev(paths);
- }
- if (!retval && !error) {
- /* if the PS file couldn't load, try to load it from the default path. */
- filename = g_build_filename(HIEROGLYPH_LIBDIR, basename, NULL);
-
- retval = _hg_vm_run(vm, filename, &error);
- g_free(filename);
- }
- if (env == NULL && !retval && !error) {
- /* still can't find a file, try to read it on current directory.
- * but someone may not prefers this way. so this behavior can be
- * disabled with specifying HIEROGLYPH_LIB_PATH anytime.
- */
- retval = _hg_vm_run(vm, file, &error);
- }
- if (basename)
- g_free(basename);
- return retval;
+ return NULL;
}
gboolean
-hg_vm_eval(HgVM *vm,
- const gchar *expression,
- HgStack *ostack,
- HgStack *estack,
- HgStack *dstack,
- gboolean *error)
-{
- HgMemPool *pool = hg_vm_get_current_pool(vm);
- HgStack *old_ostack = NULL, *old_estack = NULL, *old_dstack = NULL;
- HgFileObject *file;
+hg_vm_dict_remove(hg_vm_t *vm,
+ const gchar *name,
+ gboolean remove_all)
+{
+ hg_vm_private_t *priv;
+ hg_stack_t *dstack;
+ hg_object_t *dict, *nobject;
+ gsize i, length;
gboolean retval = FALSE;
- g_return_val_if_fail (vm != NULL, FALSE);
- g_return_val_if_fail (expression != NULL, FALSE);
-
- if (ostack) {
- old_ostack = hg_vm_get_ostack(vm);
- hg_vm_set_ostack(vm, ostack);
- }
- if (estack) {
- old_estack = hg_vm_get_estack(vm);
- hg_vm_set_estack(vm, estack);
- }
- if (dstack) {
- old_dstack = hg_vm_get_dstack(vm);
- hg_vm_set_dstack(vm, dstack);
+ hg_return_val_if_fail (vm != NULL, FALSE);
+ hg_return_val_if_fail (name != NULL, FALSE);
+
+ priv = (hg_vm_private_t *)vm;
+ dstack = priv->stack[HG_STACK_TYPE_DSTACK];
+ length = hg_stack_length(dstack);
+ for (i = 0; i < length; i++) {
+ dict = hg_stack_index(dstack, i);
+ nobject = hg_vm_name_lookup(vm, name);
+ retval |= hg_object_dict_remove(dict, nobject);
+ if (retval && remove_all == FALSE)
+ break;
}
- file = hg_file_object_new(pool,
- HG_FILE_TYPE_BUFFER,
- HG_FILE_MODE_READ,
- "%eval",
- expression, - 1);
-
- retval = _hg_vm_eval_file(vm, file, error);
-
- if (old_ostack)
- hg_vm_set_ostack(vm, old_ostack);
- if (old_estack)
- hg_vm_set_estack(vm, old_estack);
- if (old_dstack)
- hg_vm_set_dstack(vm, old_dstack);
return retval;
}
-gint32
-hg_vm_get_error_code(HgVM *vm)
+hg_object_t *
+hg_vm_get_currentdict(hg_vm_t *vm)
{
- g_return_val_if_fail (vm != NULL, -1);
+ hg_vm_private_t *priv;
+ hg_object_t *retval;
+ hg_stack_t *dstack;
- return vm->error_code;
-}
+ hg_return_val_if_fail (vm != NULL, NULL);
-void
-hg_vm_set_error_code(HgVM *vm,
- gint32 error_code)
-{
- g_return_if_fail (vm != NULL);
-
- vm->error_code = error_code;
-}
+ priv = (hg_vm_private_t *)vm;
+ dstack = priv->stack[HG_STACK_TYPE_DSTACK];
+ retval = hg_stack_index(dstack, 0);
-void
-hg_vm_shutdown(HgVM *vm,
- gint32 error_code)
-{
- g_return_if_fail (vm != NULL);
-
- vm->shutdown = TRUE;
- hg_vm_set_error_code(vm, error_code);
-}
-
-gint32
-hg_vm_get_security_level(HgVM *vm)
-{
- g_return_val_if_fail(vm != NULL, G_MAXINT32);
-
- return vm->security_level;
+ return retval;
}
-gboolean
-hg_vm_set_security_level(HgVM *vm,
- gint32 level)
+hg_object_t *
+hg_vm_name_lookup(hg_vm_t *vm,
+ const gchar *name)
{
- g_return_val_if_fail (vm != NULL, FALSE);
-
- if (hg_vm_get_security_level(vm) > level)
- return FALSE;
+ hg_return_val_if_fail (vm != NULL, NULL);
+ hg_return_val_if_fail (name != NULL, NULL);
- vm->security_level = level;
+ /* XXX */
- return TRUE;
+ return hg_object_name_new(vm, name, FALSE);
}