moo/stix/lib/stix.h
2015-05-19 15:16:18 +00:00

963 lines
31 KiB
C

/*
* $Id$
*
Copyright (c) 2014-2015 Chung, Hyung-Hwan. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _STIX_H_
#define _STIX_H_
/* TODO: move this macro out to the build files.... */
#define STIX_INCLUDE_COMPILER
/* =========================================================================
* PRIMITIVE TYPE DEFINTIONS
* ========================================================================= */
/* TODO: define these types and macros using autoconf */
typedef unsigned char stix_uint8_t;
typedef signed char stix_int8_t;
typedef unsigned short int stix_uint16_t;
typedef signed short int stix_int16_t;
#if defined(__MSDOS__)
typedef unsigned long int stix_uint32_t;
typedef signed long int stix_int32_t;
#else
typedef unsigned int stix_uint32_t;
typedef signed int stix_int32_t;
#endif
typedef unsigned long int stix_uintptr_t;
typedef unsigned long int stix_size_t;
typedef signed long int stix_ssize_t;
typedef stix_uint16_t stix_uch_t; /* TODO ... wchar_t??? */
typedef stix_int32_t stix_uci_t;
typedef char stix_bch_t;
struct stix_ucs_t
{
stix_uch_t* ptr;
stix_size_t len;
};
typedef struct stix_ucs_t stix_ucs_t;
/* =========================================================================
* PRIMITIVE MACROS
* ========================================================================= */
#define STIX_UCI_EOF ((stix_uci_t)-1)
#define STIX_UCI_NL ((stix_uci_t)'\n')
#define STIX_SIZEOF(x) (sizeof(x))
#define STIX_COUNTOF(x) (sizeof(x) / sizeof(x[0]))
/**
* The STIX_OFFSETOF() macro returns the offset of a field from the beginning
* of a structure.
*/
#define STIX_OFFSETOF(type,member) ((stix_uintptr_t)&((type*)0)->member)
/**
* The STIX_ALIGNOF() macro returns the alignment size of a structure.
* Note that this macro may not work reliably depending on the type given.
*/
#define STIX_ALIGNOF(type) STIX_OFFSETOF(struct { stix_uint8_t d1; type d2; }, d2)
/*(sizeof(struct { stix_uint8_t d1; type d2; }) - sizeof(type))*/
#if defined(__cplusplus)
# if (__cplusplus >= 201103L) /* C++11 */
# define STIX_NULL nullptr
# else
# define STIX_NULL (0)
# endif
#else
# define STIX_NULL ((void*)0)
#endif
/* make a low bit mask that can mask off low n bits*/
#define STIX_LBMASK(type,n) (~(~((type)0) << (n)))
/* get 'length' bits starting from the bit at the 'offset' */
#define STIX_GETBITS(type,value,offset,length) \
((((type)(value)) >> (offset)) & STIX_LBMASK(type,length))
#define STIX_SETBITS(type,value,offset,length,bits) \
(value = (((type)(value)) | (((bits) & STIX_LBMASK(type,length)) << (offset))))
#define STIX
/**
* The STIX_BITS_MAX() macros calculates the maximum value that the 'nbits'
* bits of an unsigned integer of the given 'type' can hold.
* \code
* printf ("%u", STIX_BITS_MAX(unsigned int, 5));
* \endcode
*/
/*#define STIX_BITS_MAX(type,nbits) ((((type)1) << (nbits)) - 1)*/
#define STIX_BITS_MAX(type,nbits) ((~(type)0) >> (STIX_SIZEOF(type) * 8 - (nbits)))
/* =========================================================================
* POINTER MANIPULATION MACROS
* ========================================================================= */
#if defined(__MSDOS__)
# define STIX_INCPTR(type,base,inc) (((type __huge*)base) + (inc))
# define STIX_DECPTR(type,base,inc) (((type __huge*)base) - (inc))
# define STIX_GTPTR(type,ptr1,ptr2) (((type __huge*)ptr1) > ((type __huge*)ptr2))
# define STIX_GEPTR(type,ptr1,ptr2) (((type __huge*)ptr1) >= ((type __huge*)ptr2))
# define STIX_LTPTR(type,ptr1,ptr2) (((type __huge*)ptr1) < ((type __huge*)ptr2))
# define STIX_LEPTR(type,ptr1,ptr2) (((type __huge*)ptr1) <= ((type __huge*)ptr2))
# define STIX_EQPTR(type,ptr1,ptr2) (((type __huge*)ptr1) == ((type __huge*)ptr2))
# define STIX_SUBPTR(type,ptr1,ptr2) (((type __huge*)ptr1) - ((type __huge*)ptr2))
#else
# define STIX_INCPTR(type,base,inc) (((type*)base) + (inc))
# define STIX_DECPTR(type,base,inc) (((type*)base) - (inc))
# define STIX_GTPTR(type,ptr1,ptr2) (((type*)ptr1) > ((type*)ptr2))
# define STIX_GEPTR(type,ptr1,ptr2) (((type*)ptr1) >= ((type*)ptr2))
# define STIX_LTPTR(type,ptr1,ptr2) (((type*)ptr1) < ((type*)ptr2))
# define STIX_LEPTR(type,ptr1,ptr2) (((type*)ptr1) <= ((type*)ptr2))
# define STIX_EQPTR(type,ptr1,ptr2) (((type*)ptr1) == ((type*)ptr2))
# define STIX_SUBPTR(type,ptr1,ptr2) (((type*)ptr1) - ((type*)ptr2))
#endif
/* =========================================================================
* MMGR
* ========================================================================= */
typedef struct stix_mmgr_t stix_mmgr_t;
/**
* allocate a memory chunk of the size \a n.
* \return pointer to a memory chunk on success, #STIX_NULL on failure.
*/
typedef void* (*stix_mmgr_alloc_t) (stix_mmgr_t* mmgr, stix_size_t n);
/**
* resize a memory chunk pointed to by \a ptr to the size \a n.
* \return pointer to a memory chunk on success, #STIX_NULL on failure.
*/
typedef void* (*stix_mmgr_realloc_t) (stix_mmgr_t* mmgr, void* ptr, stix_size_t n);
/**
* free a memory chunk pointed to by \a ptr.
*/
typedef void (*stix_mmgr_free_t) (stix_mmgr_t* mmgr, void* ptr);
/**
* The stix_mmgr_t type defines the memory management interface.
* As the type is merely a structure, it is just used as a single container
* for memory management functions with a pointer to user-defined data.
* The user-defined data pointer \a ctx is passed to each memory management
* function whenever it is called. You can allocate, reallocate, and free
* a memory chunk.
*
* For example, a stix_xxx_open() function accepts a pointer of the stix_mmgr_t
* type and the xxx object uses it to manage dynamic data within the object.
*/
struct stix_mmgr_t
{
stix_mmgr_alloc_t alloc; /**< allocation function */
stix_mmgr_realloc_t realloc; /**< resizing function */
stix_mmgr_free_t free; /**< disposal function */
void* ctx; /**< user-defined data pointer */
};
/**
* The STIX_MMGR_ALLOC() macro allocates a memory block of the \a size bytes
* using the \a mmgr memory manager.
*/
#define STIX_MMGR_ALLOC(mmgr,size) ((mmgr)->alloc(mmgr,size))
/**
* The STIX_MMGR_REALLOC() macro resizes a memory block pointed to by \a ptr
* to the \a size bytes using the \a mmgr memory manager.
*/
#define STIX_MMGR_REALLOC(mmgr,ptr,size) ((mmgr)->realloc(mmgr,ptr,size))
/**
* The STIX_MMGR_FREE() macro deallocates the memory block pointed to by \a ptr.
*/
#define STIX_MMGR_FREE(mmgr,ptr) ((mmgr)->free(mmgr,ptr))
/* =========================================================================
* CMGR
* =========================================================================*/
typedef struct stix_cmgr_t stix_cmgr_t;
typedef stix_size_t (*stix_cmgr_bctouc_t) (
const stix_bch_t* mb,
stix_size_t size,
stix_uch_t* wc
);
typedef stix_size_t (*stix_cmgr_uctobc_t) (
stix_uch_t wc,
stix_bch_t* mb,
stix_size_t size
);
/**
* The stix_cmgr_t type defines the character-level interface to
* multibyte/wide-character conversion. This interface doesn't
* provide any facility to store conversion state in a context
* independent manner. This leads to the limitation that it can
* handle a stateless multibyte encoding only.
*/
struct stix_cmgr_t
{
stix_cmgr_bctouc_t bctouc;
stix_cmgr_uctobc_t uctobc;
};
/* =========================================================================
* MACROS THAT CHANGES THE BEHAVIORS OF THE C COMPILER/LINKER
* =========================================================================*/
#if defined(_WIN32) || defined(__WATCOMC__)
# define STIX_IMPORT __declspec(dllimport)
# define STIX_EXPORT __declspec(dllexport)
# define STIX_PRIVATE
#elif defined(__GNUC__) && (__GNUC__>=4)
# define STIX_IMPORT __attribute__((visibility("default")))
# define STIX_EXPORT __attribute__((visibility("default")))
# define STIX_PRIVATE __attribute__((visibility("hidden")))
/*# define STIX_PRIVATE __attribute__((visibility("internal")))*/
#else
# define STIX_IMPORT
# define STIX_EXPORT
# define STIX_PRIVATE
#endif
#if defined(__STDC_VERSION__) && (__STDC_VERSION__>=199901L)
# define STIX_INLINE inline
# define STIX_HAVE_INLINE
#elif defined(__GNUC__) && defined(__GNUC_GNU_INLINE__)
/* gcc disables inline when -std=c89 or -ansi is used.
* so use __inline__ supported by gcc regardless of the options */
# define STIX_INLINE /*extern*/ __inline__
# define STIX_HAVE_INLINE
#else
# define STIX_INLINE
# undef STIX_HAVE_INLINE
#endif
/* ========================================================================== */
/**
* The stix_errnum_t type defines the error codes.
*/
enum stix_errnum_t
{
STIX_ENOERR, /**< no error */
STIX_EOTHER, /**< other error */
STIX_ENOIMPL, /**< not implemented */
STIX_ESYSERR, /**< subsystem error */
STIX_EINTERN, /**< internal error */
STIX_ENOMEM, /**< insufficient memory */
STIX_EINVAL, /**< invalid parameter or data */
STIX_ENOENT, /**< no matching entry */
STIX_EIOERR, /**< I/O error */
STIX_EECERR, /**< encoding conversion error */
#if defined(STIX_INCLUDE_COMPILER)
STIX_ESYNTAX /** < syntax error */
#endif
};
typedef enum stix_errnum_t stix_errnum_t;
enum stix_option_t
{
STIX_TRAIT,
STIX_DFL_SYMTAB_SIZE,
STIX_DFL_SYSDIC_SIZE
};
typedef enum stix_option_t stix_option_t;
enum stix_trait_t
{
/* perform no garbage collection when the heap is full.
* you still can use stix_gc() explicitly. */
STIX_NOGC = (1 << 0)
};
typedef enum stix_trait_t stix_trait_t;
/* NOTE: sizeof(stix_oop_t) must be equal to sizeof(stix_oow_t) */
typedef stix_uintptr_t stix_oow_t;
typedef struct stix_obj_t stix_obj_t;
typedef struct stix_obj_t* stix_oop_t;
/* these are more specialized types for stix_obj_t */
typedef struct stix_obj_oop_t stix_obj_oop_t;
typedef struct stix_obj_char_t stix_obj_char_t;
typedef struct stix_obj_uint8_t stix_obj_uint8_t;
typedef struct stix_obj_uint16_t stix_obj_uint16_t;
/* these are more specialized types for stix_oop_t */
typedef struct stix_obj_oop_t* stix_oop_oop_t;
typedef struct stix_obj_char_t* stix_oop_char_t;
typedef struct stix_obj_uint8_t* stix_oop_uint8_t;
typedef struct stix_obj_uint16_t* stix_oop_uint16_t;
#define STIX_OOW_BITS (STIX_SIZEOF(stix_oow_t) * 8)
#define STIX_OOP_BITS (STIX_SIZEOF(stix_oop_t) * 8)
/*
* The Smalltalk-80 Bytecodes
* Range Bits Function
* -------------------------------------------------------------
* 0-15 0000iiii Push Receiver Variable #iiii
* 16-31 0001iiii Push Temporary Location #iiii
* 32-63 001iiiii Push Literal Constant #iiiii
* 64-95 010iiiii Push Literal Variable #iiiii
* 96-103 01100iii Pop and Store Receiver Variable #iii
* 104-111 01101iii Pop and Store Temporary Location #iii
* 112-119 01110iii Push (receiver, _true, _false, _nil, -1, 0, 1, 2) [iii]
* 120-123 011110ii Return (receiver, _true, _false, _nil) [ii] From Message
* 124-125 0111110i Return Stack Top From (Message, Block) [i]
* 126-127 0111111i unused
* 128 10000000 jjkkkkkk Push (Receiver Variable, Temporary Location, Literal Constant, Literal Variable) [jj] #kkkkkk
* 129 10000001 jjkkkkkk Store (Receiver Variable, Temporary Location, Illegal, Literal Variable) [jj] #kkkkkk
* 130 10000010 jjkkkkkk Pop and Store (Receiver Variable, Temporary Location, Illegal, Literal Variable) [jj] #kkkkkk
* 131 10000011 jjjkkkkk Send Literal Selector #kkkkk With jjj Arguments
* 132 10000100 jjjjjjjj kkkkkkkk Send Literal Selector #kkkkkkkk With jjjjjjjj Arguments
* 133 10000101 jjjkkkkk Send Literal Selector #kkkkk To Superclass With jjj Arguments
* 134 10000110 jjjjjjjj kkkkkkkk Send Literal Selector #kkkkkkkk To Superclass With jjjjjjjj Arguments
* 135 10000111 Pop Stack Top
* 136 10001000 Duplicate Stack Top
* 137 10001001 Push Active Context
* 138-143 unused
* 144-151 10010iii Jump iii + 1 (i.e., 1 through 8)
* 152-159 10011iii Pop and Jump On False iii +1 (i.e., 1 through 8)
* 160-167 10100iii jjjjjjjj Jump(iii - 4) *256+jjjjjjjj
* 168-171 101010ii jjjjjjjj Pop and Jump On True ii *256+jjjjjjjj
* 172-175 101011ii jjjjjjjj Pop and Jump On False ii *256+jjjjjjjj
* 176-191 1011iiii Send Arithmetic Message #iiii
* 192-207 1100iiii Send Special Message #iiii
* 208-223 1101iiii Send Literal Selector #iiii With No Arguments
* 224-239 1110iiii Send Literal Selector #iiii With 1 Argument
* 240-255 1111iiii Send Literal Selector #iiii With 2 Arguments
*/
/**
* The stix_code_t type defines byte-code enumerators.
*/
enum stix_code_t
{
/* 0-15 */
STIX_PUSH_RECEIVER_VARIABLE = 0x00,
/* 16-31 */
STIX_PUSH_TEMPORARY_LOCATION = 0x10,
/* 32-63 */
STIX_PUSH_LITERAL_CONSTANT = 0x20,
/* 64-95 */
STIX_PUSH_LITERAL_VARIABLE = 0x40,
/* 96-103 */
STIX_POP_STORE_RECEIVER_VARIABLE = 0x60,
/* 104-111 */
STIX_POP_STORE_TEMPORARY_LOCATION = 0x68,
/* 112-119 */
STIX_PUSH_RECEIVER = 0x70,
STIX_PUSH_TRUE = 0x71,
STIX_PUSH_FALSE = 0x72,
STIX_PUSH_NIL = 0x73,
STIX_PUSH_MINUSONE = 0x74,
STIX_PUSH_ZERO = 0x75,
STIX_PUSH_ONE = 0x76,
STIX_PUSH_TWO = 0x77,
/* 120-123 */
STIX_RETURN_RECEIVER = 0x78,
STIX_RETURN_TRUE = 0x79,
STIX_RETURN_FALSE = 0x7A,
STIX_RETURN_NIL = 0x7B,
/* 124-125 */
STIX_RETURN_FROM_MESSAGE = 0x7C,
STIX_RETURN_FROM_BLOCK = 0x7D,
/* 128 */
STIX_PUSH_EXTENDED = 0x80,
/* 129 */
STIX_STORE_EXTENDED = 0x81,
/* 130 */
STIX_POP_STORE_EXTENDED = 0x82,
/* 131 */
STIX_SEND_TO_SELF = 0x83,
/* 132 */
STIX_SEND_TO_SUPER = 0x84,
/* 133 */
STIX_SEND_TO_SELF_EXTENDED = 0x85,
/* 134 */
STIX_SEND_TO_SUPER_EXTENDED = 0x86,
/* 135 */
STIX_POP_STACK_TOP = 0x87,
/* 136 */
STIX_DUP_STACK_TOP = 0x88,
/* 137 */
STIX_PUSH_ACTIVE_CONTEXT = 0x89,
/* 138 */
STIX_DO_PRIMITIVE = 0x8A,
/* 144-151 */
STIX_JUMP = 0x90,
/* 152-159 */
STIX_POP_JUMP_ON_FALSE = 0x98,
/* 160-167 */
STIX_JUMP_EXTENDED = 0xA0,
/* 168-171 */
STIX_POP_JUMP_ON_TRUE_EXTENDED = 0xA8,
/* 172-175 */
STIX_POP_JUMP_ON_FALSE_EXTENDED = 0xAC,
#if 0
STIX_PUSH_RECEIVER_VARIABLE_EXTENDED = 0x60
STIX_PUSH_TEMPORARY_LOCATION_EXTENDED = 0x61
STIX_PUSH_LITERAL_CONSTANT_EXTENDED = 0x62
STIX_PUSH_LITERAL_VARIABLE_EXTENDED = 0x63
STIX_STORE_RECEIVER_VARIABLE_EXTENDED = 0x64
STIX_STORE_TEMPORARY_LOCATION_EXTENDED = 0x65
STIX_POP_STACK_TOP = 0x67
STIX_DUPLICATE_STACK_TOP = 0x68
STIX_PUSH_ACTIVE_CONTEXT = 0x69
STIX_PUSH_NIL = 0x6A
STIX_PUSH_TRUE = 0x6B
STIX_PUSH_FALSE = 0x6C
STIX_PUSH_RECEIVER = 0x6D
STIX_SEND_TO_SELF = 0x70
STIX_SEND_TO_SUPER = 0x71
STIX_SEND_TO_SELF_EXTENDED = 0x72
STIX_SEND_TO_SUPER_EXTENDED = 0x73
STIX_RETURN_RECEIVER = 0x78
STIX_RETURN_TRUE = 0x79
STIX_RETURN_FALSE = 0x7A
STIX_RETURN_NIL = 0x7B
STIX_RETURN_FROM_MESSAGE = 0x7C
STIX_RETURN_FROM_BLOCK = 0x7D
STIX_DO_PRIMITIVE = 0xF0
#endif
};
typedef enum stix_code_t stix_code_t;
/*
* OOP encoding
* An object pointer(OOP) is an ordinary pointer value to an object.
* but some simple numeric values are also encoded into OOP using a simple
* bit-shifting and masking.
*
* A real OOP is stored without any bit-shifting while a non-OOP value encoded
* in an OOP is bit-shifted to the left by 2 and the 2 least-significant bits
* are set to 1 or 2.
*
* This scheme works because the object allocators aligns the object size to
* a multiple of sizeof(stix_oop_t). This way, the 2 least-significant bits
* of a real OOP are always 0s.
*/
#define STIX_OOP_TAG_BITS 2
#define STIX_OOP_TAG_SMINT 1
#define STIX_OOP_TAG_CHAR 2
#define STIX_OOP_IS_NUMERIC(oop) (((stix_oow_t)oop) & (STIX_OOP_TAG_SMINT | STIX_OOP_TAG_CHAR))
#define STIX_OOP_IS_POINTER(oop) (!STIX_OOP_IS_NUMERIC(oop))
#define STIX_OOP_GET_TAG(oop) (((stix_oow_t)oop) & STIX_LBMASK(stix_oow_t, STIX_OOP_TAG_BITS))
#define STIX_OOP_IS_SMINT(oop) (((stix_oow_t)oop) & STIX_OOP_TAG_SMINT)
#define STIX_OOP_IS_CHAR(oop) (((stix_oow_t)oop) & STIX_OOP_TAG_CHAR)
#define STIX_OOP_FROM_SMINT(num) ((stix_oop_t)((((stix_oow_t)(num)) << STIX_OOP_TAG_BITS) | STIX_OOP_TAG_SMINT))
#define STIX_OOP_TO_SMINT(oop) (((stix_oow_t)oop) >> STIX_OOP_TAG_BITS)
#define STIX_OOP_FROM_CHAR(num) ((stix_oop_t)((((stix_oow_t)(num)) << STIX_OOP_TAG_BITS) | STIX_OOP_TAG_CHAR))
#define STIX_OOP_TO_CHAR(oop) (((stix_oow_t)oop) >> STIX_OOP_TAG_BITS)
/*
* Object structure
*/
enum stix_obj_type_t
{
STIX_OBJ_TYPE_OOP,
STIX_OBJ_TYPE_CHAR,
STIX_OBJ_TYPE_UINT8,
STIX_OBJ_TYPE_UINT16
/* NOTE: you can have STIX_OBJ_SHORT, STIX_OBJ_INT
* STIX_OBJ_LONG, STIX_OBJ_FLOAT, STIX_OBJ_DOUBLE, etc
* type type field being 6 bits long, you can have up to 64 different types.
STIX_OBJ_TYPE_SHORT,
STIX_OBJ_TYPE_INT,
STIX_OBJ_TYPE_LONG,
STIX_OBJ_TYPE_FLOAT,
STIX_OBJ_TYPE_DOUBLE */
};
typedef enum stix_obj_type_t stix_obj_type_t;
/* =========================================================================
* Object header structure
*
* _flags:
* type: the type of a payload item.
* one of STIX_OBJ_TYPE_OOP, STIX_OBJ_TYPE_CHAR,
* STIX_OBJ_TYPE_UINT8, STIX_OBJ_TYPE_UINT16
* unit: the size of a payload item in bytes.
* extra: 0 or 1. 1 indicates that the payload contains 1 more
* item than the value of the size field. mostly used for a
* terminating null in a variable-char object.
* kernel: 0 or 1. indicates that the object is a kernel object.
* VM disallows layout changes of a kernel object.
* moved: 0 or 1. used by GC.
*
* _size: the number of payload items in an object.
* it doesn't include the header size.
*
* The total number of bytes occupied by an object can be calculated
* with this fomula:
* sizeof(stix_obj_t) + ALIGN((size + extra) * unit), sizeof(stix_oop_t))
*
* The ALIGN() macro is used above since allocation adjusts the payload
* size to a multiple of sizeof(stix_oop_t). it assumes that sizeof(stix_obj_t)
* is a multiple of sizeof(stix_oop_t). See the STIX_BYTESOF() macro.
*
* Due to the header structure, an object can only contain items of
* homogeneous data types in the payload.
*
* It's actually possible to split the size field into 2. For example,
* the upper half contains the number of oops and the lower half contains
* the number of bytes/chars. This way, a variable-byte class or a variable-char
* class can have normal instance variables. On the contrary, the actual byte
* size calculation and the access to the payload fields become more complex.
* Therefore, i've dropped the idea.
* ========================================================================= */
#define STIX_OBJ_FLAGS_TYPE_BITS 6
#define STIX_OBJ_FLAGS_UNIT_BITS 5
#define STIX_OBJ_FLAGS_EXTRA_BITS 1
#define STIX_OBJ_FLAGS_KERNEL_BITS 1
#define STIX_OBJ_FLAGS_MOVED_BITS 1
#define STIX_OBJ_GET_FLAGS_TYPE(oop) STIX_GETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_FLAGS_UNIT_BITS + STIX_OBJ_FLAGS_EXTRA_BITS + STIX_OBJ_FLAGS_KERNEL_BITS + STIX_OBJ_FLAGS_MOVED_BITS), STIX_OBJ_FLAGS_TYPE_BITS)
#define STIX_OBJ_GET_FLAGS_UNIT(oop) STIX_GETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_FLAGS_EXTRA_BITS + STIX_OBJ_FLAGS_KERNEL_BITS + STIX_OBJ_FLAGS_MOVED_BITS), STIX_OBJ_FLAGS_UNIT_BITS)
#define STIX_OBJ_GET_FLAGS_EXTRA(oop) STIX_GETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_FLAGS_KERNEL_BITS + STIX_OBJ_FLAGS_MOVED_BITS), STIX_OBJ_FLAGS_EXTRA_BITS)
#define STIX_OBJ_GET_FLAGS_KERNEL(oop) STIX_GETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_FLAGS_MOVED_BITS), STIX_OBJ_FLAGS_KERNEL_BITS)
#define STIX_OBJ_GET_FLAGS_MOVED(oop) STIX_GETBITS(stix_oow_t, (oop)->_flags, 0, STIX_OBJ_FLAGS_MOVED_BITS)
#define STIX_OBJ_SET_FLAGS_TYPE(oop,v) STIX_SETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_FLAGS_UNIT_BITS + STIX_OBJ_FLAGS_EXTRA_BITS + STIX_OBJ_FLAGS_KERNEL_BITS + STIX_OBJ_FLAGS_MOVED_BITS), STIX_OBJ_FLAGS_TYPE_BITS, v)
#define STIX_OBJ_SET_FLAGS_UNIT(oop,v) STIX_SETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_FLAGS_EXTRA_BITS + STIX_OBJ_FLAGS_KERNEL_BITS + STIX_OBJ_FLAGS_MOVED_BITS), STIX_OBJ_FLAGS_UNIT_BITS, v)
#define STIX_OBJ_SET_FLAGS_EXTRA(oop,v) STIX_SETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_FLAGS_KERNEL_BITS + STIX_OBJ_FLAGS_MOVED_BITS), STIX_OBJ_FLAGS_EXTRA_BITS, v)
#define STIX_OBJ_SET_FLAGS_KERNEL(oop,v) STIX_SETBITS(stix_oow_t, (oop)->_flags, (STIX_OBJ_FLAGS_MOVED_BITS), STIX_OBJ_FLAGS_KERNEL_BITS, v)
#define STIX_OBJ_SET_FLAGS_MOVED(oop,v) STIX_SETBITS(stix_oow_t, (oop)->_flags, 0, STIX_OBJ_FLAGS_MOVED_BITS, v)
#define STIX_OBJ_GET_SIZE(oop) ((oop)->_size)
#define STIX_OBJ_GET_CLASS(oop) ((oop)->_class)
#define STIX_OBJ_SET_SIZE(oop,v) ((oop)->_size = (v))
#define STIX_OBJ_SET_CLASS(oop,c) ((oop)->_class = (c))
#define STIX_OBJ_BYTESOF(oop) ((STIX_OBJ_GET_SIZE(oop) + STIX_OBJ_GET_FLAGS_EXTRA(oop)) * STIX_OBJ_GET_FLAGS_UNIT(oop))
/* this macro doesn't check the range of the actual value.
* make sure that the value of each bit fields given fall within the number
* of defined bits */
#define STIX_OBJ_MAKE_FLAGS(t,u,e,k,m) ( \
(((stix_oow_t)(t)) << (STIX_OBJ_FLAGS_UNIT_BITS + STIX_OBJ_FLAGS_EXTRA_BITS + STIX_OBJ_FLAGS_KERNEL_BITS + STIX_OBJ_FLAGS_MOVED_BITS)) | \
(((stix_oow_t)(u)) << (STIX_OBJ_FLAGS_EXTRA_BITS + STIX_OBJ_FLAGS_KERNEL_BITS + STIX_OBJ_FLAGS_MOVED_BITS)) | \
(((stix_oow_t)(e)) << (STIX_OBJ_FLAGS_KERNEL_BITS + STIX_OBJ_FLAGS_MOVED_BITS)) | \
(((stix_oow_t)(k)) << (STIX_OBJ_FLAGS_MOVED_BITS)) | \
(((stix_oow_t)(m)) << 0) \
)
#define STIX_OBJ_HEADER \
stix_oow_t _flags; \
stix_oow_t _size; \
stix_oop_t _class
struct stix_obj_t
{
STIX_OBJ_HEADER;
};
struct stix_obj_oop_t
{
STIX_OBJ_HEADER;
stix_oop_t slot[1];
};
struct stix_obj_char_t
{
STIX_OBJ_HEADER;
stix_uch_t slot[1];
};
struct stix_obj_uint8_t
{
STIX_OBJ_HEADER;
stix_uint8_t slot[1];
};
struct stix_obj_uint16_t
{
STIX_OBJ_HEADER;
stix_uint16_t slot[1];
};
#define STIX_CLASS_NAMED_INSTVARS 8
struct stix_class_t
{
STIX_OBJ_HEADER;
stix_oop_t spec; /* SmallInteger */
stix_oop_t superclass; /* Another class */
stix_oop_t subclasses; /* Array of subclasses */
stix_oop_char_t name; /* Symbol */
stix_oop_char_t instvars; /* String or Array? */
stix_oop_char_t classvars; /* String or Array? */
stix_oop_oop_t instmthds; /* instance methods, MethodDictionary */
stix_oop_oop_t classmthds; /* class methods, MethodDictionary */
/* indexed part afterwards */
stix_oop_t classvar[1]; /* most classes have not class variables. better to be 0 */
};
typedef struct stix_class_t stix_class_t;
typedef struct stix_class_t* stix_oop_class_t;
#define STIX_SET_NAMED_INSTVARS 2
struct stix_set_t
{
STIX_OBJ_HEADER;
stix_oop_t tally; /* SmallInteger */
stix_oop_oop_t bucket; /* Array */
};
typedef struct stix_set_t stix_set_t;
typedef struct stix_set_t* stix_oop_set_t;
#define STIX_ASSOCIATION_NAMED_INSTVARS 2
struct stix_association_t
{
STIX_OBJ_HEADER;
stix_oop_t key;
stix_oop_t value;
};
typedef struct stix_association_t stix_association_t;
typedef struct stix_association_t* stix_oop_association_t;
/**
* The STIX_CLASSOF() macro return the class of an object including a numeric
* object encoded into a pointer.
*/
#define STIX_CLASSOF(stix,oop) ( \
STIX_OOP_IS_SMINT(oop)? (stix)->_small_integer: \
STIX_OOP_IS_CHAR(oop)? (stix)->_character: STIX_OBJ_GET_CLASS(oop) \
)
/**
* The STIX_BYTESOF() macro returns the size of the payload of
* an object in bytes. If the pointer given encodes a numeric value,
* it returns the size of #stix_oow_t in bytes.
*/
#define STIX_BYTESOF(stix,oop) \
(STIX_OOP_IS_NUMERIC(oop)? STIX_SIZEOF(stix_oow_t): STIX_OBJ_BYTESOF(oop))
typedef struct stix_heap_t stix_heap_t;
struct stix_heap_t
{
stix_uint8_t* base; /* start of a heap */
stix_uint8_t* limit; /* end of a heap */
stix_uint8_t* ptr; /* next allocation pointer */
};
typedef struct stix_t stix_t;
typedef void (*stix_cbimpl_t) (stix_t* stix);
typedef struct stix_cb_t stix_cb_t;
struct stix_cb_t
{
stix_cbimpl_t fini;
stix_cb_t* prev;
stix_cb_t* next;
};
#if defined(STIX_INCLUDE_COMPILER)
typedef struct stix_compiler_t stix_compiler_t;
#endif
struct stix_t
{
stix_mmgr_t* mmgr;
stix_errnum_t errnum;
struct
{
int trait;
stix_oow_t dfl_symtab_size;
stix_oow_t dfl_sysdic_size;
} option;
stix_cb_t* cblist;
/* ========================= */
stix_heap_t* permheap; /* TODO: put kernel objects to here */
stix_heap_t* curheap;
stix_heap_t* newheap;
/* ========================= */
stix_oop_t _nil; /* pointer to the nil object */
stix_oop_t _true;
stix_oop_t _false;
/* == NEVER CHANGE THE ORDER OF FIELDS BELOW == */
/* stix_ignite() assumes this order */
stix_oop_t _stix; /* Stix */
stix_oop_t _nil_object; /* NilObject */
stix_oop_t _class; /* Class */
stix_oop_t _object; /* Object */
stix_oop_t _symbol; /* Symbol */
stix_oop_t _array; /* Array */
stix_oop_t _symbol_set; /* SymbolSet */
stix_oop_t _system_dictionary; /* SystemDictionary */
stix_oop_t _association; /* Association */
stix_oop_t _true_class; /* True */
stix_oop_t _false_class; /* False */
stix_oop_t _character; /* Character */
stix_oop_t _small_integer; /* SmallInteger */
/* == NEVER CHANGE THE ORDER OF FIELDS ABOVE == */
stix_oop_set_t symtab; /* system-wide symbol table. instance of SymbolSet */
stix_oop_set_t sysdic; /* system dictionary. instance of SystemDictionary */
stix_oop_t* tmp_stack[100]; /* stack for temporaries */
stix_oow_t tmp_count;
#if defined(STIX_INCLUDE_COMPILER)
stix_compiler_t* c;
#endif
};
#if defined(__cplusplus)
extern "C" {
#endif
STIX_EXPORT stix_t* stix_open (
stix_mmgr_t* mmgr,
stix_size_t xtnsize,
stix_size_t heapsize,
stix_errnum_t* errnum
);
STIX_EXPORT void stix_close (
stix_t* vm
);
STIX_EXPORT int stix_init (
stix_t* vm,
stix_mmgr_t* mmgr,
stix_size_t heapsz
);
STIX_EXPORT void stix_fini (
stix_t* vm
);
STIX_EXPORT stix_mmgr_t* stix_getmmgr (
stix_t* stix
);
STIX_EXPORT void* stix_getxtn (
stix_t* stix
);
STIX_EXPORT stix_errnum_t stix_geterrnum (
stix_t* stix
);
STIX_EXPORT void stix_seterrnum (
stix_t* stix,
stix_errnum_t errnum
);
/**
* The stix_getoption() function gets the value of an option
* specified by \a id into the buffer pointed to by \a value.
*
* \return 0 on success, -1 on failure
*/
STIX_EXPORT int stix_getoption (
stix_t* stix,
stix_option_t id,
void* value
);
/**
* The stix_setoption() function sets the value of an option
* specified by \a id to the value pointed to by \a value.
*
* \return 0 on success, -1 on failure
*/
STIX_EXPORT int stix_setoption (
stix_t* stix,
stix_option_t id,
const void* value
);
STIX_EXPORT stix_cb_t* stix_regcb (
stix_t* stix,
stix_cb_t* tmpl
);
STIX_EXPORT void stix_deregcb (
stix_t* stix,
stix_cb_t* cb
);
/**
* The stix_gc() function performs garbage collection.
* It is not affected by #STIX_NOGC.
*/
STIX_EXPORT void stix_gc (
stix_t* stix
);
/**
* The stix_findclass() function searchs the root system dictionary
* for a class named \a name. The class object pointer is set to the
* memory location pointed to by \a oop.
*
* \return 0 if found, -1 if not found.
*/
STIX_EXPORT int stix_findclass (
stix_t* vm,
const stix_uch_t* name,
stix_oop_t* oop
);
/**
* The stix_instantiate() function creates a new object of the class
* \a _class. The size of the fixed part is taken from the information
* contained in the class defintion. The \a vlen parameter specifies
* the length of the variable part. The \a vptr parameter points to
* the memory area to copy into the variable part of the new object.
* If \a vptr is #STIX_NULL, the variable part is initialized to 0 or
* an equivalent value depending on the type.
*/
STIX_EXPORT stix_oop_t stix_instantiate (
stix_t* stix,
stix_oop_t _class,
const void* vptr,
stix_oow_t vlen
);
/**
* The stix_ignite() function creates key initial objects.
*/
STIX_EXPORT int stix_ignite (
stix_t* stix
);
/* Temporary OOP management */
STIX_EXPORT void stix_pushtmp (
stix_t* stix,
stix_oop_t* oop_ptr
);
STIX_EXPORT void stix_poptmp (
stix_t* stix
);
STIX_EXPORT void stix_poptmps (
stix_t* stix,
stix_oow_t count
);
/* Memory allocation/deallocation functions using stix's MMGR */
STIX_EXPORT void* stix_allocmem (
stix_t* stix,
stix_size_t size
);
STIX_EXPORT void* stix_callocmem (
stix_t* stix,
stix_size_t size
);
STIX_EXPORT void* stix_reallocmem (
stix_t* stix,
void* ptr,
stix_size_t size
);
STIX_EXPORT void stix_freemem (
stix_t* stix,
void* ptr
);
#if defined(__cplusplus)
}
#endif
#endif