Procházet zdrojové kódy

Add some extensions that are work in progress.

mingodad před 10 roky
rodič
revize
dfca6eccd3

+ 198 - 0
SquiLu-ext/sq_dns_sd.cpp

@@ -0,0 +1,198 @@
+#ifdef WITH_DNS_SD
+
+#include "squirrel.h"
+#include <dns_sd.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "sqstdblobimpl.h"
+
+#include "dynamic_library.h"
+
+/*SquiLu
+local dns_sd_functions = [
+    ["void", "TXTRecordCreate", @"TXTRecordRef *txtRecord, uint16_t bufferLen,
+                        void *buffer"],
+    ["int", "TXTRecordSetValue", @"TXTRecordRef *txtRecord,
+                    const char *key, uint8_t valueSize, const void *value"],
+    ["void", "TXTRecordDeallocate", "TXTRecordRef *txtRecord"],
+    ["uint16_t", "TXTRecordGetLength", "const TXTRecordRef *txtRecord"],
+    ["const void *", "TXTRecordGetBytesPtr", "const TXTRecordRef *txtRecord"],
+
+    //next entry should be the last one
+    //to make valid the test made on load_libpq function
+    ["DNSServiceErrorType", "DNSServiceRegister", @"DNSServiceRef *sdRef,
+                    DNSServiceFlags flags, uint32_t interfaceIndex,
+                    const char *name, const char *regtype,
+                    const char *domain, const char *host,
+                    uint16_t port, uint16_t txtLen,
+                    const void *txtRecord, DNSServiceRegisterReply callBack,
+                    void *context "],
+];
+
+function write_dns_sd_functions_declaration(){
+    foreach(k,v in dns_sd_functions) {
+        putsnl("typedef " + v[0] + " (*" + v[1] + "_t)(" + v[2] + ");");
+        putsnl("static " + v[1] + "_t dl" + v[1] + " = 0;");
+    }
+}
+
+function write_dns_sd_functions_load(){
+    foreach(k,v in dns_sd_functions){
+        putsnl("dl" + v[1] + " = (" + v[1] + "_t) libdns_sd.dlsym(\"" + v[1] + "\");");
+        putsnl("if(!dl" + v[1] + ") return false;");
+    }
+}
+SquiLu*/
+
+static DynamicLibrary libdns_sd;
+
+//@write_dns_sd_functions_declaration();
+// generated-code:begin
+typedef void (*TXTRecordCreate_t)(TXTRecordRef *txtRecord, uint16_t bufferLen,
+                        void *buffer);
+static TXTRecordCreate_t dlTXTRecordCreate = 0;
+typedef int (*TXTRecordSetValue_t)(TXTRecordRef *txtRecord,
+                    const char *key, uint8_t valueSize, const void *value);
+static TXTRecordSetValue_t dlTXTRecordSetValue = 0;
+typedef void (*TXTRecordDeallocate_t)(TXTRecordRef *txtRecord);
+static TXTRecordDeallocate_t dlTXTRecordDeallocate = 0;
+typedef uint16_t (*TXTRecordGetLength_t)(const TXTRecordRef *txtRecord);
+static TXTRecordGetLength_t dlTXTRecordGetLength = 0;
+typedef const void * (*TXTRecordGetBytesPtr_t)(const TXTRecordRef *txtRecord);
+static TXTRecordGetBytesPtr_t dlTXTRecordGetBytesPtr = 0;
+typedef DNSServiceErrorType (*DNSServiceRegister_t)(DNSServiceRef *sdRef,
+                    DNSServiceFlags flags, uint32_t interfaceIndex,
+                    const char *name, const char *regtype,
+                    const char *domain, const char *host,
+                    uint16_t port, uint16_t txtLen,
+                    const void *txtRecord, DNSServiceRegisterReply callBack,
+                    void *context );
+static DNSServiceRegister_t dlDNSServiceRegister = 0;
+// generated-code:end
+
+#ifdef WIN32
+#define LIDNS_SD_NAME "libdns_sd.dll"
+#else
+#define LIDNS_SD_NAME "libdns_sd.so"
+#endif
+
+static bool load_libdns_sd()
+{
+    if(dlDNSServiceRegister) return true;
+    if(libdns_sd.open(LIDNS_SD_NAME))
+    {
+        //@write_dns_sd_functions_load();
+// generated-code:begin
+dlTXTRecordCreate = (TXTRecordCreate_t) libdns_sd.dlsym("TXTRecordCreate");
+if(!dlTXTRecordCreate) return false;
+dlTXTRecordSetValue = (TXTRecordSetValue_t) libdns_sd.dlsym("TXTRecordSetValue");
+if(!dlTXTRecordSetValue) return false;
+dlTXTRecordDeallocate = (TXTRecordDeallocate_t) libdns_sd.dlsym("TXTRecordDeallocate");
+if(!dlTXTRecordDeallocate) return false;
+dlTXTRecordGetLength = (TXTRecordGetLength_t) libdns_sd.dlsym("TXTRecordGetLength");
+if(!dlTXTRecordGetLength) return false;
+dlTXTRecordGetBytesPtr = (TXTRecordGetBytesPtr_t) libdns_sd.dlsym("TXTRecordGetBytesPtr");
+if(!dlTXTRecordGetBytesPtr) return false;
+dlDNSServiceRegister = (DNSServiceRegister_t) libdns_sd.dlsym("DNSServiceRegister");
+if(!dlDNSServiceRegister) return false;
+// generated-code:end
+        return true;
+    }
+    return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+static const SQChar *DNS_SD_TAG = _SC("DNS_SD");
+
+static SQRESULT sq_dns_sd_ServiceRegister(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+    TXTRecordRef txtRecord;
+	DNSServiceRef sdref;
+	DNSServiceErrorType err;
+	int ret, result = 0;
+
+    SQ_GET_STRING(v, 2, deviceName);
+    SQ_GET_STRING(v, 3, serviceType);
+
+	SQInteger rec_count = sq_getsize(v, 4);
+
+	dlTXTRecordCreate(&txtRecord, 0, NULL);
+
+	for(int i=0; i < rec_count; ++i){
+        sq_pushinteger(v, i);
+        if(SQ_SUCCEEDED(sq_get(v, 4))){
+            if((sq_gettype(v, 5) == OT_ARRAY) && (sq_getsize(v, 5) == 2)) {
+                sq_pushinteger(v, 0);
+                sq_get(v, 5);
+                SQ_GET_STRING(v, 6, key);
+                sq_pushinteger(v, 1);
+                sq_get(v, 5);
+                SQ_GET_STRING(v, 7, value);
+                sq_pop(v, 2); //remove key,value
+
+                ret = dlTXTRecordSetValue(&txtRecord, key, value_size, value);
+                if(ret != kDNSServiceErr_NoError) {
+                    sq_throwerror(v, _SC("Array with key, value expected"));
+                    result = SQ_ERROR;
+                }
+            } else {
+                sq_throwerror(v, _SC("Array with key, value expected"));
+                result = SQ_ERROR;
+            }
+            sq_pop(v, 1); //remove value
+            if(result == SQ_ERROR) {
+                break;
+            }
+        }
+    }
+
+    if(result == 0) {
+        err = dlDNSServiceRegister(&sdref,0,0,deviceName,serviceType,NULL,NULL,htons(0),
+                                dlTXTRecordGetLength(&txtRecord),dlTXTRecordGetBytesPtr(&txtRecord),NULL,NULL);
+        if(err != kDNSServiceErr_NoError) {
+            sq_throwerror(v, _SC("DNS_SD error registering service %d"),err);
+            result = SQ_ERROR;
+        }
+    }
+    dlTXTRecordDeallocate(&txtRecord);
+
+	return result;
+}
+
+#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),  sq_dns_sd_##name,nparams,tycheck}
+static SQRegFunction sq_dns_sd_methods[] =
+{
+	_DECL_FUNC(ServiceRegister,  4, _SC(".ssa")),
+	{0,0}
+};
+#undef _DECL_FUNC
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SQRESULT sqext_register_DNS_SD(HSQUIRRELVM v)
+{
+    if(load_libdns_sd())
+    {
+        sq_pushstring(v,_SC("dns_sd"),-1);
+        sq_newtable(v);
+        sq_insert_reg_funcs(v, sq_dns_sd_methods);
+        sq_newslot(v,-3,SQTrue);
+    }
+    else
+    {
+        return sq_throwerror(v, _SC("Failed to load libdns_sd !"));
+    }
+    return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //WITH_DNS_SD

+ 425 - 0
SquiLu-ext/sq_fastcgi.cpp

@@ -0,0 +1,425 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <time.h>
+
+#include "squirrel.h"
+#include "sqstdblobimpl.h"
+SQ_OPT_STRING_STRLEN();
+
+/* Lua System: Internet Server Application: FastCGI */
+
+#define FCGI_VERSION		1
+
+#define FCGI_HEADER_LEN		8
+#define FCGI_END_REQUEST_LEN	8
+
+#define FCGI_RESPONDER		1
+
+#define FCGI_KEEP_CONN		1
+
+#define FCGI_BEGIN_REQUEST	1
+#define FCGI_ABORT_REQUEST	2
+#define FCGI_END_REQUEST	3
+#define FCGI_PARAMS		4
+#define FCGI_STDIN		5
+#define FCGI_STDOUT		6
+#define FCGI_STDERR		7
+#define FCGI_DATA		8
+#define FCGI_GET_VALUES		9
+#define FCGI_GET_VALUES_RESULT	10
+#define FCGI_UNKNOWN_TYPE	11
+
+#define FCGI_REQUEST_COMPLETE	0
+#define FCGI_CANT_MPX_CONN	1
+#define FCGI_OVERLOADED		2
+#define FCGI_UNKNOWN_ROLE	3
+
+#define FCGI_NULL_REQUEST_ID	~0U
+
+#define FCGI_MAX_CONTENT_LEN	0xFFFF
+
+
+static const char *
+fcgi_decode_begin_request (HSQUIRRELVM v, const unsigned char *cp,
+                           const size_t size)
+{
+    int role, keep_conn;
+
+    if (size != 8) return "bad content";
+
+    role = (*cp++ << 8);
+    role |= *cp++;
+    keep_conn = *cp & FCGI_KEEP_CONN;
+
+    if (role != FCGI_RESPONDER) return "bad role";
+
+    sq_pushbool(v, keep_conn);
+    sq_setfield(v, -2, "keep_conn");
+
+    return NULL;
+}
+
+static const char *
+fcgi_decode_params (HSQUIRRELVM v, const unsigned char *cp, const size_t size)
+{
+    const unsigned char *endp = cp + size;
+
+    while (cp < endp)
+    {
+        unsigned int name_len, value_len;
+
+        name_len = *cp++;
+        if (name_len & 0x80)
+        {
+            if (cp + 3 >= endp) return "bad content";
+
+            name_len ^= 0x80;
+            name_len = (name_len << 8) | *cp++;
+            name_len = (name_len << 8) | *cp++;
+            name_len = (name_len << 8) | *cp++;
+        }
+        if (cp >= endp) return "bad content";
+
+        value_len = *cp++;
+        if (value_len & 0x80)
+        {
+            if (cp + 3 >= endp) return "bad content";
+
+            value_len ^= 0x80;
+            value_len = (value_len << 8) | *cp++;
+            value_len = (value_len << 8) | *cp++;
+            value_len = (value_len << 8) | *cp++;
+        }
+        if (cp + name_len + value_len > endp)
+            return "bad content";
+
+        sq_pushstring(v, (const char *) cp, name_len);
+        cp += name_len;
+        sq_pushstring(v, (const char *) cp, value_len);
+        cp += value_len;
+        sq_rawset(v, -3);
+    }
+
+    return NULL;
+}
+
+static const char *
+fcgi_decode_stdin (HSQUIRRELVM v, const unsigned char *cp, const size_t size)
+{
+    int concat = 1;
+
+    sq_getfield(v, -1, "stdin");
+    if (sq_isnil(v, -1))
+    {
+        sq_pop(v, 1);
+        concat = 0;
+    }
+
+    sq_pushstring(v, (const char *) cp, size);
+    if (concat) sq_concat(v, 2);
+    sq_setfield(L, -2, "stdin");
+
+    return NULL;
+}
+
+/*
+ * Arguments: ..., channel (table)
+ */
+static int
+fcgi_decode_record (HSQUIRRELVM v, const unsigned char *cp, const size_t size,
+                    unsigned int *ready_request_id)
+{
+    unsigned int version, type, request_id, content_len, padding_len, len;
+    int is_ready = 0;
+    const char *err = NULL;
+
+    version = *cp++;
+    type = *cp++;
+    request_id = (*cp++ << 8);
+    request_id |= *cp++;
+    content_len = (*cp++ << 8);
+    content_len |= *cp++;
+    padding_len = *cp++;
+    cp++;  /* reserved */
+
+    len = FCGI_HEADER_LEN + content_len + padding_len;
+    if (len > size) return 0;
+
+    sq_rawgeti(v, -1, request_id);
+    if (!sq_istable(v, -1))
+    {
+        sq_pop(v, 1);
+        sq_newtable(v);
+        sq_pushvalue(v, -1);
+        sq_rawseti(v, -3, request_id);
+
+        sq_pushinteger(v, request_id);
+        sq_setfield(v, -2, "id");
+
+        sq_getfield(v, -2, "request_meta");  /* metatable from channel */
+        sq_setmetatable(v, -2);
+
+        sq_pushvalue(v, -2);  /* channel */
+        sq_setfield(v, -2, "channel");
+    }
+
+    if (version != FCGI_VERSION)
+        err = "bad version";
+    else
+    {
+        switch (type)
+        {
+        case FCGI_BEGIN_REQUEST:
+            err = fcgi_decode_begin_request(v, cp, content_len);
+            break;
+        case FCGI_ABORT_REQUEST:
+            break;
+        case FCGI_PARAMS:
+            if (content_len)
+                err = fcgi_decode_params(v, cp, content_len);
+            break;
+        case FCGI_STDIN:
+            if (content_len)
+                err = fcgi_decode_stdin(v, cp, content_len);
+            else
+                is_ready = 1;
+            break;
+        default:
+            err = "bad type";
+        }
+    }
+
+    if (err)
+    {
+        sq_pushstring(v, err, -1);
+        sq_setfield(v, -2, "error");
+
+        /*
+        lua_pushinteger(L, version);
+        lua_setfield(L, -2, "version");
+
+        lua_pushinteger(L, type);
+        lua_setfield(L, -2, "type");
+
+        lua_pushlstring(L, cp, content_len);
+        lua_setfield(L, -2, "content");
+        */
+
+        is_ready = 1;
+    }
+    if (is_ready)
+    {
+        if (*ready_request_id != FCGI_NULL_REQUEST_ID)
+            sq_pushinteger(v, *ready_request_id);
+        else
+            sq_pushnil(v);
+        sq_setfield(v, -2, "next_ready");
+
+        *ready_request_id = request_id;
+    }
+    sq_pop(v, 1);
+    return len;
+}
+
+/*
+ * Arguments: {string | membuf_udata}, channel (table)
+ * Returns: [request_id (number)]
+ */
+static SQRESULT sq_fastcgi_decode (HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS(v);
+    struct sys_buffer sb;
+    const char *cp;
+    unsigned int ready_request_id = FCGI_NULL_REQUEST_ID;
+
+    if (!sys_buffer_read_init(v, 1, &sb))
+        return 0;
+    sq_checktype(v, 2, LUA_TTABLE);
+
+    cp = sb.ptr.r;
+    while (sb.size >= FCGI_HEADER_LEN)
+    {
+        const int len = fcgi_decode_record(v,
+                                           (const unsigned char *) cp, sb.size, &ready_request_id);
+
+        if (!len) break;
+        cp += len;
+        sb.size -= len;
+    }
+    sys_buffer_read_next(&sb, cp - sb.ptr.r);
+
+    if (ready_request_id != FCGI_NULL_REQUEST_ID)
+    {
+        sq_pushinteger(v, ready_request_id);
+        return 1;
+    }
+    return 0;
+}
+
+
+/*
+ * Arguments: membuf_udata, request_id (number), prev_offset (number), string
+ * Returns: offset (number)
+ */
+static SQRESULT sq_fastcgi_encode (HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS(v);
+    SQBlob *blob = NULL;
+    SQObjectType ptype = sq_gettype(v, 2);
+    if(ptype == OT_INSTANCE){
+            if(SQ_FAILED(sq_getinstanceup(v,2,(SQUserPointer*)&blob,(SQUserPointer)SQBlob::SQBlob_TAG)))
+                return sq_throwerror(v,_SC("invalid type tag"));
+            if(!blob || !blob->IsValid())
+                return sq_throwerror(v,_SC("the blob is invalid"));
+    }
+    SQ_GET_INTEGER(v, 3, request_id);
+    SQ_GET_INTEGER(v, 4, prev_offset);
+    SQ_GET_STRING(v, 5, s);
+    unsigned char *cp;
+    unsigned char *lenp;
+    SQInteger prev_len = 0, prev_padding_len = 0;
+    SQInteger data_len, padding_len;
+
+    if (s_size > FCGI_MAX_CONTENT_LEN) {
+        return sq_throwerror(v,_SC("too long"));
+    }
+
+    sys_buffer_write_init(v, 1, &sb, NULL, 0);
+
+    if (prev_offset)
+    {
+        cp = (unsigned char *) sb.ptr.w - prev_offset;
+        if (cp[-1] == (unsigned char) request_id
+                && cp[-2] == (unsigned char) (request_id >> 8))
+        {
+            prev_len = (cp[0] << 8) | cp[1];
+            prev_padding_len = cp[2];
+        }
+        else
+        {
+            prev_offset = 0;
+        }
+    }
+
+    if (!len)
+    {
+        data_len = 2 * FCGI_HEADER_LEN + FCGI_END_REQUEST_LEN;
+        prev_offset = 0;
+    }
+    else
+    {
+        data_len = len;
+        if (!prev_offset || (prev_len + len) > FCGI_MAX_CONTENT_LEN)
+        {
+            data_len += FCGI_HEADER_LEN;
+            prev_offset = 0;
+        }
+        else
+        {
+            data_len -= prev_padding_len;
+        }
+    }
+
+    if (data_len <= 0)
+    {
+        padding_len = prev_padding_len - len;  /* fits to previous padding */
+        data_len = 0;
+    }
+    else
+    {
+        padding_len = 8 - data_len % 8;
+        if (padding_len == 8) padding_len = 0;
+
+        data_len += padding_len;
+        if (!sys_buffer_write_next(v, &sb, NULL, data_len))
+            return 0;
+    }
+
+    /* buffer may be re-allocated */
+    cp = (unsigned char *) sb.ptr.w;
+
+    if (prev_offset)
+    {
+        lenp = cp - prev_offset;
+        cp -= prev_padding_len;
+        memcpy(cp, s, len);  /* concat to previous record */
+        cp += len;
+        len += prev_len;
+    }
+    else
+    {
+        *cp++ = FCGI_VERSION;
+        *cp++ = FCGI_STDOUT;
+        *cp++ = (unsigned char) (request_id >> 8);
+        *cp++ = (unsigned char) request_id;
+        lenp = cp++;  /* content_len */
+        cp++;
+        cp++;  /* padding_len */
+        *cp++ = 0;  /* reserved */
+
+        if (len)
+        {
+            memcpy(cp, s, len);
+            cp += len;
+        }
+        else
+        {
+            *cp++ = FCGI_VERSION;
+            *cp++ = FCGI_END_REQUEST;
+            *cp++ = (unsigned char) (request_id >> 8);
+            *cp++ = (unsigned char) request_id;
+            *cp++ = 0;  /* content_len */
+            *cp++ = FCGI_END_REQUEST_LEN;
+            *cp++ = 0;  /* padding_len */
+            *cp++ = 0;  /* reserved */
+
+            memset(cp, 0, FCGI_END_REQUEST_LEN);
+        }
+    }
+
+    lenp[0] = (unsigned char) (len >> 8);
+    lenp[1] = (unsigned char) len;
+    lenp[2] = (unsigned char) padding_len;
+
+    if (padding_len)
+    {
+        memset(cp, 0, padding_len);
+        cp += padding_len;
+    }
+
+    sys_buffer_write_done(v, &sb, NULL, data_len);
+
+    sq_pushinteger(v, cp - lenp);
+    return 1;
+}
+
+
+#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),  sq_fastcgi_##name,nparams,tycheck}
+static SQRegFunction sq_fastcgi_methods[] =
+{
+    _DECL_FUNC(encode,  -1, _SC("x")),
+    _DECL_FUNC(decode,  1, _SC("x")),
+    {0,0}
+};
+#undef _DECL_FUNC
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+    SQRESULT sqext_register_fastcgi(HSQUIRRELVM v)
+    {
+        //add a namespace sqfastcgi
+        sq_pushstring(v, sq_fastcgi_TAG,-1);
+        sq_newclass(v, SQFalse);
+        sq_insert_reg_funcs(v, sq_fastcgi_methods);
+        sq_newslot(v,-3,SQTrue); //add sqfastcgi table to the root table
+
+        return SQ_OK;
+    }
+
+#ifdef __cplusplus
+}
+#endif

+ 409 - 0
SquiLu-ext/sq_ffi.cpp

@@ -0,0 +1,409 @@
+#ifdef WITH_FFI
+
+#include "squirrel.h"
+#include <ffi.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "sqstdblobimpl.h"
+#include "sqstdblob.h"
+
+#ifdef WIN32
+#include <windows.h>
+#define CLOSE_LIB(lib) (FreeLibrary((HINSTANCE)lib) != 0)
+#ifdef _WIN32_WCE
+#define OPEN_LIB(lib) (void*)LoadLibraryA(lib)
+#define GET_SYM(lib, sn) GetProcAddressA((HINSTANCE)lib, sn)
+#else
+#define OPEN_LIB(lib) (void*)LoadLibrary(lib)
+#define GET_SYM(lib, sn) (void*)GetProcAddress((HINSTANCE)lib, sn)
+#endif
+typedef void* (WINAPI*cPtrFuncVarArg)(...);
+#else
+#include <dlfcn.h>
+#define CLOSE_LIB(lib) (::dlclose(lib) == 0)
+#define OPEN_LIB(lib) ::dlopen(lib,RTLD_LAZY)
+#define GET_SYM(lib, sn) ::dlsym(lib, sn)
+typedef void*(*cPtrFuncVarArg)(...);
+#endif
+
+static const SQChar *FFI_LIB_TAG = _SC("FFI_LIB");
+//static const SQChar *FFI_LIB_FUN_TAG = _SC("FFI_LIB_FUNC");
+//static const SQChar *FFI_LIB_VAR_TAG = _SC("FFI_LIB_VAR");
+
+//Code adapted from https://github.com/pfalcon/squirrel-modules
+
+static HSQOBJECT lib_method_table;
+static HSQOBJECT func_method_table;
+static HSQOBJECT var_method_table;
+
+static SQInteger sq_ffi_load(HSQUIRRELVM v)
+{
+    const SQChar *fname;
+    sq_getstring(v, 2, &fname);
+    void *mod = OPEN_LIB(fname);
+    if (!mod)
+        return sq_throwerror(v, "Cannot load library");
+    sq_pushuserpointer(v, mod);
+    void **p = (void**)sq_newuserdata(v, sizeof(mod));
+    *p = mod;
+    sq_pushobject(v, lib_method_table);
+    sq_setdelegate(v, -2);
+    return 1;
+}
+
+static SQInteger sq_ffi_sym(HSQUIRRELVM v)
+{
+    void *mod;
+    const SQChar *symname;
+    sq_getuserpointer(v, 2, &mod);
+    sq_getstring(v, 3, &symname);
+    void *sym = GET_SYM(mod, symname);
+    printf("GET_SYM(%s) = %p\n", symname, sym);
+    if (!sym)
+        return sq_throwerror(v, "Cannot find symbol");
+    void **p = (void**)sq_newuserdata(v, sizeof(sym));
+    *p = sym;
+    return 1;
+}
+
+static ffi_type *char2ffi_type(char c)
+{
+    switch (c) {
+    case 'b':
+        return &ffi_type_schar;
+    case 'B':
+        return &ffi_type_uchar;
+    case 'i':
+        return &ffi_type_sint;
+    case 'I':
+        return &ffi_type_uint;
+    case 'l':
+        return &ffi_type_slong;
+    case 'L':
+        return &ffi_type_ulong;
+    case 'P':
+    case 's':
+        return &ffi_type_pointer;
+    default:
+        return NULL;
+    }
+}
+
+static ffi_type *get_ffi_type(HSQUIRRELVM v, int idx)
+{
+    int type = sq_gettype(v, idx);
+    void *p;
+    const SQChar *s;
+    ffi_type *t;
+
+    switch (type) {
+    case OT_USERPOINTER:
+        sq_getuserpointer(v, idx, &p);
+        return (ffi_type*)p;
+    case OT_STRING:
+        sq_getstring(v, idx, &s);
+        t = char2ffi_type(*s);
+        if (t)
+            return t;
+    default:
+        sq_throwerror(v, "Type spec must be string or ffi_type");
+        return NULL;
+    }
+}
+
+typedef struct FFIFunc
+{
+    void *func;
+    char rettype;
+    ffi_cif cif;
+    ffi_type *params[0];
+} FFIFunc;
+
+typedef struct FFIVar
+{
+    void *var;
+    char type;
+} FFIVar;
+
+static SQInteger sq_lib_bind_func(HSQUIRRELVM v)
+{
+    void **modbuf;
+    void *mod;
+    void *sym;
+    const SQChar *symname;
+    const char *rettype;
+
+    sq_getuserdata(v, 1, (void**)&modbuf, NULL);
+    mod = *modbuf;
+
+    sq_getstring(v, 2, &rettype);
+
+    sq_getstring(v, 3, &symname);
+    sym = GET_SYM(mod, symname);
+    if (!sym)
+        return sq_throwerror(v, "Cannot find symbol");
+
+    int nparam = sq_getsize(v, 4);
+
+    int size = sizeof(FFIFunc) + sizeof(ffi_type*) * nparam;
+    FFIFunc *ffibuf = (FFIFunc*)sq_newuserdata(v, size);
+    sq_pushobject(v, func_method_table);
+    sq_setdelegate(v, -2);
+
+//    printf("Allocated %d bytes at %p\n", size, ffibuf);
+    ffibuf->func = sym;
+    ffibuf->rettype = *rettype;
+
+    int i;
+    for (i = 0; i < nparam; i++) {
+        sq_pushinteger(v, i);
+        sq_get(v, 4);
+        ffibuf->params[i] = get_ffi_type(v, -1);
+        if (!ffibuf->params[i])
+            return SQ_ERROR;
+        sq_poptop(v);
+    }
+    int res = ffi_prep_cif(&ffibuf->cif, FFI_DEFAULT_ABI, nparam, char2ffi_type(*rettype), ffibuf->params);
+    if (res != FFI_OK)
+        return sq_throwerror(v, "Error in ffi_prep_cif");
+    return 1;
+}
+
+static SQInteger sq_lib_bind_var(HSQUIRRELVM v)
+{
+    void **modbuf;
+    void *mod;
+    void *sym;
+    const SQChar *symname;
+    const char *type;
+
+    sq_getuserdata(v, 1, (void**)&modbuf, NULL);
+    mod = *modbuf;
+
+    sq_getstring(v, 2, &type);
+
+    sq_getstring(v, 3, &symname);
+    sym = GET_SYM(mod, symname);
+    if (!sym)
+        return sq_throwerror(v, "Cannot find symbol");
+
+    FFIVar *ffibuf = (FFIVar*)sq_newuserdata(v, sizeof(FFIVar));
+    sq_pushobject(v, var_method_table);
+    sq_setdelegate(v, -2);
+
+    ffibuf->var = sym;
+    ffibuf->type = *type;
+
+    return 1;
+}
+
+#define METAMETHOD
+#ifdef METAMETHOD
+// For metamethod, we have userdata, then delegate table
+#define EXTRA_PARAMS 2
+#else
+// For normal method, there's only userdata
+#define EXTRA_PARAMS 1
+#endif
+
+static void return_ffi_value(HSQUIRRELVM v, ptrdiff_t val, char type)
+{
+    switch (type) {
+    case 's':
+        sq_pushstring(v, (char*)val, -1);
+        break;
+    default:
+        sq_pushinteger(v, val);
+    }
+}
+
+static SQInteger sq_func__call(HSQUIRRELVM v)
+{
+    FFIFunc *ffibuf;
+    sq_getuserdata(v, 1, (void**)&ffibuf, NULL);
+    int top = sq_gettop(v);
+//    printf("ffibuf %p top %d\n", ffibuf, top);
+
+    if (ffibuf->cif.nargs != top - EXTRA_PARAMS)
+        return sq_throwerror(v, "Wrong number of args");
+
+    SQInteger values[top - EXTRA_PARAMS];
+    void *valueptrs[top - EXTRA_PARAMS];
+    int i;
+    for (i = EXTRA_PARAMS + 1; i <= top; i++) {
+        #define pi (i - (EXTRA_PARAMS + 1))
+        switch (sq_gettype(v, i)) {
+        case OT_INTEGER:
+            sq_getinteger(v, i, (SQInteger*)&values[pi]);
+            break;
+        case OT_STRING:
+            sq_getstring(v, i, (const char**)&values[pi]);
+            break;
+        case OT_INSTANCE: {
+            if (SQ_FAILED(sqstd_getblob(v, i, (SQUserPointer*)&values[pi])))
+                return SQ_ERROR;
+            break;
+        }
+        default:
+            return sq_throwerror(v, "Unimplemented type");
+        }
+        valueptrs[pi] = &values[pi];
+    }
+
+    ptrdiff_t rc;
+//    printf("Before call, %p\n", ffibuf->func);
+    ffi_call(&ffibuf->cif, (void(*)())ffibuf->func, &rc, valueptrs);
+    return_ffi_value(v, rc, ffibuf->rettype);
+    return 1;
+}
+
+static SQInteger sq_var_get(HSQUIRRELVM v)
+{
+    FFIVar *ffibuf;
+    sq_getuserdata(v, 1, (void**)&ffibuf, NULL);
+    void *pval = ffibuf->var;
+    switch (ffibuf->type) {
+    case 's':
+        sq_pushstring(v, *(char**)pval, -1);
+        break;
+    case 'i':
+        sq_pushinteger(v, *(int*)pval);
+        break;
+    case 'I':
+        sq_pushinteger(v, *(unsigned int*)pval);
+        break;
+    case 'h':
+        sq_pushinteger(v, *(short*)pval);
+        break;
+    case 'H':
+        sq_pushinteger(v, *(unsigned short*)pval);
+        break;
+    case 'l':
+        sq_pushinteger(v, *(long*)pval);
+        break;
+    case 'L':
+        sq_pushinteger(v, *(unsigned long*)pval);
+        break;
+    case 'b':
+        sq_pushinteger(v, *(char*)pval);
+        break;
+    case 'B':
+        sq_pushinteger(v, *(unsigned char*)pval);
+        break;
+    default:
+        sq_pushinteger(v, *(int*)pval);
+    }
+    return 1;
+}
+
+static SQInteger sq_ffi_setdelegate(HSQUIRRELVM v)
+{
+    if (SQ_FAILED(sq_setdelegate(v, 2)))
+        return SQ_ERROR;
+    return 0;
+}
+
+#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),  sq_ffi_##name,nparams,tycheck}
+static SQRegFunction sq_ffi_methods[] =
+{
+	_DECL_FUNC(load,  2, _SC(".s")),
+	_DECL_FUNC(sym,  3, _SC(".ps")),
+	_DECL_FUNC(setdelegate,  3, _SC("..t")),
+	{0,0}
+};
+#undef _DECL_FUNC
+
+#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),  sq_lib_##name,nparams,tycheck}
+static SQRegFunction sq_lib_methods[] =
+{
+	_DECL_FUNC(bind_func,  4, _SC("ussa")),
+	_DECL_FUNC(bind_var,  3, _SC("uss")),
+	{0,0}
+};
+#undef _DECL_FUNC
+
+#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),  sq_func_##name,nparams,tycheck}
+static SQRegFunction sq_func_methods[] =
+{
+	_DECL_FUNC(_call,  -1, _SC("u")),
+	{0,0}
+};
+#undef _DECL_FUNC
+
+#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),  sq_var_##name,nparams,tycheck}
+static SQRegFunction sq_var_methods[] =
+{
+	_DECL_FUNC(get,  1, _SC("u")),
+	{0,0}
+};
+#undef _DECL_FUNC
+
+struct FFI_type_name {
+    const char* name;
+    ffi_type *type;
+};
+
+static struct FFI_type_name ffi_types_wrap[] = {
+    {"void",    &ffi_type_void},
+    {"schar",   &ffi_type_schar},
+    {"uchar",   &ffi_type_uchar},
+    {"sshort",  &ffi_type_sshort},
+    {"ushort",  &ffi_type_ushort},
+    {"sint",    &ffi_type_sint},
+    {"uint",    &ffi_type_uint},
+    {"slong",   &ffi_type_slong},
+    {"ulong",   &ffi_type_ulong},
+    {"float",   &ffi_type_float},
+    {"double",  &ffi_type_double},
+    {"pointer", &ffi_type_pointer},
+    {NULL}
+};
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static inline void sq_create_delegate_table(HSQUIRRELVM vm, SQRegFunction *methods, HSQOBJECT *handle)
+{
+    sq_newtable(vm);
+    sq_insert_reg_funcs(vm, methods);
+    sq_resetobject(handle);
+    sq_getstackobj(vm, -1, handle);
+    sq_addref(vm, handle);
+}
+
+SQRESULT sqext_register_ffi(HSQUIRRELVM v)
+{
+    int saved_top = sq_gettop(v);
+    //add a namespace ffi
+	sq_pushstring(v,_SC("ffi"),-1);
+    sq_newclass(v,SQFalse);
+    sq_settypetag(v,-1,(void*)FFI_LIB_TAG);
+    sq_insert_reg_funcs(v, sq_ffi_methods);
+
+    int i;
+    for (i = 0; ffi_types_wrap[i].name != 0; i++) {
+        struct FFI_type_name *e = &ffi_types_wrap[i];
+        sq_pushstring(v, e->name, -1);
+        sq_pushuserpointer(v, e->type);
+        sq_newslot(v, -3, SQFalse);
+    }
+    sq_newslot(v,-3,SQTrue); //add ffi table to the root table
+
+
+    sq_create_delegate_table(v, sq_lib_methods, &lib_method_table);
+    sq_create_delegate_table(v, sq_func_methods, &func_method_table);
+    sq_create_delegate_table(v, sq_var_methods, &var_method_table);
+
+    sq_settop(v, saved_top);
+
+    return SQ_OK;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //WITH_FFI

+ 939 - 0
SquiLu-ext/sq_libclang.cpp

@@ -0,0 +1,939 @@
+//#ifdef WITH_LIBCLANG
+
+#include "squirrel.h"
+#include <clang-c/Index.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "sqstdblobimpl.h"
+
+#include "dynamic_library.h"
+
+/*SquiLu
+local libclang_functions = [
+    ["CXCodeCompleteResults *", "clang_codeCompleteAt", @"CXTranslationUnit TU,
+                                            const char *complete_filename,
+                                            unsigned complete_line,
+                                            unsigned complete_column,
+                                            struct CXUnsavedFile *unsaved_files,
+                                            unsigned num_unsaved_files,
+                                            unsigned options"],
+    ["CXDiagnostic", "clang_codeCompleteGetDiagnostic", @"CXCodeCompleteResults *Results,
+                                             unsigned Index"],
+    ["unsigned", "clang_codeCompleteGetNumDiagnostics", "CXCodeCompleteResults *Results"],
+    ["CXIndex", "clang_createIndex", @"int excludeDeclarationsFromPCH,
+                                         int displayDiagnostics"],
+    ["CXTranslationUnit", "clang_createTranslationUnit", @"CXIndex CIdx,
+                                         const char *source_filename,
+                                         int num_clang_command_line_args,
+                                   const char * const *clang_command_line_args,
+                                         unsigned num_unsaved_files,
+                                         struct CXUnsavedFile *unsaved_files"],
+    ["CXCursor", "clang_Cursor_getArgument", "CXCursor C, unsigned i"],
+    ["int", "clang_Cursor_getNumArguments", "CXCursor C"],
+    ["int", "clang_Cursor_isNull", "CXCursor cursor"],
+    ["unsigned", "clang_CXXMethod_isStatic", "CXCursor C"],
+    ["unsigned", "clang_CXXMethod_isVirtual", "CXCursor C"],
+    ["unsigned", "clang_defaultCodeCompleteOptions", "void"],
+    ["unsigned", "clang_defaultDiagnosticDisplayOptions", "void"],
+    ["void", "clang_disposeCodeCompleteResults", "CXCodeCompleteResults *Results"],
+    ["void", "clang_disposeDiagnostic", "CXDiagnostic Diagnostic"],
+    ["void", "clang_disposeIndex", "CXIndex index"],
+    ["void", "clang_disposeString", "CXString *str"],
+    ["unsigned", "clang_equalCursors", "CXCursor, CXCursor"],
+    ["unsigned", "clang_equalTypes", "CXType A, CXType B"],
+    ["CXString", "clang_formatDiagnostic", @"CXDiagnostic Diagnostic,
+                                               unsigned Options"],
+    ["CXType", "clang_getCanonicalType", "CXType T"],
+    ["CXString", "clang_getCompletionAnnotation", @"CXCompletionString completion_string,
+                              unsigned annotation_number"],
+    ["enum CXCompletionChunkKind", "clang_getCompletionChunkKind", @"CXCompletionString completion_string,
+                             unsigned chunk_number"],
+    ["CXString", "clang_getCompletionChunkText", @"CXCompletionString completion_string,
+                             unsigned chunk_number"],
+    ["unsigned", "clang_getCompletionNumAnnotations", "CXCompletionString completion_string"],
+    ["unsigned", "clang_getCompletionPriority", "CXCompletionString completion_string"],
+    ["void", "clang_getCString", "PGconn *conn, Oid lobjId"],
+    ["CXCursor", "clang_getCursorDefinition", "CXCursor"],
+    ["void", "clang_getCursorDisplayName", "PGconn *conn, int fd"],
+    ["CXSourceRange", "clang_getCursorExtent", "CXCursor"],
+    ["CXString", "clang_getCursorKind", "enum CXCursorKind Kind"],
+    ["CXCursor", "clang_getCursorReferenced", "CXCursor"],
+    ["CXType", "clang_getCursorResultType", "CXCursor C"],
+    ["CXCursor", "clang_getCursorSemanticParent", "CXCursor"],
+    ["CXString", "clang_getCursorSpelling", "CXCursor"],
+    ["CXType", "clang_getCursorType", "CXCursor"],
+    ["void", "clang_getCursorUSR", "const char *conninfo"],
+    ["enum CX_CXXAccessSpecifier", "clang_getCXXAccessSpecifier", "CXCursor"],
+    ["CXString", "clang_getDiagnosticCategoryText", "CXDiagnostic"],
+    ["CXDiagnostic", "clang_getDiagnostic", @"CXTranslationUnit Unit,
+                                                unsigned Index"],
+    ["CXString", "clang_getFileName", "CXFile SFile"],
+    ["time_t", "clang_getFileTime", "CXFile SFile"],
+    ["unsigned", "clang_getNumCompletionChunks", "CXCompletionString completion_string"],
+    ["unsigned", "clang_getNumDiagnostics", "CXTranslationUnit Unit"],
+    ["CXType", "clang_getPointeeType", "CXType"],
+    ["CXSourceLocation", "clang_getRangeEnd", "CXSourceRange range"],
+    ["CXSourceLocation", "clang_getRangeStart", "CXSourceRange range"],
+    ["void", "clang_getSpellingLocation", @"CXSourceLocation location,
+                                              CXFile *file,
+                                              unsigned *line,
+                                              unsigned *column,
+                                              unsigned *offset"],
+    ["CXCursor", "clang_getTranslationUnitCursor", "CXTranslationUnit"],
+    ["CXCursor", "clang_getTypeDeclaration", "CXType"],
+    ["CXString", "clang_getTypeKindSpelling", "enum CXTypeKind K"],
+    ["unsigned", "clang_isPODType", "CXType"],
+    ["CXTranslationUnit", "clang_parseTranslationUnit", @"CXIndex CIdx,
+                           const char *source_filename,
+                           const char *const *command_line_args,
+                           int num_command_line_args,
+                           struct CXUnsavedFile *unsaved_files,
+                           unsigned num_unsaved_files,
+                           unsigned options"],
+    ["unsigned", "clang_visitChildren", @"CXCursor parent,
+                                            CXCursorVisitor visitor,
+                                            CXClientData client_data"],
+
+    //next entry should be the last one
+    //to make valid the test made on load_libclang function
+    ["void", "clang_getCursorExtent", "const char *conninfo"],
+];
+
+function write_libclang_functions_declaration(){
+    foreach(k,v in libclang_functions) {
+        putsnl("typedef " + v[0] + " (*" + v[1] + "_t)(" + v[2] + ");");
+        putsnl("static " + v[1] + "_t dl" + v[1] + " = 0;");
+    }
+}
+
+function write_libclang_functions_load(){
+    foreach(k,v in libclang_functions){
+        putsnl("dl" + v[1] + " = (" + v[1] + "_t) libclang.dlsym(\"" + v[1] + "\");");
+        putsnl("if(!dl" + v[1] + ") return false;");
+    }
+}
+SquiLu*/
+
+static DynamicLibrary libclang;
+
+//@write_libclang_functions_declaration();
+// generated-code:begin
+typedef CXCodeCompleteResults * (*clang_codeCompleteAt_t)(CXTranslationUnit TU,
+                                            const char *complete_filename,
+                                            unsigned complete_line,
+                                            unsigned complete_column,
+                                            struct CXUnsavedFile *unsaved_files,
+                                            unsigned num_unsaved_files,
+                                            unsigned options);
+static clang_codeCompleteAt_t dlclang_codeCompleteAt = 0;
+typedef CXDiagnostic (*clang_codeCompleteGetDiagnostic_t)(CXCodeCompleteResults *Results,
+                                             unsigned Index);
+static clang_codeCompleteGetDiagnostic_t dlclang_codeCompleteGetDiagnostic = 0;
+typedef unsigned (*clang_codeCompleteGetNumDiagnostics_t)(CXCodeCompleteResults *Results);
+static clang_codeCompleteGetNumDiagnostics_t dlclang_codeCompleteGetNumDiagnostics = 0;
+typedef CXIndex (*clang_createIndex_t)(int excludeDeclarationsFromPCH,
+                                         int displayDiagnostics);
+static clang_createIndex_t dlclang_createIndex = 0;
+typedef CXTranslationUnit (*clang_createTranslationUnit_t)(CXIndex CIdx,
+                                         const char *source_filename,
+                                         int num_clang_command_line_args,
+                                   const char * const *clang_command_line_args,
+                                         unsigned num_unsaved_files,
+                                         struct CXUnsavedFile *unsaved_files);
+static clang_createTranslationUnit_t dlclang_createTranslationUnit = 0;
+typedef CXCursor (*clang_Cursor_getArgument_t)(CXCursor C, unsigned i);
+static clang_Cursor_getArgument_t dlclang_Cursor_getArgument = 0;
+typedef int (*clang_Cursor_getNumArguments_t)(CXCursor C);
+static clang_Cursor_getNumArguments_t dlclang_Cursor_getNumArguments = 0;
+typedef int (*clang_Cursor_isNull_t)(CXCursor cursor);
+static clang_Cursor_isNull_t dlclang_Cursor_isNull = 0;
+typedef unsigned (*clang_CXXMethod_isStatic_t)(CXCursor C);
+static clang_CXXMethod_isStatic_t dlclang_CXXMethod_isStatic = 0;
+typedef unsigned (*clang_CXXMethod_isVirtual_t)(CXCursor C);
+static clang_CXXMethod_isVirtual_t dlclang_CXXMethod_isVirtual = 0;
+typedef unsigned (*clang_defaultCodeCompleteOptions_t)(void);
+static clang_defaultCodeCompleteOptions_t dlclang_defaultCodeCompleteOptions = 0;
+typedef unsigned (*clang_defaultDiagnosticDisplayOptions_t)(void);
+static clang_defaultDiagnosticDisplayOptions_t dlclang_defaultDiagnosticDisplayOptions = 0;
+typedef void (*clang_disposeCodeCompleteResults_t)(CXCodeCompleteResults *Results);
+static clang_disposeCodeCompleteResults_t dlclang_disposeCodeCompleteResults = 0;
+typedef void (*clang_disposeDiagnostic_t)(CXDiagnostic Diagnostic);
+static clang_disposeDiagnostic_t dlclang_disposeDiagnostic = 0;
+typedef void (*clang_disposeIndex_t)(CXIndex index);
+static clang_disposeIndex_t dlclang_disposeIndex = 0;
+typedef void (*clang_disposeString_t)(CXString *str);
+static clang_disposeString_t dlclang_disposeString = 0;
+typedef unsigned (*clang_equalCursors_t)(CXCursor, CXCursor);
+static clang_equalCursors_t dlclang_equalCursors = 0;
+typedef unsigned (*clang_equalTypes_t)(CXType A, CXType B);
+static clang_equalTypes_t dlclang_equalTypes = 0;
+typedef CXString (*clang_formatDiagnostic_t)(CXDiagnostic Diagnostic,
+                                               unsigned Options);
+static clang_formatDiagnostic_t dlclang_formatDiagnostic = 0;
+typedef CXType (*clang_getCanonicalType_t)(CXType T);
+static clang_getCanonicalType_t dlclang_getCanonicalType = 0;
+typedef CXString (*clang_getCompletionAnnotation_t)(CXCompletionString completion_string,
+                              unsigned annotation_number);
+static clang_getCompletionAnnotation_t dlclang_getCompletionAnnotation = 0;
+typedef enum CXCompletionChunkKind (*clang_getCompletionChunkKind_t)(CXCompletionString completion_string,
+                             unsigned chunk_number);
+static clang_getCompletionChunkKind_t dlclang_getCompletionChunkKind = 0;
+typedef CXString (*clang_getCompletionChunkText_t)(CXCompletionString completion_string,
+                             unsigned chunk_number);
+static clang_getCompletionChunkText_t dlclang_getCompletionChunkText = 0;
+typedef unsigned (*clang_getCompletionNumAnnotations_t)(CXCompletionString completion_string);
+static clang_getCompletionNumAnnotations_t dlclang_getCompletionNumAnnotations = 0;
+typedef unsigned (*clang_getCompletionPriority_t)(CXCompletionString completion_string);
+static clang_getCompletionPriority_t dlclang_getCompletionPriority = 0;
+typedef void (*clang_getCString_t)(PGconn *conn, Oid lobjId);
+static clang_getCString_t dlclang_getCString = 0;
+typedef CXCursor (*clang_getCursorDefinition_t)(CXCursor);
+static clang_getCursorDefinition_t dlclang_getCursorDefinition = 0;
+typedef void (*clang_getCursorDisplayName_t)(PGconn *conn, int fd);
+static clang_getCursorDisplayName_t dlclang_getCursorDisplayName = 0;
+typedef CXSourceRange (*clang_getCursorExtent_t)(CXCursor);
+static clang_getCursorExtent_t dlclang_getCursorExtent = 0;
+typedef CXString (*clang_getCursorKind_t)(enum CXCursorKind Kind);
+static clang_getCursorKind_t dlclang_getCursorKind = 0;
+typedef CXCursor (*clang_getCursorReferenced_t)(CXCursor);
+static clang_getCursorReferenced_t dlclang_getCursorReferenced = 0;
+typedef CXType (*clang_getCursorResultType_t)(CXCursor C);
+static clang_getCursorResultType_t dlclang_getCursorResultType = 0;
+typedef CXCursor (*clang_getCursorSemanticParent_t)(CXCursor);
+static clang_getCursorSemanticParent_t dlclang_getCursorSemanticParent = 0;
+typedef CXString (*clang_getCursorSpelling_t)(CXCursor);
+static clang_getCursorSpelling_t dlclang_getCursorSpelling = 0;
+typedef CXType (*clang_getCursorType_t)(CXCursor);
+static clang_getCursorType_t dlclang_getCursorType = 0;
+typedef void (*clang_getCursorUSR_t)(const char *conninfo);
+static clang_getCursorUSR_t dlclang_getCursorUSR = 0;
+typedef enum CX_CXXAccessSpecifier (*clang_getCXXAccessSpecifier_t)(CXCursor);
+static clang_getCXXAccessSpecifier_t dlclang_getCXXAccessSpecifier = 0;
+typedef CXString (*clang_getDiagnosticCategoryText_t)(CXDiagnostic);
+static clang_getDiagnosticCategoryText_t dlclang_getDiagnosticCategoryText = 0;
+typedef CXDiagnostic (*clang_getDiagnostic_t)(CXTranslationUnit Unit,
+                                                unsigned Index);
+static clang_getDiagnostic_t dlclang_getDiagnostic = 0;
+typedef CXString (*clang_getFileName_t)(CXFile SFile);
+static clang_getFileName_t dlclang_getFileName = 0;
+typedef time_t (*clang_getFileTime_t)(CXFile SFile);
+static clang_getFileTime_t dlclang_getFileTime = 0;
+typedef unsigned (*clang_getNumCompletionChunks_t)(CXCompletionString completion_string);
+static clang_getNumCompletionChunks_t dlclang_getNumCompletionChunks = 0;
+typedef unsigned (*clang_getNumDiagnostics_t)(CXTranslationUnit Unit);
+static clang_getNumDiagnostics_t dlclang_getNumDiagnostics = 0;
+typedef CXType (*clang_getPointeeType_t)(CXType);
+static clang_getPointeeType_t dlclang_getPointeeType = 0;
+typedef CXSourceLocation (*clang_getRangeEnd_t)(CXSourceRange range);
+static clang_getRangeEnd_t dlclang_getRangeEnd = 0;
+typedef CXSourceLocation (*clang_getRangeStart_t)(CXSourceRange range);
+static clang_getRangeStart_t dlclang_getRangeStart = 0;
+typedef void (*clang_getSpellingLocation_t)(CXSourceLocation location,
+                                              CXFile *file,
+                                              unsigned *line,
+                                              unsigned *column,
+                                              unsigned *offset);
+static clang_getSpellingLocation_t dlclang_getSpellingLocation = 0;
+typedef CXCursor (*clang_getTranslationUnitCursor_t)(CXTranslationUnit);
+static clang_getTranslationUnitCursor_t dlclang_getTranslationUnitCursor = 0;
+typedef CXCursor (*clang_getTypeDeclaration_t)(CXType);
+static clang_getTypeDeclaration_t dlclang_getTypeDeclaration = 0;
+typedef CXString (*clang_getTypeKindSpelling_t)(enum CXTypeKind K);
+static clang_getTypeKindSpelling_t dlclang_getTypeKindSpelling = 0;
+typedef unsigned (*clang_isPODType_t)(CXType);
+static clang_isPODType_t dlclang_isPODType = 0;
+typedef CXTranslationUnit (*clang_parseTranslationUnit_t)(CXIndex CIdx,
+                           const char *source_filename,
+                           const char *const *command_line_args,
+                           int num_command_line_args,
+                           struct CXUnsavedFile *unsaved_files,
+                           unsigned num_unsaved_files,
+                           unsigned options);
+static clang_parseTranslationUnit_t dlclang_parseTranslationUnit = 0;
+typedef unsigned (*clang_visitChildren_t)(CXCursor parent,
+                                            CXCursorVisitor visitor,
+                                            CXClientData client_data);
+static clang_visitChildren_t dlclang_visitChildren = 0;
+typedef void (*clang_getCursorExtent_t)(const char *conninfo);
+static clang_getCursorExtent_t dlclang_getCursorExtent = 0;
+// generated-code:end
+#ifdef WIN32
+#define libclang_NAME "libclang.dll"
+#else
+#define libclang_NAME "libclang.so"
+#endif
+
+static bool load_libclang()
+{
+    if(dlPQconnectdb) return true;
+    if(libclang.open(libclang_NAME))
+    {
+        //@write_libclang_functions_load();
+// generated-code:begin
+dlclang_codeCompleteAt = (clang_codeCompleteAt_t) libclang.dlsym("clang_codeCompleteAt");
+if(!dlclang_codeCompleteAt) return false;
+dlclang_codeCompleteGetDiagnostic = (clang_codeCompleteGetDiagnostic_t) libclang.dlsym("clang_codeCompleteGetDiagnostic");
+if(!dlclang_codeCompleteGetDiagnostic) return false;
+dlclang_codeCompleteGetNumDiagnostics = (clang_codeCompleteGetNumDiagnostics_t) libclang.dlsym("clang_codeCompleteGetNumDiagnostics");
+if(!dlclang_codeCompleteGetNumDiagnostics) return false;
+dlclang_createIndex = (clang_createIndex_t) libclang.dlsym("clang_createIndex");
+if(!dlclang_createIndex) return false;
+dlclang_createTranslationUnit = (clang_createTranslationUnit_t) libclang.dlsym("clang_createTranslationUnit");
+if(!dlclang_createTranslationUnit) return false;
+dlclang_Cursor_getArgument = (clang_Cursor_getArgument_t) libclang.dlsym("clang_Cursor_getArgument");
+if(!dlclang_Cursor_getArgument) return false;
+dlclang_Cursor_getNumArguments = (clang_Cursor_getNumArguments_t) libclang.dlsym("clang_Cursor_getNumArguments");
+if(!dlclang_Cursor_getNumArguments) return false;
+dlclang_Cursor_isNull = (clang_Cursor_isNull_t) libclang.dlsym("clang_Cursor_isNull");
+if(!dlclang_Cursor_isNull) return false;
+dlclang_CXXMethod_isStatic = (clang_CXXMethod_isStatic_t) libclang.dlsym("clang_CXXMethod_isStatic");
+if(!dlclang_CXXMethod_isStatic) return false;
+dlclang_CXXMethod_isVirtual = (clang_CXXMethod_isVirtual_t) libclang.dlsym("clang_CXXMethod_isVirtual");
+if(!dlclang_CXXMethod_isVirtual) return false;
+dlclang_defaultCodeCompleteOptions = (clang_defaultCodeCompleteOptions_t) libclang.dlsym("clang_defaultCodeCompleteOptions");
+if(!dlclang_defaultCodeCompleteOptions) return false;
+dlclang_defaultDiagnosticDisplayOptions = (clang_defaultDiagnosticDisplayOptions_t) libclang.dlsym("clang_defaultDiagnosticDisplayOptions");
+if(!dlclang_defaultDiagnosticDisplayOptions) return false;
+dlclang_disposeCodeCompleteResults = (clang_disposeCodeCompleteResults_t) libclang.dlsym("clang_disposeCodeCompleteResults");
+if(!dlclang_disposeCodeCompleteResults) return false;
+dlclang_disposeDiagnostic = (clang_disposeDiagnostic_t) libclang.dlsym("clang_disposeDiagnostic");
+if(!dlclang_disposeDiagnostic) return false;
+dlclang_disposeIndex = (clang_disposeIndex_t) libclang.dlsym("clang_disposeIndex");
+if(!dlclang_disposeIndex) return false;
+dlclang_disposeString = (clang_disposeString_t) libclang.dlsym("clang_disposeString");
+if(!dlclang_disposeString) return false;
+dlclang_equalCursors = (clang_equalCursors_t) libclang.dlsym("clang_equalCursors");
+if(!dlclang_equalCursors) return false;
+dlclang_equalTypes = (clang_equalTypes_t) libclang.dlsym("clang_equalTypes");
+if(!dlclang_equalTypes) return false;
+dlclang_formatDiagnostic = (clang_formatDiagnostic_t) libclang.dlsym("clang_formatDiagnostic");
+if(!dlclang_formatDiagnostic) return false;
+dlclang_getCanonicalType = (clang_getCanonicalType_t) libclang.dlsym("clang_getCanonicalType");
+if(!dlclang_getCanonicalType) return false;
+dlclang_getCompletionAnnotation = (clang_getCompletionAnnotation_t) libclang.dlsym("clang_getCompletionAnnotation");
+if(!dlclang_getCompletionAnnotation) return false;
+dlclang_getCompletionChunkKind = (clang_getCompletionChunkKind_t) libclang.dlsym("clang_getCompletionChunkKind");
+if(!dlclang_getCompletionChunkKind) return false;
+dlclang_getCompletionChunkText = (clang_getCompletionChunkText_t) libclang.dlsym("clang_getCompletionChunkText");
+if(!dlclang_getCompletionChunkText) return false;
+dlclang_getCompletionNumAnnotations = (clang_getCompletionNumAnnotations_t) libclang.dlsym("clang_getCompletionNumAnnotations");
+if(!dlclang_getCompletionNumAnnotations) return false;
+dlclang_getCompletionPriority = (clang_getCompletionPriority_t) libclang.dlsym("clang_getCompletionPriority");
+if(!dlclang_getCompletionPriority) return false;
+dlclang_getCString = (clang_getCString_t) libclang.dlsym("clang_getCString");
+if(!dlclang_getCString) return false;
+dlclang_getCursorDefinition = (clang_getCursorDefinition_t) libclang.dlsym("clang_getCursorDefinition");
+if(!dlclang_getCursorDefinition) return false;
+dlclang_getCursorDisplayName = (clang_getCursorDisplayName_t) libclang.dlsym("clang_getCursorDisplayName");
+if(!dlclang_getCursorDisplayName) return false;
+dlclang_getCursorExtent = (clang_getCursorExtent_t) libclang.dlsym("clang_getCursorExtent");
+if(!dlclang_getCursorExtent) return false;
+dlclang_getCursorKind = (clang_getCursorKind_t) libclang.dlsym("clang_getCursorKind");
+if(!dlclang_getCursorKind) return false;
+dlclang_getCursorReferenced = (clang_getCursorReferenced_t) libclang.dlsym("clang_getCursorReferenced");
+if(!dlclang_getCursorReferenced) return false;
+dlclang_getCursorResultType = (clang_getCursorResultType_t) libclang.dlsym("clang_getCursorResultType");
+if(!dlclang_getCursorResultType) return false;
+dlclang_getCursorSemanticParent = (clang_getCursorSemanticParent_t) libclang.dlsym("clang_getCursorSemanticParent");
+if(!dlclang_getCursorSemanticParent) return false;
+dlclang_getCursorSpelling = (clang_getCursorSpelling_t) libclang.dlsym("clang_getCursorSpelling");
+if(!dlclang_getCursorSpelling) return false;
+dlclang_getCursorType = (clang_getCursorType_t) libclang.dlsym("clang_getCursorType");
+if(!dlclang_getCursorType) return false;
+dlclang_getCursorUSR = (clang_getCursorUSR_t) libclang.dlsym("clang_getCursorUSR");
+if(!dlclang_getCursorUSR) return false;
+dlclang_getCXXAccessSpecifier = (clang_getCXXAccessSpecifier_t) libclang.dlsym("clang_getCXXAccessSpecifier");
+if(!dlclang_getCXXAccessSpecifier) return false;
+dlclang_getDiagnosticCategoryText = (clang_getDiagnosticCategoryText_t) libclang.dlsym("clang_getDiagnosticCategoryText");
+if(!dlclang_getDiagnosticCategoryText) return false;
+dlclang_getDiagnostic = (clang_getDiagnostic_t) libclang.dlsym("clang_getDiagnostic");
+if(!dlclang_getDiagnostic) return false;
+dlclang_getFileName = (clang_getFileName_t) libclang.dlsym("clang_getFileName");
+if(!dlclang_getFileName) return false;
+dlclang_getFileTime = (clang_getFileTime_t) libclang.dlsym("clang_getFileTime");
+if(!dlclang_getFileTime) return false;
+dlclang_getNumCompletionChunks = (clang_getNumCompletionChunks_t) libclang.dlsym("clang_getNumCompletionChunks");
+if(!dlclang_getNumCompletionChunks) return false;
+dlclang_getNumDiagnostics = (clang_getNumDiagnostics_t) libclang.dlsym("clang_getNumDiagnostics");
+if(!dlclang_getNumDiagnostics) return false;
+dlclang_getPointeeType = (clang_getPointeeType_t) libclang.dlsym("clang_getPointeeType");
+if(!dlclang_getPointeeType) return false;
+dlclang_getRangeEnd = (clang_getRangeEnd_t) libclang.dlsym("clang_getRangeEnd");
+if(!dlclang_getRangeEnd) return false;
+dlclang_getRangeStart = (clang_getRangeStart_t) libclang.dlsym("clang_getRangeStart");
+if(!dlclang_getRangeStart) return false;
+dlclang_getSpellingLocation = (clang_getSpellingLocation_t) libclang.dlsym("clang_getSpellingLocation");
+if(!dlclang_getSpellingLocation) return false;
+dlclang_getTranslationUnitCursor = (clang_getTranslationUnitCursor_t) libclang.dlsym("clang_getTranslationUnitCursor");
+if(!dlclang_getTranslationUnitCursor) return false;
+dlclang_getTypeDeclaration = (clang_getTypeDeclaration_t) libclang.dlsym("clang_getTypeDeclaration");
+if(!dlclang_getTypeDeclaration) return false;
+dlclang_getTypeKindSpelling = (clang_getTypeKindSpelling_t) libclang.dlsym("clang_getTypeKindSpelling");
+if(!dlclang_getTypeKindSpelling) return false;
+dlclang_isPODType = (clang_isPODType_t) libclang.dlsym("clang_isPODType");
+if(!dlclang_isPODType) return false;
+dlclang_parseTranslationUnit = (clang_parseTranslationUnit_t) libclang.dlsym("clang_parseTranslationUnit");
+if(!dlclang_parseTranslationUnit) return false;
+dlclang_visitChildren = (clang_visitChildren_t) libclang.dlsym("clang_visitChildren");
+if(!dlclang_visitChildren) return false;
+dlclang_getCursorExtent = (clang_getCursorExtent_t) libclang.dlsym("clang_getCursorExtent");
+if(!dlclang_getCursorExtent) return false;
+// generated-code:end
+
+        return true;
+    }
+    return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+static const SQChar *PostgreSQL_TAG = _SC("PostgreSQL");
+
+static SQRESULT get_pgsql_instance(HSQUIRRELVM v, SQInteger idx, PGconn **self){
+    SQRESULT _rc_;
+	if((_rc_ = sq_getinstanceup(v,idx,(SQUserPointer*)self,(void*)PostgreSQL_TAG)) < 0) return _rc_;
+	if(!*self) return sq_throwerror(v, _SC("database is closed"));
+	return _rc_;
+}
+
+#define GET_pgsql_INSTANCE_AT(idx) \
+	PGconn *self=NULL; \
+	if((_rc_ = get_pgsql_instance(v,idx,&self)) < 0) return _rc_;
+
+#define GET_pgsql_INSTANCE() GET_pgsql_INSTANCE_AT(1)
+
+static const SQChar *PostgreSQL_Result_TAG = _SC("PostgreSQL_Result");
+static const SQChar *_curr_row_key = _SC("_curr_row");
+
+static SQRESULT get_pgsql_result_instance(HSQUIRRELVM v, SQInteger idx, PGresult **self){
+    SQRESULT _rc_;
+	if((_rc_ = sq_getinstanceup(v,idx,(SQUserPointer*)self,(void*)PostgreSQL_Result_TAG)) < 0) return _rc_;
+	if(!*self) return sq_throwerror(v, _SC("PGresult is closed"));
+	return _rc_;
+}
+
+#define GET_pgsql_result_INSTANCE_AT(idx) \
+	PGresult *self=NULL; \
+	if((_rc_ = get_pgsql_result_instance(v,idx,&self)) < 0) return _rc_;
+
+#define GET_pgsql_result_INSTANCE() GET_pgsql_result_INSTANCE_AT(1)
+
+static SQRESULT sq_pgsql_result_releasehook(SQUserPointer p, SQInteger size, HSQUIRRELVM v)
+{
+	PGresult *self = ((PGresult *)p);
+	if (self) dlPQclear(self);
+	return 0;
+}
+
+static SQRESULT sq_pgsql_result_close(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_pgsql_result_INSTANCE();
+	dlPQclear(self);
+    sq_setinstanceup(v, 1, 0); //next calls will fail with "Pgresult is closed"
+	return 0;
+}
+
+static SQRESULT sq_pgsql_result_col_count(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_pgsql_result_INSTANCE();
+	sq_pushinteger(v, dlPQnfields(self));
+	return 1;
+}
+
+static SQRESULT sq_pgsql_result_row_count(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_pgsql_result_INSTANCE();
+	sq_pushinteger(v, dlPQntuples(self));
+	return 1;
+}
+
+static SQRESULT sq_pgsql_result_col_name(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_pgsql_result_INSTANCE();
+	SQ_GET_INTEGER(v, 2, col);
+	sq_pushstring(v, dlPQfname(self, col), -1);
+	return 1;
+}
+
+static SQRESULT sq_pgsql_result_col_index(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_pgsql_result_INSTANCE();
+	SQ_GET_STRING(v, 2, name);
+	sq_pushinteger(v, dlPQfnumber(self, name));
+	return 1;
+}
+
+static SQRESULT sq_pgsql_result_eof(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_pgsql_result_INSTANCE();
+    sq_pushstring(v, _curr_row_key, -1);
+    if(sq_get(v, 1) == SQ_OK){
+        SQ_GET_INTEGER(v, -1, curr_row);
+        sq_pushbool(v, curr_row < dlPQntuples(self));
+    }
+	else sq_pushbool(v, SQTrue);
+	return 1;
+}
+
+static SQRESULT sq_pgsql_result_next_row(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_pgsql_result_INSTANCE();
+    sq_pushstring(v, _curr_row_key, -1);
+    sq_push(v, -1); //make a copy
+    if(sq_get(v, 1) == SQ_OK){
+        SQ_GET_INTEGER(v, -1, curr_row);
+        if(++curr_row < dlPQntuples(self)){
+            sq_poptop(v);
+            sq_pushinteger(v, curr_row);
+            sq_set(v, 1);
+            sq_pushbool(v, SQTrue);
+            return 1;
+        }
+    }
+	sq_pushbool(v, SQFalse);
+	return 1;
+}
+
+static SQRESULT sq_pgsql_result_col_value(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_pgsql_result_INSTANCE();
+	SQObjectType ptype = sq_gettype(v, 2);
+	int col = -1;
+	if(ptype == OT_STRING){
+	    SQ_GET_STRING(v, 2, col_name);
+	    col = dlPQfnumber(self, col_name);
+	}
+	else
+	{
+	    SQ_GET_INTEGER(v, 2, idx);
+	    col = idx;
+	}
+	if(col < 0) return sq_throwerror(v, _SC("invalid col index/name"));
+
+    sq_pushstring(v, _curr_row_key, -1);
+    if(sq_get(v, 1) == SQ_OK){
+        SQ_GET_INTEGER(v, -1, curr_row);
+        if(curr_row < dlPQntuples(self)){
+            sq_pushstring(v, dlPQgetvalue(self, curr_row, col), -1);
+            return 1;
+        }
+    }
+	return SQ_ERROR;
+}
+
+static SQRESULT sq_pgsql_result_row_as_array(HSQUIRRELVM v){
+	SQ_FUNC_VARS(v);
+	GET_pgsql_result_INSTANCE();
+	SQ_OPT_INTEGER(v, 2, row, -1);
+    if(row < 0){
+        sq_pushstring(v, _curr_row_key, -1);
+        if(sq_get(v, 1) == SQ_OK){
+            sq_getinteger(v, -1, &row);
+        }
+    }
+    int row_count = dlPQntuples(self);
+    if(row < 0 || row >= row_count) return sq_throwerror(v, _SC("invalid row (%d)"), row);
+
+    int col_count = dlPQnfields(self);
+    sq_newarray(v, col_count);
+    for(int i=0; i < col_count; ++i){
+        sq_pushinteger(v, i);
+        sq_pushstring(v, dlPQgetvalue(self, row, i), -1);
+        sq_rawset(v, -3);
+    }
+	return 1;
+}
+
+#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),  sq_pgsql_result_##name,nparams,tycheck}
+static SQRegFunction sq_pgsql_result_methods[] =
+{
+	_DECL_FUNC(close,  1, _SC("x")),
+	_DECL_FUNC(eof,  1, _SC("x")),
+	_DECL_FUNC(next_row,  1, _SC("x")),
+	_DECL_FUNC(col_count,  1, _SC("x")),
+	_DECL_FUNC(row_count,  1, _SC("x")),
+	_DECL_FUNC(col_name,  2, _SC("xi")),
+	_DECL_FUNC(col_index,  2, _SC("xs")),
+	_DECL_FUNC(col_value,  2, _SC("x i|s")),
+	_DECL_FUNC(row_as_array,  -1, _SC("xi")),
+	{0,0}
+};
+#undef _DECL_FUNC
+
+struct PgSqlStatement {
+    PGconn *db;
+    PGresult *result;
+    char name[64];
+};
+
+static const SQChar *PostgreSQL_Statement_TAG = _SC("PostgreSQL_Statement");
+
+static SQRESULT get_pgsql_statement_instance(HSQUIRRELVM v, SQInteger idx, PgSqlStatement **self){
+    SQRESULT _rc_;
+	if((_rc_ = sq_getinstanceup(v,idx,(SQUserPointer*)self,(void*)PostgreSQL_Statement_TAG)) < 0) return _rc_;
+	if(!*self) return sq_throwerror(v, _SC("PGstatement is closed"));
+	return _rc_;
+}
+
+#define GET_pgsql_statement_INSTANCE_AT(idx) \
+	PgSqlStatement *self=NULL; \
+	if((_rc_ = get_pgsql_statement_instance(v,idx,&self)) < 0) return _rc_;
+
+#define GET_pgsql_statement_INSTANCE() GET_pgsql_statement_INSTANCE_AT(1)
+
+static SQRESULT sq_pgsql_statement_releasehook(SQUserPointer p, SQInteger size, HSQUIRRELVM v)
+{
+	PgSqlStatement *self = ((PgSqlStatement *)p);
+	if (self && self->result){
+        char sql[128];
+        snprintf(sql, sizeof(sql), "DEALLOCATE '%s'", self->name);
+        PGresult *qres = dlPQexec(self->db, sql);
+        bool is_ok = dlPQresultStatus(qres) != PGRES_BAD_RESPONSE;
+        dlPQclear(qres);
+        if(is_ok) dlPQclear(self->result);
+        sq_free(self, sizeof(PgSqlStatement));
+	}
+	return 0;
+}
+
+static SQRESULT sq_pgsql_statement_close(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_pgsql_statement_INSTANCE();
+	sq_pgsql_statement_releasehook(self, 0, v);
+    sq_setinstanceup(v, 1, 0); //next calls will fail with "Pgstatement is closed"
+	return 0;
+}
+
+
+#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),  sq_pgsql_statement_##name,nparams,tycheck}
+static SQRegFunction sq_pgsql_statement_methods[] =
+{
+	_DECL_FUNC(close,  1, _SC("x")),
+	{0,0}
+};
+#undef _DECL_FUNC
+
+static SQRESULT sq_pgsql_releasehook(SQUserPointer p, SQInteger size, HSQUIRRELVM v)
+{
+	PGconn *self = ((PGconn *)p);
+	if (self) dlPQfinish(self);
+	return 0;
+}
+
+static SQRESULT sq_pgsql_constructor(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    SQ_GET_STRING(v, 2, szConnInfo);
+    PGconn *self=0;
+
+    if(load_libclang())
+    {
+        self = dlPQconnectdb(szConnInfo);
+        if (dlPQstatus(self) == CONNECTION_BAD) return sq_throwerror(v, _SC("Failed to connect ot database !"));
+    }
+    else return sq_throwerror(v, _SC("Failed to load libclang !"));
+
+    sq_setinstanceup(v, 1, self);
+    sq_setreleasehook(v,1, sq_pgsql_releasehook);
+
+    //save a weakref to allow statement return it's db
+    sq_pushuserpointer(v, self);
+    sq_weakref(v, 1);
+    sq_setonregistrytable(v);
+
+    return 1;
+}
+
+static SQRESULT sq_pgsql_close(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_pgsql_INSTANCE();
+	dlPQfinish(self);
+    sq_setinstanceup(v, 1, 0); //next calls will fail with "database is closed"
+	return 0;
+}
+
+static SQRESULT sq_pgsql_exec_dml(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_pgsql_INSTANCE();
+    SQ_GET_STRING(v, 2, szSQL);
+     int result = 0;
+
+    PGresult *qres = dlPQexec(self, szSQL);
+
+    bool is_ok = dlPQresultStatus(qres) == PGRES_COMMAND_OK;
+
+    if (is_ok) result = atoi(dlPQcmdTuples(qres));
+    dlPQclear(qres);
+
+    if (!is_ok) return sq_throwerror(v, dlPQerrorMessage(self));
+
+    sq_pushinteger(v, result);
+	return 1;
+}
+
+static SQRESULT sq_pgsql_exec_scalar(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_pgsql_INSTANCE();
+    SQ_GET_STRING(v, 2, szSQL);
+     int result = 0;
+
+    PGresult *qres = dlPQexec(self, szSQL);
+
+    bool is_ok = (dlPQresultStatus(qres) == PGRES_TUPLES_OK) &&
+                 (dlPQntuples(qres) == 1) && (dlPQnfields(qres) > 0);
+
+    if (is_ok) result = atoi(dlPQgetvalue(qres, 0, 0));
+    dlPQclear(qres);
+
+    if (!is_ok) return sq_throwerror(v, dlPQerrorMessage(self));
+
+    sq_pushinteger(v, result);
+	return 1;
+}
+
+static SQRESULT sq_pgsql_exec_query(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_pgsql_INSTANCE();
+    SQ_GET_STRING(v, 2, szSQL);
+
+    PGresult *qres = dlPQexec(self, szSQL);
+
+    if(dlPQresultStatus(qres) == PGRES_TUPLES_OK){
+        sq_pushroottable(v);
+        sq_pushstring(v, PostgreSQL_Result_TAG, -1);
+        if(sq_get(v, -2) == SQ_OK){
+            if(sq_createinstance(v, -1) == SQ_OK){
+                sq_setinstanceup(v, -1, qres);
+                sq_setreleasehook(v, -1, sq_pgsql_result_releasehook);
+                sq_pushstring(v, _curr_row_key, -1);
+                sq_pushinteger(v, -1);
+                sq_set(v, -3);
+                return 1;
+            }
+        }
+    }
+    return sq_throwerror(v, dlPQerrorMessage(self));
+}
+
+static SQRESULT sq_pgsql_prepare(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_pgsql_INSTANCE();
+    SQ_GET_STRING(v, 2, szSQL);
+
+    PgSqlStatement *stmt = (PgSqlStatement*)sq_malloc(sizeof(PgSqlStatement));
+    stmt->db = self;
+    snprintf(stmt->name, sizeof(stmt->name), "sq_pg_preared_stmt_%p", stmt);
+
+    stmt->result = dlPQprepare(self, stmt->name, szSQL, 0, NULL);
+
+    if(dlPQresultStatus(stmt->result) == PGRES_COMMAND_OK){
+        sq_pushroottable(v);
+        sq_pushstring(v, PostgreSQL_Statement_TAG, -1);
+        if(sq_get(v, -2) == SQ_OK){
+            if(sq_createinstance(v, -1) == SQ_OK){
+                sq_setinstanceup(v, -1, stmt);
+                sq_setreleasehook(v, -1, sq_pgsql_statement_releasehook);
+                return 1;
+            }
+        }
+    }
+    sq_free(stmt, sizeof(PgSqlStatement));
+    return sq_throwerror(v, dlPQerrorMessage(self));
+}
+
+static SQRESULT sq_pgsql_error_message(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_pgsql_INSTANCE();
+	sq_pushstring(v, dlPQerrorMessage(self), -1);
+	return 1;
+}
+
+static SQRESULT sq_pgsql_version(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_pgsql_INSTANCE();
+	sq_pushinteger(v, dlPQserverVersion(self));
+	return 1;
+}
+
+static int
+ inv_read =  0x40000,
+ inv_write = 0x20000,
+ invalidoid = 0,
+ inv_seek_set = 0,
+ inv_seek_curr = 1,
+ inv_seek_end = 2;
+
+static SQRESULT sq_pgsql_get_blob_field(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_pgsql_INSTANCE();
+	SQ_GET_INTEGER(v, 2, oid);
+    //begin_recursive_transaction();
+    char *result = 0;
+	int ofd = dllo_open(self, oid, inv_read);
+	if(ofd >= 0){
+		int blobSize = dllo_lseek(self, ofd, 0, inv_seek_end);
+		dllo_lseek(self, ofd, 0, inv_seek_set);
+	    SQBlob blob(blobSize);
+		result = (char*)blob.GetBuf();
+		int numRead = 0;
+		while(blobSize > 0){
+		 	int i = dllo_read(self, ofd, result+numRead, blobSize);
+			numRead += i;
+			blobSize -= i;
+		}
+		dllo_close(self, oid);
+		sq_pushstring(v, (const SQChar*)blob.GetBuf(), blob.Len());
+	}
+	//commit_recursive_transaction();
+	if(!result) sq_pushnull(v);
+	return 1;
+}
+
+static SQRESULT sq_pgsql_insert_blob_field(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_pgsql_INSTANCE();
+    int result = 0;
+    SQ_GET_STRING(v, 2, blob);
+    SQ_GET_BOOL(v, 3, isFileName);
+	if(isFileName){
+		result = dllo_import(self, blob);
+	} else {
+		result = dllo_creat(self, inv_write);
+		if(result){
+			int ofd = dllo_open(self, result, inv_write);
+			if (ofd >= 0){
+				int i = blob_size;
+				const char *blopPtr = (const char *)blob;
+				int numWriten = 0;
+				while(i > 0){
+				 	int i2 = dllo_write(self, ofd, blopPtr+numWriten, i);
+					numWriten += i2;
+					i -= i2;
+				}
+				dllo_close(self, ofd);
+			}
+			else return sq_throwerror(v, _SC("Failed to insert blob !"));
+		}
+	}
+	if(!result) sq_pushnull(v);
+	return 1;
+}
+
+static SQRESULT sq_pgsql_update_blob_field(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_pgsql_INSTANCE();
+    SQ_GET_INTEGER(v, 2, oid);
+    SQ_GET_STRING(v, 3, blob);
+    SQ_GET_BOOL(v, 4, isFileName);
+
+    int result_oid = 0;
+    int result_error = SQ_OK;
+	int loid = dllo_creat(self, inv_write);
+	int ofd = dllo_open(self, loid, inv_write);
+	if(ofd >= 0){
+		dllo_unlink(self, oid);
+		result_oid = loid;
+		if(isFileName)
+		{
+			char buf[2048];
+			FILE *fp = fopen(blob, "rb");
+			if(!fp) {
+			    sq_throwerror(v, _SC("Failed to update blob from file !"));
+			    result_error = SQ_ERROR;
+			}
+			else
+			{
+                char *charPtr = buf;
+                int numRead;
+                do{
+                    numRead = fread(buf, 1, sizeof(buf), fp);
+                    int numWriten = dllo_write(self, ofd, charPtr, numRead);
+                    if (numWriten != numRead) {
+                        sq_throwerror(v, _SC("Failed to update blob from file !"));
+                        result_error = SQ_ERROR;
+                        break;
+                    }
+                } while (numRead == 0);
+                fclose(fp);
+			}
+		}else{
+			int i = blob_size;
+            const char *blopPtr = (const char *)blob;
+			int numWriten = 0;
+			while(i > 0){
+			 	int i2 = dllo_write(self, ofd, blopPtr+numWriten, i);
+				numWriten += i2;
+				i -= i2;
+			}
+		}
+		dllo_close(self, ofd);
+	}
+	if(result_error == SQ_ERROR) return result_error;
+	sq_pushinteger(v, result_oid);
+	return 1;
+}
+
+static SQRESULT sq_pgsql_delete_blob_field(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_pgsql_INSTANCE();
+	SQ_GET_INTEGER(v, 2, oid);
+	sq_pushinteger(v, dllo_unlink(self, oid));
+	return 1;
+}
+
+#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),  sq_pgsql_##name,nparams,tycheck}
+static SQRegFunction sq_pgsql_methods[] =
+{
+	_DECL_FUNC(constructor,  2, _SC("xs")),
+	_DECL_FUNC(close,  1, _SC("x")),
+	_DECL_FUNC(exec_dml,  2, _SC("xs")),
+	_DECL_FUNC(exec_scalar,  2, _SC("xs")),
+	_DECL_FUNC(exec_query,  2, _SC("xs")),
+	_DECL_FUNC(prepare,  2, _SC("xs")),
+	_DECL_FUNC(error_message,  1, _SC("x")),
+	_DECL_FUNC(version,  1, _SC("x")),
+	_DECL_FUNC(get_blob_field,  2, _SC("xi")),
+	_DECL_FUNC(insert_blob_field,  3, _SC("xsb")),
+	_DECL_FUNC(update_blob_field,  3, _SC("xisb")),
+	_DECL_FUNC(delete_blob_field,  2, _SC("xi")),
+	{0,0}
+};
+#undef _DECL_FUNC
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SQRESULT sqext_register_PostgreSQL(HSQUIRRELVM v)
+{
+    sq_pushstring(v,PostgreSQL_TAG,-1);
+    sq_newclass(v,SQFalse);
+    sq_settypetag(v,-1,(void*)PostgreSQL_TAG);
+    sq_insert_reg_funcs(v, sq_pgsql_methods);
+    sq_newslot(v,-3,SQTrue);
+
+    sq_pushstring(v,PostgreSQL_Statement_TAG,-1);
+    sq_newclass(v,SQFalse);
+    sq_settypetag(v,-1,(void*)PostgreSQL_Statement_TAG);
+    sq_insert_reg_funcs(v, sq_pgsql_statement_methods);
+    sq_newslot(v,-3,SQTrue);
+
+    sq_pushstring(v,PostgreSQL_Result_TAG,-1);
+    sq_newclass(v,SQFalse);
+    sq_settypetag(v,-1,(void*)PostgreSQL_Result_TAG);
+    sq_insert_reg_funcs(v, sq_pgsql_result_methods);
+    sq_pushstring(v, _curr_row_key, -1);
+    sq_pushnull(v);
+    sq_newslot(v, -3, SQFalse);
+    sq_newslot(v,-3,SQTrue);
+
+    return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // WITH_LIBCLANG

+ 273 - 0
SquiLu-ext/sq_libcurl.cpp

@@ -0,0 +1,273 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef USE_EASYCURL
+
+#include "squirrel.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>  /* for malloc */
+#include <assert.h>  /* for a few sanity tests */
+
+#include "EasyCurl.h"
+
+static const SQChar SQ_LIBNAME[] = _SC("EasyCurl");
+
+SQ_OPT_STRING_STRLEN();
+
+static const SQChar SSL_CTX_Tag[]   = _SC("sq_EasyCurl_ctx");
+#define GET_EasyCurl_INSTANCE() SQ_GET_INSTANCE(v, 1, EASYCURL, EASYCURL_Tag) \
+	if(self == NULL) return sq_throwerror(v, _SC("EasyCurl object already closed"));
+
+
+static SQRESULT EasyCurl_release_hook(SQUserPointer p, SQInteger size, HSQUIRRELVM v)
+{
+	EASYCURL *self = (EASYCURL*)p;
+	if(self) EasyCurl_free(self);
+	return 0;
+}
+
+static SQRESULT EasyCurl_free(HSQUIRRELVM v)
+{
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_ssl_INSTANCE();
+	EasyCurl_release_hook(self, 0, v);
+	sq_setinstanceup(v, 1, 0);
+	return 0;
+}
+
+static SQRESULT EasyCurl_constructor(HSQUIRRELVM v, EASYCURL *EasyCurl, int free_on_gc)
+{
+    if(!EasyCurl)
+        return sq_throwerror(v, _SC("Could'nt create an EasyCurl object."));
+
+    sq_pushstring(v, SQ_LIBNAME, -1);
+    if(sq_getonroottable(v) == SQ_OK){
+        sq_pushstring(v, EasyCurl_NAME, -1);
+        if(sq_get(v, -2) == SQ_OK){
+            if(sq_createinstance(v, -1) == SQ_OK){
+                sq_setinstanceup(v, -1, ssl);
+                if(free_on_gc) sq_setreleasehook(v,-1, EasyCurl_release_hook);
+                return 1;
+            }
+        }
+    }
+	return SQ_ERROR;
+}
+
+
+static SQRESULT sq_EasyCurl_cleanup(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_EasyCurl_INSTANCE();
+
+//	void curl_easy_cleanup(CURL *curl)
+
+	return 0;
+}
+
+static SQRESULT sq_EasyCurl_constructor(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_EasyCurl_INSTANCE();
+
+
+	return 0;
+}
+
+static SQRESULT sq_EasyCurl_destructor(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_EasyCurl_INSTANCE();
+
+
+	return 0;
+}
+
+static SQRESULT sq_EasyCurl_easy_duphandle(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_EasyCurl_INSTANCE();
+
+//	CURL* curl_easy_duphandle(CURL *curl)
+
+	return 0;
+}
+
+static SQRESULT sq_EasyCurl_easy_getinfo(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_EasyCurl_INSTANCE();
+
+	SQ_GET_STRING(v, 2, info);
+	SQ_GET_STRING(v, 3, vargv);
+	SQ_GET_STRING(v, 4, ...);
+//	CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
+
+	return 0;
+}
+
+static SQRESULT sq_EasyCurl_easy_init(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_EasyCurl_INSTANCE();
+
+//	CURL *curl_easy_init(void)
+
+	return 0;
+}
+
+static SQRESULT sq_EasyCurl_easy_recv(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_EasyCurl_INSTANCE();
+
+//	CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, size_t *n)
+
+	return 0;
+}
+
+static SQRESULT sq_EasyCurl_easy_reset(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_EasyCurl_INSTANCE();
+
+//	void curl_easy_reset(CURL *curl)
+
+	return 0;
+}
+
+static SQRESULT sq_EasyCurl_easy_send(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_EasyCurl_INSTANCE();
+
+	SQ_GET_STRING(v, 2, buffer);
+//	CURLcode curl_easy_send(CURL *curl, const void *buffer, size_t buflen, size_t *n)
+
+	return 0;
+}
+
+static SQRESULT sq_EasyCurl_easy_setopt(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_EasyCurl_INSTANCE();
+
+	SQ_GET_STRING(v, 2, option);
+	SQ_GET_STRING(v, 3, vargv);
+	SQ_GET_STRING(v, 4, ...);
+//	CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...)
+
+	return 0;
+}
+
+static SQRESULT sq_EasyCurl_perform(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_EasyCurl_INSTANCE();
+
+//	CURLcode curl_easy_perform(CURL *curl)
+
+	return 0;
+}
+
+#define _DECL_EASYCURL_FUNC(name,nparams,pmask) {_SC(#name),sq_EasyCurl_##name,nparams,pmask}
+static SQRegFunction EasyCurl_obj_funcs[]={
+
+	_DECL_EASYCURL_FUNC(cleanup, 1, _SC(".")),
+	_DECL_EASYCURL_FUNC(constructor, 1, _SC(".")),
+	_DECL_EASYCURL_FUNC(destructor, 1, _SC(".")),
+	_DECL_EASYCURL_FUNC(easy_duphandle, 1, _SC(".")),
+	_DECL_EASYCURL_FUNC(easy_getinfo, 4, _SC("....")),
+	_DECL_EASYCURL_FUNC(easy_init, 1, _SC(".")),
+	_DECL_EASYCURL_FUNC(easy_recv, 1, _SC(".")),
+	_DECL_EASYCURL_FUNC(easy_reset, 1, _SC(".")),
+	_DECL_EASYCURL_FUNC(easy_send, 2, _SC("..")),
+	_DECL_EASYCURL_FUNC(easy_setopt, 4, _SC("....")),
+	_DECL_EASYCURL_FUNC(perform, 1, _SC(".")),
+	{0,0}
+};
+#undef _DECL_EASYCURL_FUNC
+
+typedef struct {
+  const SQChar *Str;
+  SQInteger Val;
+} KeyIntType, * KeyIntPtrType;
+
+static KeyIntType EasyCurl_constants[] = {
+    #define MK_CONST(c) {_SC(#c), c}
+    //MK_CONST(SSL_SESSION_ID_SIZE),
+
+	MK_CONST(v, CURLPROTO_DICT);
+	MK_CONST(v, CURLSSH_AUTH_ANY);
+	MK_CONST(v, CURLAUTH_NTLM_WB);
+	MK_CONST(v, CURLSSH_AUTH_KEYBOARD);
+	MK_CONST(v, CURLPROTO_SMTP);
+	MK_CONST(v, CURLPROTO_RTMP);
+	MK_CONST(v, CURLSSH_AUTH_PUBLICKEY);
+	MK_CONST(v, CURLPROTO_POP3);
+	MK_CONST(v, CURLAUTH_NEGOTIATE);
+	MK_CONST(v, CURLPROTO_POP3S);
+	MK_CONST(v, CURLHEADER_SEPARATE);
+	MK_CONST(v, CURLPROTO_RTMPTE);
+	MK_CONST(v, CURLAUTH_DIGEST_IE);
+	MK_CONST(v, CURLPROTO_ALL);
+	MK_CONST(v, CURLSSH_AUTH_HOST);
+	MK_CONST(v, CURLPROTO_HTTP);
+	MK_CONST(v, CURLAUTH_BASIC);
+	MK_CONST(v, CURLPROTO_IMAPS);
+	MK_CONST(v, CURLPROTO_RTMPTS);
+	MK_CONST(v, CURLSSH_AUTH_NONE);
+	MK_CONST(v, CURLGSSAPI_DELEGATION_NONE);
+	MK_CONST(v, CURLAUTH_DIGEST);
+	MK_CONST(v, CURLGSSAPI_DELEGATION_FLAG);
+	MK_CONST(v, CURLPROTO_LDAP);
+	MK_CONST(v, CURLAUTH_NONE);
+	MK_CONST(v, CURLPROTO_SMTPS);
+	MK_CONST(v, CURLPROTO_GOPHER);
+	MK_CONST(v, CURLSSH_AUTH_DEFAULT);
+	MK_CONST(v, CURLPROTO_SMB);
+	MK_CONST(v, CURLPROTO_RTSP);
+	MK_CONST(v, CURLSSH_AUTH_PASSWORD);
+	MK_CONST(v, CURLPROTO_SMBS);
+	MK_CONST(v, CURLAUTH_ANYSAFE);
+	MK_CONST(v, CURLPROTO_LDAPS);
+	MK_CONST(v, CURLGSSAPI_DELEGATION_POLICY_FLAG);
+	MK_CONST(v, CURLPROTO_TFTP);
+	MK_CONST(v, CURLPROTO_SFTP);
+	MK_CONST(v, CURLHEADER_UNIFIED);
+	MK_CONST(v, CURLAUTH_GSSNEGOTIATE);
+	MK_CONST(v, CURLPROTO_FILE);
+	MK_CONST(v, CURLAUTH_NTLM);
+	MK_CONST(v, CURLSSH_AUTH_AGENT);
+	MK_CONST(v, CURLPROTO_HTTPS);
+	MK_CONST(v, CURLPROTO_RTMPS);
+	MK_CONST(v, CURLAUTH_ONLY);
+	MK_CONST(v, CURLPROTO_TELNET);
+	MK_CONST(v, CURLAUTH_ANY);
+	MK_CONST(v, CURLPROTO_FTPS);
+	MK_CONST(v, CURLPROTO_IMAP);
+	MK_CONST(v, CURLPROTO_RTMPE);
+	MK_CONST(v, CURLPROTO_RTMPT);
+	MK_CONST(v, CURLPROTO_FTP);
+	MK_CONST(v, CURLPROTO_SCP);
+    {0,0}
+};
+
+/* This defines a function that opens up your library. */
+SQRESULT sqext_register_EasyCurl (HSQUIRRELVM v) {
+	//add a namespace EasyCurl
+	sq_pushstring(v, SQ_LIBNAME, -1);
+	sq_newtable(v);
+
+	sq_insert_reg_funcs(v, EasyCurl_obj_funcs);
+
+	//add constants
+	KeyIntPtrType KeyIntPtr;
+	for (KeyIntPtr = EasyCurl_constants; KeyIntPtr->Str; KeyIntPtr++) {
+		sq_pushstring(v, KeyIntPtr->Str, -1);    //first the key
+		sq_pushinteger(v, KeyIntPtr->Val);       //then the value
+		sq_newslot(v, -3, SQFalse);              //store then
+	}
+
+	sq_newslot(v,-3,SQFalse); //add EasyCurl table to the root table
+
+	return SQ_OK;
+}
+
+#ifdef __cplusplus
+}
+
+#endif //USE_EASYCURL
+
+#endif

+ 442 - 0
SquiLu-ext/sq_nanomsg.cpp

@@ -0,0 +1,442 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//#ifdef USE_NANOMSG
+
+#include "squirrel.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>  /* for malloc */
+#include <assert.h>  /* for a few sanity tests */
+
+#include "NanoMsg.h"
+
+static const SQChar SQ_LIBNAME[] = _SC("NanoMsg");
+
+SQ_OPT_STRING_STRLEN();
+
+static const SQChar SSL_CTX_Tag[]   = _SC("sq_NanoMsg_ctx");
+
+static SQRESULT get_NanoMsg_instance(HSQUIRRELVM v, SQInteger idx, sq_sqlite3_sdb **sdb)
+{
+    SQRESULT _rc_;
+    if((_rc_ = sq_getinstanceup(v,idx,(SQUserPointer*)sdb,(void*)SQLite3_TAG)) < 0) return _rc_;
+    if(!*sdb) return sq_throwerror(v, _SC("database is closed"));
+    return _rc_;
+}
+
+#define GET_NanoMsg_INSTANCE() SQ_GET_INSTANCE(v, 1, NANOMSG, NANOMSG_Tag) \
+	if(self == NULL) return sq_throwerror(v, _SC("NanoMsg object already closed"));
+
+#define GET_NanoMsg_INSTANCE_at(idx) SQ_GET_INSTANCE(v, idx, NANOMSG, NANOMSG_Tag)
+
+
+static SQRESULT NanoMsg_release_hook(SQUserPointer p, SQInteger size, HSQUIRRELVM v)
+{
+	NANOMSG *self = (NANOMSG*)p;
+	if(self) NanoMsg_free(self);
+	return 0;
+}
+
+static SQRESULT NanoMsg_free(HSQUIRRELVM v)
+{
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_ssl_INSTANCE();
+	NanoMsg_release_hook(self, 0, v);
+	sq_setinstanceup(v, 1, 0);
+	return 0;
+}
+
+static SQRESULT NanoMsg_constructor(HSQUIRRELVM v, NANOMSG *NanoMsg, int free_on_gc)
+{
+    if(!NanoMsg)
+        return sq_throwerror(v, _SC("Could'nt create an NanoMsg object."));
+
+    sq_pushstring(v, SQ_LIBNAME, -1);
+    if(sq_getonroottable(v) == SQ_OK){
+        sq_pushstring(v, NanoMsg_NAME, -1);
+        if(sq_get(v, -2) == SQ_OK){
+            if(sq_createinstance(v, -1) == SQ_OK){
+                sq_setinstanceup(v, -1, ssl);
+                if(free_on_gc) sq_setreleasehook(v,-1, NanoMsg_release_hook);
+                return 1;
+            }
+        }
+    }
+	return SQ_ERROR;
+}
+
+
+static SQRESULT sq_NanoMsg_allocmsg(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_NanoMsg_INSTANCE();
+
+	SQ_GET_INTEGER(v, 2, int_size);
+	SQ_GET_INTEGER(v, 3, int_the_type);
+//	void *nn_allocmsg (size_t size, int type)
+
+	return 0;
+}
+
+static SQRESULT sq_NanoMsg_bind(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_NanoMsg_INSTANCE();
+
+	SQ_GET_STRING(v, 2, str_addr);
+//	int nn_bind (int s, const char *addr)
+    sq_pushinteger(v, nn_bind (self->sock, str_addr));
+
+	return 1;
+}
+
+static SQRESULT sq_NanoMsg_close(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_NanoMsg_INSTANCE();
+
+//	int nn_close (int s)
+    sq_pushinteger(v, nn_close (self->sock));
+
+	return 1;
+}
+
+static SQRESULT sq_NanoMsg_connect(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_NanoMsg_INSTANCE();
+
+	SQ_GET_STRING(v, 2, str_addr);
+//	int nn_connect (int s, const char *addr)
+    sq_pushinteger(v, nn_connect (self->sock, str_addr));
+
+	return 1;
+}
+
+static SQRESULT sq_NanoMsg_constructor(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_NanoMsg_INSTANCE();
+
+	SQ_GET_INTEGER(v, 2, int_domain);
+	SQ_GET_INTEGER(v, 3, int_protocol);
+//	int nn_socket (int domain, int protocol)
+
+	return 0;
+}
+
+static SQRESULT sq_NanoMsg_destructor(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_NanoMsg_INSTANCE();
+
+//	int nn_close (int s)
+
+	return 0;
+}
+
+static SQRESULT sq_NanoMsg_device(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_NanoMsg_INSTANCE();
+
+	GET_NanoMsg_INSTANCE_at(v, 2);
+	GET_NanoMsg_INSTANCE_at(v, 3);
+//	int nn_device (int s1, int s2)
+    sq_pushinteger(v, nn_device (self->sock, str_addr));
+
+	return 1;
+}
+
+static SQRESULT sq_NanoMsg_errno(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_NanoMsg_INSTANCE();
+
+//	int nn_errno (void)
+
+	return 0;
+}
+
+static SQRESULT sq_NanoMsg_freemsg(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_NanoMsg_INSTANCE();
+
+	SQ_GET_STRING(v, 2, msg);
+//	int nn_freemsg (void *msg)
+
+	return 0;
+}
+
+static SQRESULT sq_NanoMsg_getsockopt(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_NanoMsg_INSTANCE();
+
+	SQ_GET_INTEGER(v, 2, int_level);
+	SQ_GET_INTEGER(v, 3, int_option);
+	SQ_GET_STRING(v, 4, optval);
+	SQ_GET_STRING(v, 5, optvallen);
+//	int nn_getsockopt (int s, int level, int option, void *optval, size_t *optvallen)
+
+	return 0;
+}
+
+static SQRESULT sq_NanoMsg_pollfd(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_NanoMsg_INSTANCE();
+
+	GET_NanoMsg_INSTANCE_at(v, 2, fds);
+	GET_NanoMsg_INSTANCE_at(v, 3, int_timeout);
+//	int nn_poll (struct nn_pollfd *fds, int nfds, int timeout)
+
+	return 0;
+}
+
+static SQRESULT sq_NanoMsg_reallocmsg(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_NanoMsg_INSTANCE();
+
+	SQ_GET_STRING(v, 2, msg);
+	SQ_GET_STRING(v, 3, size);
+//	void *nn_reallocmsg (void *msg, size_t size)
+
+	return 0;
+}
+
+static SQRESULT sq_NanoMsg_recv(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_NanoMsg_INSTANCE();
+
+	SQ_GET_INTEGER(v, 2, int_flags);
+//	int nn_recv (int s, void *buf, size_t len, int flags)
+
+	return 0;
+}
+
+static SQRESULT sq_NanoMsg_recvmsg(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_NanoMsg_INSTANCE();
+
+	SQ_GET_INTEGER(v, 2, int_flags);
+//	int nn_recvmsg (int s, struct nn_msghdr *msghdr, int flags)
+
+	return 0;
+}
+
+static SQRESULT sq_NanoMsg_send(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_NanoMsg_INSTANCE();
+
+	SQ_GET_STRING(v, 2, str_buf);
+	SQ_GET_INTEGER(v, 3, int_flags);
+//	int nn_send (int s, const void *buf, size_t len, int flags)
+
+	return 0;
+}
+
+static SQRESULT sq_NanoMsg_sendmsg(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_NanoMsg_INSTANCE();
+
+	SQ_GET_STRING(v, 2, msghdr);
+	SQ_GET_STRING(v, 3, flags);
+//	int nn_sendmsg (int s, const struct nn_msghdr *msghdr, int flags)
+
+	return 0;
+}
+
+static SQRESULT sq_NanoMsg_setsockopt(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_NanoMsg_INSTANCE();
+
+	SQ_GET_INTEGER(v, 2, int_level);
+	SQ_GET_INTEGER(v, 3, int_option);
+	SQ_GET_STRING(v, 4, optval);
+	SQ_GET_STRING(v, 5, optvallen);
+//	int nn_setsockopt (int s, int level, int option, const void *optval, size_t optvallen)
+
+	return 0;
+}
+
+static SQRESULT sq_NanoMsg_shutdown(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_NanoMsg_INSTANCE();
+
+	SQ_GET_INTEGER(v, 2, int_how);
+//	int nn_shutdown (int s, int how)
+
+	return 0;
+}
+
+static SQRESULT sq_NanoMsg_socket(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_NanoMsg_INSTANCE();
+
+	SQ_GET_INTEGER(v, 2, int_domain);
+	SQ_GET_INTEGER(v, 3, int_protocol);
+//	int nn_socket (int domain, int protocol)
+
+	return 0;
+}
+
+static SQRESULT sq_NanoMsg_strerror(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_NanoMsg_INSTANCE();
+
+	SQ_GET_INTEGER(v, 2, int_errnum);
+//	const char *nn_strerror (int errnum)
+
+	return 0;
+}
+
+static SQRESULT sq_NanoMsg_symbol(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_NanoMsg_INSTANCE();
+
+	SQ_GET_INTEGER(v, 2, int_i);
+	SQ_GET_STRING(v, 3, value);
+//	const char *nn_symbol (int i, int *value)
+
+	return 0;
+}
+
+static SQRESULT sq_NanoMsg_symbol_info(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_NanoMsg_INSTANCE();
+
+	SQ_GET_INTEGER(v, 2, int_i);
+//	int nn_symbol_info (int i, struct nn_symbol_properties *buf, int buflen)
+
+	return 0;
+}
+
+static SQRESULT sq_NanoMsg_tcpmuxd(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_NanoMsg_INSTANCE();
+
+	SQ_GET_INTEGER(v, 2, int_port);
+//	int nn_tcpmuxd (int port)
+
+	return 0;
+}
+
+static SQRESULT sq_NanoMsg_term(HSQUIRRELVM v){
+	SQ_FUNC_VARS_NO_TOP(v);
+	GET_NanoMsg_INSTANCE();
+
+//	void nn_term (void)
+
+	return 0;
+}
+
+#define _DECL_NANOMSG_FUNC(name,nparams,pmask) {_SC(#name),sq_NanoMsg_##name,nparams,pmask}
+static SQRegFunction NanoMsg_obj_funcs[]={
+
+	_DECL_NANOMSG_FUNC(allocmsg, 3, _SC(".ii")),
+	_DECL_NANOMSG_FUNC(bind, 2, _SC(".s")),
+	_DECL_NANOMSG_FUNC(close, 1, _SC(".")),
+	_DECL_NANOMSG_FUNC(connect, 2, _SC(".s")),
+	_DECL_NANOMSG_FUNC(constructor, 3, _SC(".ii")),
+	_DECL_NANOMSG_FUNC(destructor, 1, _SC(".")),
+	_DECL_NANOMSG_FUNC(device, 3, _SC(".ii")),
+	_DECL_NANOMSG_FUNC(errno, 1, _SC(".")),
+	_DECL_NANOMSG_FUNC(freemsg, 2, _SC("..")),
+	_DECL_NANOMSG_FUNC(getsockopt, 5, _SC(".ii..")),
+	_DECL_NANOMSG_FUNC(pollfd, 3, _SC("..i")),
+	_DECL_NANOMSG_FUNC(reallocmsg, 3, _SC("...")),
+	_DECL_NANOMSG_FUNC(recv, 2, _SC(".i")),
+	_DECL_NANOMSG_FUNC(recvmsg, 2, _SC(".i")),
+	_DECL_NANOMSG_FUNC(send, 3, _SC(".si")),
+	_DECL_NANOMSG_FUNC(sendmsg, 3, _SC("...")),
+	_DECL_NANOMSG_FUNC(setsockopt, 5, _SC(".ii..")),
+	_DECL_NANOMSG_FUNC(shutdown, 2, _SC(".i")),
+	_DECL_NANOMSG_FUNC(socket, 3, _SC(".ii")),
+	_DECL_NANOMSG_FUNC(strerror, 2, _SC(".i")),
+	_DECL_NANOMSG_FUNC(symbol, 3, _SC(".i.")),
+	_DECL_NANOMSG_FUNC(symbol_info, 2, _SC(".i")),
+	_DECL_NANOMSG_FUNC(tcpmuxd, 2, _SC(".i")),
+	_DECL_NANOMSG_FUNC(term, 1, _SC(".")),
+	{0,0}
+};
+#undef _DECL_NANOMSG_FUNC
+
+typedef struct {
+  const SQChar *Str;
+  SQInteger Val;
+} KeyIntType, * KeyIntPtrType;
+
+static KeyIntType NanoMsg_constants[] = {
+    #define MK_CONST(c) {_SC(#c), c}
+    //MK_CONST(SSL_SESSION_ID_SIZE),
+
+	MK_CONST(v, NN_NS_LIMIT);
+	MK_CONST(v, NN_SNDPRIO);
+	MK_CONST(v, NN_NS_OPTION_LEVEL);
+	MK_CONST(v, NN_NS_TRANSPORT_OPTION);
+	MK_CONST(v, NN_UNIT_MILLISECONDS);
+	MK_CONST(v, NN_RECONNECT_IVL_MAX);
+	MK_CONST(v, NN_NS_SOCKET_OPTION);
+	MK_CONST(v, NN_TYPE_STR);
+	MK_CONST(v, NN_SOL_SOCKET);
+	MK_CONST(v, NN_NS_FLAG);
+	MK_CONST(v, NN_RCVFD);
+	MK_CONST(v, NN_LINGER);
+	MK_CONST(v, NN_SNDFD);
+	MK_CONST(v, SP_HDR);
+	MK_CONST(v, NN_TYPE_INT);
+	MK_CONST(v, NN_POLLIN);
+	MK_CONST(v, NN_RCVBUF);
+	MK_CONST(v, NN_SNDBUF);
+	MK_CONST(v, NN_NS_TRANSPORT);
+	MK_CONST(v, NN_IPV4ONLY);
+	MK_CONST(v, NN_DOMAIN);
+	MK_CONST(v, NN_NS_EVENT);
+	MK_CONST(v, NN_SOCKADDR_MAX);
+	MK_CONST(v, NN_RCVTIMEO);
+	MK_CONST(v, NN_NS_OPTION_UNIT);
+	MK_CONST(v, NN_NS_PROTOCOL);
+	MK_CONST(v, NN_SNDTIMEO);
+	MK_CONST(v, NN_NS_DOMAIN);
+	MK_CONST(v, NN_SOCKET_NAME);
+	MK_CONST(v, NN_PROTOCOL);
+	MK_CONST(v, NN_NS_VERSION);
+	MK_CONST(v, PROTO_SP);
+	MK_CONST(v, NN_TYPE_NONE);
+	MK_CONST(v, NN_NS_OPTION_TYPE);
+	MK_CONST(v, NN_NS_ERROR);
+	MK_CONST(v, NN_POLLOUT);
+	MK_CONST(v, NN_DONTWAIT);
+	MK_CONST(v, NN_MSG);
+	MK_CONST(v, NN_UNIT_PRIORITY);
+	MK_CONST(v, NN_UNIT_NONE);
+	MK_CONST(v, NN_RECONNECT_IVL);
+	MK_CONST(v, NN_RCVPRIO);
+	MK_CONST(v, AF_SP_RAW);
+	MK_CONST(v, NN_UNIT_BYTES);
+	MK_CONST(v, NN_UNIT_BOOLEAN);
+	MK_CONST(v, NN_NS_NAMESPACE);
+	MK_CONST(v, AF_SP);
+    {0,0}
+};
+
+/* This defines a function that opens up your library. */
+SQRESULT sqext_register_NanoMsg (HSQUIRRELVM v) {
+	//add a namespace NanoMsg
+	sq_pushstring(v, SQ_LIBNAME, -1);
+	sq_newtable(v);
+
+	sq_insert_reg_funcs(v, NanoMsg_obj_funcs);
+
+	//add constants
+	KeyIntPtrType KeyIntPtr;
+	for (KeyIntPtr = NanoMsg_constants; KeyIntPtr->Str; KeyIntPtr++) {
+		sq_pushstring(v, KeyIntPtr->Str, -1);    //first the key
+		sq_pushinteger(v, KeyIntPtr->Val);       //then the value
+		sq_newslot(v, -3, SQFalse);              //store then
+	}
+
+	sq_newslot(v,-3,SQFalse); //add NanoMsg table to the root table
+
+	return SQ_OK;
+}
+
+#ifdef __cplusplus
+}
+
+#endif //USE_NANOMSG
+
+#endif

+ 503 - 0
SquiLu-ext/sq_sys.cpp

@@ -0,0 +1,503 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <time.h>
+
+#include "squirrel.h"
+#include "sqstdblobimpl.h"
+SQ_OPT_STRING_STRLEN();
+
+static const SQChar sq_sys_TAG[] = "sqsys";
+
+
+#ifdef _WIN32
+
+#define _WIN32_WINNT	0x0600
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#include <winsock2.h>
+#include <mmsystem.h>	/* timeGetTime */
+
+#else
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE	/* pthread_*affinity_np */
+#endif
+
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS	64
+#define _LARGEFILE_SOURCE	1
+#endif
+
+#include <sys/time.h>
+#include <unistd.h>
+#include <signal.h>
+#include <fcntl.h>
+
+#include <pthread.h>
+#include <sched.h>
+
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+#include <sys/param.h>
+#endif
+
+#endif
+
+
+#include <sys/types.h>
+#include <errno.h>
+
+
+#ifdef _WIN32
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef SSIZE_T		ssize_t;
+#endif
+
+#ifndef ULONG_PTR
+typedef SIZE_T		ULONG_PTR, DWORD_PTR;
+#endif
+
+#if (_WIN32_WINNT >= 0x0500)
+#define InitCriticalSection(cs) \
+    InitializeCriticalSectionAndSpinCount(cs, 3000)
+#else
+#define InitCriticalSection(cs) \
+    (InitializeCriticalSection(cs), TRUE)
+#endif
+
+#define SYS_ERRNO		GetLastError()
+#define SYS_IS_EAGAIN(e)	((e) == WSAEWOULDBLOCK)
+
+#else
+
+#define SYS_ERRNO		errno
+#define SYS_IS_EAGAIN(e)	((e) == EAGAIN || (e) == EWOULDBLOCK)
+
+#define SYS_SIGINTR		SIGUSR2
+
+#endif
+
+/*
+#define LUA_SYSLIBNAME "sys"
+LUALIB_API int luaopen_sys (lua_State *L);
+
+#define LUA_SOCKLIBNAME "sys.sock"
+LUALIB_API int luaopen_sys_sock (lua_State *L);
+
+#define LUA_ISAPILIBNAME "sys.isapi"
+LUALIB_API int luaopen_sys_isapi (lua_State *L);
+*/
+
+/*
+ * 64-bit integers
+ */
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef __int64			int64_t;
+typedef unsigned __int64	uint64_t;
+#else
+#include <stdint.h>
+#endif
+
+#define INT64_MAKE(lo,hi)	(((int64_t) (hi) << 32) | (unsigned int) (lo))
+#define INT64_LOW(x)		((unsigned int) (x))
+#define INT64_HIGH(x)		((unsigned int) ((x) >> 32))
+
+
+/*
+ * File and Socket Handles
+ */
+
+#define FD_TYPENAME	"sys.handle"
+
+#ifdef _WIN32
+typedef HANDLE	fd_t;
+typedef SOCKET	sd_t;
+#else
+typedef int	fd_t;
+typedef int	sd_t;
+#endif
+
+
+/*
+ * Error Reporting
+ */
+
+#define SYS_ERROR_MESSAGE	"SYS_ERR"
+
+//int sys_seterror (lua_State *L, int err);
+
+
+/*
+ * Time
+ */
+
+typedef int	msec_t;
+
+#ifdef _WIN32
+#define sys_milliseconds	timeGetTime
+#else
+msec_t sys_milliseconds (void);
+#endif
+
+#define TIMEOUT_INFINITE	((msec_t) -1)
+
+
+/*
+ * Buffer Management
+ */
+
+#define MAX_PATHNAME	512
+
+#define SYS_BUFIO_TAG	"bufio__"  /* key to indicate buffer I/O */
+#define SYS_BUFSIZE	4096
+
+struct membuf;
+
+struct sys_buffer
+{
+    union
+    {
+        const char *r;  /* read from buffer */
+        char *w;  /* write to buffer */
+    } ptr;
+    size_t size;
+    struct membuf *mb;
+};
+
+
+static int sys_buffer_read_init (HSQUIRRELVM v, int idx, struct sys_buffer *sb);
+static void sys_buffer_read_next (struct sys_buffer *sb, const size_t n);
+
+static void sys_buffer_write_init (HSQUIRRELVM v, int idx, struct sys_buffer *sb,
+                                   char *buf, const size_t buflen);
+static int sys_buffer_write_next (HSQUIRRELVM v, struct sys_buffer *sb,
+                                  char *buf, const size_t buflen);
+static int sys_buffer_write_done (HSQUIRRELVM v, struct sys_buffer *sb,
+                                  char *buf, const size_t tail);
+
+
+/*
+ * Threading
+ */
+
+struct sys_thread;
+
+static void sys_thread_set (struct sys_thread *td);
+static struct sys_thread *sys_thread_get (void);
+
+static HSQUIRRELVM sys_thread_tosquilu (struct sys_thread *td);
+
+static void sys_thread_switch (struct sys_thread *td);
+
+static void sys_thread_check (struct sys_thread *td, HSQUIRRELVM v);
+
+static void sys_vm2_enter (struct sys_thread *td);
+static void sys_vm2_leave (struct sys_thread *td);
+
+static void sys_vm_enter (HSQUIRRELVM v);
+static void sys_vm_leave (HSQUIRRELVM vL);
+
+static struct sys_thread *sys_thread_new (HSQUIRRELVM v,
+        struct sys_thread *vmtd,
+        struct sys_thread *vmtd2,
+        const int push_udata);
+static void sys_thread_del (struct sys_thread *td);
+
+static int sys_thread_suspend (struct sys_thread *td, const msec_t timeout);
+static void sys_thread_resume (struct sys_thread *td);
+
+static int sys_eintr (void);
+
+
+/*
+ * Event Queue & Scheduler
+ */
+
+#define EVQ_TYPENAME	"sys.event_queue"
+
+enum
+{
+    SYS_ERR_SYSTEM = -1,
+    SYS_ERR_TIMEOUT = 1,
+    SYS_ERR_THROW
+};
+
+enum
+{
+    EVQ_SCHED_OBJ = 0,
+    EVQ_SCHED_TIMER,
+    EVQ_SCHED_PID,
+    EVQ_SCHED_DIRWATCH,
+#ifdef _WIN32
+    EVQ_SCHED_REGWATCH,
+#endif
+    EVQ_SCHED_SIGNAL,
+    EVQ_SCHED_SOCKET
+};
+
+struct event_queue;
+
+static int sys_evq_loop (HSQUIRRELVM v, struct event_queue *evq,
+                         const msec_t timeout, const int linger,
+                         const int once, const int evq_idx);
+
+static int sys_evq_sched_add (HSQUIRRELVM vL, const int evq_idx, const int type);
+static void sys_evq_sched_del (HSQUIRRELVM v, void *ev_op, const int ev_added);
+
+static void sys_sched_event_added (HSQUIRRELVM v, void *ev);
+static void sys_sched_event_ready (HSQUIRRELVM v, void *ev);
+
+
+#ifdef _WIN32
+
+/*
+ * Windows NT specifics
+ */
+
+#ifndef STATUS_CANCELLED
+#define STATUS_CANCELLED	((DWORD) 0xC0000120L)
+#endif
+
+typedef BOOL (WINAPI *PCancelSynchronousIo) (HANDLE hThread);
+
+typedef BOOL (WINAPI *PCancelIoEx) (HANDLE hThread, LPOVERLAPPED overlapped);
+
+extern PCancelSynchronousIo pCancelSynchronousIo;
+extern PCancelIoEx pCancelIoEx;
+
+extern CRITICAL_SECTION g_CritSect;
+
+#if defined(_WIN32_WCE) || defined(WIN32_VISTA)
+#define is_WinNT	1
+#else
+extern int is_WinNT;
+#endif
+
+
+/* Windows Registry */
+
+#define WREG_TYPENAME	"sys.win32.registry"
+
+
+/*
+ * Convert Windows OS filenames to UTF-8
+ */
+
+static void *utf8_to_filename (const char *s);
+static char *filename_to_utf8 (const void *s);
+
+#endif
+
+
+/*
+ * Arguments: ..., [number]
+ * Returns: string
+ */
+static int sys_strerror (HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS(v);
+    SQ_OPT_INTEGER(v, 2, err, SYS_ERRNO);
+
+#ifndef _WIN32
+#if defined(BSD) || (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600)
+    char buf[512];
+
+    if (!err) goto success;
+
+    if (!strerror_r(err, buf, sizeof(buf)))
+    {
+        sq_pushstring(v, buf, -1);
+        return 1;
+    }
+#endif
+    sq_pushstring(v, strerror(err), -1);
+#else
+    const int flags = FORMAT_MESSAGE_IGNORE_INSERTS
+                      | FORMAT_MESSAGE_FROM_SYSTEM;
+    WCHAR buf[512];
+
+    if (!err) goto success;
+
+    if (is_WinNT
+            ? FormatMessageW(flags, NULL, err, 0, buf, sizeof(buf) / sizeof(buf[0]), NULL)
+            : FormatMessageA(flags, NULL, err, 0, (char *) buf, sizeof(buf), NULL))
+    {
+        char *s = filename_to_utf8(buf);
+        if (s)
+        {
+            char *cp;
+            for (cp = s; *cp != '\0'; ++cp)
+            {
+                if (*cp == '\r' || *cp == '\n')
+                    *cp = ' ';
+            }
+
+            sq_pushstring(v, s, -1);
+            free(s);
+            return 1;
+        }
+    }
+    sq_pushfstring(v, _SC("System error %d"), err);
+#endif
+    return 1;
+success:
+    sq_pushliteral(v, _SC("OK"));
+    return 1;
+}
+
+/*
+ * Returns: nil, string
+ */
+static int sys_seterror (HSQUIRRELVM v, int err)
+{
+  if (err) {
+#ifndef _WIN32
+    errno = err;
+#else
+    SetLastError(err);
+#endif
+  }
+  sq_pushnull(v);
+  sys_strerror(v);
+  sq_pushvalue(v, -1);
+  sq_setglobal(v, SYS_ERROR_MESSAGE);
+  return 2;
+}
+
+
+#include <sys/time.h> /* for struct timeval */
+
+#ifndef __WIN32__
+#include <sys/times.h> /* for struct tms */
+#endif
+
+#ifdef __WIN32__
+#include "win/win.h"
+#endif
+
+#include <errno.h>
+#include <limits.h> /* for CLK_TCK */
+
+#ifndef CLK_TCK
+#define CLK_TCK CLOCKS_PER_SEC
+#endif
+
+#define RUSAGE_SELF 0
+#define RUSAGE_CHILDREN (-1)
+
+struct rusage
+{
+    struct timeval ru_utime; /* user time used */
+    struct timeval ru_stime; /* system time used */
+};
+
+static int getrusage(int who, struct rusage *rusage)
+{
+#ifdef WIN32
+    FILETIME starttime;
+    FILETIME exittime;
+    FILETIME kerneltime;
+    FILETIME usertime;
+    ULARGE_INTEGER li;
+    if (who != RUSAGE_SELF)
+    {
+        /* Only RUSAGE_SELF is supported in this implementation for now */
+        errno = EINVAL;
+        return -1;
+    }
+    if (rusage == (struct rusage *) NULL)
+    {
+        errno = EFAULT;
+        return -1;
+    }
+    memset(rusage, 0, sizeof(struct rusage));
+    if (GetProcessTimes(GetCurrentProcess(),
+                        &starttime, &exittime, &kerneltime, &usertime) == 0)
+    {
+        _dosmaperr(GetLastError());
+        return -1;
+    }
+    /* Convert FILETIMEs (0.1 us) to struct timeval */
+    memcpy(&li, &kerneltime, sizeof(FILETIME));
+    li.QuadPart /= 10L; /* Convert to microseconds */
+    rusage->ru_stime.tv_sec = li.QuadPart / 1000000L;
+    rusage->ru_stime.tv_usec = li.QuadPart % 1000000L;
+    memcpy(&li, &usertime, sizeof(FILETIME));
+    li.QuadPart /= 10L; /* Convert to microseconds */
+    rusage->ru_utime.tv_sec = li.QuadPart / 1000000L;
+    rusage->ru_utime.tv_usec = li.QuadPart % 1000000L;
+#else /* all but WIN32 */
+    struct tms tms;
+    int tick_rate = CLK_TCK; /* ticks per second */
+    clock_t u,
+    s;
+    if (rusage == (struct rusage *) NULL)
+    {
+        errno = EFAULT;
+        return -1;
+    }
+    if (times(&tms) < 0)
+    {
+        /* errno set by times */
+        return -1;
+    }
+    switch (who)
+    {
+    case RUSAGE_SELF:
+        u = tms.tms_utime;
+        s = tms.tms_stime;
+        break;
+    case RUSAGE_CHILDREN:
+        u = tms.tms_cutime;
+        s = tms.tms_cstime;
+        break;
+    default:
+        errno = EINVAL;
+        return -1;
+    }
+#define TICK_TO_SEC(T, RATE) ((T)/(RATE))
+#define TICK_TO_USEC(T,RATE) (((T)%(RATE)*1000000)/RATE)
+    rusage->ru_utime.tv_sec = TICK_TO_SEC(u, tick_rate);
+    rusage->ru_utime.tv_usec = TICK_TO_USEC(u, tick_rate);
+    rusage->ru_stime.tv_sec = TICK_TO_SEC(s, tick_rate);
+    rusage->ru_stime.tv_usec = TICK_TO_USEC(u, tick_rate);
+#endif /* WIN32 */
+    return 0;
+}
+
+static SQRESULT sq_sys_getrusage(HSQUIRRELVM vm)
+{
+    return SQ_OK;
+}
+
+#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),  sq_sys_##name,nparams,tycheck}
+static SQRegFunction sq_sys_methods[] =
+{
+    _DECL_FUNC(getrusage,  -1, _SC("x")),
+    {0,0}
+};
+#undef _DECL_FUNC
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+    SQRESULT sqext_register_sys(HSQUIRRELVM v)
+    {
+        //add a namespace sqsys
+        sq_pushstring(v, sq_sys_TAG,-1);
+        sq_newclass(v, SQFalse);
+        sq_insert_reg_funcs(v, sq_sys_methods);
+        sq_newslot(v,-3,SQTrue); //add sqmix table to the root table
+
+        return SQ_OK;
+    }
+
+#ifdef __cplusplus
+}
+#endif

+ 293 - 0
SquiLu-ext/sq_unql.cpp

@@ -0,0 +1,293 @@
+/* Code generated by script */
+#include "sq_sqlite3.h"
+
+extern "C" {
+#include "xjd1.h"
+}
+
+static const SQChar *xjd1_TAG = "xjd1";
+static const SQChar *xjd1_Stmt_TAG = "xjd1Stmt";
+
+static SQRESULT get_xjd1_instance(HSQUIRRELVM v, SQInteger idx, xjd1 **db)
+{
+    SQRESULT _rc_;
+    if((_rc_ = sq_getinstanceup(v,idx,(SQUserPointer*)db,(void*)xjd1_TAG)) < 0) return _rc_;
+    if(!*db) return sq_throwerror(v, _SC("database is closed"));
+    return _rc_;
+}
+
+static SQRESULT get_xjd1_stmt_instance(HSQUIRRELVM v, SQInteger idx, xjd1_stmt **stmt)
+{
+    SQRESULT _rc_;
+    if((_rc_ = sq_getinstanceup(v,idx,(SQUserPointer*)stmt,(void*)xjd1_Stmt_TAG)) < 0) return _rc_;
+    if(!*stmt) return sq_throwerror(v, _SC("statement is closed"));
+    return _rc_;
+}
+
+static SQRESULT get_sqlite3_instance(HSQUIRRELVM v, SQInteger idx, sq_sqlite3_sdb **sdb)
+{
+    SQRESULT _rc_;
+    if((_rc_ = sq_getinstanceup(v,idx,(SQUserPointer*)sdb,(void*)SQLite3_TAG)) < 0) return _rc_;
+    if(!*sdb) return sq_throwerror(v, _SC("database is closed"));
+    return _rc_;
+}
+
+#define push_xjd1_null(v) {sq_pushstring(v, nullName, sizeof(nullName)-1);sq_get(v, 1);}
+
+#define GET_xjd1_INSTANCE_AT(idx) \
+	xjd1 *self=NULL; \
+	if((_rc_ = get_xjd1_instance(v,idx,&self)) < 0) return _rc_;
+
+#define GET_xjd1_INSTANCE() GET_xjd1_INSTANCE_AT(1)
+
+#define GET_xjd1_stmt_INSTANCE()  \
+	xjd1_stmt *self=NULL; \
+	if((_rc_ = get_xjd1_stmt_instance(v,1,&self)) < 0) return _rc_;
+
+
+static SQRESULT sq_xjd1_stmt_releasehook(SQUserPointer p, SQInteger size, HSQUIRRELVM v)
+{
+    xjd1_stmt *stmt = ((xjd1_stmt *)p);
+    if(stmt) xjd1_stmt_delete(stmt);
+    return 0;
+}
+
+static SQRESULT sq_xjd1_stmt_constructor(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    _rc_ = SQ_ERROR;
+    GET_xjd1_INSTANCE_AT(2);
+    SQ_GET_STRING(v, 3, sql);
+    xjd1_stmt *stmt = 0;
+    if(xjd1_stmt_new(self, sql, &stmt, 0) != XJD1_OK)
+    {
+        return sq_throwerror(v, xjd1_errmsg(self));
+    }
+    sq_setinstanceup(v, 1, stmt); //replace self for this instance with this new sqlite3_stmt
+    sq_setreleasehook(v,1, sq_xjd1_stmt_releasehook);
+    return SQ_OK;
+}
+
+static SQRESULT sq_xjd1_stmt_finalize(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    GET_xjd1_stmt_INSTANCE();
+    sq_setinstanceup(v, 1, 0); //next calls will fail with "statement is closed"
+    sq_pushinteger(v, xjd1_stmt_delete(self));
+    return 1;
+}
+
+static SQRESULT sq_xjd1_stmt_step(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    GET_xjd1_stmt_INSTANCE();
+    sq_pushinteger(v, xjd1_stmt_step(self));
+    return 1;
+}
+
+static SQRESULT sq_xjd1_stmt_next_row(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    GET_xjd1_stmt_INSTANCE();
+    sq_pushbool(v, xjd1_stmt_step(self) == XJD1_ROW);
+    return 1;
+}
+
+static SQRESULT sq_xjd1_stmt_rewind(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    GET_xjd1_stmt_INSTANCE();
+    sq_pushinteger(v, xjd1_stmt_rewind(self));
+    return 1;
+}
+
+static SQRESULT sq_xjd1_stmt_value(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    GET_xjd1_stmt_INSTANCE();
+    const char* value;
+    int rc = xjd1_stmt_value(self, &value);
+    if(rc == XJD1_OK) sq_pushstring(v, value, -1);
+    else return sq_throwerror(v, _SC("Erro when getting value from xjd1_stmt -> %d"), rc);
+    return 1;
+}
+
+#define _DECL_FUNC(name,nparams,tycheck, isStatic) {_SC(#name),  sq_xjd1_stmt_##name,nparams,tycheck, isStatic}
+static SQRegFunction sq_xjd1_stmt_methods[] =
+{
+    _DECL_FUNC(constructor,  3, _SC("xxs"), SQFalse),
+
+    _DECL_FUNC(finalize,  1, _SC("x"), SQFalse),
+    _DECL_FUNC(step,  1, _SC("x"), SQFalse),
+    _DECL_FUNC(next_row,  1, _SC("x"), SQFalse),
+    _DECL_FUNC(rewind,  1, _SC("x"), SQFalse),
+    _DECL_FUNC(value,  1, _SC("x"), SQFalse),
+    {0,0}
+};
+#undef _DECL_FUNC
+
+
+static SQRESULT sq_xjd1_close_release(HSQUIRRELVM v, xjd1 *db)
+{
+    SQRESULT rc = SQ_ERROR;
+    if(db)
+    {
+        if(xjd1_close(db) == XJD1_OK)
+        {
+            rc = SQ_OK;
+        }
+        else return sq_throwerror(v, xjd1_errmsg(db));
+    }
+    return rc;
+}
+
+static SQRESULT sq_xjd1_releasehook(SQUserPointer p, SQInteger size, HSQUIRRELVM v)
+{
+    xjd1 *db = ((xjd1 *)p);
+    sq_xjd1_close_release(v, db);
+    return 0;
+}
+
+static SQRESULT sq_xjd1_constructor(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    xjd1 *db;
+    sq_sqlite3_sdb *sdb = NULL;
+    int rc = XJD1_ERROR;
+    switch(sq_gettype(v, 2))
+    {
+    case OT_STRING:
+        {
+            SQ_GET_STRING(v, 2, dbname);
+            rc = xjd1_open(0, dbname, &db);
+        }
+        break;
+    case OT_INSTANCE:
+        {
+            if(get_sqlite3_instance(v, 2, &sdb) == SQ_OK)
+            {
+                rc = xjd1_open_with_db(0, sdb->db, &db);
+            }
+        }
+        break;
+    default:
+        return sq_throwerror(v, _SC("Wrong parameters to open xjd1 file name or sqlite3 expected !"));
+    }
+    if(rc != SQ_OK) return sq_throwerror(v, _SC("Failed to open database ! %d"), rc);
+    sq_setinstanceup(v, 1, db);
+    sq_setreleasehook(v,1, sq_xjd1_releasehook);
+
+    return SQ_OK;
+}
+
+static SQRESULT sq_xjd1_close(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    GET_xjd1_INSTANCE();
+    if(sq_xjd1_close_release(v, self) != SQ_OK) return SQ_ERROR;
+    sq_setinstanceup(v, 1, 0); //next calls will fail with "database is closed"
+    return 0;
+}
+
+static SQRESULT sq_xjd1_complete(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    SQ_GET_STRING(v, 2, szSql);
+    sq_pushinteger(v, xjd1_complete(szSql));
+    return 1;
+}
+
+/* stmt * prepare( const char * sql  ) */
+static SQRESULT sq_xjd1_prepare(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    //GET_xjd1_INSTANCE();
+    SQ_GET_STRING(v, 2, sql);
+    sq_pushstring(v, xjd1_Stmt_TAG, -1);
+    if(sq_getonroottable(v) == SQ_ERROR) return SQ_ERROR;
+    sq_pushroottable(v);
+    sq_push(v, 1);
+    sq_push(v, 2);
+    if(sq_call(v, 3, SQTrue, SQFalse) != SQ_OK) return SQ_ERROR;
+//printf("%d:%s\n", __LINE__, __FILE__);
+    return 1;
+}
+
+static SQRESULT sq_xjd1_errcode_name(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    GET_xjd1_INSTANCE();
+    sq_pushstring(v, xjd1_errcode_name(self), -1);
+    return 1;
+}
+
+static SQRESULT sq_xjd1_errmsg(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    GET_xjd1_INSTANCE();
+    sq_pushstring(v, xjd1_errmsg(self), -1);
+    return 1;
+}
+
+
+#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),  sq_xjd1_##name,nparams,tycheck}
+static SQRegFunction sq_xjd1_methods[] =
+{
+    _DECL_FUNC(constructor,  2, _SC("x x|s")),
+    _DECL_FUNC(close,  1, _SC("x")),
+
+    _DECL_FUNC(errcode_name,  1, _SC("x")),
+    _DECL_FUNC(errmsg,  1, _SC("x")),
+
+    _DECL_FUNC(complete,  1, _SC("s")),
+    _DECL_FUNC(prepare,  2, _SC("xs")),
+    {0,0}
+};
+
+#undef _DECL_FUNC
+
+#define INT_CONST(v,num) 	sq_pushstring(v,_SC(#num),-1);sq_pushinteger(v,num);sq_newslot(v,-3,SQTrue);
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+    SQRESULT sqext_register_xjd1(HSQUIRRELVM v)
+    {
+
+        sq_pushstring(v,xjd1_TAG,-1);
+        sq_newclass(v,SQFalse);
+        sq_settypetag(v,-1,(void*)xjd1_TAG);
+        sq_insert_reg_funcs(v, sq_xjd1_methods);
+
+        INT_CONST(v,XJD1_OK);
+        INT_CONST(v,XJD1_ERROR);
+        INT_CONST(v,XJD1_MISUSE);
+        INT_CONST(v,XJD1_NOMEM);
+        INT_CONST(v,XJD1_UNKNOWN);
+        INT_CONST(v,XJD1_SYNTAX);
+        INT_CONST(v,XJD1_ERROR_OPEN_DB);
+        INT_CONST(v,XJD1_ROW);
+        INT_CONST(v,XJD1_DONE);
+
+        sq_newslot(v,-3,SQTrue);
+
+        sq_pushstring(v, xjd1_Stmt_TAG,-1);
+        sq_newclass(v,SQFalse);
+        sq_settypetag(v,-1,(void*)xjd1_Stmt_TAG);
+        sq_insert_reg_funcs(v, sq_xjd1_stmt_methods);
+
+        INT_CONST(v,XJD1_OK);
+        INT_CONST(v,XJD1_ROW);
+        INT_CONST(v,XJD1_DONE);
+
+        sq_newslot(v,-3,SQTrue);
+        return 1;
+    }
+
+#ifdef __cplusplus
+}
+#endif
+