did a bit of stx work
This commit is contained in:
parent
f50b2835f7
commit
adcf59e44d
@ -1,4 +1,4 @@
|
|||||||
SUBDIRS = cmn awk cut sed scm http
|
SUBDIRS = cmn awk cut sed stx
|
||||||
|
|
||||||
pkgincludedir = $(includedir)/qse
|
pkgincludedir = $(includedir)/qse
|
||||||
|
|
||||||
|
@ -254,7 +254,7 @@ target_alias = @target_alias@
|
|||||||
top_build_prefix = @top_build_prefix@
|
top_build_prefix = @top_build_prefix@
|
||||||
top_builddir = @top_builddir@
|
top_builddir = @top_builddir@
|
||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
SUBDIRS = cmn awk cut sed scm http
|
SUBDIRS = cmn awk cut sed stx
|
||||||
pkginclude_HEADERS = conf_msw.h conf_os2.h conf_dos.h conf_vms.h \
|
pkginclude_HEADERS = conf_msw.h conf_os2.h conf_dos.h conf_vms.h \
|
||||||
types.h macros.h pack1.h unpack.h $(am__append_1)
|
types.h macros.h pack1.h unpack.h $(am__append_1)
|
||||||
all: config.h
|
all: config.h
|
||||||
|
@ -8,6 +8,6 @@ AM_CPPFLAGS = \
|
|||||||
|
|
||||||
lib_LTLIBRARIES = libqsestx.la
|
lib_LTLIBRARIES = libqsestx.la
|
||||||
|
|
||||||
libqsestx_la_SOURCES = stx.c err.c mem.c obj.c sym.c boot.c misc.c
|
libqsestx_la_SOURCES = stx.c err.c hash.c mem.c obj.c sym.c dic.c boot.c
|
||||||
libqsestx_la_LDFLAGS = -L../cmn -L$(libdir) -version-info 1:0:0 -no-undefined
|
libqsestx_la_LDFLAGS = -L../cmn -L$(libdir) -version-info 1:0:0 -no-undefined
|
||||||
libqsestx_la_LIBADD = -lqsecmn
|
libqsestx_la_LIBADD = -lqsecmn
|
||||||
|
@ -71,8 +71,8 @@ am__base_list = \
|
|||||||
am__installdirs = "$(DESTDIR)$(libdir)"
|
am__installdirs = "$(DESTDIR)$(libdir)"
|
||||||
LTLIBRARIES = $(lib_LTLIBRARIES)
|
LTLIBRARIES = $(lib_LTLIBRARIES)
|
||||||
libqsestx_la_DEPENDENCIES =
|
libqsestx_la_DEPENDENCIES =
|
||||||
am_libqsestx_la_OBJECTS = stx.lo err.lo mem.lo obj.lo sym.lo boot.lo \
|
am_libqsestx_la_OBJECTS = stx.lo err.lo hash.lo mem.lo obj.lo sym.lo \
|
||||||
misc.lo
|
dic.lo boot.lo
|
||||||
libqsestx_la_OBJECTS = $(am_libqsestx_la_OBJECTS)
|
libqsestx_la_OBJECTS = $(am_libqsestx_la_OBJECTS)
|
||||||
libqsestx_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
|
libqsestx_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||||
@ -239,7 +239,7 @@ AM_CPPFLAGS = \
|
|||||||
-I$(includedir)
|
-I$(includedir)
|
||||||
|
|
||||||
lib_LTLIBRARIES = libqsestx.la
|
lib_LTLIBRARIES = libqsestx.la
|
||||||
libqsestx_la_SOURCES = stx.c err.c mem.c obj.c sym.c boot.c misc.c
|
libqsestx_la_SOURCES = stx.c err.c hash.c mem.c obj.c sym.c dic.c boot.c
|
||||||
libqsestx_la_LDFLAGS = -L../cmn -L$(libdir) -version-info 1:0:0 -no-undefined
|
libqsestx_la_LDFLAGS = -L../cmn -L$(libdir) -version-info 1:0:0 -no-undefined
|
||||||
libqsestx_la_LIBADD = -lqsecmn
|
libqsestx_la_LIBADD = -lqsecmn
|
||||||
all: all-am
|
all: all-am
|
||||||
@ -317,9 +317,10 @@ distclean-compile:
|
|||||||
-rm -f *.tab.c
|
-rm -f *.tab.c
|
||||||
|
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/boot.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/boot.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dic.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/err.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/err.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Plo@am__quote@
|
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/obj.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/obj.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stx.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stx.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sym.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sym.Plo@am__quote@
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
#include "sym.h"
|
#include "sym.h"
|
||||||
#include "class.h"
|
#include "class.h"
|
||||||
|
|
||||||
|
static void make_intrinsic_classes (qse_stx_t* stx);
|
||||||
#if 0
|
#if 0
|
||||||
static void __create_builtin_classes (qse_stx_t* stx);
|
|
||||||
static qse_word_t __make_classvar_dict (
|
static qse_word_t __make_classvar_dict (
|
||||||
qse_stx_t* stx, qse_word_t class, const qse_char_t* names);
|
qse_stx_t* stx, qse_word_t class, const qse_char_t* names);
|
||||||
static void __filein_kernel (qse_stx_t* stx);
|
static void __filein_kernel (qse_stx_t* stx);
|
||||||
@ -282,7 +282,7 @@ qse_word_t QSE_INLINE __new_string (qse_stx_t* stx, const qse_char_t* str)
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __create_builtin_classes (qse_stx_t* stx)
|
static void make_intrinsic_classes (qse_stx_t* stx)
|
||||||
{
|
{
|
||||||
class_info_t* p;
|
class_info_t* p;
|
||||||
qse_word_t class, superclass, array;
|
qse_word_t class, superclass, array;
|
||||||
@ -565,13 +565,13 @@ static int sketch_key_objects (qse_stx_t* stx)
|
|||||||
/* TODO: initial symbol table size */
|
/* TODO: initial symbol table size */
|
||||||
ALLOC_WORDOBJ_TO (stx, stx->ref.symtab, 1, 256);
|
ALLOC_WORDOBJ_TO (stx, stx->ref.symtab, 1, 256);
|
||||||
/* set tally to 0. */
|
/* set tally to 0. */
|
||||||
WORDAT(stx,stx->ref.symtab,0) = INTTOREF(stx,0);
|
WORDAT(stx,stx->ref.symtab,QSE_STX_SYMTAB_TALLY) = INTTOREF(stx,0);
|
||||||
|
|
||||||
/* global system dictionary */
|
/* global system dictionary */
|
||||||
/* TODO: initial dictionary size */
|
/* TODO: initial dictionary size */
|
||||||
ALLOC_WORDOBJ_TO (stx, stx->ref.sysdic, 1, 256);
|
ALLOC_WORDOBJ_TO (stx, stx->ref.sysdic, 1, 256);
|
||||||
/* set tally to 0 */
|
/* set tally to 0 */
|
||||||
WORDAT(stx,stx->ref.sysdic,0) = INTTOREF(stx,0);
|
WORDAT(stx,stx->ref.sysdic,QSE_STX_DIC_TALLY) = INTTOREF(stx,0);
|
||||||
|
|
||||||
/* Symbol */
|
/* Symbol */
|
||||||
ALLOC_WORDOBJ_TO (stx, stx->ref.class_symbol, QSE_STX_CLASS_NFLDS, 0);
|
ALLOC_WORDOBJ_TO (stx, stx->ref.class_symbol, QSE_STX_CLASS_NFLDS, 0);
|
||||||
@ -580,12 +580,6 @@ static int sketch_key_objects (qse_stx_t* stx)
|
|||||||
/* Association */
|
/* Association */
|
||||||
ALLOC_WORDOBJ_TO (stx, stx->ref.class_association, QSE_STX_CLASS_NFLDS, 0);
|
ALLOC_WORDOBJ_TO (stx, stx->ref.class_association, QSE_STX_CLASS_NFLDS, 0);
|
||||||
|
|
||||||
qse_printf (QSE_T("%d\n"), (int)qse_stx_newsymbol (stx, stx->ref.symtab, QSE_T("abcdefg")));
|
|
||||||
qse_printf (QSE_T("%d\n"), (int)qse_stx_newsymbol (stx, stx->ref.symtab, QSE_T("abcdefx")));
|
|
||||||
qse_printf (QSE_T("%d\n"), (int)qse_stx_newsymbol (stx, stx->ref.symtab, QSE_T("abcdefy")));
|
|
||||||
qse_printf (QSE_T("%d\n"), (int)qse_stx_newsymbol (stx, stx->ref.symtab, QSE_T("abcdefg")));
|
|
||||||
qse_printf (QSE_T("%d\n"), (int)qse_stx_newsymbol (stx, stx->ref.symtab, QSE_T("abcdefc")));
|
|
||||||
|
|
||||||
/* Metaclass is a class so it has the same structure
|
/* Metaclass is a class so it has the same structure
|
||||||
* as a normal class. "Metaclass class" is an instance of
|
* as a normal class. "Metaclass class" is an instance of
|
||||||
* Metaclass. */
|
* Metaclass. */
|
||||||
@ -622,7 +616,7 @@ qse_printf (QSE_T("%d\n"), (int)qse_stx_newsymbol (stx, stx->ref.symtab, QSE_T("
|
|||||||
INTTOREF (stx, MAKE_SPEC(QSE_STX_CLASS_NFLDS,SPEC_FIXED_WORD));
|
INTTOREF (stx, MAKE_SPEC(QSE_STX_CLASS_NFLDS,SPEC_FIXED_WORD));
|
||||||
|
|
||||||
/* specs for class_metaclass, class_association,
|
/* specs for class_metaclass, class_association,
|
||||||
* class_symbol are set later in __create_builtin_classes */
|
* class_symbol are set later in make_builtin_classes */
|
||||||
|
|
||||||
/* #Symbol */
|
/* #Symbol */
|
||||||
symbol_Symbol = qse_stx_newsymbol (
|
symbol_Symbol = qse_stx_newsymbol (
|
||||||
@ -644,11 +638,11 @@ qse_printf (QSE_T("%d\n"), (int)qse_stx_newsymbol (stx, stx->ref.symtab, QSE_T("
|
|||||||
#if 0
|
#if 0
|
||||||
/* register class names into the system dictionary */
|
/* register class names into the system dictionary */
|
||||||
qse_stx_dict_put (stx,
|
qse_stx_dict_put (stx,
|
||||||
stx->sysdic, symbol_Symbol, stx->class_symbol);
|
stx->ref.sysdic, symbol_Symbol, stx->class_symbol);
|
||||||
qse_stx_dict_put (stx,
|
qse_stx_dict_put (stx,
|
||||||
stx->sysdic, symbol_Metaclass, stx->class_metaclass);
|
stx->ref.sysdic, symbol_Metaclass, stx->class_metaclass);
|
||||||
qse_stx_dict_put (stx,
|
qse_stx_dict_put (stx,
|
||||||
stx->sysdic, symbol_Association, stx->class_association);
|
stx->ref.sysdic, symbol_Association, stx->class_association);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -687,13 +681,13 @@ int qse_stx_boot (qse_stx_t* stx)
|
|||||||
stx->class_smallinteger =
|
stx->class_smallinteger =
|
||||||
qse_stx_newclass (stx, QSE_T("SmallInteger"));
|
qse_stx_newclass (stx, QSE_T("SmallInteger"));
|
||||||
|
|
||||||
__create_builtin_classes (stx);
|
make_intrisic_classes (stx);
|
||||||
|
|
||||||
/* (Object class) setSuperclass: Class */
|
/* (Object class) setSuperclass: Class */
|
||||||
object_meta = QSE_STX_CLASS(stx,stx->class_object);
|
object_meta = QSE_STX_CLASS(stx,stx->class_object);
|
||||||
QSE_STX_WORD_AT(stx,object_meta,QSE_STX_METACLASS_SUPERCLASS) = stx->class_class;
|
QSE_STX_WORD_AT(stx,object_meta,QSE_STX_METACLASS_SUPERCLASS) = stx->class_class;
|
||||||
/* instance class for Object is set here as it is not
|
/* instance class for Object is set here as it is not
|
||||||
* set in __create_builtin_classes */
|
* set in make_intrisic_classes */
|
||||||
QSE_STX_WORD_AT(stx,object_meta,QSE_STX_METACLASS_INSTANCE_CLASS) = stx->class_object;
|
QSE_STX_WORD_AT(stx,object_meta,QSE_STX_METACLASS_INSTANCE_CLASS) = stx->class_object;
|
||||||
|
|
||||||
/* for some fun here */
|
/* for some fun here */
|
||||||
|
227
qse/lib/stx/dic.c
Normal file
227
qse/lib/stx/dic.c
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stx.h"
|
||||||
|
#include <qse/cmn/str.h>
|
||||||
|
|
||||||
|
/* NOTE:
|
||||||
|
* The code here implements SystemDictionary whose key is always a symbol.
|
||||||
|
* Dictionary, on the contrary, can accept any object as a key.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct qse_stx_assoc_t
|
||||||
|
{
|
||||||
|
qse_stx_objhdr_t h;
|
||||||
|
qse_word_t key;
|
||||||
|
qse_word_t value;
|
||||||
|
};
|
||||||
|
typedef struct qse_stx_assoc_t qse_stx_assoc_t;
|
||||||
|
|
||||||
|
struct qse_stx_dic_t
|
||||||
|
{
|
||||||
|
qse_stx_objhdr_t h;
|
||||||
|
qse_word_t tally;
|
||||||
|
|
||||||
|
/* variable part begins here */
|
||||||
|
qse_word_t slot[1];
|
||||||
|
};
|
||||||
|
typedef struct qse_stx_dic_t qse_stx_dic_t;
|
||||||
|
|
||||||
|
static qse_word_t new_assoc (
|
||||||
|
qse_stx_t* stx, qse_word_t key, qse_word_t value)
|
||||||
|
{
|
||||||
|
qse_word_t x;
|
||||||
|
|
||||||
|
x = qse_stx_allocwordobj (
|
||||||
|
stx, QSE_NULL, QSE_STX_ASSOC_SIZE, QSE_NULL, 0);
|
||||||
|
if (x == stx->ref.nil) return stx->ref.nil;
|
||||||
|
|
||||||
|
OBJCLASS(stx,x) = stx->ref.class_association;
|
||||||
|
WORDAT(stx,x,QSE_STX_ASSOC_KEY) = key;
|
||||||
|
WORDAT(stx,x,QSE_STX_ASSOC_VALUE) = value;
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
static qse_word_t find_slot (
|
||||||
|
qse_stx_t* stx, qse_word_t dic, qse_word_t key)
|
||||||
|
{
|
||||||
|
qse_word_t size, hash, index, assoc, symbol;
|
||||||
|
qse_stx_dic_t* ptr;
|
||||||
|
|
||||||
|
/* ensure that dic is a system dictionary */
|
||||||
|
QSE_ASSERT (REFISIDX(stx,dic));
|
||||||
|
QSE_ASSERT (OBJTYPE(stx,dic) == WORDOBJ);
|
||||||
|
QSE_ASSERT (dic == stx->ref.sysdic ||
|
||||||
|
OBJCLASS(stx,key) == stx->ref.class_system_dictionary);
|
||||||
|
|
||||||
|
/* ensure that the key is a symbol */
|
||||||
|
QSE_ASSERT (REFISIDX(stx,key));
|
||||||
|
QSE_ASSERT (OBJCLASS(stx,key) == stx->ref.class_symbol);
|
||||||
|
|
||||||
|
size = OBJSIZE (stx, dic);
|
||||||
|
hash = qse_stx_hashobj (stx, key);
|
||||||
|
|
||||||
|
/* consider tally, the only instance variable of a system dicionary */
|
||||||
|
index = hash % (size - 1);
|
||||||
|
|
||||||
|
ptr = (qse_stx_dic_t*) REFTOIDX (stx, dic);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
assoc = ptr->slot[index];
|
||||||
|
if (assoc == stx->ref.nil) break;
|
||||||
|
|
||||||
|
symbol = WORDAT (stx, assoc, QSE_STX_ASSOC_KEY);
|
||||||
|
|
||||||
|
QSE_ASSERT (REFISIDX(stx,symbol));
|
||||||
|
QSE_ASSERT (OBJCLASS(stx,symbol) == stx->ref.class_symbol);
|
||||||
|
|
||||||
|
/* NOTE:
|
||||||
|
* shallow comparison is enough for identity check
|
||||||
|
* because a symbol can just be a key of a system dicionary
|
||||||
|
*/
|
||||||
|
if (qse_strxncmp(
|
||||||
|
QSE_STX_DATA(stx,key), OBJSIZE(stx,key),
|
||||||
|
QSE_STX_DATA(stx,symbol), OBJSIZE(stx,symbol)) == 0) break;
|
||||||
|
|
||||||
|
/* consider tally here too */
|
||||||
|
index = index % (size - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void grow_dic (qse_stx_t* stx, qse_word_t dic)
|
||||||
|
{
|
||||||
|
qse_word_t new, size, index, assoc;
|
||||||
|
|
||||||
|
/* WARNING:
|
||||||
|
* if this assertion fails, adjust the initial size of the
|
||||||
|
* system dicionary. i don't want this function to be called
|
||||||
|
* during the bootstrapping.
|
||||||
|
*/
|
||||||
|
QSE_ASSERT (stx->ref.class_system_dictionary != stx->ref.nil);
|
||||||
|
QSE_ASSERT (qse_stx_classof(stx,dic) == stx->ref.class_system_dicionary);
|
||||||
|
|
||||||
|
size = OBJSIZE(stx,dic);
|
||||||
|
new = qse_stx_instantiate (stx,
|
||||||
|
OBJCLASS(stx,dic), QSE_NULL, QSE_NULL, (size - 1) * 2);
|
||||||
|
WORDAT(stx,new,0) = QSE_STX_TO_SMALLINT(0);
|
||||||
|
|
||||||
|
for (index = 1; index < size; index++)
|
||||||
|
{
|
||||||
|
assoc = WORDAT(stx,dic,index);
|
||||||
|
if (assoc == stx->nil) continue;
|
||||||
|
|
||||||
|
qse_stx_putdic (stx, new,
|
||||||
|
WORDAT(stx,assoc,QSE_STX_ASSOC_KEY),
|
||||||
|
WORDAT(stx,assoc,QSE_STX_ASSOC_VALUE));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: explore if dic can be immediately destroyed. */
|
||||||
|
|
||||||
|
QSE_ASSERT (qse_sizeof(qse_stx_object_t*) == qse_sizeof(qse_uint_t));
|
||||||
|
|
||||||
|
QSE_SWAP (
|
||||||
|
QSE_STX_OBJPTR(stx,dic),
|
||||||
|
QSE_STX_OBJPTR(stx,new),
|
||||||
|
qse_stx_object_t*,
|
||||||
|
qse_uint_t
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_word_t qse_stx_lookupdic (
|
||||||
|
qse_stx_t* stx, qse_word_t dic, const qse_char_t* key)
|
||||||
|
{
|
||||||
|
qse_word_t size, hash, index, assoc, symbol;
|
||||||
|
qse_stx_word_object_t* ptr;
|
||||||
|
|
||||||
|
QSE_ASSERT (!QSE_STX_ISSMALLINT(dic) &&
|
||||||
|
QSE_STX_ISWORDOBJECT(stx, dic));
|
||||||
|
QSE_ASSERT (dic == stx->smalltalk ||
|
||||||
|
qse_stx_classof(stx,dic) == stx->class_system_dicionary);
|
||||||
|
|
||||||
|
size = OBJSIZE(stx,dic);
|
||||||
|
hash = qse_stx_hash(key, qse_strlen(key) * qse_sizeof(qse_char_t));
|
||||||
|
|
||||||
|
/* consider tally, the only instance variable of a system dicionary */
|
||||||
|
index = hash % (size - 1);
|
||||||
|
|
||||||
|
ptr = QSE_STX_WORD_OBJECT(stx,dic);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
assoc = ptr->slot[index];
|
||||||
|
if (assoc == stx->ref.nil) break;
|
||||||
|
|
||||||
|
symbol = WORDAT(stx,assoc,QSE_STX_ASSOC_KEY);
|
||||||
|
QSE_ASSERT (qse_stx_classof(stx,symbol) == stx->class_symbol);
|
||||||
|
|
||||||
|
if (qse_strxcmp (
|
||||||
|
QSE_STX_DATA(stx,symbol), OBJSIZE(stx,symbol), key) == 0) break;
|
||||||
|
|
||||||
|
/* consider tally here too */
|
||||||
|
index = index % (size - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return WORDAT(stx,dic,index);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
qse_word_t qse_stx_getdic (qse_stx_t* stx, qse_word_t dic, qse_word_t key)
|
||||||
|
{
|
||||||
|
return WORDAT (stx, dic, find_slot(stx, dic, key));
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_word_t qse_stx_putdic (
|
||||||
|
qse_stx_t* stx, qse_word_t dic, qse_word_t key, qse_word_t val)
|
||||||
|
{
|
||||||
|
qse_word_t slot, capa, tally, assoc;
|
||||||
|
|
||||||
|
/* the dicionary must have at least one slot excluding tally */
|
||||||
|
QSE_ASSERT (OBJSIZE(stx,dic) > 1);
|
||||||
|
|
||||||
|
capa = OBJSIZE(stx,dic) - 1;
|
||||||
|
tally = REFTOINT(WORDAT(stx,dic,0));
|
||||||
|
if (capa <= tally + 1)
|
||||||
|
{
|
||||||
|
if (grow_dic (stx, dic) == stx->ref.nil) return stx->ref.nil;
|
||||||
|
|
||||||
|
/* refresh tally */
|
||||||
|
tally = REFTOINT (stx, WORDAT (stx, dic, QSE_STX_DIC_TALLY));
|
||||||
|
}
|
||||||
|
|
||||||
|
slot = find_slot (stx, dic, key);
|
||||||
|
|
||||||
|
assoc = WORDAT (stx, dic, slot);
|
||||||
|
if (assoc == stx->ref.nil)
|
||||||
|
{
|
||||||
|
assoc = new_assoc (stx, key, value);
|
||||||
|
if (assoc == stx->ref.nil) return stx->ref.nil;
|
||||||
|
|
||||||
|
WORDAT (stx, dic, slot) = assoc;
|
||||||
|
WORDAT (stx, dic, QSE_STX_DIC_TALLY) = INTTOREF (stx, tally + 1);
|
||||||
|
}
|
||||||
|
else WORDAT (stx, assoc, QSE_STX_ASSOC_VALUE) = value;
|
||||||
|
|
||||||
|
return WORDAT(stx,dic,slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qse_stx_walkdic (
|
||||||
|
qse_stx_t* stx, qse_word_t dic,
|
||||||
|
void (*func) (qse_stx_t*,qse_word_t,void*), void* data)
|
||||||
|
{
|
||||||
|
qse_word_t index, assoc;
|
||||||
|
qse_word_t size = OBJSIZE(stx,dic);
|
||||||
|
|
||||||
|
for (index = 1; index < size; index++)
|
||||||
|
{
|
||||||
|
assoc = WORDAT (stx, dic, index);
|
||||||
|
if (assoc == stx->nil) continue;
|
||||||
|
func (stx, assoc, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
51
qse/lib/stx/dic.h
Normal file
51
qse/lib/stx/dic.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _QSE_LIB_STX_DIC_H_
|
||||||
|
#define _QSE_LIB_STX_DIC_H_
|
||||||
|
|
||||||
|
#define QSE_STX_ASSOC_SIZE 2
|
||||||
|
#define QSE_STX_ASSOC_KEY 0
|
||||||
|
#define QSE_STX_ASSOC_VALUE 1
|
||||||
|
|
||||||
|
/* The SystemDictionary is a word variable class.
|
||||||
|
* The info below is for the fixed part only */
|
||||||
|
#define QSE_STX_DIC_SIZE 1
|
||||||
|
#define QSE_STX_DIC_TALLY 0
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
qse_word_t qse_stx_lookupdic (
|
||||||
|
qse_stx_t* stx,
|
||||||
|
qse_word_t dic,
|
||||||
|
const qse_char_t* key
|
||||||
|
);
|
||||||
|
|
||||||
|
qse_word_t qse_stx_getdic (
|
||||||
|
qse_stx_t* stx,
|
||||||
|
qse_word_t dic,
|
||||||
|
qse_word_t key
|
||||||
|
);
|
||||||
|
|
||||||
|
qse_word_t qse_stx_putdic (
|
||||||
|
qse_stx_t* stx,
|
||||||
|
qse_word_t dic,
|
||||||
|
qse_word_t key,
|
||||||
|
qse_word_t value
|
||||||
|
);
|
||||||
|
|
||||||
|
void qse_stx_walkdic (
|
||||||
|
qse_stx_t* stx,
|
||||||
|
qse_word_t dic,
|
||||||
|
void (*func) (qse_stx_t*,qse_word_t,void*),
|
||||||
|
void* data
|
||||||
|
);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
66
qse/lib/stx/hash.c
Normal file
66
qse/lib/stx/hash.c
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stx.h"
|
||||||
|
#include <qse/cmn/str.h>
|
||||||
|
|
||||||
|
qse_word_t qse_stx_hashbyte (qse_stx_t* stx, const void* data, qse_word_t len)
|
||||||
|
{
|
||||||
|
qse_word_t h = 0;
|
||||||
|
qse_byte_t* bp, * be;
|
||||||
|
|
||||||
|
bp = (qse_byte_t*)data; be = bp + len;
|
||||||
|
while (bp < be) h = h * 31 + *bp++;
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_word_t qse_stx_hashstr (qse_stx_t* stx, const qse_char_t* str)
|
||||||
|
{
|
||||||
|
qse_word_t h = 0;
|
||||||
|
qse_byte_t* bp, * be;
|
||||||
|
const qse_char_t* p = str;
|
||||||
|
|
||||||
|
while (*p != QSE_T('\0'))
|
||||||
|
{
|
||||||
|
bp = (qse_byte_t*)p;
|
||||||
|
be = bp + QSE_SIZEOF(qse_char_t);
|
||||||
|
while (bp < be) h = h * 31 + *bp++;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_word_t qse_stx_hashstrx (qse_stx_t* stx, const qse_char_t* str, qse_word_t len)
|
||||||
|
{
|
||||||
|
return qse_stx_hashbytes (stx, str, len * QSE_SIZEOF(*str));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
qse_char_t* qse_stx_strword (
|
||||||
|
const qse_char_t* str, const qse_char_t* word, qse_word_t* word_index)
|
||||||
|
{
|
||||||
|
qse_char_t* p = (qse_char_t*)str;
|
||||||
|
qse_char_t* tok;
|
||||||
|
qse_size_t len;
|
||||||
|
qse_word_t index = 0;
|
||||||
|
|
||||||
|
while (p != QSE_NULL)
|
||||||
|
{
|
||||||
|
p = qse_strtok (p, QSE_T(""), &tok, &len);
|
||||||
|
if (qse_strxcmp (tok, len, word) == 0)
|
||||||
|
{
|
||||||
|
*word_index = index;
|
||||||
|
return tok;
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*word_index = index;
|
||||||
|
return QSE_NULL;
|
||||||
|
}
|
||||||
|
#endif
|
33
qse/lib/stx/hash.h
Normal file
33
qse/lib/stx/hash.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _QSE_LIB_STX_MISC_H_
|
||||||
|
#define _QSE_LIB_STX_MISC_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
qse_word_t qse_stx_hashbytes (
|
||||||
|
qse_stx_t* stx,
|
||||||
|
const void* data,
|
||||||
|
qse_word_t len
|
||||||
|
);
|
||||||
|
|
||||||
|
qse_word_t qse_stx_hashstr (
|
||||||
|
qse_stx_t* stx,
|
||||||
|
const qse_char_t* str
|
||||||
|
);
|
||||||
|
|
||||||
|
qse_word_t qse_stx_hashstrx (
|
||||||
|
qse_stx_t* stx,
|
||||||
|
const qse_char_t* str,
|
||||||
|
qse_word_t len
|
||||||
|
);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -5,6 +5,17 @@
|
|||||||
#include "stx.h"
|
#include "stx.h"
|
||||||
#include <qse/cmn/str.h>
|
#include <qse/cmn/str.h>
|
||||||
|
|
||||||
|
qse_word_t qse_stx_hashbyte (qse_stx_t* stx, const void* data, qse_word_t len)
|
||||||
|
{
|
||||||
|
qse_word_t h = 0;
|
||||||
|
qse_byte_t* bp, * be;
|
||||||
|
|
||||||
|
bp = (qse_byte_t*)data; be = bp + len;
|
||||||
|
while (bp < be) h = h * 31 + *bp++;
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
qse_word_t qse_stx_hashstr (qse_stx_t* stx, const qse_char_t* str)
|
qse_word_t qse_stx_hashstr (qse_stx_t* stx, const qse_char_t* str)
|
||||||
{
|
{
|
||||||
qse_word_t h = 0;
|
qse_word_t h = 0;
|
||||||
@ -24,32 +35,11 @@ qse_word_t qse_stx_hashstr (qse_stx_t* stx, const qse_char_t* str)
|
|||||||
|
|
||||||
qse_word_t qse_stx_hashstrx (qse_stx_t* stx, const qse_char_t* str, qse_word_t len)
|
qse_word_t qse_stx_hashstrx (qse_stx_t* stx, const qse_char_t* str, qse_word_t len)
|
||||||
{
|
{
|
||||||
qse_word_t h = 0;
|
return qse_stx_hashbytes (stx, str, len * QSE_SIZEOF(*str));
|
||||||
qse_byte_t* bp, * be;
|
|
||||||
const qse_char_t* p = str, * end = str + len;
|
|
||||||
|
|
||||||
while (p < end)
|
|
||||||
{
|
|
||||||
bp = (qse_byte_t*)p;
|
|
||||||
be = bp + QSE_SIZEOF(qse_char_t);
|
|
||||||
while (bp < be) h = h * 31 + *bp++;
|
|
||||||
p++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
qse_word_t qse_stx_hash (const void* data, qse_word_t len)
|
|
||||||
{
|
|
||||||
qse_word_t h = 0;
|
|
||||||
qse_byte_t* bp, * be;
|
|
||||||
|
|
||||||
bp = (qse_byte_t*)data; be = bp + len;
|
|
||||||
while (bp < be) h = h * 31 + *bp++;
|
|
||||||
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
qse_char_t* qse_stx_strword (
|
qse_char_t* qse_stx_strword (
|
||||||
const qse_char_t* str, const qse_char_t* word, qse_word_t* word_index)
|
const qse_char_t* str, const qse_char_t* word, qse_word_t* word_index)
|
||||||
{
|
{
|
||||||
|
@ -1,60 +1,30 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: misc.h 118 2008-03-03 11:21:33Z baconevi $
|
* $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _QSE_STX_MISC_H_
|
#ifndef _QSE_LIB_STX_MISC_H_
|
||||||
#define _QSE_STX_MISC_H_
|
#define _QSE_LIB_STX_MISC_H_
|
||||||
|
|
||||||
#include <qse/stx/stx.h>
|
|
||||||
|
|
||||||
/* TODO: remove this header later */
|
|
||||||
#include <qse/bas/stdio.h>
|
|
||||||
|
|
||||||
#ifdef _DOS
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#define qse_assert assert
|
|
||||||
#define qse_malloc malloc
|
|
||||||
#define qse_realloc realloc
|
|
||||||
#define qse_free free
|
|
||||||
#define qse_va_list va_list
|
|
||||||
#define qse_va_start va_start
|
|
||||||
#define qse_va_end va_end
|
|
||||||
#define qse_va_arg va_arg
|
|
||||||
#define qse_isspace isspace
|
|
||||||
#define qse_isdigit isdigit
|
|
||||||
#define qse_isalpha isalpha
|
|
||||||
#define qse_isalnum isalnum
|
|
||||||
#else
|
|
||||||
#include <qse/bas/memory.h>
|
|
||||||
#include <qse/bas/assert.h>
|
|
||||||
#include <qse/bas/stdarg.h>
|
|
||||||
#include <qse/bas/ctype.h>
|
|
||||||
#include <qse/bas/string.h>
|
|
||||||
#include <qse/bas/stdlib.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__BORLANDC__) || defined(_MSC_VER)
|
|
||||||
#define INLINE
|
|
||||||
#else
|
|
||||||
#define INLINE inline
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
qse_word_t qse_stx_hash (const void* data, qse_word_t len);
|
qse_word_t qse_stx_hashbytes (
|
||||||
qse_word_t qse_stx_strhash (const qse_char_t* str);
|
qse_stx_t* stx,
|
||||||
qse_word_t qse_stx_strxhash (const qse_char_t* str, qse_word_t len);
|
const void* data,
|
||||||
|
qse_word_t len
|
||||||
|
);
|
||||||
|
|
||||||
qse_char_t* qse_stx_strword (
|
qse_word_t qse_stx_hashstr (
|
||||||
const qse_char_t* str, const qse_char_t* word, qse_word_t* word_index);
|
qse_stx_t* stx,
|
||||||
|
const qse_char_t* str
|
||||||
|
);
|
||||||
|
|
||||||
|
qse_word_t qse_stx_hashstrx (
|
||||||
|
qse_stx_t* stx,
|
||||||
|
const qse_char_t* str,
|
||||||
|
qse_word_t len
|
||||||
|
);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -188,37 +188,39 @@ qse_word_t qse_stx_allocn_char_object (qse_stx_t* stx, ...)
|
|||||||
|
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
qse_word_t qse_stx_hash_object (qse_stx_t* stx, qse_word_t objref)
|
qse_word_t qse_stx_hashobj (qse_stx_t* stx, qse_word_t ref)
|
||||||
{
|
{
|
||||||
qse_word_t hv;
|
qse_word_t hv;
|
||||||
|
|
||||||
if (QSE_STX_ISSMALLINT(objref))
|
if (REFISINT(stx, ref))
|
||||||
{
|
{
|
||||||
qse_word_t tmp = QSE_STX_FROMSMALLINT(objref);
|
qse_word_t tmp = REFTOINT(stx, ref);
|
||||||
hv = qse_stx_hash (&tmp, QSE_SIZEOF(tmp));
|
hv = qse_stx_hash (&tmp, QSE_SIZEOF(tmp));
|
||||||
}
|
}
|
||||||
else if (QSE_STX_ISCHAROBJECT(stx,objref))
|
else if (QSE_STX_ISCHAROBJECT(stx,ref))
|
||||||
{
|
{
|
||||||
/* the additional null is not taken into account */
|
/* the additional null is not taken into account */
|
||||||
hv = qse_stx_hash (QSE_STX_DATA(stx,objref),
|
hv = qse_stx_hash (QSE_STX_DATA(stx,ref),
|
||||||
QSE_STX_SIZE(stx,objref) * QSE_SIZEOF(qse_char_t));
|
QSE_STX_SIZE(stx,ref) * QSE_SIZEOF(qse_char_t));
|
||||||
}
|
}
|
||||||
else if (QSE_STX_ISBYTEOBJECT(stx,objref))
|
else if (QSE_STX_ISBYTEOBJECT(stx,ref))
|
||||||
{
|
{
|
||||||
hv = qse_stx_hash (
|
hv = qse_stx_hash (
|
||||||
QSE_STX_DATA(stx,objref), QSE_STX_SIZE(stx,objref));
|
QSE_STX_DATA(stx,ref), QSE_STX_SIZE(stx,ref));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QSE_ASSERT (QSE_STX_ISWORDOBJECT(stx,objref));
|
QSE_ASSERT (QSE_STX_ISWORDOBJECT(stx,ref));
|
||||||
hv = qse_stx_hash (QSE_STX_DATA(stx,objref),
|
hv = qse_stx_hash (QSE_STX_DATA(stx,ref),
|
||||||
QSE_STX_SIZE(stx,objref) * QSE_SIZEOF(qse_word_t));
|
QSE_STX_SIZE(stx,ref) * QSE_SIZEOF(qse_word_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
return hv;
|
return hv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
qse_word_t qse_stx_instantiate (
|
qse_word_t qse_stx_instantiate (
|
||||||
qse_stx_t* stx, qse_stx_objref_t class, const void* data,
|
qse_stx_t* stx, qse_stx_objref_t class, const void* data,
|
||||||
const void* variable_data, qse_word_t variable_nflds)
|
const void* variable_data, qse_word_t variable_nflds)
|
||||||
|
@ -29,6 +29,11 @@ qse_word_t qse_stx_alloccharobj (
|
|||||||
qse_word_t variable_nflds
|
qse_word_t variable_nflds
|
||||||
);
|
);
|
||||||
|
|
||||||
|
qse_word_t qse_stx_hashobj (
|
||||||
|
qse_stx_t* stx,
|
||||||
|
qse_word_t ref
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
qse_word_t qse_stx_alloc_word_object (
|
qse_word_t qse_stx_alloc_word_object (
|
||||||
@ -44,8 +49,6 @@ qse_word_t qse_stx_alloc_char_objectx (
|
|||||||
qse_stx_t* stx, const qse_char_t* str, qse_word_t n);
|
qse_stx_t* stx, const qse_char_t* str, qse_word_t n);
|
||||||
qse_word_t qse_stx_allocn_char_object (qse_stx_t* stx, ...);
|
qse_word_t qse_stx_allocn_char_object (qse_stx_t* stx, ...);
|
||||||
|
|
||||||
qse_word_t qse_stx_hash_object (qse_stx_t* stx, qse_word_t object);
|
|
||||||
|
|
||||||
qse_word_t qse_stx_instantiate (
|
qse_word_t qse_stx_instantiate (
|
||||||
qse_stx_t* stx, qse_word_t class_index, const void* data,
|
qse_stx_t* stx, qse_word_t class_index, const void* data,
|
||||||
const void* variable_data, qse_word_t variable_nfields);
|
const void* variable_data, qse_word_t variable_nfields);
|
||||||
|
@ -18,9 +18,11 @@ typedef struct qse_stx_byteobj_t* qse_stx_byteobjptr_t;
|
|||||||
typedef struct qse_stx_charobj_t* qse_stx_charobjptr_t;
|
typedef struct qse_stx_charobj_t* qse_stx_charobjptr_t;
|
||||||
typedef struct qse_stx_wordobj_t* qse_stx_wordobjptr_t;
|
typedef struct qse_stx_wordobj_t* qse_stx_wordobjptr_t;
|
||||||
|
|
||||||
|
#include "hash.h"
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
#include "obj.h"
|
#include "obj.h"
|
||||||
#include "sym.h"
|
#include "sym.h"
|
||||||
|
#include "dic.h"
|
||||||
#include "boot.h"
|
#include "boot.h"
|
||||||
|
|
||||||
enum qse_stx_objtype_t
|
enum qse_stx_objtype_t
|
||||||
|
@ -26,21 +26,21 @@ qse_word_t qse_stx_newsymbol (
|
|||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* the table must have at least one slot excluding the tally field */
|
/* the table must have at least one slot excluding the tally field */
|
||||||
QSE_ASSERT (QSE_STX_OBJSIZE(stx,tab) > 1);
|
QSE_ASSERT (OBJSIZE(stx,tabref) > 1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
tabptr = (qse_stx_symtab_t*) PTRBYREF (stx, tabref);
|
|
||||||
|
|
||||||
capa = tabptr->h._size - 1; /* exclude the tally field */
|
capa = OBJSIZE(stx,tabref) - 1; /* exclude the tally field */
|
||||||
hash = qse_stx_hashstr (stx, name) % capa;
|
hash = qse_stx_hashstr (stx, name) % capa;
|
||||||
|
|
||||||
|
tabptr = (qse_stx_symtab_t*) PTRBYREF (stx, tabref);
|
||||||
for (count = 0; count < capa; count++)
|
for (count = 0; count < capa; count++)
|
||||||
{
|
{
|
||||||
symref = tabptr->slot[hash];
|
symref = tabptr->slot[hash];
|
||||||
if (symref == stx->ref.nil) break; /* not found */
|
if (symref == stx->ref.nil) break; /* not found */
|
||||||
|
|
||||||
|
QSE_ASSERT (OBJTYPE(stx,symref) == CHAROBJ);
|
||||||
symptr = (qse_stx_charobjptr_t) PTRBYREF (stx, symref);
|
symptr = (qse_stx_charobjptr_t) PTRBYREF (stx, symref);
|
||||||
QSE_ASSERT (symptr->h._type == QSE_STX_CHAROBJ);
|
|
||||||
|
|
||||||
if (qse_strcmp (name, symptr->fld) == 0) return symref;
|
if (qse_strcmp (name, symptr->fld) == 0) return symref;
|
||||||
|
|
||||||
@ -50,6 +50,7 @@ qse_word_t qse_stx_newsymbol (
|
|||||||
if (tabptr->tally >= capa)
|
if (tabptr->tally >= capa)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
|
/* TODO: write this part....
|
||||||
if (grow (stx, tab) <= -1) return -1;
|
if (grow (stx, tab) <= -1) return -1;
|
||||||
/* refresh tally */
|
/* refresh tally */
|
||||||
tally = QSE_STX_REFTOINT(QSE_STX_WORDAT(stx,tab,QSE_STX_SET_TALLY));
|
tally = QSE_STX_REFTOINT(QSE_STX_WORDAT(stx,tab,QSE_STX_SET_TALLY));
|
||||||
|
@ -5,6 +5,11 @@
|
|||||||
#ifndef _QSE_LIB_STX_SYM_H_
|
#ifndef _QSE_LIB_STX_SYM_H_
|
||||||
#define _QSE_LIB_STX_SYM_H_
|
#define _QSE_LIB_STX_SYM_H_
|
||||||
|
|
||||||
|
/* The SystemSymbolTable is a word variable class.
|
||||||
|
* The info below is for the fixed part only */
|
||||||
|
#define QSE_STX_SYMTAB_SIZE 1
|
||||||
|
#define QSE_STX_SYMTAB_TALLY 0
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user